1521 lines
38 KiB
C++
1521 lines
38 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 "stdafx.h"
|
|
|
|
#include "world_editor_doc.h"
|
|
#include "display.h"
|
|
|
|
using namespace NLLIGO;
|
|
using namespace NLMISC;
|
|
using namespace NL3D;
|
|
using namespace std;
|
|
|
|
// ***************************************************************************
|
|
// SPrimBuild
|
|
// ***************************************************************************
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// ***************************************************************************
|
|
// CBuilderLogic
|
|
// ***************************************************************************
|
|
|
|
// ---------------------------------------------------------------------------
|
|
CBuilderLogic::CBuilderLogic()
|
|
: _LogicCallback(0)
|
|
{
|
|
_ItemSelected = NULL;
|
|
_RegionSelected = -1;
|
|
_ToolsLogic = NULL;
|
|
_Display = NULL;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::setDisplay (CDisplay *pDisp)
|
|
{
|
|
_Display = pDisp;
|
|
}
|
|
|
|
|
|
void CBuilderLogic::notify()
|
|
{
|
|
if (_LogicCallback)
|
|
{
|
|
CWorldEditorDoc *doc = getDocument ();
|
|
uint primCount = doc->getNumDatabaseElement ();
|
|
for (uint i=0; i<primCount; i++)
|
|
{
|
|
_LogicCallback->onLogicChanged (i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBuilderLogic::setLogicCallback(ILogicCallback *logicCallback)
|
|
{
|
|
_LogicCallback = logicCallback;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::setToolsLogic (CToolsLogic *pTool)
|
|
{
|
|
_ToolsLogic = pTool;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::uninit()
|
|
{
|
|
_Display = NULL;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::updateToolsLogic ()
|
|
{
|
|
notify();
|
|
// Regenerate the toolsLogic with the data in the region
|
|
if (_ToolsLogic == NULL)
|
|
return;
|
|
|
|
_ToolsLogic->reset();
|
|
uint32 i, j;
|
|
sint32 tempItem = -1;
|
|
for (j = 0; j < getDocument ()->getNumDatabaseElement (); ++j)
|
|
{
|
|
const CPrimRegion &rRegion = getDocument ()->getPrimRegion (j);
|
|
sint32 nReg = j;
|
|
|
|
map<string,uint32> mapGroups;
|
|
map<string,uint32>::iterator itGroups;
|
|
|
|
// Create Regions
|
|
nReg = _ToolsLogic->createNewRegion (rRegion.Name);
|
|
|
|
// Create Groups
|
|
for (i = 0; i < rRegion.VPoints.size(); ++i)
|
|
{
|
|
itGroups = mapGroups.find(rRegion.VPoints[i].LayerName);
|
|
if (itGroups == mapGroups.end())
|
|
{
|
|
uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VPoints[i].LayerName);
|
|
mapGroups.insert (make_pair(rRegion.VPoints[i].LayerName, nGroup));
|
|
}
|
|
}
|
|
for (i = 0; i < rRegion.VPaths.size(); ++i)
|
|
{
|
|
itGroups = mapGroups.find(rRegion.VPaths[i].LayerName);
|
|
if (itGroups == mapGroups.end())
|
|
{
|
|
uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VPaths[i].LayerName);
|
|
mapGroups.insert (make_pair(rRegion.VPaths[i].LayerName, nGroup));
|
|
}
|
|
}
|
|
for (i = 0; i < rRegion.VZones.size(); ++i)
|
|
{
|
|
itGroups = mapGroups.find(rRegion.VZones[i].LayerName);
|
|
if (itGroups == mapGroups.end())
|
|
{
|
|
uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VZones[i].LayerName);
|
|
mapGroups.insert (make_pair(rRegion.VZones[i].LayerName, nGroup));
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < rRegion.VPoints.size(); ++i)
|
|
{
|
|
HTREEITEM newItem = (HTREEITEM)tempItem;
|
|
tempItem--;
|
|
itGroups = mapGroups.find(rRegion.VPoints[i].LayerName);
|
|
if (itGroups != mapGroups.end())
|
|
if (rRegion.VPoints[i].Name != "-- Delete Me --")
|
|
{
|
|
newItem = _ToolsLogic->addPoint (nReg, itGroups->second, rRegion.VPoints[i].Name.c_str(), rRegion.VHidePoints[i]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < rRegion.VPaths.size(); ++i)
|
|
{
|
|
HTREEITEM newItem = (HTREEITEM)tempItem;
|
|
tempItem--;
|
|
itGroups = mapGroups.find(rRegion.VPaths[i].LayerName);
|
|
if (itGroups != mapGroups.end())
|
|
if (rRegion.VPaths[i].Name != "-- Delete Me --")
|
|
{
|
|
newItem = _ToolsLogic->addPath (nReg, itGroups->second, rRegion.VPaths[i].Name.c_str(), rRegion.VHidePaths[i]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < rRegion.VZones.size(); ++i)
|
|
{
|
|
HTREEITEM newItem = (HTREEITEM)tempItem;
|
|
tempItem--;
|
|
itGroups = mapGroups.find(rRegion.VZones[i].LayerName);
|
|
if (itGroups != mapGroups.end())
|
|
if (rRegion.VZones[i].Name != "-- Delete Me --")
|
|
{
|
|
newItem = _ToolsLogic->addZone (nReg, itGroups->second, rRegion.VZones[i].Name.c_str(), rRegion.VHideZones[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
_VerticesSelected.resize (0);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
const string &CBuilderLogic::getZoneRegionName (uint32 nPos)
|
|
{
|
|
return _PRegions[nPos]->Name;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::move (const string ®Name, float x, float y)
|
|
{
|
|
uint32 i, j, k;
|
|
|
|
for (i = 0; i < _PRegions.size(); ++i)
|
|
if (_PRegions[i]->Name == regName)
|
|
{
|
|
_MustAskSaves[i] = true;
|
|
for (j = 0; j < _PRegions[i]->VPoints.size(); ++j)
|
|
{
|
|
_PRegions[i]->VPoints[j].Point.x += x;
|
|
_PRegions[i]->VPoints[j].Point.y += y;
|
|
}
|
|
|
|
for (j = 0; j < _PRegions[i]->VPaths.size(); ++j)
|
|
{
|
|
for (k = 0; k < _PRegions[i]->VPaths[j].VPoints.size(); ++k)
|
|
{
|
|
_PRegions[i]->VPaths[j].VPoints[k].x += x;
|
|
_PRegions[i]->VPaths[j].VPoints[k].y += y;
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < _PRegions[i]->VZones.size(); ++j)
|
|
{
|
|
for (k = 0; k < _PRegions[i]->VZones[j].VPoints.size(); ++k)
|
|
{
|
|
_PRegions[i]->VZones[j].VPoints[k].x += x;
|
|
_PRegions[i]->VZones[j].VPoints[k].y += y;
|
|
}
|
|
}
|
|
notify();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void CBuilderLogic::insertPoint (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName)
|
|
{
|
|
|
|
CPrimPointEditor pp;
|
|
pp.LayerName = LayerName;
|
|
pp.Name = Name;
|
|
pp.Point = CVector(0.0f, 0.0f, 0.0f);
|
|
_PRegions[pos]->VPoints.push_back (pp);
|
|
_PRegions[pos]->VHidePoints.push_back (false);
|
|
SPrimBuild pB;
|
|
pB.Type = 0; // Point
|
|
pB.Pos = _PRegions[pos]->VPoints.size()-1;
|
|
pB.PRegion = _PRegions[pos];
|
|
_Primitives.insert (map<HTREEITEM, SPrimBuild>::value_type(item, pB));
|
|
_MustAskSaves[pos] = true;
|
|
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::insertPath (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName)
|
|
{
|
|
|
|
CPrimPathEditor pp;
|
|
pp.LayerName = LayerName;
|
|
pp.Name = Name;
|
|
_PRegions[pos]->VPaths.push_back (pp);
|
|
_PRegions[pos]->VHidePaths.push_back (false);
|
|
SPrimBuild pB;
|
|
pB.Type = 1; // Path
|
|
pB.Pos = _PRegions[pos]->VPaths.size()-1;
|
|
pB.PRegion = _PRegions[pos];
|
|
_Primitives.insert (map<HTREEITEM, SPrimBuild>::value_type(item, pB));
|
|
_MustAskSaves[pos] = true;
|
|
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::insertZone (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName)
|
|
{
|
|
CPrimZoneEditor pz;
|
|
pz.LayerName = LayerName;
|
|
pz.Name = Name;
|
|
_PRegions[pos]->VZones.push_back (pz);
|
|
_PRegions[pos]->VHideZones.push_back (false);
|
|
SPrimBuild pB;
|
|
pB.Type = 2; // Zone
|
|
pB.Pos = _PRegions[pos]->VZones.size()-1;
|
|
pB.PRegion = _PRegions[pos];
|
|
_Primitives.insert (map<HTREEITEM, SPrimBuild>::value_type(item, pB));
|
|
_MustAskSaves[pos] = true;
|
|
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::del (HTREEITEM item)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
|
|
if (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
// Delete the entry in the document
|
|
|
|
|
|
// Delete in the region
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
{
|
|
PRegion.VPoints.erase (PRegion.VPoints.begin()+rPB.Pos);
|
|
PRegion.VHidePoints.erase (PRegion.VHidePoints.begin()+rPB.Pos);
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
PRegion.VPaths.erase (PRegion.VPaths.begin()+rPB.Pos);
|
|
PRegion.VHidePaths.erase (PRegion.VHidePaths.begin()+rPB.Pos);
|
|
}
|
|
break;
|
|
case 2:
|
|
PRegion.VZones.erase (PRegion.VZones.begin()+rPB.Pos);
|
|
PRegion.VHideZones.erase (PRegion.VHideZones.begin()+rPB.Pos);
|
|
break;
|
|
}
|
|
// Update position
|
|
map<HTREEITEM, SPrimBuild>::iterator it2 = _Primitives.begin ();
|
|
while (it2 != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB2 = it2->second;
|
|
|
|
if ((rPB2.PRegion == rPB.PRegion)&&(rPB2.Type == rPB.Type))
|
|
if (rPB2.Pos > rPB.Pos)
|
|
rPB2.Pos -= 1;
|
|
|
|
++it2;
|
|
}
|
|
// Delete the entry in the map
|
|
_Primitives.erase (it);
|
|
|
|
for (uint32 z = 0; z < _PRegions.size(); ++z)
|
|
if (_PRegions[z] == &PRegion)
|
|
{
|
|
_MustAskSaves[z] = true;
|
|
break;
|
|
}
|
|
}
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::primHide (HTREEITEM item)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
rPB.hidden = true;
|
|
if (rPB.Type == 0) // Points
|
|
{
|
|
rPB.PRegion->VHidePoints[rPB.Pos] = true;
|
|
}
|
|
else if (rPB.Type == 1) // Paths
|
|
{
|
|
rPB.PRegion->VHidePaths[rPB.Pos] = true;
|
|
}
|
|
else if (rPB.Type == 2) /// Zones
|
|
{
|
|
rPB.PRegion->VHideZones[rPB.Pos] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::primUnhide (HTREEITEM item)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
rPB.hidden = false;
|
|
if (rPB.Type == 0) // Points
|
|
{
|
|
rPB.PRegion->VHidePoints[rPB.Pos] = false;
|
|
}
|
|
else if (rPB.Type == 1) // Paths
|
|
{
|
|
rPB.PRegion->VHidePaths[rPB.Pos] = false;
|
|
}
|
|
else if (rPB.Type == 2) /// Zones
|
|
{
|
|
rPB.PRegion->VHideZones[rPB.Pos] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::hideAll (uint32 nPos, sint32 nID, bool bHide)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
|
|
if (rPB.PRegion == _PRegions[nPos])
|
|
{
|
|
if (rPB.Type == nID)
|
|
{
|
|
rPB.hidden = bHide;
|
|
if (rPB.Type == 0) // Points
|
|
{
|
|
rPB.PRegion->VHidePoints[rPB.Pos] = bHide;
|
|
}
|
|
else if (rPB.Type == 1) // Paths
|
|
{
|
|
rPB.PRegion->VHidePaths[rPB.Pos] = bHide;
|
|
}
|
|
else if (rPB.Type == 2) /// Zones
|
|
{
|
|
rPB.PRegion->VHideZones[rPB.Pos] = bHide;
|
|
}
|
|
}
|
|
}
|
|
|
|
++it;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::regionSetName (uint32 nPos, HTREEITEM item, const string &sRegionName)
|
|
{
|
|
CPrimRegion &rPR = *_PRegions[nPos];
|
|
rPR.Name = sRegionName;
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::regionCreateGroup (uint32 nPos, HTREEITEM newItem, const string &sGroupName)
|
|
{
|
|
insertPoint (nPos, (HTREEITEM)-1, "-- Delete Me --", sGroupName.c_str());
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::regionDeleteGroup (uint32 nPos, const std::string &sGroupName)
|
|
{
|
|
sint32 i, j;
|
|
for (i = 0; i < (sint32)_PRegions[nPos]->VPoints.size(); ++i)
|
|
{
|
|
if (_PRegions[nPos]->VPoints[i].LayerName == sGroupName)
|
|
{
|
|
for (j = i+1; j < (sint32)_PRegions[nPos]->VPoints.size(); ++j)
|
|
_PRegions[nPos]->VPoints[j-1] = _PRegions[nPos]->VPoints[j];
|
|
_PRegions[nPos]->VPoints.resize (_PRegions[nPos]->VPoints.size()-1);
|
|
i = -1;
|
|
}
|
|
}
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::regionHideAll (uint32 nPos, bool bHide)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
|
|
if (rPB.PRegion == _PRegions[nPos])
|
|
rPB.hidden = bHide;
|
|
|
|
++it;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::regionHideType (uint32 nPos, const string &Type, bool bHide)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
|
|
if (rPB.PRegion == _PRegions[nPos])
|
|
{
|
|
string Name, Tmp;
|
|
switch (rPB.Type)
|
|
{
|
|
case 0: Name = _PRegions[nPos]->VPoints[rPB.Pos].Name; break;
|
|
case 1: Name = _PRegions[nPos]->VPaths[rPB.Pos].Name; break;
|
|
case 2: Name = _PRegions[nPos]->VZones[rPB.Pos].Name; break;
|
|
}
|
|
|
|
uint32 i = 0;
|
|
while (Name[i] != '-') ++i;
|
|
i++;
|
|
while ((Name[i] != '-') && (i < Name.size()))
|
|
{
|
|
Tmp += Name[i];
|
|
++i;
|
|
}
|
|
if (Tmp == Type)
|
|
rPB.hidden = bHide;
|
|
}
|
|
|
|
++it;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
int CBuilderLogic::getMaxPostfix (const char *prefix)
|
|
{
|
|
int nTmp;
|
|
int nZeMax = -1;
|
|
int nPFLen = strlen(prefix);
|
|
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
nTmp = 0;
|
|
switch (rPB.Type)
|
|
{
|
|
case 0: // Point
|
|
if (strncmp(prefix, rPB.PRegion->VPoints[rPB.Pos].Name.c_str(), nPFLen) == 0)
|
|
{
|
|
CPrimPointEditor &rP = rPB.PRegion->VPoints[rPB.Pos];
|
|
if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') &&
|
|
(rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') &&
|
|
(rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9'))
|
|
{
|
|
nTmp = (rP.Name[nPFLen+0] - '0')*100;
|
|
nTmp += (rP.Name[nPFLen+1] - '0')*10;
|
|
nTmp += (rP.Name[nPFLen+2] - '0')*1;
|
|
}
|
|
}
|
|
break;
|
|
case 1: // Path
|
|
if (strncmp(prefix, rPB.PRegion->VPaths[rPB.Pos].Name.c_str(), nPFLen) == 0)
|
|
{
|
|
CPrimPathEditor &rP = rPB.PRegion->VPaths[rPB.Pos];
|
|
if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') &&
|
|
(rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') &&
|
|
(rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9'))
|
|
{
|
|
nTmp = (rP.Name[nPFLen+0] - '0')*100;
|
|
nTmp += (rP.Name[nPFLen+1] - '0')*10;
|
|
nTmp += (rP.Name[nPFLen+2] - '0')*1;
|
|
}
|
|
}
|
|
break;
|
|
case 2: // Zone
|
|
if (strncmp(prefix, rPB.PRegion->VZones[rPB.Pos].Name.c_str(), nPFLen) == 0)
|
|
{
|
|
CPrimZoneEditor &rP = rPB.PRegion->VZones[rPB.Pos];
|
|
if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') &&
|
|
(rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') &&
|
|
(rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9'))
|
|
{
|
|
nTmp = (rP.Name[nPFLen+0] - '0')*100;
|
|
nTmp += (rP.Name[nPFLen+1] - '0')*10;
|
|
nTmp += (rP.Name[nPFLen+2] - '0')*1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (nZeMax < nTmp)
|
|
nZeMax = nTmp;
|
|
|
|
++it;
|
|
}
|
|
|
|
return nZeMax;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
bool CBuilderLogic::isAlreadyExisting (const char *sPrimitiveName)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0: // Point
|
|
if (strcmp(sPrimitiveName, rPB.PRegion->VPoints[rPB.Pos].Name.c_str()) == 0)
|
|
return true;
|
|
break;
|
|
case 1: // Path
|
|
if (strcmp(sPrimitiveName, rPB.PRegion->VPaths[rPB.Pos].Name.c_str()) == 0)
|
|
return true;
|
|
break;
|
|
case 2: // Zone
|
|
if (strcmp(sPrimitiveName, rPB.PRegion->VZones[rPB.Pos].Name.c_str()) == 0)
|
|
return true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
const char* CBuilderLogic::getName (HTREEITEM item)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it == _Primitives.end())
|
|
return NULL;
|
|
else
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
return PRegion.VPoints[rPB.Pos].Name.c_str();
|
|
break;
|
|
case 1:
|
|
return PRegion.VPaths[rPB.Pos].Name.c_str();
|
|
break;
|
|
case 2:
|
|
return PRegion.VZones[rPB.Pos].Name.c_str();
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
const char* CBuilderLogic::getLayerName (HTREEITEM item)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it == _Primitives.end())
|
|
return NULL;
|
|
else
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
return PRegion.VPoints[rPB.Pos].LayerName.c_str();
|
|
break;
|
|
case 1:
|
|
return PRegion.VPaths[rPB.Pos].LayerName.c_str();
|
|
break;
|
|
case 2:
|
|
return PRegion.VZones[rPB.Pos].LayerName.c_str();
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::getAllPrimZoneNames (vector<string> &allNames)
|
|
{
|
|
allNames.clear ();
|
|
for (uint32 i = 0; i < _PRegions.size(); ++i)
|
|
for (uint32 j = 0; j < _PRegions[i]->VZones.size(); ++j)
|
|
allNames.push_back (_PRegions[i]->VZones[j].Name);
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
bool CBuilderLogic::isHidden (HTREEITEM item)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it == _Primitives.end())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
return rPB.hidden;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::setName (HTREEITEM item, const char* pStr)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
else
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
PRegion.VPoints[rPB.Pos].Name = pStr;
|
|
break;
|
|
case 1:
|
|
PRegion.VPaths[rPB.Pos].Name = pStr;
|
|
break;
|
|
case 2:
|
|
PRegion.VZones[rPB.Pos].Name = pStr;
|
|
break;
|
|
}
|
|
|
|
for (uint32 z = 0; z < _PRegions.size(); ++z)
|
|
if (_PRegions[z] == &PRegion)
|
|
{
|
|
_MustAskSaves[z] = true;
|
|
break;
|
|
}
|
|
|
|
}
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::setLayerName (HTREEITEM item, const char* pStr)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
else
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
PRegion.VPoints[rPB.Pos].LayerName = pStr;
|
|
break;
|
|
case 1:
|
|
PRegion.VPaths[rPB.Pos].LayerName = pStr;
|
|
break;
|
|
case 2:
|
|
PRegion.VZones[rPB.Pos].LayerName = pStr;
|
|
break;
|
|
}
|
|
|
|
for (uint32 z = 0; z < _PRegions.size(); ++z)
|
|
if (_PRegions[z] == &PRegion)
|
|
{
|
|
_MustAskSaves[z] = true;
|
|
break;
|
|
}
|
|
}
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
HTREEITEM CBuilderLogic::getSelPB ()
|
|
{
|
|
return _ItemSelected;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
std::string CBuilderLogic::getSelPBName ()
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it != _Primitives.end())
|
|
{
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0: return PRegion.VPoints[rPB.Pos].Name;
|
|
case 1: return PRegion.VPaths[rPB.Pos].Name;
|
|
case 2: return PRegion.VZones[rPB.Pos].Name;
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::setSelPB (HTREEITEM item)
|
|
{
|
|
_VerticesSelected.clear ();
|
|
_ItemSelected = NULL;
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (item);
|
|
if (it != _Primitives.end())
|
|
{
|
|
_ItemSelected = item;
|
|
_ItemSelectedName = getName(_ItemSelected);
|
|
_ToolsLogic->GetTreeCtrl()->Select(item, TVGN_CARET);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::createVertexOnSelPB (CVector &v, sint32 atPos)
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
if (!rPB.Created)
|
|
{
|
|
PRegion.VPoints[rPB.Pos].Point = v;
|
|
rPB.Created = true;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (!rPB.Created)
|
|
{
|
|
rPB.Created = true;
|
|
}
|
|
if (atPos != -1)
|
|
{
|
|
PRegion.VPaths[rPB.Pos].VPoints.insert (PRegion.VPaths[rPB.Pos].VPoints.begin()+atPos, v);
|
|
}
|
|
else
|
|
{
|
|
PRegion.VPaths[rPB.Pos].VPoints.push_back(v);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!rPB.Created)
|
|
{
|
|
rPB.Created = true;
|
|
}
|
|
if (atPos != -1)
|
|
{
|
|
PRegion.VZones[rPB.Pos].VPoints.insert (PRegion.VZones[rPB.Pos].VPoints.begin()+atPos, v);
|
|
}
|
|
else
|
|
{
|
|
PRegion.VZones[rPB.Pos].VPoints.push_back(v);
|
|
}
|
|
break;
|
|
}
|
|
for (uint32 z = 0; z < _PRegions.size(); ++z)
|
|
if (_PRegions[z] == &PRegion)
|
|
{
|
|
_MustAskSaves[z] = true;
|
|
break;
|
|
}
|
|
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
bool CBuilderLogic::selectVerticesOnSelPB (CVector &selMin, CVector &selMax)
|
|
{
|
|
_VerticesSelected.clear ();
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it == _Primitives.end())
|
|
return false;
|
|
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
if (!rPB.Created)
|
|
return false;
|
|
|
|
CPrimVector *pV = NULL;
|
|
uint32 nNbV = 0;
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
nNbV = 1;
|
|
pV = &(PRegion.VPoints[rPB.Pos].Point);
|
|
break;
|
|
case 1:
|
|
nNbV = PRegion.VPaths[rPB.Pos].VPoints.size();
|
|
pV = &(PRegion.VPaths[rPB.Pos].VPoints[0]);
|
|
break;
|
|
case 2:
|
|
nNbV = PRegion.VZones[rPB.Pos].VPoints.size();
|
|
pV = &(PRegion.VZones[rPB.Pos].VPoints[0]);
|
|
break;
|
|
}
|
|
float selMinX = min(selMin.x, selMax.x);
|
|
float selMinY = min(selMin.y, selMax.y);
|
|
float selMaxX = max(selMin.x, selMax.x);
|
|
float selMaxY = max(selMin.y, selMax.y);
|
|
|
|
for (uint32 i = 0; i < nNbV; ++i)
|
|
{
|
|
if ((pV[i].x > selMinX) && (pV[i].x < selMaxX) &&
|
|
(pV[i].y > selMinY) && (pV[i].y < selMaxY))
|
|
{
|
|
_VerticesSelected.push_back (i);
|
|
}
|
|
}
|
|
if (_VerticesSelected.size() == 0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::createIsoVertexOnSelVertexOnSelPB ()
|
|
{
|
|
if ((_VerticesSelected.size() <= 1) || (_ItemSelected == NULL))
|
|
return;
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
CVector v(0.0f, 0.0f, 0.0f);
|
|
|
|
sint minvs = 30000;
|
|
for (uint32 i = 0; i < _VerticesSelected.size(); ++i)
|
|
{
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
v += PRegion.VPoints[rPB.Pos].Point;
|
|
break;
|
|
case 1:
|
|
v += PRegion.VPaths[rPB.Pos].VPoints[_VerticesSelected[i]];
|
|
break;
|
|
case 2:
|
|
v += PRegion.VZones[rPB.Pos].VPoints[_VerticesSelected[i]];
|
|
break;
|
|
}
|
|
if (_VerticesSelected[i] < minvs)
|
|
minvs = _VerticesSelected[i];
|
|
}
|
|
v /= (float)_VerticesSelected.size();
|
|
|
|
if (rPB.Type == 2)
|
|
{
|
|
CPrimZoneEditor &pz = PRegion.VZones[rPB.Pos];
|
|
if (((_VerticesSelected[0] == 0) && (_VerticesSelected[1] == ((sint32)pz.VPoints.size()-1))) ||
|
|
((_VerticesSelected[0] == ((sint32)pz.VPoints.size()-1)) && (_VerticesSelected[1] == 0)))
|
|
{
|
|
createVertexOnSelPB (v, 0);
|
|
}
|
|
else
|
|
{
|
|
createVertexOnSelPB (v, minvs+1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
createVertexOnSelPB (v, minvs+1);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
bool CBuilderLogic::isSelection()
|
|
{
|
|
return (_VerticesSelected.size() > 0);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::setSelVerticesOnSelPB (NLMISC::CVector &v)
|
|
{
|
|
if ((_VerticesSelected.size() == 0) || (_ItemSelected == NULL))
|
|
return;
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
for (uint32 i = 0; i < _VerticesSelected.size(); ++i)
|
|
{
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
PRegion.VPoints[rPB.Pos].Point += v;
|
|
break;
|
|
case 1:
|
|
PRegion.VPaths[rPB.Pos].VPoints[_VerticesSelected[i]] += v;
|
|
break;
|
|
case 2:
|
|
PRegion.VZones[rPB.Pos].VPoints[_VerticesSelected[i]] += v;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (uint32 z = 0; z < _PRegions.size(); ++z)
|
|
if (_PRegions[z] == &PRegion)
|
|
{
|
|
_MustAskSaves[z] = true;
|
|
break;
|
|
}
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::delSelVerticesOnSelPB ()
|
|
{
|
|
if ((_VerticesSelected.size() == 0) || (_ItemSelected == NULL))
|
|
return;
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
|
|
uint32 i;
|
|
for (uint32 k = 0; k < _VerticesSelected.size(); ++k)
|
|
{
|
|
int VertexSelected = _VerticesSelected[k];
|
|
switch (rPB.Type)
|
|
{
|
|
case 0:
|
|
rPB.Created = false;
|
|
break;
|
|
case 1:
|
|
if (PRegion.VPaths[rPB.Pos].VPoints.size() == 1)
|
|
rPB.Created = false;
|
|
|
|
for (i = VertexSelected+1; i < PRegion.VPaths[rPB.Pos].VPoints.size(); ++i)
|
|
PRegion.VPaths[rPB.Pos].VPoints[i-1] = PRegion.VPaths[rPB.Pos].VPoints[i];
|
|
PRegion.VPaths[rPB.Pos].VPoints.resize (PRegion.VPaths[rPB.Pos].VPoints.size()-1);
|
|
break;
|
|
case 2:
|
|
if (PRegion.VZones[rPB.Pos].VPoints.size() == 1)
|
|
rPB.Created = false;
|
|
|
|
for (i = VertexSelected+1; i < PRegion.VZones[rPB.Pos].VPoints.size(); ++i)
|
|
PRegion.VZones[rPB.Pos].VPoints[i-1] = PRegion.VZones[rPB.Pos].VPoints[i];
|
|
PRegion.VZones[rPB.Pos].VPoints.resize (PRegion.VZones[rPB.Pos].VPoints.size()-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (uint32 z = 0; z < _PRegions.size(); ++z)
|
|
if (_PRegions[z] == &PRegion)
|
|
{
|
|
_MustAskSaves[z] = true;
|
|
break;
|
|
}
|
|
|
|
notify();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::stackSelPB ()
|
|
{
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.find (_ItemSelected);
|
|
if (it == _Primitives.end())
|
|
return;
|
|
SPrimBuild &rPB = it->second;
|
|
CPrimRegion &PRegion = *rPB.PRegion;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
string CBuilderLogic::getZonesNameAt (CVector &v)
|
|
{
|
|
string ret;
|
|
for (uint32 i = 0; i < _PRegions.size(); ++i)
|
|
{
|
|
for (uint32 j = 0; j < _PRegions[i]->VZones.size(); ++j)
|
|
{
|
|
CPrimZoneEditor *pz = &_PRegions[i]->VZones[j];
|
|
|
|
// Find if the patat is visible
|
|
bool bHidden = true;
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
if ((it->second.Type == 2) && ((sint32)j == it->second.Pos))
|
|
{
|
|
if (it->second.hidden)
|
|
bHidden = true;
|
|
else
|
|
bHidden = false;
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
if ((!bHidden) && (pz->contains(v)))
|
|
{
|
|
if (ret.size() == 0)
|
|
{
|
|
ret += pz->Name;
|
|
}
|
|
else
|
|
{
|
|
ret += ", " + pz->Name;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::selectZoneAt (NLMISC::CVector &v)
|
|
{
|
|
vector<string> zonelist;
|
|
uint32 i, j;
|
|
|
|
for (i = 0; i < _PRegions.size(); ++i)
|
|
{
|
|
for (j = 0; j < _PRegions[i]->VZones.size(); ++j)
|
|
{
|
|
CPrimZoneEditor *pz = &_PRegions[i]->VZones[j];
|
|
// Find if the patat is visible
|
|
bool bHidden = true;
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
if ((it->second.Type == 2) && ((sint32)j == it->second.Pos))
|
|
{
|
|
if (it->second.hidden)
|
|
bHidden = true;
|
|
else
|
|
bHidden = false;
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
|
|
if ((!bHidden) && (pz->contains(v)))
|
|
{
|
|
zonelist.push_back (pz->Name);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (zonelist.size() == 0)
|
|
return;
|
|
|
|
string sSelPB = getSelPBName();
|
|
for (i = 0; i < zonelist.size(); ++i)
|
|
{
|
|
if (zonelist[i] == sSelPB)
|
|
break;
|
|
}
|
|
|
|
if (i == zonelist.size())
|
|
i = 0;
|
|
else
|
|
i = (i+1)%zonelist.size();
|
|
sSelPB = zonelist[i];
|
|
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin ();
|
|
while (it != _Primitives.end())
|
|
{
|
|
if (sSelPB == getName(it->first))
|
|
{
|
|
setSelPB (it->first);
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
CRGBA CBuilderLogic::findColor(const string &Name) // region-type-001
|
|
{
|
|
// Get the type from the name
|
|
string sType;
|
|
uint32 i = 0;
|
|
while (i < Name.size())
|
|
{
|
|
if (Name[i]=='-') break;
|
|
++i;
|
|
}
|
|
if (i == Name.size())
|
|
return CRGBA (255, 255, 255, 255);
|
|
++i;
|
|
while (i < Name.size())
|
|
{
|
|
if (Name[i]=='-') break;
|
|
sType += Name[i];
|
|
++i;
|
|
}
|
|
if (i == Name.size())
|
|
return CRGBA (255, 255, 255, 255);
|
|
|
|
vector<SType> &rTypes = _Display->_MainFrame->_Environnement.Types;
|
|
for (i = 0; i < rTypes.size(); ++i)
|
|
if (sType == rTypes[i].Name)
|
|
return rTypes[i].Color;
|
|
|
|
return CRGBA (255, 255, 255, 255);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::render (CVector &viewMin, CVector &viewMax)
|
|
{
|
|
if (DontUse3D)
|
|
return;
|
|
// Accelerate rendering with vertex buffer
|
|
CVertexBuffer VB;
|
|
CPrimitiveBlock PB;
|
|
CVertexBuffer VBL;
|
|
CPrimitiveBlock PBL;
|
|
CMaterial Mat;
|
|
|
|
CRGBA colSel = CRGBA(255, 0, 0, 192);
|
|
|
|
Mat.initUnlit ();
|
|
Mat.setSrcBlend(CMaterial::srcalpha);
|
|
Mat.setDstBlend(CMaterial::invsrcalpha);
|
|
Mat.setBlend (true);
|
|
Mat.setColor (CRGBA(255, 255, 255, 192));
|
|
VB.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag);
|
|
VBL.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag);
|
|
|
|
// Parse the map
|
|
map<HTREEITEM, SPrimBuild>::iterator it = _Primitives.begin();
|
|
while (it != _Primitives.end())
|
|
{
|
|
HTREEITEM curItem = it->first;
|
|
SPrimBuild &curPB = it->second;
|
|
CPrimRegion &PRegion = *curPB.PRegion;
|
|
|
|
CRGBA col;
|
|
uint32 i;
|
|
|
|
// If not created do not display or hidden
|
|
if ((!curPB.Created)||(curPB.hidden))
|
|
{
|
|
++it;
|
|
continue;
|
|
}
|
|
|
|
CPrimVector *pVec = NULL;
|
|
uint32 nNbVec = 0;
|
|
|
|
// Clip
|
|
|
|
if (curPB.Type == 0) // Point
|
|
{
|
|
col = findColor (PRegion.VPoints[curPB.Pos].Name);
|
|
pVec = &PRegion.VPoints[curPB.Pos].Point;
|
|
nNbVec = 1;
|
|
}
|
|
|
|
if (curPB.Type == 1) // Path
|
|
{
|
|
col = findColor (PRegion.VPaths[curPB.Pos].Name);
|
|
nNbVec = PRegion.VPaths[curPB.Pos].VPoints.size();
|
|
if (nNbVec > 0)
|
|
pVec = &PRegion.VPaths[curPB.Pos].VPoints[0];
|
|
}
|
|
|
|
if (curPB.Type == 2) // Zone
|
|
{
|
|
col = findColor (PRegion.VZones[curPB.Pos].Name);
|
|
nNbVec = PRegion.VZones[curPB.Pos].VPoints.size();
|
|
if (nNbVec > 0)
|
|
pVec = &PRegion.VZones[curPB.Pos].VPoints[0];
|
|
}
|
|
|
|
col.A = 192;
|
|
|
|
if (nNbVec == 0)
|
|
{
|
|
++it;
|
|
continue;
|
|
}
|
|
|
|
if (clip(pVec, nNbVec, viewMin, viewMax))
|
|
{
|
|
++it;
|
|
continue;
|
|
}
|
|
|
|
|
|
// Draw all interiors
|
|
|
|
if (curPB.Type == 2) // For Zones
|
|
{
|
|
vector<sint32> vRef;
|
|
uint32 nStart, VBStart = VB.getNumVertices(), PBStart = PB.getNumTri();
|
|
vRef.resize(nNbVec);
|
|
for(i = 0; i < vRef.size(); ++i)
|
|
vRef[i] = i;
|
|
|
|
nStart = 0;
|
|
while (vRef.size() > 2)
|
|
{
|
|
// Is triangle (nStart, nStart+1, nStart+2) back face ?
|
|
sint32 nP1 = vRef[nStart];
|
|
sint32 nP2 = vRef[(nStart+1)%vRef.size()];
|
|
sint32 nP3 = vRef[(nStart+2)%vRef.size()];
|
|
CVector pos1 = pVec[nP1];
|
|
CVector pos2 = pVec[nP2];
|
|
CVector pos3 = pVec[nP3];
|
|
if (((pos2.x-pos1.x) * (pos3.y-pos1.y) - (pos2.y-pos1.y) * (pos3.x-pos1.x)) < 0.0f)
|
|
{
|
|
// Yes -> next triangle
|
|
nStart++;
|
|
//nlassert(nStart != vRef.size());
|
|
if (nStart == vRef.size())
|
|
{
|
|
VB.setNumVertices (VBStart);
|
|
PB.setNumTri(PBStart);
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
// Is triangle (nStart, nStart+1, nStart+2) contains the other point ?
|
|
bool bInside = false;
|
|
for (i = 0; i < vRef.size(); ++i)
|
|
{
|
|
if ((vRef[i] != nP1) && (vRef[i] != nP2) && (vRef[i] != nP3))
|
|
{
|
|
if (isInTriangleOrEdge( pVec[vRef[i]].x, pVec[vRef[i]].y,
|
|
pos1.x, pos1.y,
|
|
pos2.x, pos2.y,
|
|
pos3.x, pos3.y ))
|
|
{
|
|
bInside = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (bInside)
|
|
{
|
|
// Yes -> next triangle
|
|
nStart++;
|
|
//nlassert(nStart != vRef.size());
|
|
if (nStart == vRef.size())
|
|
{
|
|
VB.setNumVertices (VBStart);
|
|
PB.setNumTri(PBStart);
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Draw the triangle
|
|
convertToScreen (&pos1, 1, viewMin, viewMax);
|
|
convertToScreen (&pos2, 1, viewMin, viewMax);
|
|
convertToScreen (&pos3, 1, viewMin, viewMax);
|
|
if (curItem == _ItemSelected)
|
|
renderDrawTriangle(pos1, pos2, pos3, colSel, &VB, &PB);
|
|
else
|
|
renderDrawTriangle(pos1, pos2, pos3, col, &VB, &PB);
|
|
|
|
// Erase the point in the middle
|
|
for (i = 1+((nStart+1)%vRef.size()); i < vRef.size(); ++i)
|
|
vRef[i-1] = vRef[i];
|
|
vRef.resize (vRef.size()-1);
|
|
nStart = 0;
|
|
}
|
|
}
|
|
|
|
// Draw all lines
|
|
|
|
if ((curPB.Type == 1) || (curPB.Type == 2)) // For Pathes and Zones
|
|
{
|
|
uint32 nNbLineToDraw = (curPB.Type == 2)?(nNbVec):(nNbVec-1);
|
|
if ((nNbLineToDraw == 1)&&(curPB.Type == 2))
|
|
nNbLineToDraw = 0;
|
|
for (i = 0; i < nNbLineToDraw; ++i)
|
|
{
|
|
CVector pos = pVec[i];
|
|
CVector pos2 = pVec[(i+1)%(nNbVec)];
|
|
|
|
convertToScreen (&pos, 1, viewMin, viewMax);
|
|
convertToScreen (&pos2, 1, viewMin, viewMax);
|
|
if (curItem == _ItemSelected)
|
|
renderDrawLine (pos, pos2, colSel, &VBL, &PBL);
|
|
else
|
|
renderDrawLine (pos, pos2, col, &VBL, &PBL);
|
|
}
|
|
}
|
|
|
|
// Draw all points
|
|
bool bDrawPoints = true;
|
|
|
|
if (curPB.Type == 2) // Zone
|
|
if (curItem != _ItemSelected)
|
|
bDrawPoints = false; // Do not draw the points on zone other than selected one
|
|
|
|
if (bDrawPoints)
|
|
for (i = 0; i < nNbVec; ++i) // For Points, Pathes and Zones
|
|
{
|
|
CVector pos = pVec[i];
|
|
convertToScreen (&pos, 1, viewMin, viewMax);
|
|
if (curItem == _ItemSelected)
|
|
{
|
|
bool bFound = false;
|
|
for (uint32 k = 0; k < _VerticesSelected.size(); ++k)
|
|
if (_VerticesSelected[k] == (sint32)i)
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
if (bFound)
|
|
renderDrawPoint (pos, colSel, &VBL, &PBL);
|
|
else
|
|
renderDrawPoint (pos, col, &VBL, &PBL);
|
|
}
|
|
else
|
|
{
|
|
renderDrawPoint (pos, col, &VBL, &PBL);
|
|
}
|
|
}
|
|
|
|
++it;
|
|
}
|
|
|
|
// Flush the Vertex Buffer
|
|
|
|
CMatrix mtx;
|
|
mtx.identity();
|
|
CNELU::Driver->setupViewport (CViewport());
|
|
CNELU::Driver->setupViewMatrix (mtx);
|
|
CNELU::Driver->setupModelMatrix (mtx);
|
|
CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
|
|
CNELU::Driver->activeVertexBuffer(VB);
|
|
CNELU::Driver->render(PB, Mat);
|
|
CNELU::Driver->activeVertexBuffer(VBL);
|
|
CNELU::Driver->render(PBL, Mat);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::renderDrawPoint (CVector &pos, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB)
|
|
{
|
|
if (DontUse3D)
|
|
return;
|
|
|
|
if (pVB == NULL)
|
|
{
|
|
CDRU::drawLine (pos.x-0.01f, pos.y, pos.x+0.01f, pos.y, *CNELU::Driver, col);
|
|
CDRU::drawLine (pos.x, pos.y-0.01f, pos.x, pos.y+0.01f, *CNELU::Driver, col);
|
|
}
|
|
else
|
|
{
|
|
sint32 nVBPos = pVB->getNumVertices();
|
|
pVB->setNumVertices (nVBPos+4);
|
|
pVB->setVertexCoord (nVBPos+0, pos.x-0.01f, pos.z, pos.y);
|
|
pVB->setVertexCoord (nVBPos+1, pos.x+0.01f, pos.z, pos.y);
|
|
pVB->setVertexCoord (nVBPos+2, pos.x, pos.z, pos.y-0.01f);
|
|
pVB->setVertexCoord (nVBPos+3, pos.x, pos.z, pos.y+0.01f);
|
|
pVB->setColor (nVBPos+0, col);
|
|
pVB->setColor (nVBPos+1, col);
|
|
pVB->setColor (nVBPos+2, col);
|
|
pVB->setColor (nVBPos+3, col);
|
|
sint32 nPBPos = pPB->getNumLine();
|
|
pPB->setNumLine (nPBPos+2);
|
|
pPB->setLine (nPBPos+0, nVBPos+0, nVBPos+1);
|
|
pPB->setLine (nPBPos+1, nVBPos+2, nVBPos+3);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::renderDrawLine (CVector &pos, CVector &pos2, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB)
|
|
{
|
|
sint32 nVBPos = pVB->getNumVertices();
|
|
pVB->setNumVertices (nVBPos+2);
|
|
pVB->setVertexCoord (nVBPos+0, pos.x, pos.z, pos.y);
|
|
pVB->setVertexCoord (nVBPos+1, pos2.x, pos2.z, pos2.y);
|
|
pVB->setColor (nVBPos+0, col);
|
|
pVB->setColor (nVBPos+1, col);
|
|
sint32 nPBPos = pPB->getNumLine();
|
|
pPB->setNumLine (nPBPos+1);
|
|
pPB->setLine (nPBPos+0, nVBPos+0, nVBPos+1);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::renderDrawTriangle (CVector &pos, CVector &pos2, CVector &pos3, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB)
|
|
{
|
|
sint32 nVBPos = pVB->getNumVertices();
|
|
pVB->setNumVertices (nVBPos+3);
|
|
pVB->setVertexCoord (nVBPos+0, pos.x, pos.z, pos.y);
|
|
pVB->setVertexCoord (nVBPos+1, pos2.x, pos2.z, pos2.y);
|
|
pVB->setVertexCoord (nVBPos+2, pos3.x, pos3.z, pos3.y);
|
|
pVB->setColor (nVBPos+0, col);
|
|
pVB->setColor (nVBPos+1, col);
|
|
pVB->setColor (nVBPos+2, col);
|
|
sint32 nPBPos = pPB->getNumTri();
|
|
pPB->setNumTri (nPBPos+1);
|
|
pPB->setTri (nPBPos+0, nVBPos+0, nVBPos+1, nVBPos+2);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
bool CBuilderLogic::clip (CPrimVector *pVec, uint32 nNbVec, CVector &viewMin, CVector &viewMax)
|
|
{
|
|
uint32 i;
|
|
for (i = 0; i < nNbVec; ++i)
|
|
if (pVec[i].x > viewMin.x)
|
|
break;
|
|
if (i == nNbVec)
|
|
return true; // Entirely clipped
|
|
|
|
for (i = 0; i < nNbVec; ++i)
|
|
if (pVec[i].x < viewMax.x)
|
|
break;
|
|
if (i == nNbVec)
|
|
return true;
|
|
|
|
for (i = 0; i < nNbVec; ++i)
|
|
if (pVec[i].y > viewMin.y)
|
|
break;
|
|
if (i == nNbVec)
|
|
return true;
|
|
|
|
for (i = 0; i < nNbVec; ++i)
|
|
if (pVec[i].y < viewMax.y)
|
|
break;
|
|
if (i == nNbVec)
|
|
return true;
|
|
return false; // Not entirely clipped
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
void CBuilderLogic::convertToScreen (CVector* pVec, sint nNbVec, CVector &viewMin, CVector &viewMax)
|
|
{
|
|
for (sint i = 0; i < nNbVec; ++i)
|
|
{
|
|
pVec[i].x = (pVec[i].x-viewMin.x)/(viewMax.x-viewMin.x);
|
|
pVec[i].y = (pVec[i].y-viewMin.y)/(viewMax.y-viewMin.y);
|
|
pVec[i].z = 0.0f;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
bool CBuilderLogic::isInTriangleOrEdge( double x, double y,
|
|
double xt1, double yt1,
|
|
double xt2, double yt2,
|
|
double xt3, double yt3 )
|
|
{
|
|
// Test vector T1X and T1T2
|
|
double sign1 = ((xt2-xt1)*(y-yt1) - (yt2-yt1)*(x-xt1));
|
|
// Test vector T2X and T2T3
|
|
double sign2 = ((xt3-xt2)*(y-yt2) - (yt3-yt2)*(x-xt2));
|
|
// Test vector T3X and T3T1
|
|
double sign3 = ((xt1-xt3)*(y-yt3) - (yt1-yt3)*(x-xt3));
|
|
if( (sign1 <= 0.0)&&(sign2 <= 0.0)&&(sign3 <= 0.0) )
|
|
return true;
|
|
if( (sign1 >= 0.0)&&(sign2 >= 0.0)&&(sign3 >= 0.0) )
|
|
return true;
|
|
return false;
|
|
}
|