Serious-Engine/Sources/WorldEditor/WorldEditor.cpp

2994 lines
97 KiB
C++
Raw Permalink Normal View History

2016-03-12 01:20:51 +01:00
/* 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. */
2016-03-11 14:57:17 +01:00
// WorldEditor.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "WorldEditor.h"
#include "DlgTipOfTheDay.h"
#include <Engine/Templates/Stock_CTextureData.h>
#include <Engine/Templates/Stock_CModelData.h>
#include <sys/stat.h>
#include <sys/utime.h>
#include <process.h>
#ifdef _DEBUG
#undef new
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
UINT _uiMessengerMsg=-1;
UINT _uiMessengerForcePopup=-1;
extern FLOAT _fFlyModeSpeedMultiplier = 1.0f;
FLOAT _fLastMipBrushingOptionUsed = -10000.0f;
extern INDEX wed_iMaxFPSActive = 500;
extern FLOAT wed_fFrontClipDistance = 0.5f;
extern struct GameGUI_interface *_pGameGUI = NULL;
extern INDEX wed_bUseGenericTextureReplacement = FALSE;
CTFileName fnmPersistentSymbols = CTString("Scripts\\PersistentSymbols.ini");
// Macros used for ini i/o operations
#define INI_PRIMITIVE_READ( strname, default_val) \
strcpy( strIni, CStringA(theApp.GetProfileString( L"World editor prefs", CString(strPrimitiveType+" "+ strname ), CString( default_val ))))
#define INI_PRIMITIVE_WRITE( strname) \
theApp.WriteProfileString( L"World editor prefs", CString(strPrimitiveType+" "+strname), CString(strIni))
#define INI_READ( strname, default_val) \
strcpy( strIni, CStringA(theApp.GetProfileString( L"World editor prefs", CString( strname ), CString(default_val))))
#define GET_FLAG( var) \
if( strcmp( strIni, "YES") == 0) var = TRUE; \
else var = FALSE;
#define GET_COLOR( var) \
sscanf( strIni, "0X%08x", &var);
#define GET_INDEX( var) \
sscanf( strIni, "%d", &var);
#define GET_FLOAT( var) \
sscanf( strIni, "%f", &var);
#define GET_STRING( var) \
var = CTString( strIni);
#define SET_FLAG( var) \
if( var) strcpy( strIni, "YES"); \
else strcpy( strIni, "NO");
#define SET_COLOR( var) \
sprintf( strIni, "0x%08x", var); \
_strupr( strIni);
#define SET_INDEX( var) \
sprintf( strIni, "%d", var); \
_strupr( strIni);
#define SET_FLOAT( var) \
sprintf( strIni, "%f", var); \
_strupr( strIni);
#define SET_STRING( var) \
sprintf( strIni, "%s", var);
#define INI_WRITE( strname) \
theApp.WriteProfileString( L"World editor prefs", CString( strname ), CString(strIni))
void InitializeGame(void)
{
try {
#ifndef NDEBUG
#define GAMEDLL _fnmApplicationExe.FileDir()+"GameGUI"+_strModExt+"D.dll"
#else
#define GAMEDLL _fnmApplicationExe.FileDir()+"GameGUI"+_strModExt+".dll"
#endif
CTFileName fnmExpanded;
ExpandFilePath(EFP_READ, CTString(GAMEDLL), fnmExpanded);
HMODULE hGame = LoadLibraryA(fnmExpanded);
if (hGame==NULL) {
ThrowF_t("%s", GetWindowsError(GetLastError()));
}
GameGUI_interface* (*GAMEGUI_Create)(void) = (GameGUI_interface* (*)(void))GetProcAddress(hGame, "GAMEGUI_Create");
if (GAMEGUI_Create==NULL) {
ThrowF_t("%s", GetWindowsError(GetLastError()));
}
_pGameGUI = GAMEGUI_Create();
} catch (char *strError) {
FatalError("%s", strError);
}
_pGameGUI->Initialize(CTString("Data\\WorldEditor.gms"));
}
/////////////////////////////////////////////////////////////////////////////
// CWorldEditorApp
BEGIN_MESSAGE_MAP(CWorldEditorApp, CWinApp)
//{{AFX_MSG_MAP(CWorldEditorApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_FILE_PREFERENCES, OnFilePreferences)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_IMPORT_3D_OBJECT, OnImport3DObject)
ON_COMMAND(ID_DECADIC_GRID, OnDecadicGrid)
ON_UPDATE_COMMAND_UI(ID_DECADIC_GRID, OnUpdateDecadicGrid)
ON_COMMAND(ID_CONVERT_WORLDS, OnConvertWorlds)
ON_COMMAND(ID_SET_AS_DEFAULT, OnSetAsDefault)
ON_COMMAND(ID_HELP_SHOWTIPOFTHEDAY, OnHelpShowTipOfTheDay)
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWorldEditorApp construction
void SetRenderingPrefs( CViewPrefs vp)
{
// store current shadows on/off state
CWorldRenderPrefs::ShadowsType sht=_wrpWorldRenderPrefs.GetShadowsType();
_wrpWorldRenderPrefs = vp.m_wrpWorldRenderPrefs;
_mrpModelRenderPrefs = vp.m_mrpModelRenderPrefs;
_wrpWorldRenderPrefs.SetSelectedEntityModel( theApp.m_pEntityMarkerModelObject);
_wrpWorldRenderPrefs.SetSelectedPortalModel( theApp.m_pPortalMarkerModelObject);
_wrpWorldRenderPrefs.SetEmptyBrushModel( theApp.m_pEmptyBrushModelObject);
// restore current shadows on/off state
_wrpWorldRenderPrefs.SetShadowsType( sht);
}
void WED_ApplyChildSettings(INDEX iChildCfg)
{
CChildConfiguration &cc = theApp.m_ccChildConfigurations[ iChildCfg];
// find perspective view
for( INDEX iView=0; iView<cc.m_iHorizontalSplitters*cc.m_iHorizontalSplitters; iView++)
{
if( cc.m_ptProjectionType[ iView] == CSlaveViewer::PT_PERSPECTIVE)
{
SetRenderingPrefs( cc.m_vpViewPrefs[ iView]);
}
}
}
void WED_ApplyChildSettings0(void) { WED_ApplyChildSettings(0);}
void WED_ApplyChildSettings1(void) { WED_ApplyChildSettings(1);}
void WED_ApplyChildSettings2(void) { WED_ApplyChildSettings(2);}
void WED_ApplyChildSettings3(void) { WED_ApplyChildSettings(3);}
void WED_ApplyChildSettings4(void) { WED_ApplyChildSettings(4);}
void WED_ApplyChildSettings5(void) { WED_ApplyChildSettings(5);}
void WED_ApplyChildSettings6(void) { WED_ApplyChildSettings(6);}
void WED_ApplyChildSettings7(void) { WED_ApplyChildSettings(7);}
void WED_ApplyChildSettings8(void) { WED_ApplyChildSettings(8);}
void WED_ApplyChildSettings9(void) { WED_ApplyChildSettings(9);}
void WED_ApplyRenderingSettings0(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[0]);}
void WED_ApplyRenderingSettings1(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[1]);}
void WED_ApplyRenderingSettings2(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[2]);}
void WED_ApplyRenderingSettings3(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[3]);}
void WED_ApplyRenderingSettings4(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[4]);}
void WED_ApplyRenderingSettings5(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[5]);}
void WED_ApplyRenderingSettings6(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[6]);}
void WED_ApplyRenderingSettings7(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[7]);}
void WED_ApplyRenderingSettings8(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[8]);}
void WED_ApplyRenderingSettings9(void) { SetRenderingPrefs(theApp.m_vpViewPrefs[9]);}
void FindEmptyBrushes( void);
void WED_FindEmptyBrushes(void) { FindEmptyBrushes(); }
// Create primitive default values
CValuesForPrimitive::CValuesForPrimitive()
{
vfp_csgtCSGOperation = CSG_ILLEGAL;
vfp_ptPrimitiveType = PT_CONUS;
vfp_avVerticesOnBaseOfPrimitive.Clear();
vfp_avVerticesOnBaseOfPrimitive.New(4);
vfp_avVerticesOnBaseOfPrimitive[0] = DOUBLE3D( -8.0f, 0.0f, -8.0f);
vfp_avVerticesOnBaseOfPrimitive[1] = DOUBLE3D( 8.0f, 0.0f, -8.0f);
vfp_avVerticesOnBaseOfPrimitive[2] = DOUBLE3D( 8.0f, 0.0f, 8.0f);
vfp_avVerticesOnBaseOfPrimitive[3] = DOUBLE3D( -8.0f, 0.0f, 8.0f);
vfp_bClosed = TRUE;
vfp_ttTriangularisationType = TT_NONE;
vfp_bDummy = FALSE;
vfp_bAutoCreateMipBrushes = FALSE;
vfp_fXMin = -8.0f;
vfp_fXMax = 8.0f;
vfp_fYMin = -8.0f;
vfp_fYMax = 8.0f;
vfp_fZMin = -8.0f;
vfp_fZMax = 8.0f;
vfp_fShearX = 0.0f;
vfp_fShearZ = 0.0f;
vfp_fStretchX = 1.0f;
vfp_fStretchY = 1.0f;
vfp_plPrimitive.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f);
vfp_plPrimitive.pl_OrientationAngle = ANGLE3D(0,0,0);
vfp_colSectorsColor = C_BLUE;
vfp_colPolygonsColor = C_RED;
vfp_fRadius = 32.0f;
vfp_bLinearStaircases = FALSE;
vfp_bOuter = TRUE;
vfp_iSlicesIn360 = 12;
vfp_iNoOfSlices = 6;
vfp_iMeridians = 6;
vfp_iParalels = 6;
vfp_iSlicesPerWidth = 6;
vfp_iSlicesPerHeight= 6;
vfp_iTopShape = 0;
vfp_iBottomShape = 0;
vfp_fAmplitude = 50.0f;
vfp_fMipStart = 6.0f;
vfp_fMipStep = 1.5f;
}
CWorldEditorApp::CWorldEditorApp()
{
// register message
_uiMessengerMsg = RegisterWindowMessageA("Croteam Messenger: Incoming Message");
_uiMessengerForcePopup = RegisterWindowMessageA("Croteam Messenger: Force Popup Message");
m_fnClassForDropMarker = CTFILENAME("Classes\\Marker.ecl");
m_bChangeDisplayModeInProgress = FALSE;
m_bDisableDataExchange = FALSE;
m_pLastActivatedDocument = NULL;
//#ifdef NDEBUG
m_bShowStatusInfo = TRUE;
//#else
// m_bShowStatusInfo = FALSE;
//#endif
m_bDocumentChangeOn = FALSE;
m_bCSGReportEnabled = TRUE;
m_bRememberUndo = TRUE;
m_bMeasureModeOn = FALSE;
m_bCutModeOn = FALSE;
m_pfntSystem = NULL;
m_ptdError = NULL;
m_ptoError = NULL;
m_ptdIconsTray = NULL;
m_ptdActiveTexture = NULL;
m_vLastTerrainHit=FLOAT3D(0,0,0);
m_penLastTerrainHit=NULL;
m_fCurrentTerrainBrush=4.0f;
m_fTerrainBrushPressure=1024.0f*3.0f/4.0f; //75%
m_iTerrainEditMode=TEM_HEIGHTMAP;
m_iTerrainBrushMode=0;
m_fTerrainBrushPressureEnum=-1.0f;
m_fnDistributionNoiseTexture=CTFILENAME("Textures\\Editor\\RandomNoise.tex");
m_fnContinousNoiseTexture=CTFILENAME("Textures\\Editor\\RandomNoise.tex");
m_iFBMOctaves=4;
m_fFBMHighFrequencyStep=1.0f;
m_fFBMStepFactor=2.2f;
m_fFBMMaxAmplitude=64.0f;
m_fFBMfAmplitudeDecreaser=0.5f;
m_bFBMAddNegativeValues=TRUE;
m_bFBMRandomOffset=FALSE;
m_uwEditAltitude=0;
m_fPaintPower=1.0f;
m_fSmoothPower=1.0f;
m_iFilter=FLT_SHARPEN;
m_fFilterPower=1.0f;
m_fPosterizeStep=2.0f;
m_fNoiseAltitude=1.0f;
m_iRNDSubdivideAndDisplaceItterations=2;
m_iTerrainGenerationMethod=0;
m_pbpoClipboardPolygon = new CBrushPolygon;
m_pbpoPolygonWithDeafultValues = new CBrushPolygon;
m_bFirstTimeStarted = FALSE;
// no copy operations performed yet
m_ctLastCopyType = CT_NONE;
m_colSectorAmbientClipboard = C_BLACK;
m_bDecadicGrid = FALSE;
// give personality to each values for primitive class
m_vfpConus.vfp_ptPrimitiveType = PT_CONUS;
m_vfpTorus.vfp_ptPrimitiveType = PT_TORUS;
m_vfpStaircases.vfp_ptPrimitiveType = PT_STAIRCASES;
m_vfpSphere.vfp_ptPrimitiveType = PT_SPHERE;
m_vfpTerrain.vfp_ptPrimitiveType = PT_TERRAIN;
m_bTexture1 = TRUE;
m_bTexture2 = TRUE;
m_bTexture3 = TRUE;
m_fTerrainSwitchStart = 100.0f;
m_fTerrainSwitchStep = 1.0f;
m_iLastClassSortAplied = 0;
m_bInvertClassSort = FALSE;
m_iLastAutoColorizeColor = 0;
m_plClipboard1 = CPlacement3D( FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
m_plClipboard2 = CPlacement3D( FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
m_tmStartStatusLineInfo=0;
}
// default constructor
CViewPrefs::CViewPrefs( void)
{
// set default values
SetDefaultValues();
}
/*
* Set default values for view preferences
*/
void CViewPrefs::SetDefaultValues( void)
{
// set view's defaults
m_bAutoRenderingRange = TRUE;
m_fRenderingRange = 100.0f;
m_PaperColor = C_WHITE;
m_SelectionColor = C_RED;
m_GridColor = 0xAFBDFE;
m_bMeasurementTape = FALSE;
// set defaults for world
m_wrpWorldRenderPrefs.SetHiddenLinesOn( TRUE);
m_wrpWorldRenderPrefs.SetEditorModelsOn( TRUE);
m_wrpWorldRenderPrefs.SetFieldBrushesOn( TRUE);
m_wrpWorldRenderPrefs.SetBackgroundTextureOn( FALSE);
m_wrpWorldRenderPrefs.SetVerticesFillType( CWorldRenderPrefs::FT_NONE);
m_wrpWorldRenderPrefs.SetVerticesInkColor( C_RED);
m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_POLYGONCOLOR);
m_wrpWorldRenderPrefs.SetEdgesInkColor( C_BLACK);
m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_NONE);
m_wrpWorldRenderPrefs.SetPolygonsInkColor( C_GRAY);
m_wrpWorldRenderPrefs.SetLensFlaresType( CWorldRenderPrefs::LFT_NONE);
m_wrpWorldRenderPrefs.SetFogOn( FALSE);
m_wrpWorldRenderPrefs.SetHazeOn( FALSE);
m_wrpWorldRenderPrefs.SetMirrorsOn( FALSE);
m_wrpWorldRenderPrefs.SetShowTargetsOn( FALSE);
m_wrpWorldRenderPrefs.SetShowEntityNamesOn( FALSE);
// set defaults for models
m_mrpModelRenderPrefs.SetRenderType( RT_TEXTURE);
m_mrpModelRenderPrefs.SetShadingType( RT_SHADING_PHONG);
m_mrpModelRenderPrefs.SetShadowQuality( 0);
m_mrpModelRenderPrefs.SetInkColor( C_BLACK);
m_mrpModelRenderPrefs.BBoxFrameShow( FALSE);
m_mrpModelRenderPrefs.BBoxAllShow( FALSE);
m_mrpModelRenderPrefs.SetWire( FALSE);
sprintf( m_achrBcgPicture, "");
}
void CViewPrefs::ClearInvalidConfigPointers(void)
{
m_wrpWorldRenderPrefs.SetSelectedEntityModel(NULL);
m_wrpWorldRenderPrefs.SetSelectedPortalModel(NULL);
m_wrpWorldRenderPrefs.SetEmptyBrushModel(NULL);
}
CAppPrefs::~CAppPrefs()
{
}
CWorldEditorApp::~CWorldEditorApp()
{
}
CWorldEditorDoc* CWorldEditorApp::GetActiveDocument(void)
{
// if document change process is on (document view switching)
if( m_bDocumentChangeOn)
{
return NULL;
}
else
{
// obtain active view
CWorldEditorView *pWorldEditorView = GetActiveView();
// if there is active view
if( pWorldEditorView != NULL)
{
// return document that view represents
return GetActiveView()->GetDocument();
}
// otherwise
else
{
return NULL;
}
}
}
CWorldEditorView* CWorldEditorApp::GetActiveView(void)
{
CWorldEditorView *res;
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
res = DYNAMIC_DOWNCAST(CWorldEditorView, pMainFrame->GetActiveFrame()->GetActiveView());
return res;
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CWorldEditorApp object
CWorldEditorApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CWorldEditorApp initialization
BOOL CWorldEditorApp::InitInstance()
{
_CrtSetBreakAlloc(55);
BOOL bResult;
CTSTREAM_BEGIN {
bResult = SubInitInstance();
} CTSTREAM_END;
return bResult;
}
static CTString _strCmd;
static CString _strCmdW;
static CTString cmd_strOutput;
static CTString cmd_strMod;
// get first next word or quoted string
static CTString GetNextParam(void)
{
// strip leading spaces/tabs
_strCmd.TrimSpacesLeft();
// if nothing left
if (_strCmd=="") {
// no word to return
return "";
}
// if the first char is quote
if (_strCmd[0]=='"') {
// find first next quote
const char *pchClosingQuote = strchr(_strCmd+1, '"');
// if not found
if (pchClosingQuote==NULL) {
// error in command line
cmd_strOutput+=CTString(0, TRANS("Command line error!\n"));
// finish parsing
_strCmd = "";
return "";
}
INDEX iQuote = pchClosingQuote-_strCmd;
// get the quoted string
CTString strWord;
CTString strRest;
_strCmd.Split(iQuote, strWord, strRest);
// remove the quotes
strWord.DeleteChar(0);
strRest.DeleteChar(0);
// get the word
_strCmd = strRest;
return strWord;
// if the first char is not quote
} else {
// find first next space
INDEX iSpace;
INDEX ctChars = strlen(_strCmd);
for(iSpace=0; iSpace<ctChars; iSpace++) {
if (isspace(_strCmd[iSpace])) {
break;
}
}
// get the word string
CTString strWord;
CTString strRest;
_strCmd.Split(iSpace, strWord, strRest);
// remove the space
strRest.DeleteChar(0);
// get the word
_strCmd = strRest;
return strWord;
}
}
// check for custom parameters
void CWorldEditorApp::MyParseCommandLine(void)
{
_strCmd = CStringA(m_lpCmdLine);
cmd_strOutput = "";
cmd_strOutput+=CTString(0, TRANS("Command line: '%s'\n"), _strCmd);
// if no command line
if (strlen(_strCmd) == 0) {
// do nothing
return;
}
FOREVER {
CTString strWord = GetNextParam();
if (strWord=="") {
cmd_strOutput+="\n";
_strCmdW = CString(_strCmd);
m_lpCmdLine = (LPWSTR)(LPCWSTR)_strCmdW;
return;
} else if (strWord=="+game") {
CTString strMod = GetNextParam();
if (strMod!="SeriousSam") { // (we ignore default mod - always use base dir in that case)
cmd_strMod = strMod;
_fnmMod = "Mods\\"+strMod+"\\";
}
} else {
_strCmdW = CString(_strCmd);
m_lpCmdLine = (LPWSTR)(LPCWSTR)_strCmdW;
return;
}
}
}
BOOL CWorldEditorApp::SubInitInstance()
{
// required for visual styles
InitCommonControls();
// 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.
// Initialize OLE 2.0 libraries
if (!AfxOleInit())
{
AfxMessageBox(L"ERROR: Failed to initialize OLE 2.0 libraries");
return FALSE;
}
AfxEnableControlContainer();
// check for custom parameters
MyParseCommandLine();
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
// initialize entire engine
SE_InitEngine("SeriousEditor");
SE_LoadDefaultFonts();
// settings will be saved into registry instead of ini file
if (_strModExt=="") {
SetRegistryKey( CString("CroTeam"));
} else {
SetRegistryKey( CString("CroTeam\\"+_strModExt));
}
CPrintF("%s", cmd_strOutput);
// if the registry is not set yet
CString strDefaultTexture = GetProfileString( L"World editor prefs", L"Default primitive texture", L"");
if (strDefaultTexture == L"") {
// load registry from the ini file
CTString strCommand;
strCommand.PrintF("regedit.exe -s \"%s%s\"",
(const CTString&)_fnmApplicationPath,
(const CTString&)CTString("Data\\Defaults\\WorldEditor.reg"));
system(strCommand);
/* _spawnlp(_P_WAIT, "regedit.exe",
"-s",
(const CTString&)(_fnmApplicationPath+CTString("Data\\Defaults\\WorldEditor.reg")),
NULL);
*/
}
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.
m_pDocTemplate = new CMultiDocTemplate(
IDR_WEDTYPE,
RUNTIME_CLASS(CWorldEditorDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CWorldEditorView));
AddDocTemplate(m_pDocTemplate);
// create application windows font
LOGFONT logFont;
memset(&logFont, 0, sizeof(logFont));
if( !::GetSystemMetrics(SM_DBCSENABLED)){
logFont.lfHeight = -11;
logFont.lfWeight = FW_REGULAR;
logFont.lfPitchAndFamily = FF_ROMAN;
logFont.lfOrientation = 10;
logFont.lfQuality = PROOF_QUALITY;
logFont.lfItalic = TRUE;
lstrcpy(logFont.lfFaceName, L"Arial");
if( !m_Font.CreateFontIndirect(&logFont))
TRACE0("Could Not create font for combo\n");
} else {
m_Font.Attach(::GetStockObject(SYSTEM_FONT));
}
memset(&logFont, 0, sizeof(logFont));
if( !::GetSystemMetrics(SM_DBCSENABLED)){
logFont.lfHeight = -11;
logFont.lfWeight = FW_REGULAR;
logFont.lfPitchAndFamily = FF_MODERN;
logFont.lfOrientation = 10;
logFont.lfQuality = PROOF_QUALITY;
logFont.lfItalic = FALSE;
lstrcpy(logFont.lfFaceName, L"Courier New");
if( !m_FixedFont.CreateFontIndirect(&logFont))
TRACE0("Could Not create fixed font\n");
} else {
m_FixedFont.Attach(::GetStockObject(SYSTEM_FONT));
}
// 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);
// add console variables
extern INDEX wed_bSaveTestGameFirstTime;
_pShell->DeclareSymbol("user INDEX wed_bSaveTestGameFirstTime;", &wed_bSaveTestGameFirstTime);
_pShell->DeclareSymbol("persistent user INDEX wed_iMaxFPSActive;", &wed_iMaxFPSActive);
_pShell->DeclareSymbol("persistent user FLOAT wed_fFrontClipDistance;", &wed_fFrontClipDistance);
_pShell->DeclareSymbol("persistent user INDEX wed_bUseGenericTextureReplacement;", &wed_bUseGenericTextureReplacement);
// functions that are used to change rendering preferences while testing game
_pShell->DeclareSymbol("user void WED_ApplyChildSettings0(void);", &WED_ApplyChildSettings0);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings1(void);", &WED_ApplyChildSettings1);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings2(void);", &WED_ApplyChildSettings2);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings3(void);", &WED_ApplyChildSettings3);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings4(void);", &WED_ApplyChildSettings4);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings5(void);", &WED_ApplyChildSettings5);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings6(void);", &WED_ApplyChildSettings6);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings7(void);", &WED_ApplyChildSettings7);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings8(void);", &WED_ApplyChildSettings8);
_pShell->DeclareSymbol("user void WED_ApplyChildSettings9(void);", &WED_ApplyChildSettings9);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings0(void);", &WED_ApplyRenderingSettings0);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings1(void);", &WED_ApplyRenderingSettings1);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings2(void);", &WED_ApplyRenderingSettings2);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings3(void);", &WED_ApplyRenderingSettings3);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings4(void);", &WED_ApplyRenderingSettings4);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings5(void);", &WED_ApplyRenderingSettings5);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings6(void);", &WED_ApplyRenderingSettings6);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings7(void);", &WED_ApplyRenderingSettings7);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings8(void);", &WED_ApplyRenderingSettings8);
_pShell->DeclareSymbol("user void WED_ApplyRenderingSettings9(void);", &WED_ApplyRenderingSettings9);
_pShell->DeclareSymbol("user void WED_FindEmptyBrush(void);", &WED_FindEmptyBrushes);
// load persistent symbols
_pShell->Execute(CTString("include \""+fnmPersistentSymbols+"\";"));
// prepare full screen mode
_EngineGUI.GetFullScreenModeFromRegistry( "Display modes", m_dmFullScreen, m_gatFullScreen);
_EngineGUI.SetFullScreenModeToRegistry( "Display modes", m_dmFullScreen, m_gatFullScreen);
m_iApi=GAT_OGL;
m_iApi=AfxGetApp()->GetProfileInt(L"Display modes", L"SED Gfx API", GAT_OGL);
// (re)set default display mode
_pGfx->ResetDisplayMode((enum GfxAPIType) m_iApi);
// initialize game itself (GameShell interface) and load settings
InitializeGame();
// load startup script
_pShell->Execute( "include \"Scripts\\WorldEditor_startup.ini\"");
// read all data from ini file
ReadFromIniFileOnInit();
ReadDefaultPolygonValues();
// load primitives history buffer
CTString strPrimitives("Data\\PrimitivesHistory.pri");
if (FileExists(strPrimitives)) {
CTFileStream strmFile;
try
{
strmFile.Open_t(strPrimitives);
INDEX ctHistory;
strmFile >> ctHistory;
for( INDEX iPrim=0; iPrim<ctHistory; iPrim++)
{
CPrimitiveInHistoryBuffer *ppihbMember = new CPrimitiveInHistoryBuffer;
ppihbMember->pihb_vfpPrimitive.Read_t( strmFile);
m_lhPrimitiveHistory.AddTail( ppihbMember->pihb_lnNode);
}
}
catch( char *strError)
{
WarningMessage( strError);
}
}
m_bDecadicGrid = !m_Preferences.ap_BinaryGrid;
// don't start new document automatically
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
// create temporary directory to contain undo files
CreateDirectoryA( _fnmApplicationPath + "Temp\\", NULL);
// try to
try
{
// load error texture
DECLARE_CTFILENAME( fnErrorTexture, "Textures\\Editor\\Error.tex");
m_ptdError = _pTextureStock->Obtain_t( fnErrorTexture);
// load error texture
DECLARE_CTFILENAME( fnViewIcons, "Models\\Editor\\ViewIcons.tex");
m_pViewIconsTD = _pTextureStock->Obtain_t( fnViewIcons);
// load icon tray texture
DECLARE_CTFILENAME( fnIconTrayTexture, "Textures\\Editor\\IconsTray.tex");
m_ptdIconsTray = _pTextureStock->Obtain_t( fnIconTrayTexture);
}
catch( char *err_str)
{
AfxMessageBox( CString(err_str));
return FALSE;
}
m_ptoError = new CTextureObject;
m_ptoError->SetData( m_ptdError);
// assign system font
m_pfntSystem = _pfdDisplayFont;
try
{
// load entity selection marker model
DECLARE_CTFILENAME( fnEntityMarker, "Models\\Editor\\EntityMarker.mdl");
m_pEntityMarkerModelData = _pModelStock->Obtain_t( fnEntityMarker);
m_pEntityMarkerModelObject = new CModelObject;
m_pEntityMarkerModelObject->SetData(m_pEntityMarkerModelData);
m_pEntityMarkerModelObject->SetAnim( 0);
// load entity selection marker model's texture
DECLARE_CTFILENAME( fnEntityMarkerTex, "Models\\Editor\\EntityMarker.tex");
m_ptdEntityMarkerTexture = _pTextureStock->Obtain_t( fnEntityMarkerTex);
m_pEntityMarkerModelObject->mo_toTexture.SetData( m_ptdEntityMarkerTexture);
// load portal selection marker model
DECLARE_CTFILENAME( fnPortalMarker, "Models\\Editor\\PortalMarker.mdl");
m_pPortalMarkerModelData = _pModelStock->Obtain_t( fnPortalMarker);
m_pPortalMarkerModelObject = new CModelObject;
m_pPortalMarkerModelObject->SetData(m_pPortalMarkerModelData);
m_pPortalMarkerModelObject->SetAnim( 0);
// load portal selection marker model's texture
DECLARE_CTFILENAME( fnPortalMarkerTex, "Models\\Editor\\PortalMarker.tex");
m_ptdPortalMarkerTexture = _pTextureStock->Obtain_t( fnPortalMarkerTex);
m_pPortalMarkerModelObject->mo_toTexture.SetData( m_ptdPortalMarkerTexture);
// load empty brush model
DECLARE_CTFILENAME( fnEmptyBrush, "Models\\Editor\\EmptyBrush.mdl");
m_pEmptyBrushModelData = _pModelStock->Obtain_t( fnEmptyBrush);
m_pEmptyBrushModelObject = new CModelObject;
m_pEmptyBrushModelObject->SetData(m_pEmptyBrushModelData);
m_pEmptyBrushModelObject->SetAnim( 0);
// load empty brush model's texture
DECLARE_CTFILENAME( fnEmptyBrushTex, "Models\\Editor\\EmptyBrush.tex");
m_ptdEmptyBrushTexture = _pTextureStock->Obtain_t( fnEmptyBrushTex);
m_pEmptyBrushModelObject->mo_toTexture.SetData( m_ptdEmptyBrushTexture);
// load range sphere
DECLARE_CTFILENAME( fnRangeSphere, "Models\\Editor\\RangeSphere.mdl");
m_pRangeSphereModelData = _pModelStock->Obtain_t( fnRangeSphere);
m_pRangeSphereModelObject = new CModelObject;
m_pRangeSphereModelObject->SetData(m_pRangeSphereModelData);
m_pRangeSphereModelObject->SetAnim( 0);
// load range sphere model's texture
DECLARE_CTFILENAME( fnRangeSphereTex, "Models\\Editor\\RangeSphere.tex");
m_ptdRangeSphereTexture = _pTextureStock->Obtain_t( fnRangeSphereTex);
m_pRangeSphereModelObject->mo_toTexture.SetData( m_ptdRangeSphereTexture);
// load angle 3d model
DECLARE_CTFILENAME( fnAngle3D, "Models\\Editor\\AngleVector.mdl");
m_pAngle3DModelData = _pModelStock->Obtain_t( fnAngle3D);
m_pAngle3DModelObject = new CModelObject;
m_pAngle3DModelObject->SetData(m_pAngle3DModelData);
m_pAngle3DModelObject->SetAnim( 0);
// load angle 3d model's texture
DECLARE_CTFILENAME( fnAngle3DTex, "Models\\Editor\\Vector.tex");
m_ptdAngle3DTexture = _pTextureStock->Obtain_t( fnAngle3DTex);
m_pAngle3DModelObject->mo_toTexture.SetData( m_ptdAngle3DTexture);
// load bounding box
DECLARE_CTFILENAME( fnBoundingBox, "Models\\Editor\\BoundingBox.mdl");
m_pBoundingBoxModelData = _pModelStock->Obtain_t( fnBoundingBox);
m_pBoundingBoxModelObject = new CModelObject;
m_pBoundingBoxModelObject->SetData(m_pBoundingBoxModelData);
m_pBoundingBoxModelObject->SetAnim( 0);
// load bounding box model's texture
DECLARE_CTFILENAME( fnBoundingBoxTex, "Models\\Editor\\BoundingBox.tex");
m_ptdBoundingBoxTexture = _pTextureStock->Obtain_t( fnBoundingBoxTex);
m_pBoundingBoxModelObject->mo_toTexture.SetData( m_ptdBoundingBoxTexture);
}
catch (char *error)
{
FatalError("Cannot load one of entity selection model components: %s", error);
return FALSE;
}
// initialize browsing window's view port
CBrowseWindow *pBrowseWindow = &pMainFrame->m_Browser.m_BrowseWindow;
_pGfx->CreateWindowCanvas( pMainFrame->m_Browser.m_BrowseWindow.m_hWnd, &pBrowseWindow->m_pViewPort,
&pBrowseWindow->m_pDrawPort);
pMainFrame->m_Browser.OpenSelectedDirectory();
// assure that terrain brushes exist
GenerateNonExistingTerrainEditBrushes();
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The main window has been initialized, so show and update it.
pMainFrame->ShowWindow(SW_SHOWMAXIMIZED);
pMainFrame->UpdateWindow();
// show tip of the day
if (m_bShowTipOfTheDay) {
OnHelpShowTipOfTheDay();
}
// if we should automatically call preferences dialog (because WED is first time started)
if( m_bFirstTimeStarted) OnFilePreferences();
CTString strCmdLine=CTString(CStringA(m_lpCmdLine));
if(strCmdLine[0]=='\"' && strCmdLine[strCmdLine.Length()-1]=='\"')
{
strCmdLine.DeleteChar(0);
strCmdLine.DeleteChar(strCmdLine.Length()-1);
}
if (strCmdLine != "" && !strCmdLine.RemovePrefix("/dde"))
{
// Open a file passed as the first command line parameter.
OpenDocumentFile(m_lpCmdLine);
}
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 CWorldEditorApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
/////////////////////////////////////////////////////////////////////////////
// CWorldEditorApp commands
BOOL CWorldEditorApp::SaveAllModified()
{
CMainFrame* pMainFrame = (CMainFrame *) m_pMainWnd;
if( (pMainFrame != NULL) && (pMainFrame->m_Browser.m_bVirtualTreeChanged) )
{
switch(::MessageBoxA( pMainFrame->m_hWnd,
"Virtual tree changed but not saved. Do You want to save it?", "Warning !",
MB_YESNOCANCEL | MB_ICONWARNING | MB_DEFBUTTON1 | MB_TASKMODAL | MB_TOPMOST) )
{
case IDYES:
{
pMainFrame->m_Browser.SaveVirtualTree(pMainFrame->m_fnLastVirtualTree, &pMainFrame->m_Browser.m_VirtualTree);
break;
}
case IDCANCEL:
{
return FALSE;
}
}
}
return CWinApp::SaveAllModified();
}
void CWorldEditorApp::ReadFromIniFileOnInit(void)
{
char strIni[ 256];
// read data that can be saved multiple times to ini file
ReadFromIniFile();
// obtain texture for primitive
CString strTexture = GetProfileString( L"World editor prefs", L"Default primitive texture", L"Textures\\Editor\\Default.tex");
// if exists in ini file
if( strTexture != L"")
{
theApp.SetNewActiveTexture( _fnmApplicationPath + CTString(CStringA(strTexture)));
}
INI_READ( "Paint power", "1.0");
GET_FLOAT( m_fPaintPower);
INI_READ( "Smooth power", "1.0");
GET_FLOAT( m_fSmoothPower);
INI_READ( "Current filter", "1");
GET_INDEX( m_iFilter);
INI_READ( "Posterize step", "2.0");
GET_FLOAT( m_fPosterizeStep);
INI_READ( "Terrain generation method", "0");
GET_INDEX( m_iTerrainGenerationMethod);
INI_READ( "Subdivade and displace itterations", "2");
GET_INDEX( m_iRNDSubdivideAndDisplaceItterations);
INI_READ( "Noise altitude", "1.0");
GET_FLOAT( m_fNoiseAltitude);
INI_READ( "Distribution noise texture", CTFILENAME("Textures\\Editor\\RandomNoise.tex"));
GET_STRING( m_fnDistributionNoiseTexture);
INI_READ( "Continous noise texture", CTFILENAME("Textures\\Editor\\RandomNoise.tex"));
GET_STRING( m_fnContinousNoiseTexture);
INI_READ( "FBM Octaves", "4");
GET_INDEX( m_iFBMOctaves);
INI_READ( "FBM High frequency step", "1.0");
GET_FLOAT( m_fFBMHighFrequencyStep);
INI_READ( "FBM Step factor", "2.0");
GET_FLOAT( m_fFBMStepFactor);
INI_READ( "FBM Max amplitude", "64.0");
GET_FLOAT( m_fFBMMaxAmplitude);
INI_READ( "FBM Amplitude decreaser", "0.5");
GET_FLOAT( m_fFBMfAmplitudeDecreaser);
INI_READ( "FBM Add negative values", "NO");
GET_FLAG( m_bFBMAddNegativeValues);
INI_READ( "FBM Random offset", "NO");
GET_FLAG( m_bFBMRandomOffset);
m_bShowTipOfTheDay = GetProfileInt(L"World editor", L"Show Tip of the Day", TRUE);
m_iCurrentTipOfTheDay = GetProfileInt(L"World editor", L"Current Tip of the Day", 0);
_fFlyModeSpeedMultiplier=m_Preferences.ap_fDefaultFlyModeSpeed;
}
void CWorldEditorApp::ReadFromIniFile()
{
// if loading of world and model's rendering preferences file fails
if( !LoadRenderingPreferences())
{
CViewPrefs tempVP;
// for all view's rendering preferences
for( INDEX i=0; i< VIEW_PREFERENCES_CT; i++)
{
// clear possibly wrong loaded values
m_vpViewPrefs[ i] = tempVP;
// set default values
m_vpViewPrefs[ i].SetDefaultValues();
}
// BUFFER 0: -default view
// BUFFER 1: -no REM
m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetLensFlaresType( CWorldRenderPrefs::LFT_REFLECTIONS_AND_GLARE);
// BUFFER 2: -polygon color, edges ink, no REM
m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_POLYGONCOLOR);
m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_INKCOLOR);
m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetLensFlaresType( CWorldRenderPrefs::LFT_REFLECTIONS_AND_GLARE);
// BUFFER 3: -wire frame (lines in color of polygons)
m_vpViewPrefs[ 3].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_NONE);
m_vpViewPrefs[ 3].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ 3].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
m_vpViewPrefs[ 3].m_mrpModelRenderPrefs.BBoxAllShow( TRUE);
// BUFFER 4: -polygons show sector color, no REM
m_vpViewPrefs[ 4].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_INKCOLOR);
m_vpViewPrefs[ 4].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_SECTORCOLOR);
m_vpViewPrefs[ 4].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ 4].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
// BUFFER 5: -polygons in gray color, no REM
m_vpViewPrefs[ 5].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_vpViewPrefs[ 5].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_INKCOLOR);
m_vpViewPrefs[ 5].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ 5].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
m_vpViewPrefs[ 5].m_wrpWorldRenderPrefs.SetPolygonsInkColor( C_GRAY);
// BUFFER 6: -polygons color, no REM
m_vpViewPrefs[ 6].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_POLYGONCOLOR);
m_vpViewPrefs[ 6].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_vpViewPrefs[ 6].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ 6].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
// BUFFER 7: -polygons in white color
m_vpViewPrefs[ 7].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_INKCOLOR);
m_vpViewPrefs[ 7].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_INKCOLOR);
m_vpViewPrefs[ 7].m_wrpWorldRenderPrefs.SetPolygonsInkColor( C_WHITE);
// BUFFER 8: -polygons use texture, edges ink
m_vpViewPrefs[ 8].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
m_vpViewPrefs[ 8].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_INKCOLOR);
// BUFFER 9: -game view with background texture
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetLensFlaresType( CWorldRenderPrefs::LFT_REFLECTIONS_AND_GLARE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetBackgroundTextureOn( TRUE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetFogOn( TRUE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetHazeOn( TRUE);
m_vpViewPrefs[ VIEW_PREFERENCES_CT-1].m_wrpWorldRenderPrefs.SetMirrorsOn( TRUE);
}
// if loading of child configuration file fails
if( !LoadChildConfigurations())
{
// for all child configurations
for( INDEX i=0; i<CHILD_CONFIGURATIONS_CT; i++)
{
// set default values
m_ccChildConfigurations[ i].SetDefaultValues();
}
// CONFIGURATION 0: 3+1 defaults, perspective has no wire frame, but has texture
m_ccChildConfigurations[ 0].m_vpViewPrefs[ 1] = theApp.m_vpViewPrefs[ 0];
m_ccChildConfigurations[ 0].m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_ccChildConfigurations[ 0].m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
// CONFIGURATION 1: 3+1, same as 0 but no editor models
m_ccChildConfigurations[ 1].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 1];
m_ccChildConfigurations[ 1].m_vpViewPrefs[ 1] = theApp.m_vpViewPrefs[ 1];
m_ccChildConfigurations[ 1].m_vpViewPrefs[ 2] = theApp.m_vpViewPrefs[ 1];
m_ccChildConfigurations[ 1].m_vpViewPrefs[ 3] = theApp.m_vpViewPrefs[ 1];
m_ccChildConfigurations[ 1].m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_ccChildConfigurations[ 1].m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
// CONFIGURATION 2: 3+1, polygon color, edges ink, no REM
m_ccChildConfigurations[ 2].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 1];
m_ccChildConfigurations[ 2].m_vpViewPrefs[ 1] = theApp.m_vpViewPrefs[ 2];
m_ccChildConfigurations[ 2].m_vpViewPrefs[ 2] = theApp.m_vpViewPrefs[ 1];
m_ccChildConfigurations[ 2].m_vpViewPrefs[ 3] = theApp.m_vpViewPrefs[ 1];
// CONFIGURATION 3: 3+1, texture fill in all views, no wire
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 0];
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 1] = theApp.m_vpViewPrefs[ 0];
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 2] = theApp.m_vpViewPrefs[ 0];
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 3] = theApp.m_vpViewPrefs[ 0];
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 0].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 0].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 1].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 2].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 3].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
m_ccChildConfigurations[ 3].m_vpViewPrefs[ 3].m_wrpWorldRenderPrefs.SetPolygonsFillType( CWorldRenderPrefs::FT_TEXTURE);
// CONFIGURATION 4: 1, shadows (gray), no REM
m_ccChildConfigurations[ 4].m_iHorizontalSplitters = 1;
m_ccChildConfigurations[ 4].m_iVerticalSplitters = 1;
m_ccChildConfigurations[ 4].m_ptProjectionType[ 0] = CSlaveViewer::PT_PERSPECTIVE;
m_ccChildConfigurations[ 4].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 5];
// CONFIGURATION 5: 1, wire frame
m_ccChildConfigurations[ 5].m_iHorizontalSplitters = 1;
m_ccChildConfigurations[ 5].m_iVerticalSplitters = 1;
m_ccChildConfigurations[ 5].m_ptProjectionType[ 0] = CSlaveViewer::PT_PERSPECTIVE;
m_ccChildConfigurations[ 5].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 3];
// CONFIGURATION 6: 1, clean, game view
m_ccChildConfigurations[ 6].m_iHorizontalSplitters = 1;
m_ccChildConfigurations[ 6].m_iVerticalSplitters = 1;
m_ccChildConfigurations[ 6].m_ptProjectionType[ 0] = CSlaveViewer::PT_PERSPECTIVE;
m_ccChildConfigurations[ 6].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ VIEW_PREFERENCES_CT-1];
// CONFIGURATION 7: 1, shadows + black wire frame
m_ccChildConfigurations[ 7].m_iHorizontalSplitters = 1;
m_ccChildConfigurations[ 7].m_iVerticalSplitters = 1;
m_ccChildConfigurations[ 7].m_ptProjectionType[ 0] = CSlaveViewer::PT_PERSPECTIVE;
m_ccChildConfigurations[ 7].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 5];
m_ccChildConfigurations[ 7].m_vpViewPrefs[ 0].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_INKCOLOR);
// CONFIGURATION 8: 1, clean, edges ink
m_ccChildConfigurations[ 8].m_iHorizontalSplitters = 1;
m_ccChildConfigurations[ 8].m_iVerticalSplitters = 1;
m_ccChildConfigurations[ 8].m_ptProjectionType[ 0] = CSlaveViewer::PT_PERSPECTIVE;
m_ccChildConfigurations[ 8].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 8];
m_ccChildConfigurations[ 8].m_vpViewPrefs[ 0].m_wrpWorldRenderPrefs.SetEditorModelsOn( FALSE);
m_ccChildConfigurations[ 8].m_vpViewPrefs[ 0].m_wrpWorldRenderPrefs.SetFieldBrushesOn( FALSE);
// CONFIGURATION 9: 1, polygons use texture, edges ink
m_ccChildConfigurations[ 9].m_iHorizontalSplitters = 1;
m_ccChildConfigurations[ 9].m_iVerticalSplitters = 1;
m_ccChildConfigurations[ 9].m_ptProjectionType[ 0] = CSlaveViewer::PT_PERSPECTIVE;
m_ccChildConfigurations[ 9].m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 8];
m_ccChildConfigurations[ 9].m_vpViewPrefs[ 0].m_wrpWorldRenderPrefs.SetEdgesFillType( CWorldRenderPrefs::FT_NONE);
}
// read values for preferences
m_Preferences.ReadFromIniFile();
// read from INI primitive settings
m_vfpPreLast.ReadFromIniFile("PreLast");
m_vfpLast.ReadFromIniFile("Last");
m_vfpCurrent.ReadFromIniFile("Current");
m_vfpConus.ReadFromIniFile("Conus");
m_vfpConus.vfp_ptPrimitiveType = PT_CONUS;
m_vfpTorus.ReadFromIniFile("Torus");
m_vfpTorus.vfp_ptPrimitiveType = PT_TORUS;
m_vfpStaircases.ReadFromIniFile("Staircases");
m_vfpStaircases.vfp_ptPrimitiveType = PT_STAIRCASES;
m_vfpSphere.ReadFromIniFile("Sphere");
m_vfpSphere.vfp_ptPrimitiveType = PT_SPHERE;
m_vfpTerrain.ReadFromIniFile("Terrain");
m_vfpTerrain.vfp_ptPrimitiveType = PT_TERRAIN;
}
// World editor ini read function for preferences
void CAppPrefs::ReadFromIniFile()
{
char strIni[ 256];
INI_READ( "Copy existing window preferences", "NO");
GET_FLAG( ap_CopyExistingWindowPrefs);
INI_READ( "Auto maximize window", "YES");
GET_FLAG( ap_AutoMaximizeWindow);
INI_READ( "Set default colors", "YES");
GET_FLAG( ap_SetDefaultColors);
INI_READ( "Automatic info", "YES");
GET_FLAG( ap_AutomaticInfo);
INI_READ( "Update allways", "NO");
GET_FLAG( ap_UpdateAllways);
INI_READ( "Binary grid", "YES");
GET_FLAG( ap_BinaryGrid);
INI_READ( "Save undo for delete", "YES");
GET_FLAG( ap_bSaveUndoForDelete);
INI_READ( "Auto colorize primitives", "YES");
GET_FLAG( ap_bAutoColorize);
INI_READ( "Show all on open", "YES");
GET_FLAG( ap_bShowAllOnOpen);
INI_READ( "Hide shadows on open", "NO");
GET_FLAG( ap_bHideShadowsOnOpen);
INI_READ( "Auto update displace map", "YES");
GET_FLAG( ap_bAutoUpdateDisplaceMap);
INI_READ( "Undo levels", "10");
GET_INDEX( ap_iUndoLevels);
INI_READ( "Startup window setup", "0");
GET_INDEX( ap_iStartupWindowSetup);
INI_READ( "Ink color", "0X00000000");
GET_COLOR( ap_DefaultInkColor);
INI_READ( "Paper color", "0XAAAAAAAA");
GET_COLOR( ap_DefaultPaperColor);
INI_READ( "Current selection color", "0XFFFFFFFF");
GET_COLOR( ap_DefaultSelectionColor);
INI_READ( "Current grid color", "0XFF000000");
GET_COLOR( ap_DefaultGridColor);
INI_READ( "Source safe project", "$/Flesh/");
GET_STRING( ap_strSourceSafeProject);
INI_READ( "Default fly mode speed", "1.0");
GET_FLOAT( ap_fDefaultFlyModeSpeed);
INI_READ( "Terrain selection visible", "0");
GET_INDEX( ap_iTerrainSelectionVisible);
INI_READ( "Terrain selection hidden", "1");
GET_INDEX( ap_iTerrainSelectionHidden);
INI_READ( "Memory for terrain undo", "32");
GET_INDEX( ap_iMemoryForTerrainUndo);
INI_READ( "Auto generate distribution", "YES");
GET_FLAG( ap_bAutoUpdateTerrainDistribution);
}
// read from INI last values for primitive
void CValuesForPrimitive::ReadFromIniFile(CTString strPrimitiveType)
{
CSetFPUPrecision FPUPrecision(FPT_53BIT);
char strIni[ 256];
INI_PRIMITIVE_READ( "primitive type", "1");
GET_INDEX( vfp_ptPrimitiveType);
INI_PRIMITIVE_READ( "x", "0.0");
GET_FLOAT( vfp_plPrimitive.pl_PositionVector(1));
INI_PRIMITIVE_READ( "y", "0.0");
GET_FLOAT( vfp_plPrimitive.pl_PositionVector(2));
INI_PRIMITIVE_READ( "z", "0.0");
GET_FLOAT( vfp_plPrimitive.pl_PositionVector(3));
INI_PRIMITIVE_READ( "heading", "0.0");
GET_FLOAT( vfp_plPrimitive.pl_OrientationAngle(1));
INI_PRIMITIVE_READ( "pitch", "0.0");
GET_FLOAT( vfp_plPrimitive.pl_OrientationAngle(2));
INI_PRIMITIVE_READ( "banking", "0.0");
GET_FLOAT( vfp_plPrimitive.pl_OrientationAngle(3));
INI_PRIMITIVE_READ( "triangularisation type", "0");
GET_INDEX( vfp_ttTriangularisationType);
INI_PRIMITIVE_READ( "closed", "NO");
GET_FLAG( vfp_bClosed);
INI_PRIMITIVE_READ( "gouraud shadows", "NO");
GET_FLAG( vfp_bDummy);
INI_PRIMITIVE_READ( "auto create mip brushes", "NO");
GET_FLAG( vfp_bAutoCreateMipBrushes);
INI_PRIMITIVE_READ( "sectors color", "0X0000FF00");
GET_COLOR( vfp_colSectorsColor);
INI_PRIMITIVE_READ( "polygons color", "0XFF000000");
GET_COLOR( vfp_colPolygonsColor);
INI_PRIMITIVE_READ( "x min", "-8");
GET_FLOAT( vfp_fXMin);
INI_PRIMITIVE_READ( "x max", "8");
GET_FLOAT( vfp_fXMax);
INI_PRIMITIVE_READ( "y min", "0");
GET_FLOAT( vfp_fYMin);
INI_PRIMITIVE_READ( "y max", "8");
GET_FLOAT( vfp_fYMax);
INI_PRIMITIVE_READ( "z min", "-8");
GET_FLOAT( vfp_fZMin);
INI_PRIMITIVE_READ( "z max", "8");
GET_FLOAT( vfp_fZMax);
INI_PRIMITIVE_READ( "shear x", "0.0");
GET_FLOAT( vfp_fShearX);
INI_PRIMITIVE_READ( "shear z", "0.0");
GET_FLOAT( vfp_fShearZ);
INI_PRIMITIVE_READ( "stretch x", "1.0");
GET_FLOAT( vfp_fStretchX);
INI_PRIMITIVE_READ( "stretch y", "1.0");
GET_FLOAT( vfp_fStretchY);
INI_PRIMITIVE_READ( "linear staircases", "NO");
GET_FLAG( vfp_bLinearStaircases);
INI_PRIMITIVE_READ( "outer", "YES");
GET_FLAG( vfp_bOuter);
INI_PRIMITIVE_READ( "slices in 360", "12");
GET_INDEX( vfp_iSlicesIn360);
INI_PRIMITIVE_READ( "no of slices", "6");
GET_INDEX( vfp_iNoOfSlices);
INI_PRIMITIVE_READ( "radius", "32.0");
GET_FLOAT( vfp_fRadius);
INI_PRIMITIVE_READ( "Primitive no of slices", "6");
GET_INDEX( vfp_iNoOfSlices);
INI_PRIMITIVE_READ( "meridians", "6");
GET_INDEX( vfp_iMeridians);
INI_PRIMITIVE_READ( "paralels", "6");
GET_INDEX( vfp_iParalels);
INI_PRIMITIVE_READ( "slices per width", "6");
GET_INDEX( vfp_iSlicesPerWidth);
INI_PRIMITIVE_READ( "slices per height", "6");
GET_INDEX( vfp_iSlicesPerHeight);
INI_PRIMITIVE_READ( "top shape", "0");
GET_INDEX( vfp_iTopShape);
INI_PRIMITIVE_READ( "bottom shape", "0");
GET_INDEX( vfp_iBottomShape);
INI_PRIMITIVE_READ( "csg operation", "0");
GET_INDEX( vfp_csgtCSGOperation);
INI_PRIMITIVE_READ( "amplitude", "50.0");
GET_FLOAT( vfp_fAmplitude);
INI_PRIMITIVE_READ( "mip start", "6.0");
GET_FLOAT( vfp_fMipStart);
INI_PRIMITIVE_READ( "mip step", "1.5");
GET_FLOAT( vfp_fMipStep);
INI_PRIMITIVE_READ( "displacement picture", "");
GET_STRING( vfp_fnDisplacement);
INDEX ctPrimitiveBaseVertices;
INI_PRIMITIVE_READ( "base vertices", "4");
GET_INDEX( ctPrimitiveBaseVertices);
vfp_avVerticesOnBaseOfPrimitive.Clear();
vfp_avVerticesOnBaseOfPrimitive.New( ctPrimitiveBaseVertices);
CalculatePrimitiveBase();
}
// write to INI last used values for primitive
void CValuesForPrimitive::WriteToIniFile(CTString strPrimitiveType)
{
char strIni[ 256];
SET_INDEX( vfp_ptPrimitiveType);
INI_PRIMITIVE_WRITE( "primitive type");
SET_INDEX( vfp_avVerticesOnBaseOfPrimitive.Count());
INI_PRIMITIVE_WRITE( "base vertices");
SET_FLOAT( vfp_plPrimitive.pl_PositionVector(1));
INI_PRIMITIVE_WRITE( "x");
SET_FLOAT( vfp_plPrimitive.pl_PositionVector(2));
INI_PRIMITIVE_WRITE( "y");
SET_FLOAT( vfp_plPrimitive.pl_PositionVector(3));
INI_PRIMITIVE_WRITE( "z");
SET_FLOAT( vfp_plPrimitive.pl_OrientationAngle(1));
INI_PRIMITIVE_WRITE( "heading");
SET_FLOAT( vfp_plPrimitive.pl_OrientationAngle(2));
INI_PRIMITIVE_WRITE( "pitch");
SET_FLOAT( vfp_plPrimitive.pl_OrientationAngle(3));
INI_PRIMITIVE_WRITE( "banking");
SET_INDEX( vfp_ttTriangularisationType);
INI_PRIMITIVE_WRITE( "triangularisation type");
SET_FLAG( vfp_bClosed);
INI_PRIMITIVE_WRITE( "closed");
SET_FLAG( vfp_bDummy);
INI_PRIMITIVE_WRITE( "gouraud shadows");
SET_FLAG( vfp_bAutoCreateMipBrushes);
INI_PRIMITIVE_WRITE( "auto create mip brushes");
SET_COLOR( vfp_colSectorsColor);
INI_PRIMITIVE_WRITE( "sectors color");
SET_COLOR( vfp_colPolygonsColor);
INI_PRIMITIVE_WRITE( "polygons color");
SET_FLOAT( vfp_fXMin);
INI_PRIMITIVE_WRITE( "x min");
SET_FLOAT( vfp_fXMax);
INI_PRIMITIVE_WRITE( "x max");
SET_FLOAT( vfp_fYMin);
INI_PRIMITIVE_WRITE( "y min");
SET_FLOAT( vfp_fYMax);
INI_PRIMITIVE_WRITE( "y max");
SET_FLOAT( vfp_fZMin);
INI_PRIMITIVE_WRITE( "z min");
SET_FLOAT( vfp_fZMax);
INI_PRIMITIVE_WRITE( "z max");
SET_FLOAT( vfp_fShearX);
INI_PRIMITIVE_WRITE( "shear x");
SET_FLOAT( vfp_fShearZ);
INI_PRIMITIVE_WRITE( "shear z");
SET_FLOAT( vfp_fStretchX);
INI_PRIMITIVE_WRITE( "stretch x");
SET_FLOAT( vfp_fStretchY);
INI_PRIMITIVE_WRITE( "stretch y");
SET_FLAG( vfp_bLinearStaircases);
INI_PRIMITIVE_WRITE( "linear staircases");
SET_FLAG( vfp_bOuter);
INI_PRIMITIVE_WRITE( "outer");
SET_INDEX( vfp_iSlicesIn360);
INI_PRIMITIVE_WRITE( "slices in 360");
SET_INDEX( vfp_iNoOfSlices);
INI_PRIMITIVE_WRITE( "no of slices");
SET_FLOAT( vfp_fRadius);
INI_PRIMITIVE_WRITE( "radius");
SET_INDEX( vfp_iNoOfSlices);
INI_PRIMITIVE_WRITE( "Primitive no of slices");
SET_INDEX( vfp_iMeridians);
INI_PRIMITIVE_WRITE( "meridians");
SET_INDEX( vfp_iParalels);
INI_PRIMITIVE_WRITE( "paralels");
SET_INDEX( vfp_iSlicesPerWidth);
INI_PRIMITIVE_WRITE( "slices per width");
SET_INDEX( vfp_iSlicesPerHeight);
INI_PRIMITIVE_WRITE( "slices per height");
SET_INDEX( vfp_iTopShape);
INI_PRIMITIVE_WRITE( "top shape");
SET_INDEX( vfp_iBottomShape);
INI_PRIMITIVE_WRITE( "bottom shape");
SET_INDEX( vfp_csgtCSGOperation);
INI_PRIMITIVE_WRITE( "csg operation");
SET_FLOAT( vfp_fAmplitude);
INI_PRIMITIVE_WRITE( "amplitude");
SET_FLOAT( vfp_fMipStart);
INI_PRIMITIVE_WRITE( "mip start");
SET_FLOAT( vfp_fMipStep);
INI_PRIMITIVE_WRITE( "mip step");
SET_STRING( vfp_fnDisplacement);
INI_PRIMITIVE_WRITE( "displacement picture");
}
void CValuesForPrimitive::CalculatePrimitiveBase(void)
{
ASSERT(GetFPUPrecision()==FPT_53BIT);
// pick up number of vertices for base polygon
INDEX vtxCt = vfp_avVerticesOnBaseOfPrimitive.Count();
// calculate width and lenght
DOUBLE fWidth = (vfp_fXMax-vfp_fXMin)/2.0f;
DOUBLE fLenght = (vfp_fZMax-vfp_fZMin)/2.0f;
// some values must be valid, if they are not, coorect them
if( fWidth < SNAP_FLOAT_12) fWidth = SNAP_FLOAT_12;
if( fLenght < SNAP_FLOAT_12) fLenght = SNAP_FLOAT_12;
// We calculate vertices as this is box-type primitive
// Step, ammount of angle ct increasement
ANGLE angle = AngleDeg(360.0)/vtxCt;
ANGLE angleCt = -angle/2;
// Radius of circle surrounding polygon if height of polygon's basic triangle is 1 m
DOUBLE dA = fWidth/Cos(angle/2);
DOUBLE dB = dA*fLenght/fWidth;
// if base is created inside circle
if( !vfp_bOuter)
{
angleCt = 0.0;
dA = fWidth;
dB = fLenght;
}
// for all of the base vertices
for(INDEX iVtx=0; iVtx<vtxCt; iVtx++)
{
DOUBLE x = Cos( angleCt) * dA + (vfp_fXMin+vfp_fXMax)/2.0f;
DOUBLE z = Sin( angleCt) * dB + (vfp_fZMin+vfp_fZMax)/2.0f;
// snap X coordinate (1 cm)
//Snap(x, SNAP_DOUBLE_CM);
// snap Y coordinate (1 cm)
//Snap(z, SNAP_DOUBLE_CM);
// calculate vertice on base polygon of the primitive
vfp_avVerticesOnBaseOfPrimitive[ iVtx] = DOUBLE3D( x, 0.0, z);
angleCt += angle;
}
}
void CValuesForPrimitive::Write_t(CTStream &strmFile)
{
strmFile.WriteID_t( CChunkID(VALUES_FOR_PRIMITIVE_VERSION3));
strmFile << (INDEX) vfp_ptPrimitiveType;
INDEX ctBaseVtx = vfp_avVerticesOnBaseOfPrimitive.Count();
strmFile << ctBaseVtx;
for( INDEX iBaseVtx=0; iBaseVtx<ctBaseVtx; iBaseVtx++)
{
strmFile << vfp_avVerticesOnBaseOfPrimitive[iBaseVtx];
}
strmFile << vfp_plPrimitive;
strmFile << (INDEX) vfp_ttTriangularisationType;
strmFile << vfp_bClosed;
strmFile << vfp_bDummy;
INDEX iPrimitiveType = (INDEX) vfp_ptPrimitiveType;
strmFile << iPrimitiveType;
strmFile << vfp_bAutoCreateMipBrushes;
strmFile << vfp_colSectorsColor;
strmFile << vfp_colPolygonsColor;
strmFile << vfp_fXMin;
strmFile << vfp_fXMax;
strmFile << vfp_fYMin;
strmFile << vfp_fYMax;
strmFile << vfp_fZMin;
strmFile << vfp_fZMax;
strmFile << vfp_fShearX;
strmFile << vfp_fShearZ;
strmFile << vfp_fStretchX;
strmFile << vfp_fStretchY;
strmFile << vfp_bLinearStaircases;
strmFile << vfp_bOuter;
strmFile << vfp_iSlicesIn360;
strmFile << vfp_iNoOfSlices;
strmFile << vfp_fRadius;
strmFile << vfp_iMeridians;
strmFile << vfp_iParalels;
strmFile << vfp_iSlicesPerWidth;
strmFile << vfp_iSlicesPerHeight;
strmFile << vfp_iTopShape;
strmFile << vfp_iBottomShape;
strmFile << vfp_fAmplitude;
strmFile << vfp_fnDisplacement;
strmFile << vfp_fMipStart;
strmFile << vfp_fMipStep;
}
void CValuesForPrimitive::Read_t(CTStream &strmFile)
{
CChunkID cidVersion = strmFile.GetID_t();
if( !((cidVersion == CChunkID(VALUES_FOR_PRIMITIVE_VERSION2)) ||
(cidVersion == CChunkID(VALUES_FOR_PRIMITIVE_VERSION3))) )
{
throw( "Only versions 2 and 3 of primitive value files is supported!");
}
INDEX iPrimitiveType;
strmFile >> iPrimitiveType;
vfp_ptPrimitiveType = (enum PrimitiveType) iPrimitiveType;
INDEX ctBaseVtx;
strmFile >> ctBaseVtx;
vfp_avVerticesOnBaseOfPrimitive.Clear();
vfp_avVerticesOnBaseOfPrimitive.New( ctBaseVtx);
for( INDEX iBaseVtx=0; iBaseVtx<ctBaseVtx; iBaseVtx++)
{
strmFile >> vfp_avVerticesOnBaseOfPrimitive[iBaseVtx];
}
strmFile >> vfp_plPrimitive;
INDEX iTriangularisationType;
strmFile >> iTriangularisationType;
vfp_ttTriangularisationType = (enum TriangularisationType) iTriangularisationType;
strmFile >> vfp_bClosed;
strmFile >> vfp_bDummy;
INDEX iCSGOperation;
strmFile >> iCSGOperation;
vfp_csgtCSGOperation = (enum CSGType) iCSGOperation;
strmFile >> vfp_bAutoCreateMipBrushes;
strmFile >> vfp_colSectorsColor;
strmFile >> vfp_colPolygonsColor;
strmFile >> vfp_fXMin;
strmFile >> vfp_fXMax;
strmFile >> vfp_fYMin;
strmFile >> vfp_fYMax;
strmFile >> vfp_fZMin;
strmFile >> vfp_fZMax;
strmFile >> vfp_fShearX;
strmFile >> vfp_fShearZ;
strmFile >> vfp_fStretchX;
strmFile >> vfp_fStretchY;
strmFile >> vfp_bLinearStaircases;
strmFile >> vfp_bOuter;
strmFile >> vfp_iSlicesIn360;
strmFile >> vfp_iNoOfSlices;
strmFile >> vfp_fRadius;
strmFile >> vfp_iMeridians;
strmFile >> vfp_iParalels;
strmFile >> vfp_iSlicesPerWidth;
strmFile >> vfp_iSlicesPerHeight;
strmFile >> vfp_iTopShape;
strmFile >> vfp_iBottomShape;
strmFile >> vfp_fAmplitude;
strmFile >> vfp_fnDisplacement;
if( cidVersion == CChunkID(VALUES_FOR_PRIMITIVE_VERSION3))
{
strmFile >> vfp_fMipStart;
strmFile >> vfp_fMipStep;
}
}
void CWorldEditorApp::WriteToIniFileOnEnd(void)
{
char strIni[ 256];
// write data that can be saved multiple times to ini file
WriteToIniFile();
if( theApp.m_ptdActiveTexture != NULL)
{
CTFileName fnTextureForPrimitive( theApp.m_ptdActiveTexture->GetName());
fnTextureForPrimitive.SetAbsolutePath();
strcpy( strIni, fnTextureForPrimitive);
WriteProfileString( L"World editor prefs", L"Default primitive texture", CString(strIni));
}
SET_FLOAT( m_fPaintPower);
INI_WRITE( "Paint power");
SET_FLOAT( m_fSmoothPower);
INI_WRITE( "Smooth power");
SET_INDEX( m_iFilter);
INI_WRITE( "Current filter");
SET_FLOAT( m_fPosterizeStep);
INI_WRITE( "Posterize step");
SET_INDEX( m_iTerrainGenerationMethod);
INI_WRITE( "Terrain generation method");
SET_INDEX( m_iRNDSubdivideAndDisplaceItterations);
INI_WRITE( "Subdivade and displace itterations");
SET_FLOAT( m_fNoiseAltitude);
INI_WRITE( "Noise altitude");
SET_STRING( m_fnDistributionNoiseTexture);
INI_WRITE( "Distribution noise texture");
SET_STRING( m_fnContinousNoiseTexture);
INI_WRITE( "Continous noise texture");
SET_INDEX( m_iFBMOctaves);
INI_WRITE( "FBM Octaves");
SET_FLOAT( m_fFBMHighFrequencyStep);
INI_WRITE( "FBM High frequency step");
SET_FLOAT( m_fFBMStepFactor);
INI_WRITE( "FBM Step factor");
SET_FLOAT( m_fFBMMaxAmplitude);
INI_WRITE( "FBM Max amplitude");
SET_FLOAT( m_fFBMfAmplitudeDecreaser);
INI_WRITE( "FBM Amplitude decreaser");
SET_FLAG( m_bFBMAddNegativeValues);
INI_WRITE( "FBM Add negative values");
SET_FLAG( m_bFBMRandomOffset);
INI_WRITE( "FBM Random offset");
WriteProfileInt(L"World editor", L"Show Tip of the Day", m_bShowTipOfTheDay);
WriteProfileInt(L"World editor", L"Current Tip of the Day", m_iCurrentTipOfTheDay);
WriteProfileInt(L"Display modes", L"SED Gfx API", m_iApi);
}
void CWorldEditorApp::WriteToIniFile()
{
// write values for preferences
m_Preferences.WriteToIniFile();
// write to INI file last values used for primitive
m_vfpPreLast.WriteToIniFile("PreLast");
m_vfpLast.WriteToIniFile("Last");
m_vfpCurrent.WriteToIniFile("Current");
// write to INI last values for each type of primitive
m_vfpConus.WriteToIniFile("Conus");
m_vfpTorus.WriteToIniFile("Torus");
m_vfpStaircases.WriteToIniFile("Staircases");
m_vfpSphere.WriteToIniFile("Sphere");
m_vfpTerrain.WriteToIniFile("Terrain");
// save world and model rendering preferences
SaveRenderingPreferences();
// save child configurations
SaveChildConfigurations();
}
// World editor ini write function for preferences
void CAppPrefs::WriteToIniFile()
{
char strIni[ 256];
SET_FLAG( ap_CopyExistingWindowPrefs);
INI_WRITE( "Copy existing window preferences");
SET_FLAG( ap_AutoMaximizeWindow);
INI_WRITE( "Auto maximize window");
SET_FLAG( ap_SetDefaultColors);
INI_WRITE( "Set default colors");
SET_FLAG( ap_AutomaticInfo);
INI_WRITE( "Automatic info");
SET_FLAG( ap_UpdateAllways);
INI_WRITE( "Update allways");
SET_FLAG( ap_BinaryGrid);
INI_WRITE( "Binary grid");
SET_FLAG( ap_bSaveUndoForDelete);
INI_WRITE( "Save undo for delete");
SET_FLAG( ap_bAutoColorize);
INI_WRITE( "Auto colorize primitives");
SET_FLAG( ap_bShowAllOnOpen);
INI_WRITE( "Show all on open");
SET_FLAG( ap_bHideShadowsOnOpen);
INI_WRITE( "Hide shadows on open");
SET_FLAG( ap_bAutoUpdateDisplaceMap);
INI_WRITE( "Auto update displace map");
SET_INDEX( ap_iUndoLevels);
INI_WRITE( "Undo levels");
SET_INDEX( ap_iStartupWindowSetup);
INI_WRITE( "Startup window setup");
SET_COLOR( ap_DefaultInkColor);
INI_WRITE( "Ink color");
SET_COLOR( ap_DefaultPaperColor);
INI_WRITE( "Paper color");
SET_COLOR( ap_DefaultSelectionColor);
INI_WRITE( "Current selection color");
SET_COLOR( ap_DefaultGridColor);
INI_WRITE( "Current grid color");
SET_STRING( ap_strSourceSafeProject);
INI_WRITE( "Source safe project");
SET_FLOAT( ap_fDefaultFlyModeSpeed);
INI_WRITE( "Default fly mode speed");
SET_INDEX( ap_iTerrainSelectionVisible);
INI_WRITE( "Terrain selection visible");
SET_INDEX( ap_iTerrainSelectionHidden);
INI_WRITE( "Terrain selection hidden");
SET_INDEX( ap_iMemoryForTerrainUndo);
INI_WRITE( "Memory for terrain undo");
SET_FLAG( ap_bAutoUpdateTerrainDistribution);
INI_WRITE( "Auto generate distribution");
}
BOOL CWorldEditorApp::LoadRenderingPreferences()
{
CTFileName fnRenderingPrefs = CTString("Data\\WEDRenderingPrefs.bin");
// if rendering preferences file does not exist
if (!FileExists(fnRenderingPrefs)) {
// just reset to defaults without a note
return FALSE;
}
// load world and model rendering preferences
CTFileStream strmFile;
try
{
// open binary file to read rendering preferences
strmFile.Open_t( fnRenderingPrefs);
// read file ID
strmFile.ExpectID_t( CChunkID( "RPRF")); // rendering preferences
// check version number
if( !(CChunkID( VIEW_PREFERENCES_VER) == strmFile.GetID_t()) )
{
throw( "Invalid version of rendering preferences, switching to defaults.");
}
// read view rendering preferences
strmFile.Read_t( &m_vpViewPrefs, sizeof( m_vpViewPrefs));
for(INDEX i=0; i<ARRAYCOUNT(m_vpViewPrefs); i++) {
m_vpViewPrefs[i].ClearInvalidConfigPointers();
}
// read ID for end of rendering prefs
strmFile.ExpectID_t( CChunkID( "RPED")); // rendering preferences end
}
catch( char *err_str)
{
char achrMessage[ 256];
sprintf( achrMessage, "%s\nWorld editor's rendering preferences will be switched "
"to defaults.", err_str);
AfxMessageBox( CString(achrMessage));
return FALSE;
}
return TRUE;
}
void CWorldEditorApp::SaveRenderingPreferences(void)
{
// save world and model rendering preferences
CTFileStream strmFile;
try
{
// open binary file to save rendering preferences
CTFileName fnRenderingPrefs = CTString("Data\\WEDRenderingPrefs.bin");
strmFile.Create_t( fnRenderingPrefs, CTStream::CM_BINARY);
// write file ID
strmFile.WriteID_t( CChunkID( "RPRF")); // child configurations
// write version number
strmFile.WriteID_t( CChunkID( VIEW_PREFERENCES_VER));
// write child configurations array
strmFile.Write_t( &m_vpViewPrefs, sizeof( m_vpViewPrefs));
// write ID for end of rendering prefs
strmFile.WriteID_t( CChunkID( "RPED")); // rendering preferences end
}
catch( char *err_str)
{
AfxMessageBox( CString(err_str));
}
}
/*
* Set default values for view preferences
*/
void CChildConfiguration::SetDefaultValues(void)
{
m_iHorizontalSplitters = 2;
m_iVerticalSplitters = 2;
m_fPercentageLeft = 0.480064f;
m_fPercentageTop = 0.476654f;
m_bGridOn = TRUE;
m_vpViewPrefs[ 0] = theApp.m_vpViewPrefs[ 0];
m_vpViewPrefs[ 1] = theApp.m_vpViewPrefs[ 0];
m_vpViewPrefs[ 2] = theApp.m_vpViewPrefs[ 0];
m_vpViewPrefs[ 3] = theApp.m_vpViewPrefs[ 0];
m_ptProjectionType[ 0] = CSlaveViewer::PT_ISOMETRIC_TOP;
m_ptProjectionType[ 1] = CSlaveViewer::PT_PERSPECTIVE;
m_ptProjectionType[ 2] = CSlaveViewer::PT_ISOMETRIC_FRONT;
m_ptProjectionType[ 3] = CSlaveViewer::PT_ISOMETRIC_RIGHT;
}
void CChildConfiguration::ClearInvalidConfigPointers(void)
{
m_vpViewPrefs[0].ClearInvalidConfigPointers();
m_vpViewPrefs[1].ClearInvalidConfigPointers();
m_vpViewPrefs[2].ClearInvalidConfigPointers();
m_vpViewPrefs[3].ClearInvalidConfigPointers();
}
BOOL CWorldEditorApp::LoadChildConfigurations(void)
{
CTFileName fnChildConfigurations = CTString("Data\\WEDChildConfigurations.bin");
// if child configuration file does not exist
if (!FileExists(fnChildConfigurations)) {
// just reset to defaults without a note
return FALSE;
}
// load child configurations
CTFileStream strmFile;
try
{
// create binary file to receive child configurations
strmFile.Open_t( fnChildConfigurations);
// read file ID
strmFile.ExpectID_t( CChunkID( "CCFG")); // child configurations
// check version number
if( !( CChunkID(CHILD_CONFIGURATION_VER) == strmFile.GetID_t()) )
{
throw( "Invalid version of child configurations file, switching to defaults.");
}
// clear configurations
m_ccChildConfigurations->SetDefaultValues();
// read child configurations array
strmFile.Read_t( &m_ccChildConfigurations, sizeof( m_ccChildConfigurations));
// read end of file ID
strmFile.ExpectID_t( CChunkID( "CCED")); // end of child configurations ID
}
catch( char *err_str)
{
char achrMessage[ 256];
sprintf( achrMessage, "%s\nSplit window configurations will be switched to defaults.", err_str);
AfxMessageBox( CString(achrMessage));
ClearInvalidConfigPointers();
return FALSE;
}
ClearInvalidConfigPointers();
return TRUE;
}
void CWorldEditorApp::SaveChildConfigurations(void)
{
ClearInvalidConfigPointers();
// save child configurations
CTFileStream strmFile;
try
{
CTFileName fnChildConfigurations = CTString("Data\\WEDChildConfigurations.bin");
// create binary file to receive child configurations
strmFile.Create_t( fnChildConfigurations, CTStream::CM_BINARY);
// write file ID
strmFile.WriteID_t( CChunkID( "CCFG")); // child configurations
// write version number
strmFile.WriteID_t( CChunkID( CHILD_CONFIGURATION_VER));
// write child configurations array
strmFile.Write_t( &m_ccChildConfigurations, sizeof( m_ccChildConfigurations));
// write end of file ID
strmFile.WriteID_t( CChunkID( "CCED")); // end of child configurations ID
}
catch( char *err_str)
{
AfxMessageBox( CString(err_str));
}
}
// clear possibly invalid pointers in view configurations
void CWorldEditorApp::ClearInvalidConfigPointers(void)
{
for(INDEX i=0; i<ARRAYCOUNT(m_ccChildConfigurations); i++) {
m_ccChildConfigurations[i].ClearInvalidConfigPointers();
}
}
int CWorldEditorApp::ExitInstance()
{
// cleanup game library
_pGameGUI->End();
// delete clipboard file
RemoveFile( CTString("Temp\\ClipboardWorld.wld"));
WriteToIniFileOnEnd();
WriteDefaultPolygonValues();
// release entity marker texture
if( m_ptdEntityMarkerTexture != NULL)
{
_pTextureStock->Release( m_ptdEntityMarkerTexture);
m_ptdEntityMarkerTexture = NULL;
}
// and entity marker model data
if( m_pEntityMarkerModelData != NULL)
{
_pModelStock->Release( m_pEntityMarkerModelData);
delete m_pEntityMarkerModelObject;
m_pEntityMarkerModelObject = NULL;
}
// release portal marker texture
if( m_ptdPortalMarkerTexture != NULL)
{
_pTextureStock->Release( m_ptdPortalMarkerTexture);
m_ptdPortalMarkerTexture = NULL;
}
// and portal marker model data
if( m_pPortalMarkerModelData != NULL)
{
_pModelStock->Release( m_pPortalMarkerModelData);
delete m_pPortalMarkerModelObject;
m_pPortalMarkerModelObject = NULL;
}
// release empty brush texture
if( m_ptdEmptyBrushTexture != NULL)
{
_pTextureStock->Release( m_ptdEmptyBrushTexture);
m_ptdEmptyBrushTexture = NULL;
}
// and empty brush model data
if( m_pEmptyBrushModelData != NULL)
{
_pModelStock->Release( m_pEmptyBrushModelData);
delete m_pEmptyBrushModelObject;
m_pEmptyBrushModelObject = NULL;
}
// release range sphere texture
if( m_ptdRangeSphereTexture != NULL)
{
_pTextureStock->Release( m_ptdRangeSphereTexture);
m_ptdRangeSphereTexture = NULL;
}
// and range sphere model data
if( m_pRangeSphereModelData != NULL)
{
_pModelStock->Release( m_pRangeSphereModelData);
delete m_pRangeSphereModelObject;
m_pRangeSphereModelObject = NULL;
}
// release angle3d texture
if( m_ptdAngle3DTexture != NULL)
{
_pTextureStock->Release( m_ptdAngle3DTexture);
m_ptdAngle3DTexture = NULL;
}
// and angle3d model data
if( m_pAngle3DModelData != NULL)
{
_pModelStock->Release( m_pAngle3DModelData);
delete m_pAngle3DModelObject;
m_pAngle3DModelObject = NULL;
}
// release bounding box texture
if( m_ptdBoundingBoxTexture != NULL)
{
_pTextureStock->Release( m_ptdBoundingBoxTexture);
m_ptdBoundingBoxTexture = NULL;
}
// and range bounding box model data
if( m_pBoundingBoxModelData != NULL)
{
_pModelStock->Release( m_pBoundingBoxModelData);
delete m_pBoundingBoxModelObject;
m_pBoundingBoxModelObject = NULL;
}
// release error texture object
if( m_ptoError != NULL)
{
delete m_ptoError;
}
// release error texture
if( m_ptdError != NULL)
{
_pTextureStock->Release( m_ptdError);
}
// release icons tray texture
if( m_ptdIconsTray != NULL)
{
_pTextureStock->Release( m_ptdIconsTray);
}
// release orientation icons
if( m_pViewIconsTD != NULL)
{
_pTextureStock->Release( m_pViewIconsTD);
}
// release default primitive texture
if( m_ptdActiveTexture != NULL)
{
_pTextureStock->Release( m_ptdActiveTexture);
}
/*
FORDELETELIST( CDisplayMode, dm_Node, m_AvailableModes, litDM)
{
delete &litDM.Current();
} */
FORDELETELIST( CPrimitiveInHistoryBuffer, pihb_lnNode, theApp.m_lhPrimitiveHistory, itPrim)
{
delete &itPrim.Current();
}
delete m_pbpoClipboardPolygon;
// end entire engine
SE_EndEngine();
int iResult = CWinApp::ExitInstance();
return iResult;
}
void CWorldEditorApp::OnFilePreferences()
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
CDlgPreferences dlg;
dlg.m_dmFullScreen = m_dmFullScreen;
dlg.m_gatFullScreen = m_gatFullScreen;
if( dlg.DoModal() == IDOK)
{ // remember new full screen mode
m_dmFullScreen = dlg.m_dmFullScreen;
m_gatFullScreen = dlg.m_gatFullScreen;
}
}
BOOL CWorldEditorApp::OnIdle(LONG lCount)
{
// if game is on
if( _pInput->IsInputEnabled())
{
ASSERT(FALSE); //!!!!!
return FALSE;
}
// if game is on, everithing else is off (don't execute this)
else if( !(lCount&0xF))
{
POSITION pos = m_pDocTemplate->GetFirstDocPosition();
while (pos!=NULL) {
CWorldEditorDoc *pdocCurrent = (CWorldEditorDoc *)m_pDocTemplate->GetNextDoc(pos);
pdocCurrent->OnIdle();
}
// remember the world pointer of current document
CWorldEditorView *pvCurrent = GetActiveView();
if (pvCurrent!=NULL) {
CWorldEditorDoc *pdocCurrent = pvCurrent->GetDocument();
if (pdocCurrent!=NULL) {
_pShell->SetCurrentWorld(&pdocCurrent->m_woWorld);
2016-03-11 14:57:17 +01:00
}
}
((CMainFrame *)m_pMainWnd)->OnIdle( lCount);
}
BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
BOOL bRMB = (GetKeyState( VK_RBUTTON)&0x8000) != 0;
BOOL bResult=CWinApp::OnIdle(lCount);
return bResult||bLMB||bRMB;
}
// force all documents to repaint thir views
void CWorldEditorApp::RefreshAllDocuments( void)
{
POSITION pos = m_pDocTemplate->GetFirstDocPosition();
while (pos!=NULL)
{
CWorldEditorDoc *pdocCurrent = (CWorldEditorDoc *)m_pDocTemplate->GetNextDoc(pos);
pdocCurrent->UpdateAllViews( NULL);
}
}
// sets new active texture for primitive's default material
void CWorldEditorApp::SetNewActiveTexture( CTFileName fnFullTexName)
{
CMainFrame *pMainFrame = (CMainFrame *)m_pMainWnd;
// to hold new texture
CTextureData *pdtNewTexture = NULL;
// to hold short texture name
CTFileName fnTexName = fnFullTexName;
// try to
try
{
// obtain the new texture
fnTexName.RemoveApplicationPath_t();
pdtNewTexture = _pTextureStock->Obtain_t( fnTexName);
}
// if failed
catch( char *err_str)
{
pdtNewTexture = _pTextureStock->Obtain_t( CTFILENAME("Textures\\Editor\\Default.tex") );
(void)err_str;
// report error
//AfxMessageBox( CString(err_str));
//return;
}
ASSERT(pdtNewTexture != NULL);
// if there is old texture
if (m_ptdActiveTexture!=NULL) {
// release it
_pTextureStock->Release(m_ptdActiveTexture);
}
// remember the new texture
m_ptdActiveTexture = pdtNewTexture;
// if info frame exists, update it
if( pMainFrame->m_pInfoFrame != NULL)
{
CInfoSheet *pSheet = pMainFrame->m_pInfoFrame->m_pInfoSheet;
// redraw info frame
pMainFrame->m_pInfoFrame->Invalidate(FALSE);
// info's page is pg global
if( (pSheet->GetActivePage() == &pSheet->m_PgGlobal) )
{
// update texture description
pMainFrame->m_pInfoFrame->m_pInfoSheet->m_PgGlobal.UpdateData( FALSE);
}
// get active view
CWorldEditorView *pWorldEditorView = theApp.GetActiveView();
// get active document
CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
// if view and second layer exist (CSG is on), and primitive mode is on
if( (pWorldEditorView != NULL) &&
(pDoc->m_pwoSecondLayer != NULL) &&
(pDoc->m_bPrimitiveMode) )
{
// apply texture change for CSG primitive
pSheet->m_PgPrimitive.ApplySCGChange();
}
}
}
// opens directory wich contains given item
void CWorldEditorApp::FindItemInBrowser( CTFileName fnItemFileName)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
pMainFrame->m_Browser.SelectItemDirectory( fnItemFileName);
}
void CWorldEditorApp::TexturizeSelection(void)
{
// get active document
CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
// if it exists
if( pDoc != NULL)
{
// try to apply new texture to current selection
try
{
// if polygon mode
if( (pDoc->m_iMode == POLYGON_MODE) && (m_ptdActiveTexture != NULL) )
{
// get name from serial object
CTFileName fnTextureName = m_ptdActiveTexture->GetName();
pDoc->PasteTextureOverSelection_t( fnTextureName);
}
}
// if failed
catch( char *err_str)
{
// report error
AfxMessageBox( CString(err_str));
return;
}
}
}
void CWorldEditorApp::OnFileOpen()
{
// call file requester for opening documents
CDynamicArray<CTFileName> afnOpenedWorlds;
_EngineGUI.FileRequester( "Choose worlds to open", FILTER_WLD FILTER_ALL FILTER_END,
"Open world directory", "Worlds\\", "", &afnOpenedWorlds);
FOREACHINDYNAMICARRAY( afnOpenedWorlds, CTFileName, itWorld)
{
// try to load document
m_pDocTemplate->OpenDocumentFile( CString(_fnmApplicationPath+itWorld.Current()));
}
}
void CWorldEditorApp::OnConvertWorlds()
{
_pShell->Execute( CTString("con_bNoWarnings=1;"));
// call file requester for list containing worlds to convert
CTFileName fnFileList = _EngineGUI.FileRequester( "Choose list file for conversion",
FILTER_LST FILTER_TXT FILTER_ALL FILTER_END, "List files directory", "");
if( fnFileList == "") return;
INDEX ctLines = 0;
char achrLine[256];
CTFileStream fsFileList;
// count lines in list file
try {
fsFileList.Open_t( fnFileList);
while( !fsFileList.AtEOF()) {
fsFileList.GetLine_t( achrLine, 256);
// increase counter only for lines that are not blank
if( achrLine != "") ctLines++;
}
fsFileList.Close();
}
// if the list file can't be opened
catch(char *strError) {
_pShell->Execute( CTString("con_bNoWarnings=0;"));
WarningMessage( "Error reading list file: %s", strError);
return;
}
// process list file
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
CDlgProgress dlgProgressDialog( pMainFrame, TRUE);
dlgProgressDialog.Create( IDD_PROGRESS_DIALOG); // create progress dialog
dlgProgressDialog.SetWindowText( L"Convert files");
dlgProgressDialog.ShowWindow( SW_SHOW); // show progress window
dlgProgressDialog.CenterWindow(); // center window
dlgProgressDialog.m_ctrlProgres.SetRange( 0, (short)ctLines); // set progress range
// prepare error file
CTFileStream fsErrorFile;
CTFileName fnErrorFile = fnFileList.NoExt() + ".err";
// reopen list file
fsFileList.Open_t( fnFileList);
INDEX iCurrent = 0;
BOOL bConvertError = FALSE;
CTString strReport;
CTFileName fnmFile, fnmExt, fnmFileFull;
// loop thru lines
while( !fsFileList.AtEOF())
{
try {
if( dlgProgressDialog.m_bCancelPressed) break;
// read one line from list file
fsFileList.GetLine_t( achrLine, 256);
// ignore blank lines
if( achrLine == "") continue;
// set message and progress position
char achrProgressMessage[256];
sprintf( achrProgressMessage, "Converting files ... (%d / %d)", iCurrent+1, ctLines);
dlgProgressDialog.SetProgressMessageAndPosition( achrProgressMessage, iCurrent+1);
// convert needed type of object
fnmFile = CTString( achrLine);
fnmFileFull = _fnmApplicationPath+fnmFile;
fnmExt = fnmFile.FileExt();
struct _stat FileStat;
struct _utimbuf FileTime;
// convert world?
if( fnmExt == ".wld")
{
// load the world
CWorld woWorld;
woWorld.Load_t(fnmFile);
// reinitialize all entities
woWorld.ReinitializeEntities();
// flush stale caches
_pShell->Execute("FreeUnusedStock();");
// show all sectors and entities
woWorld.ShowAllSectors();
woWorld.ShowAllEntities();
// recalculate shadows on all brush polygons in the world
woWorld.DiscardAllShadows();
woWorld.CalculateDirectionalShadows();
woWorld.CalculateNonDirectionalShadows();
// get original file date
if( _stat( fnmFileFull, &FileStat)) throw "Error getting file date.";
// save world in new format
woWorld.Save_t(fnmFile);
_pShell->Execute( CTString( "bReinitializeShadowLayers=0;"));
woWorld.Clear();
// revert to original file date
FileTime.actime = FileStat.st_atime;
FileTime.modtime = FileStat.st_mtime;
if( _utime( fnmFileFull, &FileTime)) throw "Error setting file date.";
}
// convert texture?
else if( fnmExt == ".tex" || fnmExt == ".tbn")
{
// convert textures (but keep the file date)
CTextureData tdTex;
tdTex.Load_t( fnmFile);
// if old texture has been loaded
if( tdTex.td_ulFlags & TEX_WASOLD) {
// cannost convert mangled textures
if( tdTex.td_ptegEffect==NULL && tdTex.IsModified()) throw( TRANS("Cannot write texture that has modified frames."));
// get original file date
if( _stat( fnmFileFull, &FileStat)) throw "Error getting file date.";
// save texture in new format
tdTex.Save_t( fnmFile);
// revert to original file date
FileTime.actime = FileStat.st_atime;
FileTime.modtime = FileStat.st_mtime;
if( _utime( fnmFileFull, &FileTime)) throw "Error setting file date.";
}
}
// convert WHAT?
else if( fnmFile=="")
{
continue;
}
else
{
ThrowF_t( "Unsupported file format: %s", (CTString&)fnmExt);
}
}
// if file can't be opened
catch( char *strError) {
try {
// on first error
if( !bConvertError) {
// (re)create error file
fsErrorFile.Create_t( fnErrorFile);
bConvertError = TRUE;
}
// report error to file
strReport.PrintF( "File: %s\nHad error: %s\n", (CTString)fnmFile, strError);
fsErrorFile.PutString_t( strReport);
fsErrorFile.PutLine_t( "-----------------------------------------------");
}
// here should be no errors,
catch( char *strError) {
// otherwise ...
(void) strError;
WarningMessage( "Fatal error occured while working with error file!");
break;
}
}
// advance to next line
iCurrent++;
}
fsFileList.Close();
dlgProgressDialog.DestroyWindow(); // destroy progress dialog
_pShell->Execute( CTString("con_bNoWarnings=0;"));
// report error situation (if any)
if( bConvertError) {
fsErrorFile.PutLine_t( "DONE.");
fsErrorFile.Close();
WarningMessage( "There were some errors in conversion. They are listed in file:\n %s", fnErrorFile);
}
}
CEntity *CWorldEditorApp::CreateWorldBaseEntity(CWorld &woWorld, BOOL bZoning,
CPlacement3D plWorld/*=CPlacement3D(FLOAT3D(0,0,0),ANGLE3D(0,0,0))*/)
{
CEntity *penwb;
// try to
try
{
// create world base entity
penwb = woWorld.CreateEntity_t(plWorld, CTFILENAME("Classes\\WorldBase.ecl"));
}
// catch and
catch( char *err_str)
{
// report errors
AfxMessageBox( CString(err_str));
return NULL;
}
// prepare the entity
penwb->Initialize();
if( bZoning)
{
EFirstWorldBase eFirstWorldBase;
penwb->SendEvent( eFirstWorldBase);
CEntity::HandleSentEvents();
}
return penwb;
}
BOOL CWorldEditorApp::Add3DObject(CWorldEditorDoc *pDoc, CEntity *penwb, CTFileName fnFile, BOOL bAdd)
{
CObject3D o3d;
// temporary world
CWorld woWorld;
CEntity *penwb2=CreateWorldBaseEntity(woWorld, FALSE);
if( penwb2==NULL)
{
return FALSE;
}
// try to
try
{
// load 3D object
FLOATmatrix3D mStretch;
mStretch.Diagonal(1.0f);
if (fnFile.FileExt()==".obj") { // Maya Obj has different orientation
mStretch.Diagonal(FLOAT3D(-1.0f, 1.0f, -1.0f));
}
o3d.LoadAny3DFormat_t( fnFile, mStretch);
FOREACHINDYNAMICARRAY(o3d.ob_aoscSectors, CObjectSector, itosc)
{
// for each material in object3D
FOREACHINDYNAMICARRAY(itosc->osc_aomtMaterials, CObjectMaterial, itom)
{
if( !FileExists(itom->omt_Name))
{
itom->omt_Name = "Textures\\Editor\\Default.tex";
}
}
}
// create world base's brush from object 3D
CBrush3D *pbr = penwb2->GetBrush();
pbr->FromObject3D_t( o3d);
pbr->CalculateBoundingBoxes();
CPlacement3D plDummy;
plDummy.pl_PositionVector = FLOAT3D(0.0f,0.0f,0.0f);
plDummy.pl_OrientationAngle = ANGLE3D(0,0,0);
// if should apply CSG add
if(bAdd)
{
penwb->en_pwoWorld->CSGAdd(*penwb, woWorld, *penwb2, plDummy);
}
// if should perform join layers
else
{
// copy entities
penwb->en_pwoWorld->CopyEntities( woWorld, woWorld.wo_cenEntities, pDoc->m_selEntitySelection, plDummy);
}
}
// catch and
catch( char *err_str)
{
// report errors
AfxMessageBox( CString(err_str));
return FALSE;
}
return TRUE;
}
/*
* Import 3d object(s), create new document
*/
void CWorldEditorApp::OnImport3DObject()
{
// try to load document
CWorldEditorDoc *pDoc = (CWorldEditorDoc *) m_pDocTemplate->CreateNewDocument();
// create the World entity
CEntity *pwb=CreateWorldBaseEntity(pDoc->m_woWorld, TRUE);
if( pwb==NULL)
{
delete pDoc;
return;
}
// create 3d objects
INDEX ctImported=Insert3DObjects(pDoc);
if( ctImported==0)
{
delete pDoc;
return;
}
// finish creating document
if (pDoc == NULL)
{
TRACE0("CDocTemplate::CreateNewDocument returned NULL.\n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return;
}
ASSERT_VALID(pDoc);
BOOL bAutoDelete = pDoc->m_bAutoDelete;
pDoc->m_bAutoDelete = FALSE; // don't destroy if something goes wrong
CFrameWnd* pFrame = m_pDocTemplate->CreateNewFrame(pDoc, NULL);
pDoc->m_bAutoDelete = bAutoDelete;
if (pFrame == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
delete pDoc; // explicit delete on error
return;
}
ASSERT_VALID(pFrame);
pDoc->SetModifiedFlag();
// set document name and don't add it into MRU
//pDoc->SetPathName( _fnmApplicationPath+"Worlds\\"+"Untitled.wld", FALSE);
//pDoc->SetTitle( fn3D.FileName() + ".wld");
m_pDocTemplate->InitialUpdateFrame(pFrame, pDoc, TRUE);
pDoc->SetModifiedFlag( TRUE);
}
INDEX CWorldEditorApp::Insert3DObjects(CWorldEditorDoc *pDoc)
{
INDEX ctInserted=0;
CDynamicArray<CTFileName> afnFiles;
CTFileName fn3D = _EngineGUI.FileRequester( "Import 3D object series",
FILTER_3DOBJ FILTER_LWO FILTER_OBJ FILTER_3DS FILTER_ALL FILTER_END,
"Import 3D object directory", "", "", &afnFiles);
if( afnFiles.Count() == 0) return 0;
// get first file (when strings are sorted)
CTString strMin="a";
((char *)(const char *) strMin)[0]=char(255);
CTFileName *pfn=NULL;
{FOREACHINDYNAMICARRAY(afnFiles, CTFileName, itfn)
{
CTString str=itfn->FileName();
if( strcmp(str, strMin)<0)
{
strMin=str;
pfn=&*itfn;
}
}}
ASSERT(pfn!=NULL);
if(pfn==NULL) return ctInserted;
// create main World entity
CEntity *pwb=CreateWorldBaseEntity(pDoc->m_woWorld, TRUE);
if( pwb==NULL)
{
return 0;
}
// add first 3D file as zoning base
if( !Add3DObject(pDoc, pwb, *pfn, TRUE))
{
return 0;
}
ctInserted++;
// remove added file from dynamic container
afnFiles.Delete(pfn);
// add other files
{FOREACHINDYNAMICARRAY(afnFiles, CTFileName, itfn)
{
CTString &str=*itfn;
CTString strName=itfn->FileName();
if( ((char *)(const char *)strName)[strlen(strName)-1] == 'E')
{
// join layers
Add3DObject(pDoc, pwb, *itfn, FALSE);
}
else
{
// CSG add
Add3DObject(pDoc, pwb, *itfn, TRUE);
}
ctInserted++;
}}
return ctInserted;
}
CWorldEditorDoc* CWorldEditorApp::GetLastActivatedDocument(void)
{
return m_pLastActivatedDocument;
}
void CWorldEditorApp::ActivateDocument(CWorldEditorDoc *pDocToActivate)
{
// remember document to be activated as last activated
m_pLastActivatedDocument = pDocToActivate;
}
CWorldEditorDoc *CWorldEditorApp::GetDocument()
{
// obtain current view ptr
CWorldEditorView *pWorldEditorView = GetActiveView();
// if view does not exist, return
if( pWorldEditorView == NULL)
{
return NULL;
}
// obtain document ptr
CWorldEditorDoc *pDoc = pWorldEditorView->GetDocument();
// return it
return pDoc;
}
void CWorldEditorApp::OnFileNew()
{
CWinApp::OnFileNew();
// obtain new document ptr
CWorldEditorDoc *pDoc = GetDocument();
CTFileName fnDefaultBcg = CTString(CStringA(theApp.GetProfileString(
L"World editor prefs", L"Default background picture",
CString("Textures\\Editor\\Default.tex"))));
try
{
//!!!! pDoc->m_woWorld.SetBackgroundTexture_t( fnDefaultBcg);
}
catch( char *strError)
{
(void) strError;
}
try
{
//!!!! pDoc->m_woWorld.SetBackgroundTexture_t( CTString("Textures\\Editor\\Default.tex"));
}
catch( char *strError)
{
AfxMessageBox( CString(strError));
}
char chrColor[ 16];
COLOR colBackground;
// obtain background color form INI file
strcpy( chrColor, CStringA(theApp.GetProfileString( L"World editor prefs",
L"Default background color", L"0XFF000000")));
sscanf( chrColor, "0X%08x", &colBackground);
// set background color to color button
pDoc->m_woWorld.SetBackgroundColor( colBackground);
pDoc->m_woWorld.SetDescription( "No mission description");
pDoc->SetModifiedFlag( TRUE);
CString strOpenPath;
strOpenPath = CStringA(theApp.GetProfileString(L"World editor", L"Open directory", L""));
// set default document's name and don't set it into MRU
pDoc->SetPathName( strOpenPath + "Untitled.wld", FALSE);
pDoc->SetTitle( L"Untitled.wld");
}
int CWorldEditorApp::Run()
{
int iResult;
CTSTREAM_BEGIN {
iResult=CWinApp::Run();
} CTSTREAM_END;
return iResult;
}
BOOL CWorldEditorApp::PreTranslateMessage(MSG* pMsg)
{
return CWinApp::PreTranslateMessage(pMsg);
}
CTString CWorldEditorApp::GetNameForVirtualTreeNode( CVirtualTreeNode *pvtnNode)
{
ASSERT( pvtnNode != NULL);
// start from selected directory
CVirtualTreeNode *pvtnCurrentDir = pvtnNode;
// reset curently opened virtual directory name
CTString strResult = "";
// compile full path name
while( pvtnCurrentDir->vnt_pvtnParent != NULL)
{
strResult = pvtnCurrentDir->vtn_strName+"\\"+ strResult;
pvtnCurrentDir = pvtnCurrentDir->vnt_pvtnParent;
}
// if given is root directory
if( strResult == "")
{
strResult = "<ROOT>";
}
return strResult;
}
void CWorldEditorApp::OnDecadicGrid()
{
m_bDecadicGrid = !m_bDecadicGrid;
// refresh all documents
RefreshAllDocuments();
}
void CWorldEditorApp::OnUpdateDecadicGrid(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck( m_bDecadicGrid);
}
void CCustomToolTip::ManualOn( PIX pixManualX, PIX pixManualY, TTCFunction_type *pCallBack, void *pThis)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
cct_pCallback = pCallBack;
cct_pThis = pThis;
if( pMainFrame->m_pwndToolTip != NULL)
{
ManualOff();
}
pMainFrame->ManualToolTipOn( pixManualX, pixManualY);
}
void CCustomToolTip::ManualOff( void)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
pMainFrame->m_pwndToolTip->ManualOff();
pMainFrame->m_pwndToolTip = NULL;
}
void CCustomToolTip::ManualUpdate(void)
{
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
pMainFrame->ManualToolTipUpdate();
}
void CCustomToolTip::MouseMoveNotify( HWND hwndCaller, ULONG ulTime, TTCFunction_type *pCallBack, void *pThis)
{
cct_hwndCaller = hwndCaller;
cct_pCallback = pCallBack;
cct_pThis = pThis;
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
pMainFrame->KillTimer( 0);
pMainFrame->SetTimer( 0, ulTime, NULL);
}
void CWorldEditorApp::OnSetAsDefault()
{
CWorldEditorDoc *pDoc = GetDocument();
ASSERT( pDoc->m_selPolygonSelection.Count() == 1);
pDoc->m_selPolygonSelection.Lock();
m_pbpoPolygonWithDeafultValues->CopyPropertiesWithoutTexture( pDoc->m_selPolygonSelection[0]);
pDoc->m_selPolygonSelection.Unlock();
}
void CWorldEditorApp::ReadDefaultPolygonValues()
{
char strIni[ 256];
INI_READ( "Default polygon flags", "0");
GET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_ulFlags);
INI_READ( "Default polygon shadow color", "0XFFFFFFFF");
GET_COLOR( m_pbpoPolygonWithDeafultValues->bpo_colShadow);
INI_READ( "Default polygon surface", "0");
GET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubSurfaceType);
INI_READ( "Default polygon illumination", "0");
GET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubIlluminationType);
INI_READ( "Default polygon blend", "1");
GET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubShadowBlend);
INI_READ( "Default polygon mirror", "0");
GET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubMirrorType);
INI_READ( "Default polygon cluster size", "2");
GET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_sbShadowClusterSize);
}
void CWorldEditorApp::WriteDefaultPolygonValues()
{
char strIni[ 256];
SET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_ulFlags);
INI_WRITE( "Default polygon flags");
SET_COLOR( m_pbpoPolygonWithDeafultValues->bpo_colShadow);
INI_WRITE( "Default polygon shadow color");
SET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubSurfaceType);
INI_WRITE( "Default polygon surface");
SET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubIlluminationType);
INI_WRITE( "Default polygon illumination");
SET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubShadowBlend);
INI_WRITE( "Default polygon blend");
SET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_ubMirrorType);
INI_WRITE( "Default polygon mirror");
SET_INDEX( m_pbpoPolygonWithDeafultValues->bpo_bppProperties.bpp_sbShadowClusterSize);
INI_WRITE( "Default polygon cluster size");
}
void CWorldEditorApp::OnHelpShowTipOfTheDay()
{
CDlgTipOfTheDay dlgTips;
dlgTips.DoModal();
m_bShowTipOfTheDay = dlgTips.m_bShowTipsAtStartup;
}
void FindEmptyBrushes( void)
{
// remember the world pointer of current document
CWorldEditorView *pvCurrent = theApp.GetActiveView();
if (pvCurrent!=NULL)
{
CWorldEditorDoc *pDoc = pvCurrent->GetDocument();
if (pDoc!=NULL)
{
// for each entity in the world
FOREACHINDYNAMICCONTAINER(pDoc->m_woWorld.wo_cenEntities, CEntity, iten) {
FLOAT3D vPos = iten->GetPlacement().pl_PositionVector;
// if it is brush entity
if (iten->en_RenderType == CEntity::RT_BRUSH) {
INDEX iMip = 0;
// for each mip in its brush
FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm)
{
if( itbm->bm_abscSectors.Count() == 0)
{
CPrintF("Found brush named %s, without sectors in mip %d at coordinates: (%g, %g, %g)\n",
iten->GetName(), iMip, vPos(1), vPos(2), vPos(3));
}
iMip++;
}
}
}
}
}
}
void CWorldEditorApp::WinHelp(DWORD dwData, UINT nCmd)
{
// TODO: Add your specialized code here and/or call the base class
if (nCmd == HELP_CONTEXT) {
DisplayHelp(CTFILENAME("Help\\SeriousEditorContext.hlk"), HH_HELP_CONTEXT, dwData);
} else {
CWinApp::WinHelp(dwData, nCmd);
}
}
void CWorldEditorApp::DisplayHelp(const CTFileName &fnHlk, UINT uCommand, DWORD dwData)
{
CTString strHelpPath;
BOOL bHlkFound = TRUE;
try
{
strHelpPath.Load_t(fnHlk.NoExt()+".hlk");
}
catch(char *strError)
{
(void) strError;
if (fnHlk.FileExt()==".ecl") {
WarningMessage("No help available for class: %s", fnHlk.FileName());
}
bHlkFound = FALSE;
}
// extract prefix
CTString strHelpFormatID = strHelpPath;
strHelpFormatID.OnlyFirstLine();
strHelpPath.RemovePrefix(strHelpFormatID);
strHelpPath.DeleteChar(0);
strHelpPath.OnlyFirstLine();
if( bHlkFound)
{
if( strHelpFormatID=="HTM" || strHelpFormatID=="HTML" || strHelpFormatID=="TXT")
{
// obtain iexplore path
CTString strKey = "HKEY_CLASSES_ROOT\\.htm\\";
CTString strString;
REG_GetString(strKey, strString);
strKey = "HKEY_CLASSES_ROOT\\"+strString+"\\shell\\open\\command\\";
REG_GetString(strKey, strString);
// now extract file path between two "
char aExePath[PATH_MAX];
sscanf( strString, "\"%1024[^\"]\"", aExePath);
CTString strCommand = "\""+CTString(aExePath)+"\"";
CTString strInputParam = "\""+_fnmApplicationPath+strHelpPath+"\"";
const char *argv[4];
argv[0] = strCommand;
argv[1] = strInputParam;
argv[2] = NULL;
_spawnvp(_P_NOWAIT, aExePath, argv);
return;
}
else if( strHelpFormatID=="CHM")
{
HtmlHelp(dwData);
//HtmlHelp(NULL,
// _fnmApplicationPath+strHelpPath, uCommand, dwData);
return;
}
else
{
WarningMessage("Expected TXT, HTM, HTML, or CHM help format indentifier.");
}
}
HtmlHelp(dwData);
//HtmlHelp(NULL,
// _fnmApplicationPath+"Help\\ToolsHelp.chm::/SeriousEditor/Overview.htm", uCommand, dwData);
}
CEntity *GetTerrainEntity(void)
{
CTerrain *ptTerrain=GetTerrain();
if(ptTerrain!=NULL)
{
return ptTerrain->tr_penEntity;
}
return NULL;
}
CTerrain *GetTerrain(void)
{
CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
if(pDoc==NULL) return NULL;
return pDoc->m_ptrSelectedTerrain;
}
CTerrainLayer *GetLayer(INDEX iLayer)
{
CTerrain *ptTerrain=GetTerrain();
if(ptTerrain==NULL) return NULL;
if(!(ptTerrain->tr_atlLayers.Count()>0) || iLayer>=ptTerrain->tr_atlLayers.Count()) return NULL;
return &ptTerrain->tr_atlLayers[iLayer];
}
CTerrainLayer *GetLayer(void)
{
CTerrain *ptTerrain=GetTerrain();
if(ptTerrain==NULL) return NULL;
if(!(ptTerrain->tr_atlLayers.Count()>0)) return NULL;
if(ptTerrain->tr_iSelectedLayer>=ptTerrain->tr_atlLayers.Count())
{
ptTerrain->tr_iSelectedLayer=0;
}
return &ptTerrain->tr_atlLayers[ptTerrain->tr_iSelectedLayer];
}
INDEX GetLayerIndex(void)
{
CTerrain *ptTerrain=GetTerrain();
if(ptTerrain==NULL) return 0;
if(ptTerrain->tr_atlLayers.Count()<=0 ||
ptTerrain->tr_iSelectedLayer>=ptTerrain->tr_atlLayers.Count())
{
ptTerrain->tr_iSelectedLayer=0;
}
return ptTerrain->tr_iSelectedLayer;
}
void SelectLayer(INDEX iLayer)
{
CTerrain *ptrTerrain=GetTerrain();
if(ptrTerrain==NULL) return;
if(ptrTerrain->tr_atlLayers.Count()<=iLayer || iLayer<0)
{
ptrTerrain->tr_iSelectedLayer=0;
}
else
{
ptrTerrain->tr_iSelectedLayer=iLayer;
}
}