khanat-opennel-code/code/ryzom/tools/leveldesign/export/export.cpp
2016-01-15 16:42:21 +01:00

2211 lines
64 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "export.h"
#include "formFlora.h"
#include "formPlant.h"
#ifdef NL_OS_WINDOWS
#define NOMINMAX
#include <windows.h>
#endif // NL_OS_WINDOWS
#include "nel/ligo/zone_region.h"
#include "nel/ligo/primitive.h"
#include "nel/georges/u_form_loader.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_elm.h"
#include "nel/3d/zone.h"
#include "nel/3d/landscape.h"
#include "nel/3d/scene_group.h"
#include "nel/3d/visual_collision_manager.h"
#include "nel/3d/visual_collision_entity.h"
#include "nel/misc/o_xml.h"
#include "nel/misc/i_xml.h"
#include "nel/misc/path.h"
#include "nel/misc/file.h"
#include "tools.h"
#include "../master/ContinentCfg.h"
using namespace std;
using namespace NLMISC;
using namespace NL3D;
using namespace NLLIGO;
using namespace NLGEORGES;
#define MAX_SYS_DIR 6
const char *gExportSysDir[MAX_SYS_DIR] =
{
".",
"..",
"ZoneBitmaps",
"ZoneLigos",
"dfn",
"tmp"
};
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------
// Segment line intersection P1P2 and P3P4
bool CExport::segmentIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
double denominator = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1);
if( denominator == 0.0 )
return false; // The segment are colinear
double k = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3) ) / denominator;
if( (k<=0.0) || (k>=1.0) ) return false;
k = ( (x2-x1)*(y1-y3) - (y2-y1)*(x1-x3) ) / denominator;
if( (k<=0.0) || (k>=1.0) ) return false;
return true;
}
// ---------------------------------------------------------------------------
void CExport::delIGZone (sint32 x, sint32 y)
{
string sZoneName = CExport::getZoneNameFromXY (x, y);
sZoneName += ".ig";
if (CFile::deleteFile(sZoneName))
{
CTools::chdir (_ExeDir);
string sTmp = string(" zone ") + sZoneName + " deleted";
if (_ExportCB != NULL)
_ExportCB->dispInfo(sTmp);
}
}
// ---------------------------------------------------------------------------
void CExport::delAllIGZoneUnderPoint (float fCellSize, CPrimPoint *pPoint, const string &sIGOutputDir)
{
if (pPoint == NULL) return;
sint32 nX, nY;
CTools::chdir (sIGOutputDir);
nX = (sint32) floor (pPoint->Point.x / fCellSize);
nY = (sint32) floor (pPoint->Point.y / fCellSize);
delIGZone (nX, nY);
CTools::chdir (sIGOutputDir);
}
// ---------------------------------------------------------------------------
void CExport::delAllIGZoneUnderPath (float fCellSize, CPrimPath *pPath, const string &sIGOutputDir)
{
if (pPath == NULL) return;
if (pPath->VPoints.size() == 0) return;
uint32 i, j;
CVector vMin, vMax;
CTools::chdir (sIGOutputDir);
vMin = vMax = pPath->VPoints[0];
for (i = 0; i < pPath->VPoints.size(); ++i)
{
if (vMin.x > pPath->VPoints[i].x) vMin.x = pPath->VPoints[i].x;
if (vMin.y > pPath->VPoints[i].y) vMin.y = pPath->VPoints[i].y;
if (vMin.z > pPath->VPoints[i].z) vMin.z = pPath->VPoints[i].z;
if (vMax.x < pPath->VPoints[i].x) vMax.x = pPath->VPoints[i].x;
if (vMax.y < pPath->VPoints[i].y) vMax.y = pPath->VPoints[i].y;
if (vMax.z < pPath->VPoints[i].z) vMax.z = pPath->VPoints[i].z;
}
sint32 x, y;
sint32 nMinX, nMinY, nMaxX, nMaxY;
nMinX = (sint32) floor (vMin.x / fCellSize);
nMinY = (sint32) floor (vMin.y / fCellSize);
nMaxX = (sint32) floor (vMax.x / fCellSize);
nMaxY = (sint32) floor (vMax.y / fCellSize);
for (x = nMinX; x <= nMaxX; ++x)
for (y = nMinY; y <= nMaxY; ++y)
{
// Does the zone (x,y) is under the patah ?
CVector vSquare[4];
vSquare[0].x = x * fCellSize;
vSquare[0].y = y * fCellSize;
vSquare[0].z = 0.0f;
vSquare[1].x = (x+1) * fCellSize;
vSquare[1].y = y * fCellSize;
vSquare[1].z = 0.0f;
vSquare[2].x = (x+1) * fCellSize;
vSquare[2].y = (y+1) * fCellSize;
vSquare[2].z = 0.0f;
vSquare[3].x = x * fCellSize;
vSquare[3].y = (y+1) * fCellSize;
vSquare[3].z = 0.0f;
// Is a vertex of the path inside the zone ?
for (i = 0; i < pPath->VPoints.size(); ++i)
{
if ((pPath->VPoints[i].x >= (x*fCellSize)) &&
(pPath->VPoints[i].x <= ((x+1)*fCellSize)) &&
(pPath->VPoints[i].y <= (y*fCellSize)) &&
(pPath->VPoints[i].y <= ((y+1)*fCellSize)))
{
delIGZone (x, y);
CTools::chdir (sIGOutputDir);
}
}
// Is an segment of the path cut an edge of the patat ?
for (i = 0; i < pPath->VPoints.size()-1; ++i)
for (j = 0; j < 4; ++j)
{
double x1 = vSquare[j].x;
double y1 = vSquare[j].y;
double x2 = vSquare[(j+1)%4].x;
double y2 = vSquare[(j+1)%4].y;
double x3 = pPath->VPoints[i].x;
double y3 = pPath->VPoints[i].y;
double x4 = pPath->VPoints[i+1].x;
double y4 = pPath->VPoints[i+1].y;
if (segmentIntersection(x1, y1, x2, y2, x3, y3, x4, y4))
{
delIGZone (x, y);
CTools::chdir (sIGOutputDir);
}
}
}
}
// ---------------------------------------------------------------------------
void CExport::delAllIGZoneUnderPatat (float fCellSize, CPrimZone *pPatat, const string &sIGOutputDir)
{
if (pPatat == NULL) return;
if (pPatat->VPoints.size() == 0) return;
uint32 i, j;
CVector vMin, vMax;
CTools::chdir (sIGOutputDir);
vMin = vMax = pPatat->VPoints[0];
for (i = 0; i < pPatat->VPoints.size(); ++i)
{
if (vMin.x > pPatat->VPoints[i].x) vMin.x = pPatat->VPoints[i].x;
if (vMin.y > pPatat->VPoints[i].y) vMin.y = pPatat->VPoints[i].y;
if (vMin.z > pPatat->VPoints[i].z) vMin.z = pPatat->VPoints[i].z;
if (vMax.x < pPatat->VPoints[i].x) vMax.x = pPatat->VPoints[i].x;
if (vMax.y < pPatat->VPoints[i].y) vMax.y = pPatat->VPoints[i].y;
if (vMax.z < pPatat->VPoints[i].z) vMax.z = pPatat->VPoints[i].z;
}
sint32 x, y;
sint32 nMinX, nMinY, nMaxX, nMaxY;
nMinX = (sint32) floor (vMin.x / fCellSize);
nMinY = (sint32) floor (vMin.y / fCellSize);
nMaxX = (sint32) floor (vMax.x / fCellSize);
nMaxY = (sint32) floor (vMax.y / fCellSize);
for (x = nMinX; x <= nMaxX; ++x)
for (y = nMinY; y <= nMaxY; ++y)
{
// Does the zone (x,y) is under the patat ?
// Is a vertex of the zone in the patat ?
CVector vSquare[4];
vSquare[0].x = x * fCellSize;
vSquare[0].y = y * fCellSize;
vSquare[0].z = 0.0f;
vSquare[1].x = (x+1) * fCellSize;
vSquare[1].y = y * fCellSize;
vSquare[1].z = 0.0f;
vSquare[2].x = (x+1) * fCellSize;
vSquare[2].y = (y+1) * fCellSize;
vSquare[2].z = 0.0f;
vSquare[3].x = x * fCellSize;
vSquare[3].y = (y+1) * fCellSize;
vSquare[3].z = 0.0f;
for (i = 0; i < 4; ++i)
{
if (pPatat->contains(vSquare[i]))
{
delIGZone (x, y);
CTools::chdir (sIGOutputDir);
}
}
// Is a vertex of the patat inside the zone ?
for (i = 0; i < pPatat->VPoints.size(); ++i)
{
if ((pPatat->VPoints[i].x >= (x*fCellSize)) &&
(pPatat->VPoints[i].x <= ((x+1)*fCellSize)) &&
(pPatat->VPoints[i].y <= (y*fCellSize)) &&
(pPatat->VPoints[i].y <= ((y+1)*fCellSize)))
{
delIGZone (x, y);
CTools::chdir (sIGOutputDir);
}
}
// Is an edge of the zone cut an edge of the patat ?
for (i = 0; i < pPatat->VPoints.size(); ++i)
for (j = 0; j < 4; ++j)
{
double x1 = vSquare[j].x;
double y1 = vSquare[j].y;
double x2 = vSquare[(j+1)%4].x;
double y2 = vSquare[(j+1)%4].y;
double x3 = pPatat->VPoints[i].x;
double y3 = pPatat->VPoints[i].y;
double x4 = pPatat->VPoints[(i+1)%pPatat->VPoints.size()].x;
double y4 = pPatat->VPoints[(i+1)%pPatat->VPoints.size()].y;
if (segmentIntersection(x1, y1, x2, y2, x3, y3, x4, y4))
{
delIGZone (x, y);
CTools::chdir (sIGOutputDir);
}
}
}
}
// ---------------------------------------------------------------------------
// A patat needs an update if there is at least one zone under itself that is not present
bool CExport::isPatatNeedUpdate (float fCellSize, CPrimZone *pPatat, const string &sIGOutputDir)
{
uint32 i, j;
CVector vMin, vMax;
CTools::chdir (sIGOutputDir);
if (pPatat->VPoints.size() == 0)
return false;
vMin = vMax = pPatat->VPoints[0];
for (i = 0; i < pPatat->VPoints.size(); ++i)
{
if (vMin.x > pPatat->VPoints[i].x) vMin.x = pPatat->VPoints[i].x;
if (vMin.y > pPatat->VPoints[i].y) vMin.y = pPatat->VPoints[i].y;
if (vMin.z > pPatat->VPoints[i].z) vMin.z = pPatat->VPoints[i].z;
if (vMax.x < pPatat->VPoints[i].x) vMax.x = pPatat->VPoints[i].x;
if (vMax.y < pPatat->VPoints[i].y) vMax.y = pPatat->VPoints[i].y;
if (vMax.z < pPatat->VPoints[i].z) vMax.z = pPatat->VPoints[i].z;
}
sint32 x, y;
sint32 nMinX, nMinY, nMaxX, nMaxY;
nMinX = (sint32) floor (vMin.x / fCellSize);
nMinY = (sint32) floor (vMin.y / fCellSize);
nMaxX = (sint32) floor (vMax.x / fCellSize);
nMaxY = (sint32) floor (vMax.y / fCellSize);
for (x = nMinX; x <= nMaxX; ++x)
for (y = nMinY; y <= nMaxY; ++y)
{
// Does the zone (x,y) is under the patat ?
bool bZoneUnderPatat = false;
// Is a vertex of the zone in the patat ?
CVector vSquare[4];
vSquare[0].x = x * fCellSize;
vSquare[0].y = y * fCellSize;
vSquare[0].z = 0.0f;
vSquare[1].x = (x+1) * fCellSize;
vSquare[1].y = y * fCellSize;
vSquare[1].z = 0.0f;
vSquare[2].x = (x+1) * fCellSize;
vSquare[2].y = (y+1) * fCellSize;
vSquare[2].z = 0.0f;
vSquare[3].x = x * fCellSize;
vSquare[3].y = (y+1) * fCellSize;
vSquare[3].z = 0.0f;
for (i = 0; i < 4; ++i)
{
if (pPatat->contains(vSquare[i]))
{
string sTmp = CExport::getZoneNameFromXY(x,y) + ".ig";
if (!CTools::fileExist(sTmp)) // If the file does not exist
return true; // need update
}
}
// Is a vertex of the patat inside the zone ?
for (i = 0; i < pPatat->VPoints.size(); ++i)
{
if ((pPatat->VPoints[i].x >= (x*fCellSize)) &&
(pPatat->VPoints[i].x <= ((x+1)*fCellSize)) &&
(pPatat->VPoints[i].y >= (y*fCellSize)) &&
(pPatat->VPoints[i].y <= ((y+1)*fCellSize)))
{
string sTmp = CExport::getZoneNameFromXY(x,y) + ".ig";
if (!CTools::fileExist(sTmp)) // If the file does not exist
return true; // need update
}
}
// Is an edge of the zone cut an edge of the patat ?
for (i = 0; i < pPatat->VPoints.size(); ++i)
for (j = 0; j < 4; ++j)
{
double x1 = vSquare[j].x;
double y1 = vSquare[j].y;
double x2 = vSquare[(j+1)%4].x;
double y2 = vSquare[(j+1)%4].y;
double x3 = pPatat->VPoints[i].x;
double y3 = pPatat->VPoints[i].y;
double x4 = pPatat->VPoints[(i+1)%pPatat->VPoints.size()].x;
double y4 = pPatat->VPoints[(i+1)%pPatat->VPoints.size()].y;
if (segmentIntersection(x1, y1, x2, y2, x3, y3, x4, y4))
{
string sTmp = CExport::getZoneNameFromXY (x, y) + ".ig";
if (!CTools::fileExist(sTmp)) // If the file does not exist
return true; // need update
}
}
}
return false;
}
// ---------------------------------------------------------------------------
// A path needs an update if there is at least one zone under itself that is not present
bool CExport::isPathNeedUpdate (float fCellSize, CPrimPath *pPath, const string &sIGOutputDir)
{
uint32 i, j;
CVector vMin, vMax;
CTools::chdir (sIGOutputDir);
if (pPath->VPoints.size() == 0)
return false;
vMin = vMax = pPath->VPoints[0];
for (i = 0; i < pPath->VPoints.size(); ++i)
{
if (vMin.x > pPath->VPoints[i].x) vMin.x = pPath->VPoints[i].x;
if (vMin.y > pPath->VPoints[i].y) vMin.y = pPath->VPoints[i].y;
if (vMin.z > pPath->VPoints[i].z) vMin.z = pPath->VPoints[i].z;
if (vMax.x < pPath->VPoints[i].x) vMax.x = pPath->VPoints[i].x;
if (vMax.y < pPath->VPoints[i].y) vMax.y = pPath->VPoints[i].y;
if (vMax.z < pPath->VPoints[i].z) vMax.z = pPath->VPoints[i].z;
}
sint32 x, y;
sint32 nMinX, nMinY, nMaxX, nMaxY;
nMinX = (sint32) floor (vMin.x / fCellSize);
nMinY = (sint32) floor (vMin.y / fCellSize);
nMaxX = (sint32) floor (vMax.x / fCellSize);
nMaxY = (sint32) floor (vMax.y / fCellSize);
for (x = nMinX; x <= nMaxX; ++x)
for (y = nMinY; y <= nMaxY; ++y)
{
// Does the zone (x,y) is under the patat ?
bool bZoneUnderPatat = false;
// Is a vertex of the zone in the patat ?
CVector vSquare[4];
vSquare[0].x = x * fCellSize;
vSquare[0].y = y * fCellSize;
vSquare[0].z = 0.0f;
vSquare[1].x = (x+1) * fCellSize;
vSquare[1].y = y * fCellSize;
vSquare[1].z = 0.0f;
vSquare[2].x = (x+1) * fCellSize;
vSquare[2].y = (y+1) * fCellSize;
vSquare[2].z = 0.0f;
vSquare[3].x = x * fCellSize;
vSquare[3].y = (y+1) * fCellSize;
vSquare[3].z = 0.0f;
// Is a vertex of the path inside the zone ?
for (i = 0; i < pPath->VPoints.size(); ++i)
{
if ((pPath->VPoints[i].x >= (x*fCellSize)) &&
(pPath->VPoints[i].x <= ((x+1)*fCellSize)) &&
(pPath->VPoints[i].y >= (y*fCellSize)) &&
(pPath->VPoints[i].y <= ((y+1)*fCellSize)))
{
string sTmp = CExport::getZoneNameFromXY(x,y) + ".ig";
if (!CTools::fileExist(sTmp)) // If the file does not exist
return true; // need update
}
}
// Is an edge of the zone cut an edge of the patat ?
for (i = 0; i < (pPath->VPoints.size()-1); ++i)
for (j = 0; j < 4; ++j)
{
double x1 = vSquare[j].x;
double y1 = vSquare[j].y;
double x2 = vSquare[(j+1)%4].x;
double y2 = vSquare[(j+1)%4].y;
double x3 = pPath->VPoints[i].x;
double y3 = pPath->VPoints[i].y;
double x4 = pPath->VPoints[i+1].x;
double y4 = pPath->VPoints[i+1].y;
if (segmentIntersection(x1, y1, x2, y2, x3, y3, x4, y4))
{
string sTmp = CExport::getZoneNameFromXY (x, y) + ".ig";
if (!CTools::fileExist(sTmp)) // If the file does not exist
return true; // need update
}
}
}
return false;
}
// ---------------------------------------------------------------------------
// A path needs an update if there is at least one zone under itself that is not present
bool CExport::isPointNeedUpdate (float fCellSize, CPrimPoint *pPoint, const string &sIGOutputDir)
{
CTools::chdir (sIGOutputDir);
sint32 x, y;
x = (sint32) floor (pPoint->Point.x / fCellSize);
y = (sint32) floor (pPoint->Point.y / fCellSize);
// Does the zone (x,y) is under the patat ?
bool bZoneUnderPatat = false;
// Is a vertex of the zone in the patat ?
CVector vSquare[4];
vSquare[0].x = x * fCellSize;
vSquare[0].y = y * fCellSize;
vSquare[0].z = 0.0f;
vSquare[1].x = (x+1) * fCellSize;
vSquare[1].y = y * fCellSize;
vSquare[1].z = 0.0f;
vSquare[2].x = (x+1) * fCellSize;
vSquare[2].y = (y+1) * fCellSize;
vSquare[2].z = 0.0f;
vSquare[3].x = x * fCellSize;
vSquare[3].y = (y+1) * fCellSize;
vSquare[3].z = 0.0f;
// Is the vertex inside the zone ?
if ((pPoint->Point.x >= (x*fCellSize)) &&
(pPoint->Point.x <= ((x+1)*fCellSize)) &&
(pPoint->Point.y >= (y*fCellSize)) &&
(pPoint->Point.y <= ((y+1)*fCellSize)))
{
string sTmp = CExport::getZoneNameFromXY(x,y) + ".ig";
if (!CTools::fileExist(sTmp)) // If the file does not exist
return true; // need update
}
return false;
}
// ---------------------------------------------------------------------------
// SExportOptions
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
SExportOptions::SExportOptions ()
{
CellSize = 160.0f;
}
// ---------------------------------------------------------------------------
bool SExportOptions::loadcf (CConfigFile &cf)
{
// Out
CConfigFile::CVar &cvOutIGDir = cf.getVar("EXP_OutIGDir");
OutIGDir = cvOutIGDir.asString();
// In
CConfigFile::CVar &cvInLandscapeDir = cf.getVar("EXP_ZoneWDir");
InLandscapeDir = cvInLandscapeDir.asString();
CConfigFile::CVar &cvLandBankFile = cf.getVar("EXP_SmallBank");
LandBankFile = cvLandBankFile.asString();
CConfigFile::CVar &cvLandFarBankFile = cf.getVar("EXP_FarBank");
LandFarBankFile = cvLandFarBankFile.asString();
CConfigFile::CVar &cvLandTileNoiseDir = cf.getVar("EXP_DisplaceDir");
LandTileNoiseDir = cvLandTileNoiseDir.asString();
CConfigFile::CVar &cvCellSize = cf.getVar("EXP_CellSize");
CellSize = cvCellSize.asFloat();
CConfigFile::CVar &cvPrimFloraDir = cf.getVar("EXP_PrimFloraDir");
PrimFloraDir = cvPrimFloraDir.asString();
return true;
}
// ---------------------------------------------------------------------------
bool SExportOptions::save (FILE *f)
{
fprintf (f,"\n// Export Options\n");
fprintf (f, "EXP_OutIGDir = \"%s\";\n", OutIGDir.c_str());
fprintf (f, "EXP_ZoneWDir = \"%s\";\n", InLandscapeDir.c_str());
fprintf (f, "EXP_SmallBank = \"%s\";\n", LandBankFile.c_str());
fprintf (f, "EXP_FarBank = \"%s\";\n", LandFarBankFile.c_str());
fprintf (f, "EXP_DisplaceDir = \"%s\";\n", LandTileNoiseDir.c_str());
fprintf (f, "EXP_CellSize = %f;\n", CellSize);
fprintf (f, "EXP_PrimFloraDir = \"%s\";\n", PrimFloraDir.c_str());
return true;
}
// ---------------------------------------------------------------------------
// SExportPrimitive
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
bool SExportPrimitive::operator == (const SExportPrimitive &rRightArg)
{
if (strcmp(this->FullPrimName.c_str(), rRightArg.FullPrimName.c_str()) == 0)
if (strcmp(this->PrimitiveName.c_str(), rRightArg.PrimitiveName.c_str()) == 0)
return true;
return false;
}
// ---------------------------------------------------------------------------
// CExport
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
CExport::CExport()
{
_Landscape = NULL;
_VCM = NULL;
_VCE = NULL;
_ExportCB = NULL;
_Options = NULL;
}
// ---------------------------------------------------------------------------
CExport::~CExport()
{
if (_Landscape != NULL)
delete _Landscape;
if (_VCM != NULL)
{
_VCM->deleteEntity (_VCE);
delete _VCM;
}
}
// ---------------------------------------------------------------------------
bool CExport::newExport (SExportOptions &opt, IExportCB *expCB)
{
_ExeDir = CTools::pwd();
_Options = &opt;
_ExportCB = expCB;
string sTmp;
uint32 i, j, k, m;
// First of all read the CFG
string sContinentDir = _Options->PrimFloraDir;
sContinentDir = CTools::normalizePath (sContinentDir);
CTools::chdir (sContinentDir.c_str()); // Relative to absolute path
sContinentDir = CTools::pwd () + "\\";
CTools::chdir (_ExeDir);
// Read continent.cfg
SContinentCfg ContinentCFG;
{
string sTmp = sContinentDir + "continent.cfg";
if (!ContinentCFG.load(sTmp.c_str()))
throw Exception("Cannot load continent.cfg");
}
// Ok set parameters from options first and with CFG if no options set
if (_Options->OutIGDir == "")
_OutIGDir = CTools::normalizePath (ContinentCFG.OutIGDir);
else
_OutIGDir = CTools::normalizePath (_Options->OutIGDir);
if (_Options->LandFile == "")
_LandFile = ContinentCFG.LandFile;
else
_LandFile = _Options->LandFile;
if (_Options->DfnDir == "")
_DfnDir = ContinentCFG.DfnDir;
else
_DfnDir = _Options->DfnDir;
if (_Options->GameElemDir == "")
_GameElemDir = ContinentCFG.GameElemDir;
else
_GameElemDir = _Options->GameElemDir;
if (_Options->InLandscapeDir == "")
_InLandscapeDir = ContinentCFG.LandZoneWDir; // Directory where to get .zonew files
else
_InLandscapeDir = _Options->InLandscapeDir;
if (_Options->LandFarBankFile == "")
_LandBankFile = ContinentCFG.LandBankFile; // The .smallbank file associated with the landscape
else
_LandBankFile = _Options->LandBankFile;
if (_Options->LandFarBankFile == "")
_LandFarBankFile = ContinentCFG.LandFarBankFile; // The .farbank file
else
_LandFarBankFile = _Options->LandFarBankFile;
if (_Options->LandTileNoiseDir == "")
_LandTileNoiseDir = ContinentCFG.LandTileNoiseDir; // Directory where to get displacement map
else
_LandTileNoiseDir = _Options->LandTileNoiseDir;
// Now create output directory
CTools::mkdir (_OutIGDir);
CTools::chdir (_OutIGDir.c_str());
_OutIGDir = CTools::pwd () + "\\";
CTools::chdir (_ExeDir);
CPath::addSearchPath (_DfnDir, true, true);
CPath::addSearchPath (_GameElemDir, true, true);
CPath::addSearchPath (_LandTileNoiseDir, true, true);
// Get all regions
vector<string> vRegions;
WIN32_FIND_DATA findData;
HANDLE hFind;
CTools::chdir (sContinentDir);
hFind = FindFirstFile ("*.*", &findData);
while (hFind != INVALID_HANDLE_VALUE)
{
if (GetFileAttributes(findData.cFileName)&FILE_ATTRIBUTE_DIRECTORY)
{
// Look if the name is a system directory
bool bFound = false;
for (i = 0; i < MAX_SYS_DIR; ++i)
if (stricmp (findData.cFileName, gExportSysDir[i]) == 0)
{
bFound = true;
break;
}
if (!bFound) // No, ok lets recurse it
{
vRegions.push_back (findData.cFileName);
}
}
if (FindNextFile (hFind, &findData) == 0)
break;
}
FindClose (hFind);
// Process all regions
uint32 nRegion;
for (nRegion = 0; nRegion < vRegions.size(); ++nRegion)
{
CTools::chdir (sContinentDir + vRegions[nRegion]);
// Process if a flora has been modified
vector<SFloraToUpdate> vFloraToUpdate;
uint32 nFloraFile;
// Fill the structure for update
{
// Get all new flora of the region
vector<string> vFloraFiles;
CTools::dirSub ("*.flora", vFloraFiles, true);
for (nFloraFile = 0; nFloraFile < vFloraFiles.size(); ++nFloraFile)
{
// Compare the date with the old file stored in the IG output directory
CTools::chdir (sContinentDir + vRegions[nRegion]);
string sBaseName = vFloraFiles[nFloraFile].substr(sContinentDir.size());
sBaseName = sBaseName.substr(0,sBaseName.rfind('\\'));
for (i = 0; i < sBaseName.size(); ++i)
if (sBaseName[i] == '\\')
sBaseName[i] = '-';
sBaseName += '-';
string sOldFloraName = _OutIGDir + sBaseName + vFloraFiles[nFloraFile].substr(vFloraFiles[nFloraFile].rfind('\\')+1);
if (CTools::fileExist(sOldFloraName))
{
if (CTools::fileDateCmp(vFloraFiles[nFloraFile], sOldFloraName) > 0)
{
// Delete zones from the 2 files
SFloraToUpdate ftuTmp;
// Delete zones from the newest file
ftuTmp.FloraFile = vFloraFiles[nFloraFile];
CTools::chdir (vFloraFiles[nFloraFile].substr(0,vFloraFiles[nFloraFile].rfind('\\')));
CTools::dir ("*.prim", ftuTmp.PrimFile, true);
vFloraToUpdate.push_back (ftuTmp);
// Delete zones from the oldest file
CTools::chdir (_OutIGDir);
ftuTmp.FloraFile = sOldFloraName;
CTools::dir (sBaseName + "*.prim", ftuTmp.PrimFile, true);
vFloraToUpdate.push_back (ftuTmp);
CTools::chdir (_ExeDir);
sTmp = vFloraFiles[nFloraFile] + " has been modified.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
else
{
CTools::chdir (_ExeDir);
sTmp = vFloraFiles[nFloraFile] + string(" up to date.");
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
}
else
{
// Delete zone from newest file
SFloraToUpdate ftuTmp;
ftuTmp.FloraFile = vFloraFiles[nFloraFile];
CTools::chdir (vFloraFiles[nFloraFile].substr(0,vFloraFiles[nFloraFile].rfind('\\')));
CTools::dir ("*.prim", ftuTmp.PrimFile, true);
vFloraToUpdate.push_back (ftuTmp);
CTools::chdir (_ExeDir);
sTmp = vFloraFiles[nFloraFile] + " not generated.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
}
// Get all old flora of the current region
CTools::chdir (_OutIGDir);
CTools::dir (vRegions[nRegion] + "-*.flora", vFloraFiles, true);
for (nFloraFile = 0; nFloraFile < vFloraFiles.size(); ++nFloraFile)
{
CTools::chdir (_OutIGDir);
// if the old flora file still exist but the new one not -> delete zone for the oldest file
string sNewFloraName = vFloraFiles[nFloraFile].substr(vFloraFiles[nFloraFile].rfind('\\')+1);
string sBaseName = sNewFloraName.substr (0, vFloraFiles[nFloraFile].rfind('-'));
for (i = 0; i < sNewFloraName.size(); ++i)
if (sNewFloraName[i] == '-')
sNewFloraName[i] = '\\';
sNewFloraName = sContinentDir + sNewFloraName;
if (!CTools::fileExist(sNewFloraName))
{
SFloraToUpdate ftuTmp;
// Delete zones from the oldest file
ftuTmp.FloraFile = vFloraFiles[nFloraFile];
CTools::dir (sBaseName + "*.prim", ftuTmp.PrimFile, true);
vFloraToUpdate.push_back (ftuTmp);
CTools::chdir (_ExeDir);
sTmp = vFloraFiles[nFloraFile] + " not needed anymore.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
}
}
// End of fill the structure for update
// Interpret the FloraToUpdate
for (nFloraFile = 0; nFloraFile < vFloraToUpdate.size(); ++nFloraFile)
{
// Get all patats referenced by the flora and suppress zones under
// Load the .flora file
SFormFlora FormFlora;
{
// Get a loader
UFormLoader *loader = UFormLoader::createLoader ();
// Load the form
CSmartPtr<UForm> form = loader->loadForm (vFloraToUpdate[nFloraFile].FloraFile.c_str ());
if (form)
FormFlora.build (form->getRootNode ());
// Release the loader
UFormLoader::releaseLoader (loader);
}
// Load all the .prim files that can be referenced by the flora
vector<CPrimRegion> vPrimRegions;
{
vector<string> &rPrimFiles = vFloraToUpdate[nFloraFile].PrimFile;
for (i = 0; i < rPrimFiles.size(); ++i)
{
CPrimRegion tmpPrimRegion;
CIFile fileIn;
fileIn.open (rPrimFiles[i]);
CIXml input;
input.init (fileIn);
tmpPrimRegion.serial (input);
vPrimRegions.push_back (tmpPrimRegion);
}
}
// Delete zones under the old prims referenced by the old zone
for (i = 0; i < FormFlora.IncludePatats.size(); ++i)
{
// Get the patat
CPrimZone *pPatat = NULL;
CPrimPoint *pPoint = NULL;
CPrimPath *pPath = NULL;
for (j = 0; j < vPrimRegions.size(); ++j)
{
for (k = 0; k < vPrimRegions[j].VZones.size(); ++k)
if (vPrimRegions[j].VZones[k].getName() == FormFlora.IncludePatats[i])
pPatat = &vPrimRegions[j].VZones[k];
for (k = 0; k < vPrimRegions[j].VPoints.size(); ++k)
if (vPrimRegions[j].VPoints[k].getName() == FormFlora.IncludePatats[i])
pPoint = &vPrimRegions[j].VPoints[k];
for (k = 0; k < vPrimRegions[j].VPaths.size(); ++k)
if (vPrimRegions[j].VPaths[k].getName() == FormFlora.IncludePatats[i])
pPath = &vPrimRegions[j].VPaths[k];
}
if ((pPatat == NULL) && (pPoint == NULL) && (pPath == NULL))
{
CTools::chdir (_ExeDir);
sTmp = "WARNING : Cannot find " + FormFlora.IncludePatats[i];
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
continue;
}
if ((pPatat != NULL) && (pPatat->VPoints.size() <= 2))
{
CTools::chdir (_ExeDir);
sTmp = "Patat " + pPatat->getName() + " has less than 3 points";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
continue;
}
if ((pPath != NULL) && (pPath->VPoints.size() < 2))
{
CTools::chdir (_ExeDir);
sTmp = "Patat " + pPatat->getName() + " has less than 2 points";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
continue;
}
if (pPatat != NULL)
delAllIGZoneUnderPatat (160.0f, pPatat, _OutIGDir);
if (pPoint != NULL)
delAllIGZoneUnderPoint (160.0f, pPoint, _OutIGDir);
if (pPath != NULL)
delAllIGZoneUnderPath (160.0f, pPath, _OutIGDir);
}
}
// End of Process if a flora has been modified
// Process if a prim has been modified
// Fill the structure for update
CTools::chdir (sContinentDir + vRegions[nRegion]);
vector<SPrimToUpdate> vPrimToUpdate;
{
uint32 nPrimFile;
vector<string> vPrimFiles;
// Get all new prim of the region
CTools::dirSub ("*.prim", vPrimFiles, true);
for (nPrimFile = 0; nPrimFile < vPrimFiles.size(); ++nPrimFile)
{
CTools::chdir (sContinentDir + vRegions[nRegion]);
// Compare the date with the old file stored in the IG output directory
string sBaseName = vPrimFiles[nPrimFile].substr(sContinentDir.size());
sBaseName = sBaseName.substr(0,sBaseName.rfind('\\'));
for (i = 0; i < sBaseName.size(); ++i)
if (sBaseName[i] == '\\')
sBaseName[i] = '-';
sBaseName += '-';
string sOldPrimName = _OutIGDir + sBaseName + vPrimFiles[nPrimFile].substr(vPrimFiles[nPrimFile].rfind('\\')+1);
if (CTools::fileExist(sOldPrimName))
{
if (CTools::fileDateCmp(vPrimFiles[nPrimFile], sOldPrimName) > 0)
{
// Delete zones from the 2 files
SPrimToUpdate ptuTmp;
// Delete zones from the newest file
ptuTmp.PrimFile = vPrimFiles[nPrimFile];
CTools::chdir (vPrimFiles[nPrimFile].substr(0,vPrimFiles[nPrimFile].rfind('\\')));
CTools::dir ("*.flora", ptuTmp.FloraFile, true);
vPrimToUpdate.push_back (ptuTmp);
// Delete zones from the oldest file
CTools::chdir (_OutIGDir);
ptuTmp.PrimFile = sOldPrimName;
CTools::dir (sBaseName + "*.flora", ptuTmp.FloraFile, true);
vPrimToUpdate.push_back (ptuTmp);
CTools::chdir (_ExeDir);
sTmp = vPrimFiles[nPrimFile] + " has been modified.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
else
{
CTools::chdir (_ExeDir);
sTmp = vPrimFiles[nPrimFile] + " up to date.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
}
else
{
// Delete zone from newest file
SPrimToUpdate ptuTmp;
ptuTmp.PrimFile = vPrimFiles[nPrimFile];
CTools::chdir (vPrimFiles[nPrimFile].substr(0,vPrimFiles[nPrimFile].rfind('\\')));
CTools::dir ("*.flora", ptuTmp.FloraFile, true);
vPrimToUpdate.push_back (ptuTmp);
CTools::chdir (_ExeDir);
sTmp = vPrimFiles[nPrimFile] + " not generated.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
}
// Get all old prim of the current region
CTools::chdir (_OutIGDir);
CTools::dir (vRegions[nRegion] + "-*.prim", vPrimFiles, false);
for (nPrimFile = 0; nPrimFile < vPrimFiles.size(); ++nPrimFile)
{
CTools::chdir (_OutIGDir);
// if the old prim file still exist but the new one not -> delete zone for the oldest file
string sNewPrimName = vPrimFiles[nPrimFile].substr(vPrimFiles[nPrimFile].rfind('\\')+1);
string sBaseName = sNewPrimName.substr (0, vPrimFiles[nPrimFile].rfind('-'));
for (i = 0; i < sNewPrimName.size(); ++i)
if (sNewPrimName[i] == '-')
sNewPrimName[i] = '\\';
sNewPrimName = sContinentDir + sNewPrimName;
if (!CTools::fileExist(sNewPrimName))
{
// Delete zones from the oldest file
CPrimRegion PrimRegion;
{
CIFile fileIn;
fileIn.open (vPrimFiles[nPrimFile]);
CIXml input;
input.init (fileIn);
PrimRegion.serial (input);
}
for (j = 0; j < PrimRegion.VZones.size(); ++j)
delAllIGZoneUnderPatat (_Options->CellSize, &PrimRegion.VZones[j], _OutIGDir);
for (j = 0; j < PrimRegion.VPaths.size(); ++j)
delAllIGZoneUnderPath (_Options->CellSize, &PrimRegion.VPaths[j], _OutIGDir);
for (j = 0; j < PrimRegion.VPoints.size(); ++j)
delAllIGZoneUnderPoint (_Options->CellSize, &PrimRegion.VPoints[j], _OutIGDir);
CTools::chdir (_ExeDir);
sTmp = vPrimFiles[nPrimFile] + " not needed anymore.";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
}
}
}
// End of fill the structure for update
// Interpretation of structure for update
for (i = 0; i < vPrimToUpdate.size(); ++i)
{
// Load all the .flora file
vector<SFormFlora> vFormFloras;
for (j = 0; j < vPrimToUpdate[i].FloraFile.size(); ++j)
{
// Create the loader
UFormLoader *loader = UFormLoader::createLoader ();
// Load the form
CSmartPtr<UForm> form = loader->loadForm (vPrimToUpdate[i].FloraFile[j].c_str ());
if (form)
{
SFormFlora FormFloraTmp;
FormFloraTmp.build (form->getRootNode ());
vFormFloras.push_back (FormFloraTmp);
}
// Release the loader
UFormLoader::releaseLoader (loader);
}
// Load all the .prim files that can be referenced by the flora
CPrimRegion PrimRegion;
{
CIFile fileIn;
fileIn.open (vPrimToUpdate[i].PrimFile);
CIXml input;
input.init (fileIn);
PrimRegion.serial (input);
}
// Delete zones under the prims that has been referenced by a flora
for (j = 0; j < PrimRegion.VZones.size(); ++j)
{
// Get the patat
CPrimZone *pPatat = NULL;
// Check if the current patat is referenced by a flora
for (k = 0; k < vFormFloras.size(); ++k)
for (m = 0; m < vFormFloras[k].IncludePatats.size(); ++m)
if (PrimRegion.VZones[j].getName() == vFormFloras[k].IncludePatats[m])
pPatat = &PrimRegion.VZones[j];
if ((pPatat == NULL) || (pPatat->VPoints.size() <= 2))
{
continue;
}
delAllIGZoneUnderPatat (_Options->CellSize, pPatat, _OutIGDir);
}
for (j = 0; j < PrimRegion.VPoints.size(); ++j)
{
// Get the point
CPrimPoint *pPoint = NULL;
// Check if the current point is referenced by a flora
for (k = 0; k < vFormFloras.size(); ++k)
for (m = 0; m < vFormFloras[k].IncludePatats.size(); ++m)
if (PrimRegion.VPoints[j].getName() == vFormFloras[k].IncludePatats[m])
pPoint = &PrimRegion.VPoints[j];
delAllIGZoneUnderPoint (_Options->CellSize, pPoint, _OutIGDir);
}
for (j = 0; j < PrimRegion.VPaths.size(); ++j)
{
// Get the path
CPrimPath *pPath = NULL;
// Check if the current path is referenced by a flora
for (k = 0; k < vFormFloras.size(); ++k)
for (m = 0; m < vFormFloras[k].IncludePatats.size(); ++m)
if (PrimRegion.VPaths[j].getName() == vFormFloras[k].IncludePatats[m])
pPath = &PrimRegion.VPaths[j];
delAllIGZoneUnderPath (_Options->CellSize, pPath, _OutIGDir);
}
}
// End of Process if a prim has been modified
}
// End of process all regions
// Check all patat to export (a patat that has no zone under itself (deleted or not present))
vector<SExportPrimitive> vExportPrimitives;
vector<string> vAllPrimFiles; // All prim files of a continent
CTools::chdir (sContinentDir);
CTools::dirSub ("*.prim", vAllPrimFiles, true);
for (i = 0; i < vAllPrimFiles.size(); ++i)
{
vAllPrimFiles[i] = strlwr(vAllPrimFiles[i]);
// Load the primfile
CPrimRegion PrimRegion;
{
CIFile fileIn;
fileIn.open (vAllPrimFiles[i]);
CIXml input;
input.init (fileIn);
PrimRegion.serial (input);
}
for (j = 0; j < PrimRegion.VZones.size(); ++j)
{
// Check all zones to know if this patat must be updated
if (isPatatNeedUpdate(_Options->CellSize, &PrimRegion.VZones[j], _OutIGDir))
{
SExportPrimitive epTmp;
epTmp.FullPrimName = vAllPrimFiles[i];
epTmp.PrimitiveName = PrimRegion.VZones[j].getName();
vExportPrimitives.push_back (epTmp);
}
}
for (j = 0; j < PrimRegion.VPaths.size(); ++j)
{
// Check all pathes to know if some must be updated (if no zone under)
if (isPathNeedUpdate(_Options->CellSize, &PrimRegion.VPaths[j], _OutIGDir))
{
SExportPrimitive epTmp;
epTmp.FullPrimName = vAllPrimFiles[i];
epTmp.PrimitiveName = PrimRegion.VPaths[j].getName();
vExportPrimitives.push_back (epTmp);
}
}
for (j = 0; j < PrimRegion.VPoints.size(); ++j)
{
// Check all points to know if some must be updated (if no zone under)
if (isPointNeedUpdate(_Options->CellSize, &PrimRegion.VPoints[j], _OutIGDir))
{
SExportPrimitive epTmp;
epTmp.FullPrimName = vAllPrimFiles[i];
epTmp.PrimitiveName = PrimRegion.VPoints[j].getName();
vExportPrimitives.push_back (epTmp);
}
}
}
// Export
CTools::chdir (_ExeDir);
_Options->PrimFloraDir = sContinentDir;
sTmp = "Exporting";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
doExport (*_Options, _ExportCB, &vExportPrimitives);
// Copy new files for incremental purpose
CTools::chdir (_ExeDir);
sTmp = "Incrementing";
if (_ExportCB != NULL) _ExportCB->dispInfo (sTmp);
for (nRegion = 0; nRegion < vRegions.size(); ++nRegion)
{
CTools::chdir (sContinentDir + vRegions[nRegion]);
vector<string> vFiles;
CTools::dirSub ("*.prim", vFiles, true);
for (i = 0; i < vFiles.size(); ++i)
{
string sDst = vFiles[i].substr (sContinentDir.size());
for (j = 0; j < sDst.size(); ++j)
if (sDst[j] == '\\')
sDst[j] = '-';
sDst = _OutIGDir + sDst;
CTools::copy (sDst, vFiles[i]);
}
CTools::chdir (sContinentDir + vRegions[nRegion]);
CTools::dirSub ("*.flora", vFiles, true);
for (i = 0; i < vFiles.size(); ++i)
{
string sDst = vFiles[i].substr (sContinentDir.size());
for (j = 0; j < sDst.size(); ++j)
if (sDst[j] == '\\')
sDst[j] = '-';
sDst = _OutIGDir + sDst;
CTools::copy (sDst, vFiles[i]);
}
// -------------------------------------------------------------------
// If the new file do not exists anymore but the old file exists -> delete old file
CTools::chdir (_OutIGDir);
CTools::dir (vRegions[nRegion] + "-*.prim", vFiles, false);
for (i = 0; i < vFiles.size(); ++i)
{
// Get the name of the recent file
string sNewName = vFiles[i];
for (j = 0; j < sNewName.size(); ++j)
if (sNewName[j] == '-')
sNewName[j] = '\\';
sNewName = sContinentDir + sNewName;
if (!CTools::fileExist(sNewName))
{
// Delete the oldest file
CFile::deleteFile(vFiles[i]);
}
}
// If the new file do not exists anymore but the old file exists -> delete old file
CTools::dir (vRegions[nRegion] + "-*.flora", vFiles, false);
for (i = 0; i < vFiles.size(); ++i)
{
// Get the name of the recent file
string sNewName = vFiles[i];
for (j = 0; j < sNewName.size(); ++j)
if (sNewName[j] == '-')
sNewName[j] = '\\';
sNewName = sContinentDir + sNewName;
if (!CTools::fileExist(sNewName))
{
// Delete the oldest file
CFile::deleteFile(vFiles[i]);
}
}
}
CTools::chdir (_ExeDir);
return true;
}
// ---------------------------------------------------------------------------
bool CExport::doExport (SExportOptions &opt, IExportCB *expCB, vector<SExportPrimitive> *selection)
{
char sTmp[MAX_PATH];
GetCurrentDirectory (MAX_PATH, sTmp);
_Options = &opt;
_ExportCB = expCB;
// Does we have something to export
if ((selection != NULL) && (selection->size() == 0))
{
if (_ExportCB)
_ExportCB->dispInfo ("Nothing to export");
return true;
}
// If we want to generate flora then we have to load the landscape
uint32 i;
if (_ExportCB)
_ExportCB->dispPass ("Load Landscape");
if (_Landscape == NULL)
{
_Landscape = new CLandscape;
_Landscape->init ();
_VCM = new CVisualCollisionManager;
_VCE = _VCM->createEntity ();
_VCM->setLandscape (_Landscape);
_VCE->setSnapToRenderedTesselation (false);
try
{
CIFile bankFile (_LandBankFile);
_Landscape->TileBank.serial (bankFile);
CIFile farbankFile (_LandFarBankFile);
_Landscape->TileFarBank.serial (farbankFile);
_Landscape->TileBank.makeAllPathRelative ();
_Landscape->TileBank.setAbsPath ("");
_Landscape->TileBank.makeAllExtensionDDS ();
_Landscape->initTileBanks ();
loadLandscape (_LandFile);
}
catch (const Exception &/*e*/)
{
if (_ExportCB)
_ExportCB->dispError ("Cannot load banks files");
}
}
_FloraInsts.clear ();
if (_ExportCB)
_ExportCB->dispPass ("Generate Flora");
vector<string> allFloraFiles;
SetCurrentDirectory (_Options->PrimFloraDir.c_str());
getAllFiles (".Flora", allFloraFiles);
SetCurrentDirectory (sTmp);
for (i = 0; i < allFloraFiles.size(); ++i)
{
generateIGFromFlora (allFloraFiles[i], selection);
}
writeFloraIG (_LandFile, (selection != NULL)); // If selection != NULL then test for writing
SetCurrentDirectory (sTmp);
if (_ExportCB)
_ExportCB->dispPass ("Finished");
return true;
}
// ---------------------------------------------------------------------------
void CExport::getAllFiles (const string &ext, vector<string> &files)
{
char sCurDir[MAX_PATH];
GetCurrentDirectory (MAX_PATH, sCurDir);
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile ("*.*", &findData);
while (hFind != INVALID_HANDLE_VALUE)
{
if (!((strcmp (findData.cFileName, ".") == 0) || (strcmp (findData.cFileName, "..") == 0)))
{
if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
string sNewDir = sCurDir;
sNewDir += string("\\") + findData.cFileName;
SetCurrentDirectory (sNewDir.c_str());
getAllFiles (ext, files);
SetCurrentDirectory (sCurDir);
}
else
{
if (strlen(findData.cFileName) > strlen(ext.c_str()))
if (stricmp(&findData.cFileName[strlen(findData.cFileName)-strlen(ext.c_str())], ext.c_str()) == 0)
{
string fullName = sCurDir;
fullName += string("\\") + findData.cFileName;
fullName = strlwr (fullName);
files.push_back (fullName);
}
}
}
if (FindNextFile (hFind, &findData) == 0)
break;
}
FindClose (hFind);
SetCurrentDirectory (sCurDir);
}
// ---------------------------------------------------------------------------
bool CExport::searchFile (const std::string &plantName, std::string &dir)
{
char sCurDir[MAX_PATH];
bool bFound = false;
GetCurrentDirectory (MAX_PATH, sCurDir);
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile ("*.*", &findData);
while (hFind != INVALID_HANDLE_VALUE)
{
string filename = findData.cFileName;
filename = strlwr(filename);
if (!((filename == ".") || (filename == "..")))
{
if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
string sNewDir = sCurDir;
sNewDir += string("\\") + filename;
SetCurrentDirectory (sNewDir.c_str());
if (searchFile (plantName, dir))
{
bFound = true;
break;
}
SetCurrentDirectory (sCurDir);
}
else
{
if (strlwr(plantName) == filename)
{
dir = sCurDir;
bFound = true;
break;
}
}
}
if (FindNextFile (hFind, &findData) == 0)
break;
}
FindClose (hFind);
SetCurrentDirectory (sCurDir);
return bFound;
}
// ---------------------------------------------------------------------------
bool CExport::generateIGFromFlora (const std::string &SrcFile, std::vector<SExportPrimitive> *selection)
{
uint32 i, j, k, l, m;
if (_ExportCB)
_ExportCB->dispPass ("Generating From " + SrcFile);
// Load all .prim
vector<CPrimRegion> allPrimRegion;
vector<string> allPrimFiles;
{
char sCurDir[MAX_PATH];
GetCurrentDirectory (MAX_PATH, sCurDir);
SetCurrentDirectory (_Options->PrimFloraDir.c_str());
getAllFiles (".prim", allPrimFiles);
SetCurrentDirectory (sCurDir);
for (i = 0; i < allPrimFiles.size(); ++i)
{
try
{
CPrimRegion tmpPrimRegion;
CIFile fileIn;
fileIn.open (allPrimFiles[i]);
CIXml input;
input.init (fileIn);
tmpPrimRegion.serial (input);
allPrimRegion.push_back (tmpPrimRegion);
}
catch (const Exception &/*e*/)
{
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Cant load ") + allPrimFiles[i]);
CPrimRegion tmpPrimRegion;
allPrimRegion.push_back (tmpPrimRegion);
}
}
}
// Load the .Flora file (georges file) and load all associated .plant
SFormFlora formFlora;
map<string, SFormPlant> Plants;
{
// Create a loader
UFormLoader *loader = UFormLoader::createLoader ();
// CPath::addSearchPath (_Options->DfnDir, true, true);
// CPath::addSearchPath (_Options->GameElemDir, true, true);
// CPath::addSearchPath (_Options->LandTileNoiseDir, true, true);
// Load the form
CSmartPtr<UForm> form = loader->loadForm (SrcFile.c_str ());
if (form == NULL)
{
if (_ExportCB != NULL)
_ExportCB->dispError (string("Cant load ") + SrcFile );
}
else
{
// Read .Flora
formFlora.build (form->getRootNode ());
// Load the .plant associated
for (i = 0; i < formFlora.PlantInstances.size(); ++i)
{
const string &plantName = formFlora.PlantInstances[i].Name;
map<string, SFormPlant>::iterator it = Plants.find (plantName);
if (it != Plants.end()) // Already here ?!
continue; // Zap it
char sCurDir[MAX_PATH];
GetCurrentDirectory (MAX_PATH, sCurDir);
try
{
SetCurrentDirectory (_GameElemDir.c_str());
string dir;
if (searchFile (plantName, dir))
{
string tmpName = dir + string("\\") + plantName;
CSmartPtr<UForm> form2 = loader->loadForm (tmpName.c_str());
if (form2)
{
SFormPlant plantTmp;
plantTmp.build (form2->getRootNode ());
Plants.insert (map<string, SFormPlant>::value_type(plantName, plantTmp));
}
else
{
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Cant load ") + plantName);
}
}
else
{
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Cant load ") + plantName);
}
SetCurrentDirectory (sCurDir);
}
catch (const Exception &e)
{
SetCurrentDirectory (sCurDir);
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Cant load ") + plantName + "(" + e.what() + ")" );
}
}
}
}
// Sort PlantInstances by biggest radius first
if (formFlora.PlantInstances.size() > 1)
for (i = 0; i < (formFlora.PlantInstances.size()-1); ++i)
for (j = i+1; j < formFlora.PlantInstances.size(); ++j)
{
SPlantInstance &rPlantI = formFlora.PlantInstances[i];
SPlantInstance &rPlantJ = formFlora.PlantInstances[j];
map<string, SFormPlant>::iterator it = Plants.find (rPlantI.Name);
if (it == Plants.end())
continue;
SFormPlant &rFormPlantI = it->second;
it = Plants.find (rPlantJ.Name);
if (it == Plants.end())
continue;
SFormPlant &rFormPlantJ = it->second;
if (rFormPlantI.BoundingRadius < rFormPlantJ.BoundingRadius)
{
SPlantInstance pi = formFlora.PlantInstances[i];
formFlora.PlantInstances[i] = formFlora.PlantInstances[j];
formFlora.PlantInstances[j] = pi;
}
}
// Generating
float jitter = formFlora.JitterPos;
clamp (jitter, 0.0f, 1.0f);
srand (formFlora.RandomSeed);
for (i = 0; i < formFlora.IncludePatats.size(); ++i)
{
uint32 nCurPlant = 0;
CVector vMin, vMax;
if (_ExportCB)
_ExportCB->dispPass ("IncludePatats("+toString(i+1)+"/"+toString(formFlora.IncludePatats.size())+")");
// Get the patat
CPrimZone *pPatat = NULL;
CPrimPoint *pPoint = NULL;
CPrimPath *pPath = NULL;
// Look if this is a patat
for (j = 0; j < allPrimRegion.size(); ++j)
{
for (k = 0; k < allPrimRegion[j].VZones.size(); ++k)
{
if (allPrimRegion[j].VZones[k].getName() == formFlora.IncludePatats[i])
{
if (selection != NULL)
{
SExportPrimitive epTmp;
epTmp.FullPrimName = allPrimFiles[j];
epTmp.PrimitiveName = allPrimRegion[j].VZones[k].getName();
for (m = 0; m < selection->size(); ++m)
if (selection->operator[](m) == epTmp)
{
pPatat = &allPrimRegion[j].VZones[k];
break;
}
}
else
{
pPatat = &allPrimRegion[j].VZones[k];
}
}
}
}
//Look if this is a point
for (j = 0; j < allPrimRegion.size(); ++j)
{
for (k = 0; k < allPrimRegion[j].VPoints.size(); ++k)
{
if (allPrimRegion[j].VPoints[k].getName() == formFlora.IncludePatats[i])
{
if (selection != NULL)
{
SExportPrimitive epTmp;
epTmp.FullPrimName = allPrimFiles[j];
epTmp.PrimitiveName = allPrimRegion[j].VPoints[k].getName();
for (m = 0; m < selection->size(); ++m)
if (selection->operator[](m) == epTmp)
{
pPoint = &allPrimRegion[j].VPoints[k];
break;
}
}
else
{
pPoint = &allPrimRegion[j].VPoints[k];
}
}
}
}
//Look if this is a path
for (j = 0; j < allPrimRegion.size(); ++j)
{
for (k = 0; k < allPrimRegion[j].VPaths.size(); ++k)
{
if (allPrimRegion[j].VPaths[k].getName() == formFlora.IncludePatats[i])
{
if (selection != NULL)
{
SExportPrimitive epTmp;
epTmp.FullPrimName = allPrimFiles[j];
epTmp.PrimitiveName = allPrimRegion[j].VPaths[k].getName();
for (m = 0; m < selection->size(); ++m)
if (selection->operator[](m) == epTmp)
{
pPath = &allPrimRegion[j].VPaths[k];
break;
}
}
else
{
pPath = &allPrimRegion[j].VPaths[k];
}
}
}
}
if ((pPatat == NULL) && (pPoint == NULL) && (pPath == NULL))
{
if (selection == NULL)
if (_ExportCB)
_ExportCB->dispWarning ("Cannot find " + formFlora.IncludePatats[i]);
continue;
}
if ((pPatat != NULL) && (pPatat->VPoints.size() <= 2))
{
if (_ExportCB)
_ExportCB->dispWarning ("Patat " + pPatat->getName() + " has less than 3 points");
continue;
}
if ((pPath != NULL) && (pPath->VPoints.size() <= 1))
{
if (_ExportCB)
_ExportCB->dispWarning ("Path " + pPath->getName() + " has less than 2 points");
continue;
}
// Generate for a patat
if (pPatat != NULL)
{
vMin = vMax = pPatat->VPoints[0];
for (j = 0; j < pPatat->VPoints.size(); ++j)
{
if (vMin.x > pPatat->VPoints[j].x) vMin.x = pPatat->VPoints[j].x;
if (vMin.y > pPatat->VPoints[j].y) vMin.y = pPatat->VPoints[j].y;
if (vMin.z > pPatat->VPoints[j].z) vMin.z = pPatat->VPoints[j].z;
if (vMax.x < pPatat->VPoints[j].x) vMax.x = pPatat->VPoints[j].x;
if (vMax.y < pPatat->VPoints[j].y) vMax.y = pPatat->VPoints[j].y;
if (vMax.z < pPatat->VPoints[j].z) vMax.z = pPatat->VPoints[j].z;
}
for (j = 0; j < formFlora.PlantInstances.size(); ++j)
{
SPlantInstance &rPlant = formFlora.PlantInstances[j];
map<string, SFormPlant>::iterator it = Plants.find (rPlant.Name);
if (it == Plants.end())
{
if (_ExportCB)
_ExportCB->dispWarning ("Cannot find " + rPlant.Name);
continue;
}
SFormPlant &rFormPlant = it->second;
float squareLength = (float)sqrt (Pi*rFormPlant.BoundingRadius*rFormPlant.BoundingRadius / rPlant.Density);
uint32 nNbPlantX = 1+(int)floor ((vMax.x-vMin.x) / squareLength);
uint32 nNbPlantY = 1+(int)floor ((vMax.y-vMin.y) / squareLength);
for (l = 0; l < nNbPlantY; ++l)
for (k = 0; k < nNbPlantX; ++k)
{
if (_ExportCB)
_ExportCB->dispPassProgress (((float)(k+l*nNbPlantX))/((float)(nNbPlantX*nNbPlantY)));
bool bExists = false;
CVector pos;
float scaleTmp;
for (m = 0; m < 32; ++m)
{
pos.x = vMin.x + squareLength * k + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength;
pos.y = vMin.y + squareLength * l + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength;
pos.z = 0.0f;
scaleTmp = (formFlora.ScaleMax-formFlora.ScaleMin)*frand(1.0)+formFlora.ScaleMin;
if (pPatat->contains(pos))
{
if (isWellPlaced(pos, rPlant, rFormPlant, scaleTmp))
{
// Testt finally with the exclude patats ...
bExists = true;
for (uint32 expat = 0; expat < formFlora.ExcludePatats.size(); ++expat)
{
CPrimZone *pExPatat = NULL;
for (uint32 epj = 0; epj < allPrimRegion.size(); ++epj)
for (uint32 epk = 0; epk < allPrimRegion[epj].VZones.size(); ++epk)
if (allPrimRegion[epj].VZones[epk].getName() == formFlora.ExcludePatats[expat])
{
pExPatat = &allPrimRegion[epj].VZones[epk];
break;
}
if (pExPatat != NULL)
{
if (pExPatat->contains(pos))
{
bExists = false;
break;
}
}
}
if (bExists)
break;
}
}
}
if (!bExists)
continue;
SFloraInst vi;
vi.ShapeName = rFormPlant.Shape;
vi.PlantName = rPlant.Name;
vi.Scale = scaleTmp;
vi.Radius = rFormPlant.BoundingRadius * vi.Scale;
vi.Rot = (float)Pi * frand (1.0);
if (formFlora.PutOnWater)
{
if (pos.z < formFlora.WaterHeight)
pos.z = formFlora.WaterHeight;
}
vi.Pos = pos;
_FloraInsts.push_back (vi);
} // End of for all position of a plant x,y check if we cant put it
} // End of for all plant instances
} // End of Generate for a patat
// Generate for a point
if (pPoint != NULL)
{
// Choose a plant
float total = 0.0f;
for (j = 0; j < formFlora.PlantInstances.size(); ++j)
{
total += formFlora.PlantInstances[j].Density;
}
float posf = total * frand(1.0);
total = 0.0f;
for (j = 0; j < formFlora.PlantInstances.size(); ++j)
{
total += formFlora.PlantInstances[j].Density;
if (posf < total) break;
}
if (j == formFlora.PlantInstances.size())
j = (uint32)formFlora.PlantInstances.size()-1;
SPlantInstance &rPlant = formFlora.PlantInstances[j];
map<string, SFormPlant>::iterator it = Plants.find (rPlant.Name);
if (it == Plants.end())
{
if (_ExportCB)
_ExportCB->dispWarning ("Cannot find " + rPlant.Name);
continue;
}
SFormPlant &rFormPlant = it->second;
SFloraInst vi;
vi.ShapeName = rFormPlant.Shape;
vi.PlantName = rPlant.Name;
vi.Scale = (formFlora.ScaleMax-formFlora.ScaleMin)*frand(1.0)+formFlora.ScaleMin;
vi.Radius = rFormPlant.BoundingRadius * vi.Scale;
vi.Rot = (float)Pi * frand (1.0);
CVector pos;
pos.x = pPoint->Point.x;
pos.y = pPoint->Point.y;
pos.z = getZFromXY (pos.x, pos.y);
if (formFlora.PutOnWater)
{
if (pos.z < formFlora.WaterHeight)
pos.z = formFlora.WaterHeight;
}
vi.Pos = pos;
if (pos.z > -90000.0f)
_FloraInsts.push_back (vi);
} // End of Generate for a point
// Generate for a path
if (pPath != NULL)
{
float rLength = 0.0f; // Total length of the broken line
for (j = 0; j < pPath->VPoints.size()-1; ++j)
{
rLength += (pPath->VPoints[j]-pPath->VPoints[j+1]).norm();
}
for (j = 0; j < formFlora.PlantInstances.size(); ++j)
{
SPlantInstance &rPlant = formFlora.PlantInstances[j];
map<string, SFormPlant>::iterator it = Plants.find (rPlant.Name);
if (it == Plants.end())
{
if (_ExportCB)
_ExportCB->dispWarning ("Cannot find " + rPlant.Name);
continue;
}
SFormPlant &rFormPlant = it->second;
float squareLength = (float)(2*rFormPlant.BoundingRadius / rPlant.Density);
uint32 nNbPlant = 1+(int)floor (rLength / squareLength);
for (k = 0; k < nNbPlant; ++k)
{
if (_ExportCB)
_ExportCB->dispPassProgress (((float)(k))/((float)(nNbPlant)));
bool bExists = false;
CVector pos;
float scaleTmp;
for (m = 0; m < 32; ++m)
{
// Calculate the curviline abscisse
float curvAbs = squareLength * k + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength;
float TempLength = 0.0f;
// Convert to a real point along the curve (broken line)
for (l = 0; l < pPath->VPoints.size()-1; ++l)
{
float newSize = (pPath->VPoints[l]-pPath->VPoints[l+1]).norm();
if (curvAbs < (TempLength+newSize))
{
curvAbs -= TempLength;
break;
}
TempLength += newSize;
}
if (l == (pPath->VPoints.size()-1))
{
l = (uint32)pPath->VPoints.size()-2;
curvAbs = (pPath->VPoints[l]-pPath->VPoints[l+1]).norm();
}
// Calculate the coord
curvAbs = curvAbs / (pPath->VPoints[l]-pPath->VPoints[l+1]).norm();
pos = pPath->VPoints[l] + (pPath->VPoints[l+1]-pPath->VPoints[l])*curvAbs;
pos.z = 0.0f;
scaleTmp = (formFlora.ScaleMax-formFlora.ScaleMin)*frand(1.0)+formFlora.ScaleMin;
if (isWellPlaced(pos, rPlant, rFormPlant, scaleTmp))
{
// Test finally with the exclude patats ...
bExists = true;
for (uint32 expat = 0; expat < formFlora.ExcludePatats.size(); ++expat)
{
CPrimZone *pExPatat = NULL;
for (uint32 epj = 0; epj < allPrimRegion.size(); ++epj)
for (uint32 epk = 0; epk < allPrimRegion[epj].VZones.size(); ++epk)
if (allPrimRegion[epj].VZones[epk].getName() == formFlora.ExcludePatats[expat])
{
pExPatat = &allPrimRegion[epj].VZones[epk];
break;
}
if (pExPatat != NULL)
{
if (pExPatat->contains(pos))
{
bExists = false;
break;
}
}
}
if (bExists)
break;
}
}
if (!bExists)
continue;
SFloraInst vi;
vi.ShapeName = rFormPlant.Shape;
vi.PlantName = rPlant.Name;
vi.Scale = scaleTmp;
vi.Radius = rFormPlant.BoundingRadius * vi.Scale;
vi.Rot = (float)Pi * frand (1.0);
if (formFlora.PutOnWater)
{
if (pos.z < formFlora.WaterHeight)
pos.z = formFlora.WaterHeight;
}
vi.Pos = pos;
_FloraInsts.push_back (vi);
} // End of for all position of a plant x,y check if we cant put it
} // End of for all plant instances
} // End of Generate for a path
} // End of for all IncludePatats
return true;
}
// ---------------------------------------------------------------------------
float CExport::getZFromXY (float x, float y)
{
CVector pos = CVector(x, y, 0);
CVector normal;
float z, zmin, zmax;
// Approximate the z with patch bounding boxes
sint32 zoneX = (sint32)floor (x/_Options->CellSize);
sint32 zoneY = (sint32)floor (-y/_Options->CellSize);
sint32 zoneId = zoneY * 256 + zoneX;
CZone *pZone = _Landscape->getZone (zoneId);
if (pZone == NULL)
return -100000.0f;
CAABBoxExt bb = pZone->getZoneBB();
zmin = bb.getMin().z;
zmax = bb.getMax().z;
pos.z = zmin;
z = zmin;
while (z < zmax)
{
if (_VCE->snapToGround(pos, normal))
break;
z += CVisualCollisionEntity::BBoxRadiusZ / 2.0f; // Super sampling due to max frequency on radiosity
pos.z = z;
}
if (z >= zmax)
return -100000.0f;
return pos.z;
}
// ---------------------------------------------------------------------------
bool CExport::isWellPlaced (CVector &pos, SPlantInstance &rPI, SFormPlant &rFP, float scale)
{
uint32 i;
// Look if this Flora intersect with one of the current ones
for (i = 0; i < _FloraInsts.size(); ++i)
{
CVector temp = _FloraInsts[i].Pos - pos;
temp.z = 0.0f;
if (temp.norm() < (_FloraInsts[i].Radius + scale*rFP.BoundingRadius))
return false;
}
// Get the real Z
pos.z = getZFromXY (pos.x, pos.y);
if (pos.z < -90000.0f)
return false;
// Get some Z around to see if we can put the Flora on the ground
uint32 nNbSamples = 8; // Const to be put somewhere
vector<CVector> base;
base.resize (nNbSamples);
for (i = 0; i < nNbSamples; ++i)
{
base[i] = pos;
base[i].x += scale * rFP.CollisionRadius * cosf((2.0f*(float)Pi*i)/(float)nNbSamples);
base[i].y += scale * rFP.CollisionRadius * sinf((2.0f*(float)Pi*i)/(float)nNbSamples);
base[i].z = getZFromXY (base[i].x, base[i].y);
if (fabs(base[i].z-pos.z) > 0.8f)
return false;
}
return true;
}
// ---------------------------------------------------------------------------
void CExport::writeFloraIG (const string &LandFile, bool bTestForWriting)
{
sint32 i, j, k;
if (_FloraInsts.size() == 0)
return;
CZoneRegion zoneRegion;
CIFile inFile;
if (inFile.open (LandFile))
{
CIXml xml(true);
xml.init (inFile);
zoneRegion.serial (xml);
inFile.close();
}
else
{
nlwarning ("Can't open the file %s", LandFile.c_str());
}
// Load all zone
for (j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j)
for (i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i)
{
if ((zoneRegion.getName(i,j) == STRING_OUT_OF_BOUND) ||
(zoneRegion.getName(i,j) == STRING_UNUSED))
continue;
vector<int> vegZone;
// Take all Flora instances in the zone (i,j)
for (k = 0; k < (sint32)_FloraInsts.size(); ++k)
{
if (((i*_Options->CellSize) < _FloraInsts[k].Pos.x) && (_FloraInsts[k].Pos.x < ((i+1)*_Options->CellSize)) &&
((j*_Options->CellSize) < _FloraInsts[k].Pos.y) && (_FloraInsts[k].Pos.y < ((j+1)*_Options->CellSize)))
{
vegZone.push_back (k);
}
}
// Make the .IG
string ZoneName;
ZoneName += NLMISC::toString(-j) + "_";
ZoneName += 'a' + (i/26);
ZoneName += 'a' + (i%26);
CVector vGlobalPos = CVector (0.0f, 0.0f, 0.0f);
CInstanceGroup::TInstanceArray Instances;
vector<CCluster> Portals;
vector<CPortal> Clusters;
Instances.resize (vegZone.size());
for (k = 0; k < (sint32)vegZone.size(); ++k)
{
//vGlobalPos += _FloraInsts[vegZone[k]].Pos;
Instances[k].Pos = _FloraInsts[vegZone[k]].Pos;
Instances[k].Rot = CQuat(CVector::K, _FloraInsts[vegZone[k]].Rot);
Instances[k].Scale = CVector(_FloraInsts[vegZone[k]].Scale, _FloraInsts[vegZone[k]].Scale, _FloraInsts[vegZone[k]].Scale);
Instances[k].nParent = -1;
Instances[k].Name = _FloraInsts[vegZone[k]].ShapeName;
Instances[k].InstanceName = _FloraInsts[vegZone[k]].PlantName;
/*Instances[k].InstanceName = "Flora_"; // see if it works
Instances[k].InstanceName += ZoneName + "_";
Instances[k].InstanceName += '0' + ((k/1000)%10);
Instances[k].InstanceName += '0' + ((k/100) %10);
Instances[k].InstanceName += '0' + ((k/10) %10);
Instances[k].InstanceName += '0' + ( k %10);*/
}
// \todo trap -> look why it dont seems to work with a global positionning
//vGlobalPos /= (float)vegZone.size();
//for (k = 0; k < (sint32)vegZone.size(); ++k)
// Instances[k].Pos -= vGlobalPos;
CInstanceGroup IG;
IG.build (vGlobalPos, Instances, Portals, Clusters);
ZoneName = _OutIGDir + "\\" + ZoneName;
ZoneName += ".ig";
CIFile inFile; // If file already exists and we have selection...
if (bTestForWriting)
if (inFile.open(ZoneName))
{
inFile.close();
continue;
}
try
{
COFile outFile (ZoneName);
IG.serial (outFile);
if (_ExportCB != NULL)
_ExportCB->dispInfo (ZoneName + " generated");
}
catch (const Exception &e)
{
if (_ExportCB != NULL)
_ExportCB->dispWarning ("Cant write " + ZoneName + " (" + e.what() + ")");
}
}
}
// ---------------------------------------------------------------------------
void CExport::loadLandscape (const string &LandFile)
{
CZoneRegion zoneRegion;
CIFile inFile;
try
{
if (inFile.open (LandFile))
{
CIXml xml(true);
xml.init (inFile);
zoneRegion.serial (xml);
inFile.close();
}
else
{
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Can't open file ") + LandFile);
}
}
catch (const Exception &e)
{
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Cant load ") + LandFile + " : " + e.what());
}
// Load all zone
sint32 nTotalFile = (1 + zoneRegion.getMaxY() - zoneRegion.getMinY()) * (1 + zoneRegion.getMaxX() - zoneRegion.getMinX());
sint32 nCurrentFile = 0;
for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j)
for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i)
{
++nCurrentFile;
if (_ExportCB != NULL)
_ExportCB->dispPassProgress(((float)nCurrentFile)/((float)nTotalFile));
if ((zoneRegion.getName(i,j) == STRING_OUT_OF_BOUND) ||
(zoneRegion.getName(i,j) == STRING_UNUSED))
continue;
// Generate zone name
string ZoneName = getZoneNameFromXY (i, j);
ZoneName = _InLandscapeDir + string("\\") + ZoneName;
//if (_ExportCB != NULL)
// _ExportCB->dispInfo (string("Loading ") + ZoneName);
try
{
CZone zone;
if (!inFile.open (ZoneName + string(".zonew")))
inFile.open (ZoneName + string(".zonel"));
zone.serial (inFile);
inFile.close ();
_Landscape->addZone (zone);
}
catch(const Exception &/*e*/)
{
if (_ExportCB != NULL)
_ExportCB->dispWarning (string("Cant load ") + ZoneName + string(".zone(l,w)"));
}
if ((_ExportCB != NULL) && (_ExportCB->isCanceled()))
return;
}
}
// Public Helpers
// **************
// ---------------------------------------------------------------------------
string CExport::getZoneNameFromXY (sint32 x, sint32 y)
{
string tmp;
if ((y>0) || (y<-255) || (x<0) || (x>255))
return "NOT VALID";
tmp = toString(-y) + "_";
tmp += ('A' + (x/26));
tmp += ('A' + (x%26));
return tmp;
}
// ---------------------------------------------------------------------------
sint32 CExport::getXFromZoneName (const string &ZoneName)
{
string xStr, yStr;
uint32 i = 0;
while (ZoneName[i] != '_')
{
yStr += ZoneName[i]; ++i;
if (i == ZoneName.size())
return -1;
}
++i;
while (i < ZoneName.size())
{
xStr += ZoneName[i]; ++i;
}
return ((xStr[0] - 'A')*26 + (xStr[1] - 'A'));
}
// ---------------------------------------------------------------------------
sint32 CExport::getYFromZoneName (const string &ZoneName)
{
string xStr, yStr;
uint32 i = 0;
while (ZoneName[i] != '_')
{
yStr += ZoneName[i]; ++i;
if (i == ZoneName.size())
return 1;
}
++i;
while (i < ZoneName.size())
{
xStr += ZoneName[i]; ++i;
}
return -atoi(yStr.c_str());
}