00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "nel/misc/types_nl.h"
00025 #include "nel/misc/hierarchical_timer.h"
00026 #include "nel/ligo/primitive.h"
00027 #include "nel/ligo/ligo_config.h"
00028 #include "nel/ligo/primitive_class.h"
00029 #include "nel/misc/i_xml.h"
00030 #include "nel/misc/path.h"
00031
00032 using namespace NLMISC;
00033 using namespace std;
00034
00035 const uint32 NLLIGO_PRIMITIVE_VERSION = 1;
00036
00037 namespace NLLIGO
00038 {
00039
00040 CPrimitiveContext *CPrimitiveContext::_Instance = NULL;
00041
00042
00043
00044
00045
00046
00047 void Error (const char *filename, const char *format, ...)
00048 {
00049 va_list args;
00050 va_start( args, format );
00051 char buffer[1024];
00052 vsnprintf( buffer, 1024, format, args );
00053 va_end( args );
00054
00055 nlwarning ("In File (%s) %s", filename, buffer);
00056 }
00057
00058
00059
00060 void XMLError (xmlNodePtr xmlNode, const char *filename, const char *format, ... )
00061 {
00062 va_list args;
00063 va_start( args, format );
00064 char buffer[1024];
00065 vsnprintf( buffer, 1024, format, args );
00066 va_end( args );
00067
00068 Error (filename, "node (%s), line (%d) : %s", xmlNode->name, (ptrdiff_t)xmlNode->content, buffer);
00069 }
00070
00071
00072
00073
00074 xmlNodePtr GetFirstChildNode (xmlNodePtr xmlNode, const char *filename, const char *childName)
00075 {
00076
00077 xmlNodePtr result = CIXml::getFirstChildNode (xmlNode, childName);
00078 if (result) return result;
00079
00080
00081 XMLError (xmlNode, filename, "Can't find XML node named (%s)", childName);
00082 return NULL;
00083 }
00084
00085
00086
00087 bool GetPropertyString (string &result, const char *filename, xmlNodePtr xmlNode, const char *propName)
00088 {
00089
00090 if (!CIXml::getPropertyString (result, xmlNode, propName))
00091 {
00092
00093 XMLError (xmlNode, filename, "Can't find XML node property (%s)", propName);
00094 return false;
00095 }
00096 return true;
00097 }
00098
00099
00100
00101 bool ReadInt (const char *propName, int &result, const char *filename, xmlNodePtr xmlNode)
00102 {
00103 string value;
00104 if (GetPropertyString (value, filename, xmlNode, propName))
00105 {
00106 result = atoi (value.c_str ());
00107 return true;
00108 }
00109 return false;
00110 }
00111
00112
00113
00114 void WriteInt (const char *propName, int value, xmlNodePtr xmlNode)
00115 {
00116
00117 xmlSetProp (xmlNode, (const xmlChar*)propName, (const xmlChar*)(toString (value).c_str ()));
00118 }
00119
00120
00121
00122 bool ReadUInt (const char *propName, uint &result, const char *filename, xmlNodePtr xmlNode)
00123 {
00124 string value;
00125 if (GetPropertyString (value, filename, xmlNode, propName))
00126 {
00127 result = strtoul (value.c_str (), NULL, 10);
00128 return true;
00129 }
00130 return false;
00131 }
00132
00133
00134
00135 void WriteUInt (const char *propName, uint value, xmlNodePtr xmlNode)
00136 {
00137
00138 xmlSetProp (xmlNode, (const xmlChar*)propName, (const xmlChar*)(toString (value).c_str ()));
00139 }
00140
00141
00142
00143 bool ReadFloat (const char *propName, float &result, const char *filename, xmlNodePtr xmlNode)
00144 {
00145 string value;
00146 if (GetPropertyString (value, filename, xmlNode, propName))
00147 {
00148 result = (float)atof (value.c_str ());
00149 return true;
00150 }
00151 return false;
00152 }
00153
00154
00155
00156 void WriteFloat (const char *propName, float value, xmlNodePtr xmlNode)
00157 {
00158
00159 xmlSetProp (xmlNode, (const xmlChar*)propName, (const xmlChar*)(toString (value).c_str ()));
00160 }
00161
00162
00163
00164 bool ReadVector (CPrimVector &point, const char *filename, xmlNodePtr xmlNode)
00165 {
00166 CPrimVector pos;
00167 if (ReadFloat ("X", pos.x, filename, xmlNode))
00168 {
00169 if (ReadFloat ("Y", pos.y, filename, xmlNode))
00170 {
00171 if (ReadFloat ("Z", pos.z, filename, xmlNode))
00172 {
00173 pos.Selected = false;
00174 string result;
00175 if (CIXml::getPropertyString (result, xmlNode, "SELECTED"))
00176 {
00177 if (result == "true")
00178 pos.Selected = true;
00179 }
00180 point = pos;
00181 return true;
00182 }
00183 }
00184 }
00185 return false;
00186 }
00187
00188
00189
00190 void WriteVector (const CPrimVector &point, xmlNodePtr xmlNode)
00191 {
00192
00193 xmlSetProp (xmlNode, (const xmlChar*)"X", (const xmlChar*)(toString (point.x).c_str ()));
00194 xmlSetProp (xmlNode, (const xmlChar*)"Y", (const xmlChar*)(toString (point.y).c_str ()));
00195 xmlSetProp (xmlNode, (const xmlChar*)"Z", (const xmlChar*)(toString (point.z).c_str ()));
00196 if (point.Selected)
00197 xmlSetProp (xmlNode, (const xmlChar*)"SELECTED", (const xmlChar*)"true");
00198 }
00199
00200
00201
00202
00203 bool GetNodeString (string &result, const char *filename, xmlNodePtr xmlNode, const char *nodeName)
00204 {
00205
00206 xmlNodePtr node = CIXml::getFirstChildNode (xmlNode, nodeName);
00207 if (!node)
00208 {
00209 XMLError (xmlNode, filename, "Can't find XML node named (%s)", nodeName);
00210 return false;
00211 }
00212
00213
00214 if (!CIXml::getContentString (result, node))
00215 {
00216 XMLError (xmlNode, filename, "Can't find any text in the node named (%s)", nodeName);
00217 return false;
00218 }
00219
00220 return true;
00221 }
00222
00223
00224
00225 bool GetContentString (string &result, const char *filename, xmlNodePtr xmlNode)
00226 {
00227
00228 if (!CIXml::getContentString (result, xmlNode))
00229 {
00230 XMLError (xmlNode, filename, "Can't find any text in the node");
00231 return false;
00232 }
00233
00234 return true;
00235 }
00236
00237
00238
00239
00240
00241 CPropertyString::CPropertyString (const char *str)
00242 {
00243 String = str;
00244 }
00245
00246 CPropertyString::CPropertyString (const std::string &str)
00247 {
00248 String = str;
00249 }
00250
00251
00252
00253 CPropertyString::CPropertyString (const char *str, bool _default)
00254 {
00255 String = str;
00256 Default = _default;
00257 }
00258
00259
00260
00261
00262
00263 CPropertyStringArray::CPropertyStringArray (const std::vector<std::string> &stringArray)
00264 {
00265 StringArray = stringArray;
00266 }
00267
00268
00269
00270 CPropertyStringArray::CPropertyStringArray (const std::vector<std::string> &stringArray, bool _default)
00271 {
00272 StringArray = stringArray;
00273 Default = _default;
00274 }
00275
00276
00277
00278 void CPrimPoint::serial (NLMISC::IStream &f)
00279 {
00280
00281 IPrimitive::serial(f);
00282 f.serial(Point);
00283 f.serial(Angle);
00284 }
00285
00286
00287 void CPrimPath::serial (NLMISC::IStream &f)
00288 {
00289 IPrimitive::serial(f);
00290 f.serialCont(VPoints);
00291 }
00292
00293
00294
00295 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<CPrimVector> &points)
00296 {
00297 uint32 i;
00298 CVector vMin, vMax;
00299
00300
00301 if (points.size() < 3)
00302 return false;
00303
00304
00305 vMax = vMin = points[0];
00306 for (i = 0; i < points.size(); ++i)
00307 {
00308 if (vMin.x > points[i].x)
00309 vMin.x = points[i].x;
00310 if (vMin.y > points[i].y)
00311 vMin.y = points[i].y;
00312
00313 if (vMax.x < points[i].x)
00314 vMax.x = points[i].x;
00315 if (vMax.y < points[i].y)
00316 vMax.y = points[i].y;
00317 }
00318
00319 if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00320 return false;
00321
00322 uint32 nNbIntersection = 0;
00323 for (i = 0; i < points.size(); ++i)
00324 {
00325 const CVector &p1 = points[i];
00326 const CVector &p2 = points[(i+1)%points.size()];
00327
00328 if (((p1.y-v.y) <= 0.0)&&((p2.y-v.y) <= 0.0))
00329 continue;
00330 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00331 continue;
00332 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00333 if (xinter > v.x)
00334 ++nNbIntersection;
00335 }
00336 if ((nNbIntersection&1) == 1)
00337 return true;
00338 else
00339 return false;
00340 }
00341
00342
00343
00344 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<NLMISC::CVector> &points)
00345 {
00346 uint32 i;
00347 CVector vMin, vMax;
00348
00349
00350 if (points.size() < 3)
00351 return false;
00352
00353
00354 vMax = vMin = points[0];
00355 for (i = 0; i < points.size(); ++i)
00356 {
00357 if (vMin.x > points[i].x)
00358 vMin.x = points[i].x;
00359 if (vMin.y > points[i].y)
00360 vMin.y = points[i].y;
00361
00362 if (vMax.x < points[i].x)
00363 vMax.x = points[i].x;
00364 if (vMax.y < points[i].y)
00365 vMax.y = points[i].y;
00366 }
00367
00368 if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00369 return false;
00370
00371 uint32 nNbIntersection = 0;
00372 for (i = 0; i < points.size(); ++i)
00373 {
00374 const CVector &p1 = points[i];
00375 const CVector &p2 = points[(i+1)%points.size()];
00376
00377 if (((p1.y-v.y) <= 0.0)&&((p2.y-v.y) <= 0.0))
00378 continue;
00379 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00380 continue;
00381 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00382 if (xinter > v.x)
00383 ++nNbIntersection;
00384 }
00385 if ((nNbIntersection&1) == 1)
00386 return true;
00387 else
00388 return false;
00389 }
00390
00391
00392
00393
00394
00395 bool CPrimNode::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config)
00396 {
00397 return IPrimitive::read (xmlNode, filename, version, config);
00398 }
00399
00400
00401
00402 uint CPrimNode::getNumVector () const
00403 {
00404 return 0;
00405 }
00406
00407
00408
00409 const CPrimVector *CPrimNode::getPrimVector () const
00410 {
00411 return NULL;
00412 }
00413
00414
00415
00416 CPrimVector *CPrimNode::getPrimVector ()
00417 {
00418 return NULL;
00419 }
00420
00421
00422
00423 NLLIGO::IPrimitive *CPrimNode::copy () const
00424 {
00425 return new CPrimNode (*this);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 uint CPrimPoint::getNumVector () const
00466 {
00467 return 1;
00468 }
00469
00470
00471
00472 const CPrimVector *CPrimPoint::getPrimVector () const
00473 {
00474 return &Point;
00475 }
00476
00477
00478
00479 CPrimVector *CPrimPoint::getPrimVector ()
00480 {
00481 return &Point;
00482 }
00483
00484
00485
00486 NLLIGO::IPrimitive *CPrimPoint::copy () const
00487 {
00488 return new CPrimPoint (*this);
00489 }
00490
00491
00492
00493 bool CPrimPoint::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config)
00494 {
00495
00496 xmlNodePtr ptNode = GetFirstChildNode (xmlNode, filename, "PT");
00497 if (ptNode)
00498 {
00499
00500 if (!ReadVector (Point, filename, ptNode))
00501 return false;
00502
00503 ptNode = CIXml::getFirstChildNode (xmlNode, "ANGLE");
00504 if (ptNode)
00505 {
00506
00507 if (!ReadFloat ("VALUE", Angle, filename, ptNode))
00508 return false;
00509 }
00510 else
00511 Angle = 0;
00512 }
00513 else
00514 {
00515 return false;
00516 }
00517
00518 return IPrimitive::read (xmlNode, filename, version, config);
00519 }
00520
00521
00522
00523 void CPrimPoint::write (xmlNodePtr xmlNode, const char *filename) const
00524 {
00525
00526 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PT", NULL);
00527 WriteVector (Point, ptNode);
00528
00529
00530 if (Angle != 0)
00531 {
00532 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"ANGLE", NULL);
00533 WriteFloat ("VALUE", Angle, ptNode);
00534 }
00535
00536 IPrimitive::write (xmlNode, filename);
00537 }
00538
00539
00540
00541
00542
00543 uint CPrimPath::getNumVector () const
00544 {
00545 return VPoints.size ();
00546 }
00547
00548
00549
00550 const CPrimVector *CPrimPath::getPrimVector () const
00551 {
00552 if (VPoints.empty())
00553 return NULL;
00554 return &(VPoints[0]);
00555 }
00556
00557
00558
00559 NLLIGO::IPrimitive *CPrimPath::copy () const
00560 {
00561 return new CPrimPath (*this);
00562 }
00563
00564
00565
00566 CPrimVector *CPrimPath::getPrimVector ()
00567 {
00568 if (VPoints.empty())
00569 return NULL;
00570 return &(VPoints[0]);
00571 }
00572
00573
00574
00575 bool CPrimPath::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config)
00576 {
00577
00578 VPoints.clear ();
00579 VPoints.reserve (CIXml::countChildren (xmlNode, "PT"));
00580 xmlNodePtr ptNode = CIXml::getFirstChildNode (xmlNode, "PT");
00581 if (ptNode)
00582 {
00583 do
00584 {
00585
00586 VPoints.push_back (CPrimVector ());
00587 if (!ReadVector (VPoints.back (), filename, ptNode))
00588 return false;
00589
00590 ptNode = CIXml::getNextChildNode (ptNode, "PT");
00591 }
00592 while (ptNode);
00593 }
00594
00595 return IPrimitive::read (xmlNode, filename, version, config);
00596 }
00597
00598
00599
00600 void CPrimPath::write (xmlNodePtr xmlNode, const char *filename) const
00601 {
00602
00603 for (uint i=0; i<VPoints.size (); i++)
00604 {
00605 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PT", NULL);
00606 WriteVector (VPoints[i], ptNode);
00607 }
00608
00609 IPrimitive::write (xmlNode, filename);
00610 }
00611
00612
00613
00614
00615
00616 uint CPrimZone::getNumVector () const
00617 {
00618 return VPoints.size ();
00619 }
00620
00621
00622
00623 const CPrimVector *CPrimZone::getPrimVector () const
00624 {
00625 if (VPoints.empty())
00626 return NULL;
00627 return &(VPoints[0]);
00628 }
00629
00630
00631
00632 NLLIGO::IPrimitive *CPrimZone::copy () const
00633 {
00634 return new CPrimZone (*this);
00635 }
00636
00637
00638
00639 CPrimVector *CPrimZone::getPrimVector ()
00640 {
00641 if(VPoints.empty()) return 0;
00642 return &(VPoints[0]);
00643 }
00644
00645
00646
00647 bool CPrimZone::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config)
00648 {
00649
00650 VPoints.clear ();
00651 VPoints.reserve (CIXml::countChildren (xmlNode, "PT"));
00652 xmlNodePtr ptNode = CIXml::getFirstChildNode (xmlNode, "PT");
00653 if (ptNode)
00654 {
00655 do
00656 {
00657
00658 VPoints.push_back (CPrimVector ());
00659 if (!ReadVector (VPoints.back (), filename, ptNode))
00660 return false;
00661
00662 ptNode = CIXml::getNextChildNode (ptNode, "PT");
00663 }
00664 while (ptNode);
00665 }
00666
00667 return IPrimitive::read (xmlNode, filename, version, config);
00668 }
00669
00670
00671
00672 void CPrimZone::write (xmlNodePtr xmlNode, const char *filename) const
00673 {
00674
00675 for (uint i=0; i<VPoints.size (); i++)
00676 {
00677 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PT", NULL);
00678 WriteVector (VPoints[i], ptNode);
00679 }
00680
00681 IPrimitive::write (xmlNode, filename);
00682 }
00683
00684
00685
00686 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<CPrimVector> &points, float &distance, NLMISC::CVector &nearPos, bool isPath)
00687 {
00688 H_AUTO(NLLIGO_Contains1)
00689 uint32 i;
00690 CVector vMin, vMax;
00691 float nearest = FLT_MAX;
00692 CVector pos;
00693
00694
00695 if (points.size() < 3 || isPath)
00696 {
00697
00698 if (points.size() == 1)
00699 {
00700 distance = (points[0] - v).norm();
00701 nearPos = points[0];
00702 }
00703 else if (points.size() == 2)
00704 {
00705 distance = getSegmentDist(v, points[0], points[1], nearPos);
00706 }
00707 else
00708 {
00709
00710 for (i = 0; i < points.size()-1; ++i)
00711 {
00712 const CVector &p1 = points[i];
00713 const CVector &p2 = points[i+1];
00714
00715 float dist = getSegmentDist(v, p1, p2, pos);
00716 if( dist < nearest)
00717 {
00718 nearest = dist;
00719 nearPos = pos;
00720 }
00721 }
00722 distance = nearest;
00723 }
00724 return false;
00725 }
00726
00727
00728 vMax = vMin = points[0];
00729 for (i = 0; i < points.size(); ++i)
00730 {
00731 vMin.x = min(vMin.x, points[i].x);
00732 vMin.y = min(vMin.y, points[i].y);
00733 vMax.x = max(vMax.x, points[i].x);
00734 vMax.y = max(vMax.y, points[i].y);
00735 }
00736
00737 if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00738 {
00739
00740 for (uint i=0; i<points.size(); ++i)
00741 {
00742 float dist = getSegmentDist(v, points[i], points[(i+1) % points.size()], pos);
00743
00744 if (dist < nearest)
00745 {
00746 nearest = dist;
00747 nearPos = pos;
00748 }
00749 }
00750 distance = nearest;
00751 return false;
00752 }
00753
00754 uint32 nNbIntersection = 0;
00755 for (i = 0; i < points.size(); ++i)
00756 {
00757 const CVector &p1 = points[i];
00758 const CVector &p2 = points[(i+1)%points.size()];
00759
00760 float dist = getSegmentDist(v, p1, p2, pos);
00761 if( dist < nearest)
00762 {
00763 nearest = dist;
00764 nearPos = pos;
00765 }
00766
00767 if (((p1.y-v.y) <= 0.0)&&((p2.y-v.y) <= 0.0))
00768 continue;
00769 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00770 continue;
00771 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00772 if (xinter > v.x)
00773 ++nNbIntersection;
00774 }
00775
00776 distance = nearest;
00777 if ((nNbIntersection&1) == 1)
00778 return true;
00779 else
00780 return false;
00781 }
00782
00783
00784
00785 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<CVector> &points, float &distance, NLMISC::CVector &nearPos, bool isPath)
00786 {
00787 H_AUTO(NLLIGO_Contains2)
00788 uint32 i;
00789 CVector vMin, vMax;
00790 float nearest = FLT_MAX;
00791 CVector pos;
00792
00793
00794 if (points.size() < 3 || isPath)
00795 {
00796
00797 if (points.size() == 1)
00798 {
00799 distance = (points[0] - v).norm();
00800 nearPos = points[0];
00801 }
00802 else if (points.size() == 2)
00803 {
00804 distance = getSegmentDist(v, points[0], points[1], nearPos);
00805 }
00806 else
00807 {
00808
00809 for (i = 0; i < points.size()-1; ++i)
00810 {
00811 const CVector &p1 = points[i];
00812 const CVector &p2 = points[i+1];
00813
00814 float dist = getSegmentDist(v, p1, p2, pos);
00815 if( dist < nearest)
00816 {
00817 nearest = dist;
00818 nearPos = pos;
00819 }
00820 }
00821 distance = nearest;
00822 }
00823 return false;
00824 }
00825
00826
00827 vMax = vMin = points[0];
00828 for (i = 0; i < points.size(); ++i)
00829 {
00830 vMin.x = min(vMin.x, points[i].x);
00831 vMin.y = min(vMin.y, points[i].y);
00832 vMax.x = max(vMax.x, points[i].x);
00833 vMax.y = max(vMax.y, points[i].y);
00834 }
00835
00836 if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00837 {
00838
00839 for (uint i=0; i<points.size(); ++i)
00840 {
00841 float dist = getSegmentDist(v, points[i], points[(i+1) % points.size()], pos);
00842
00843 if (dist < nearest)
00844 {
00845 nearest = dist;
00846 nearPos = pos;
00847 }
00848 }
00849 distance = nearest;
00850 return false;
00851 }
00852
00853 uint32 nNbIntersection = 0;
00854 for (i = 0; i < points.size(); ++i)
00855 {
00856 const CVector &p1 = points[i];
00857 const CVector &p2 = points[(i+1)%points.size()];
00858
00859 float dist = getSegmentDist(v, p1, p2, pos);
00860 if( dist < nearest)
00861 {
00862 nearest = dist;
00863 nearPos = pos;
00864 }
00865
00866 if (((p1.y-v.y) <= 0.0)&&((p2.y-v.y) <= 0.0))
00867 continue;
00868 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00869 continue;
00870 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00871 if (xinter > v.x)
00872 ++nNbIntersection;
00873 }
00874
00875 distance = nearest;
00876 if ((nNbIntersection&1) == 1)
00877 return true;
00878 else
00879 return false;
00880 }
00881
00882
00883
00884 float CPrimZone::getSegmentDist(const NLMISC::CVector v, const NLMISC::CVector &p1, const NLMISC::CVector &p2, NLMISC::CVector &nearPos)
00885 {
00886
00887 CVector V = (p2-p1).normed();
00888 double length= (p2-p1).norm();
00889 float distance;
00890
00891
00892 if(length==0.0)
00893 {
00894 nearPos= p1;
00895 distance = (p1-v).norm();
00896 }
00897
00898 else
00899 {
00900 float t = (float)((double)((v-p1)*V)/length);
00901 if (t < 0.0f)
00902 {
00903 nearPos = p1;
00904 distance = (p1-v).norm();
00905 }
00906 else if (t > 1.0f)
00907 {
00908 nearPos = p2;
00909 distance = (p2-v).norm();
00910 }
00911 else
00912 {
00913 nearPos = p1 + t*(p2-p1);
00914 distance = (v-nearPos).norm();
00915 }
00916 }
00917
00918 return distance;
00919 }
00920
00921
00922
00923 NLMISC::CVector CPrimZone::getBarycentre() const
00924 {
00925 CVector sum( CVector::Null );
00926 uint n = VPoints.size();
00927 if ( n != 0 )
00928 {
00929 for ( uint i=0; i!=n; ++i )
00930 sum += VPoints[i];
00931 return sum / (float)n;
00932 }
00933 else
00934 return sum;
00935 }
00936
00937
00938 void CPrimZone::getAABox( NLMISC::CVector& cornerMin, NLMISC::CVector& cornerMax ) const
00939 {
00940 cornerMin.x = FLT_MAX;
00941 cornerMin.y = FLT_MAX;
00942 cornerMin.z = 0;
00943 cornerMax.x = -FLT_MAX;
00944 cornerMax.y = -FLT_MAX;
00945 cornerMax.z = 0;
00946 for ( uint i=0; i!=VPoints.size(); ++i )
00947 {
00948 const CVector& p = VPoints[i];
00949 if ( p.x < cornerMin.x )
00950 cornerMin.x = p.x;
00951 if ( p.x > cornerMax.x )
00952 cornerMax.x = p.x;
00953 if ( p.y < cornerMin.y )
00954 cornerMin.y = p.y;
00955 if ( p.y > cornerMax.y )
00956 cornerMax.y = p.y;
00957 }
00958 }
00959
00960
00961
00962 float CPrimZone::getAreaOfAABox() const
00963 {
00964 CVector cornerMin, cornerMax;
00965 getAABox( cornerMin, cornerMax );
00966 return (cornerMax.x-cornerMin.x) * (cornerMax.y-cornerMin.y);
00967 }
00968
00969
00970
00971 void CPrimZone::serial (NLMISC::IStream &f)
00972 {
00973 IPrimitive::serial(f);
00974 f.serialCont(VPoints);
00975 }
00976
00977
00978 void CPrimRegion::serial (NLMISC::IStream &f)
00979 {
00980 f.xmlPushBegin ("REGION");
00981
00982 f.xmlSetAttrib ("NAME");
00983 f.serial (Name);
00984
00985 f.xmlPushEnd();
00986
00987 sint version = 2;
00988 version = f.serialVersion (version);
00989 string check = "REGION";
00990 f.serialCheck (check);
00991
00992 f.xmlPush ("POINTS");
00993 f.serialCont (VPoints);
00994 f.xmlPop ();
00995 f.xmlPush ("PATHES");
00996 f.serialCont (VPaths);
00997 f.xmlPop ();
00998 f.xmlPush ("ZONES");
00999 f.serialCont (VZones);
01000 f.xmlPop ();
01001
01002 if (version > 1)
01003 {
01004 f.xmlPush ("HIDEPOINTS");
01005 f.serialCont (VHidePoints);
01006 f.xmlPop ();
01007 f.xmlPush ("HIDEZONES");
01008 f.serialCont (VHideZones);
01009 f.xmlPop ();
01010 f.xmlPush ("HIDEPATHS");
01011 f.serialCont (VHidePaths);
01012 f.xmlPop ();
01013 }
01014 else
01015 {
01016 VHidePoints.resize (VPoints.size(), false);
01017 VHideZones.resize (VZones.size(), false);
01018 VHidePaths.resize (VPaths.size(), false);
01019 }
01020 }
01021
01022
01023
01024
01025
01026 IPrimitive::IPrimitive ()
01027 {
01028 _Parent = NULL;
01029 }
01030
01031
01032 IPrimitive::IPrimitive (const IPrimitive &node) : IStreamable()
01033 {
01034 _Parent = NULL;
01035 IPrimitive::operator= (node);
01036 }
01037
01038
01039
01040 void IPrimitive::serial (NLMISC::IStream &f)
01041 {
01042
01043
01044
01045 if (f.isReading())
01046 {
01047 uint32 size;
01048 f.serial(size);
01049 for (uint i=0; i<size; ++i)
01050 {
01051 std::string s;
01052 f.serial(s);
01053 IProperty *&pp = _Properties[s];
01054 f.serialPolyPtr(pp);
01055 }
01056 }
01057 else
01058 {
01059 uint32 size = _Properties.size();
01060 f.serial(size);
01061 std::map<std::string, IProperty*>::iterator first(_Properties.begin()), last(_Properties.end());
01062 for (; first != last; ++first)
01063 {
01064 std::string &s = const_cast<std::string&>(first->first);
01065
01066 f.serial(s);
01067 f.serialPolyPtr(first->second);
01068 }
01069 }
01070 f.serial(_ChildId);
01071
01072
01073
01074
01075
01076
01077 if (f.isReading())
01078 {
01079 std::vector<IPrimitive*> children;
01080 f.serialContPolyPtr(children);
01081 uint index = 0;
01082 for(std::vector<IPrimitive*>::iterator it = children.begin(); it != children.end(); ++it, ++index)
01083 {
01084 insertChild(*it, index);
01085 }
01086 }
01087 else
01088 {
01089 f.serialContPolyPtr(_Children);
01090 }
01091
01092 if (f.isReading())
01093 {
01094
01095 vector<IPrimitive*>::iterator first(_Children.begin()), last(_Children.end());
01096 for (; first != last; ++first)
01097 {
01098 if (*first)
01099 (*first)->_Parent = this;
01100 }
01101 }
01102 }
01103
01104
01105
01106
01107 void IPrimitive::updateChildId (uint index)
01108 {
01109 uint i;
01110 uint count = _Children.size ();
01111 for (i=index; i<count; i++)
01112 _Children[i]->_ChildId = i;
01113 }
01114
01115
01116
01117 void IPrimitive::branchLink()
01118 {
01119 onBranchLink();
01120 std::vector<IPrimitive*>::iterator first(_Children.begin()), last(_Children.end());
01121 for (; first != last; ++first)
01122 {
01123 (*first)->branchLink();
01124 }
01125 }
01126
01127
01128
01129 void IPrimitive::branchUnlink()
01130 {
01131 onBranchUnlink();
01132 std::vector<IPrimitive*>::iterator first(_Children.begin()), last(_Children.end());
01133 for (; first != last; ++first)
01134 {
01135 (*first)->branchUnlink();
01136 }
01137 }
01138
01139
01140
01141
01142 void IPrimitive::operator= (const IPrimitive &node)
01143 {
01144
01145 removeChildren ();
01146 removeProperties ();
01147
01148
01149
01150
01151
01152
01153 _UnparsedProperties = node._UnparsedProperties;
01154
01155
01156
01157 _ChildId = node._ChildId;
01158
01159
01160 _Children.resize (node._Children.size ());
01161 for (uint child = 0; child < node._Children.size (); child++)
01162 {
01163
01164 _Children[child] = node._Children[child]->copy ();
01165
01166
01167 _Children[child]->_Parent = this;
01168 }
01169
01170
01171 std::map<std::string, IProperty*>::const_iterator ite = node._Properties.begin ();
01172 while (ite != node._Properties.end ())
01173 {
01174
01175 CPropertyString *propString = dynamic_cast<CPropertyString *>(ite->second);
01176 if (propString)
01177 {
01178
01179 CPropertyString *newProp = new CPropertyString ();
01180 *newProp = *propString;
01181 _Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01182 }
01183 else
01184 {
01185 CPropertyStringArray *propStringArray = dynamic_cast<CPropertyStringArray *>(ite->second);
01186 if (propStringArray)
01187 {
01188
01189 CPropertyStringArray *newProp = new CPropertyStringArray ();
01190 *newProp = *propStringArray;
01191 _Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01192 }
01193 else
01194 {
01195 CPropertyColor *propColor = dynamic_cast<CPropertyColor *>(ite->second);
01196 nlverify (propColor);
01197
01198
01199 CPropertyColor *newProp = new CPropertyColor ();
01200 *newProp = *propColor;
01201 _Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01202 }
01203 }
01204
01205 ite++;
01206 }
01207
01208 #ifdef NLLIGO_DEBUG
01209 _DebugClassName = node._DebugClassName;
01210 _DebugPrimitiveName = node._DebugPrimitiveName;
01211 #endif
01212 }
01213
01214
01215 const IPrimitive *IPrimitive::getPrimitive (const std::string &absoluteOrRelativePath) const
01216 {
01217 const IPrimitive *cursor=this;
01218 string path=absoluteOrRelativePath;
01219
01220 if (path.find("//")==0)
01221 {
01222 while (cursor->getParent())
01223 cursor=cursor->getParent();
01224 path.erase(0,2);
01225 }
01226
01227 while (path.size()>0)
01228 {
01229 if (path.find("/")==0)
01230 {
01231 path.erase(0,1);
01232 continue;
01233 }
01234 if (path.find("..")==0)
01235 {
01236 cursor=cursor->getParent();
01237 if (!cursor)
01238 return NULL;
01239
01240 path.erase(0,2);
01241 continue;
01242 }
01243
01244 string::size_type indexStr=path.find("/");
01245 string childName;
01246 if (indexStr==string::npos)
01247 {
01248 childName=path;
01249 path="";
01250 }
01251 else
01252 {
01253 childName=path.substr(0,indexStr);
01254 path.erase(0, indexStr);
01255 }
01256 childName=toUpper(childName);
01257 const IPrimitive*child=NULL;
01258 uint childIndex;
01259 for (childIndex=0;childIndex<cursor->getNumChildren();childIndex++)
01260 {
01261 cursor->getChild(child,childIndex);
01262 string name;
01263 if ( child->getPropertyByName("class", name)
01264 && toUpper(name)==childName )
01265 break;
01266 }
01267 if (childIndex>=cursor->getNumChildren())
01268 return NULL;
01269
01270 cursor=child;
01271 }
01272 return cursor;
01273 }
01274
01275
01276
01277 bool IPrimitive::getProperty (uint index, std::string &property_name, const IProperty *&result) const
01278 {
01279
01280 std::map<std::string, IProperty*>::const_iterator ite = _Properties.begin ();
01281 while (ite != _Properties.end ())
01282 {
01283 if (index == 0)
01284 {
01285 property_name = ite->first;
01286 result = ite->second;
01287 return true;
01288 }
01289 index--;
01290 ite ++;
01291 }
01292 nlwarning ("NLLIGO::IPrimitive::getProperty : invalid index (index : %d, size : %d).", index, _Properties.size ());
01293 return false;
01294 }
01295
01296
01297
01298 bool IPrimitive::getProperty (uint index, std::string &property_name, IProperty *&result)
01299 {
01300
01301 std::map<std::string, IProperty*>::iterator ite = _Properties.begin ();
01302 while (ite != _Properties.end ())
01303 {
01304 if (index == 0)
01305 {
01306 property_name = ite->first;
01307 result = ite->second;
01308 return true;
01309 }
01310 index--;
01311 ite ++;
01312 }
01313 nlwarning ("NLLIGO::IPrimitive::getProperty : invalid index (index : %d, size : %d).", index, _Properties.size ());
01314 return false;
01315 }
01316
01317
01318
01319 bool IPrimitive::getPropertyByName (const char *property_name, const IProperty *&result) const
01320 {
01321
01322 std::map<std::string, IProperty*>::const_iterator ite = _Properties.find (property_name);
01323 if (ite != _Properties.end ())
01324 {
01325 result = ite->second;
01326 return true;
01327 }
01328 return false;
01329 }
01330
01331
01332
01333 bool IPrimitive::getPropertyByName (const char *property_name, IProperty *&result) const
01334 {
01335
01336 std::map<std::string, IProperty*>::const_iterator ite = _Properties.find (property_name);
01337 if (ite != _Properties.end ())
01338 {
01339 result = ite->second;
01340 return true;
01341 }
01342 return false;
01343 }
01344
01345
01346
01347 bool IPrimitive::getPropertyByName (const char *property_name, std::string *&result) const
01348 {
01349
01350 IProperty *prop;
01351 if (getPropertyByName (property_name, prop))
01352 {
01353 CPropertyString *strProp = dynamic_cast<CPropertyString *> (prop);
01354 if (strProp)
01355 {
01356 result = &(strProp->String);
01357 return true;
01358 }
01359 else
01360 {
01361 nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01362 }
01363 }
01364 return false;
01365 }
01366
01367
01368
01369 bool IPrimitive::getPropertyByName (const char *property_name, std::string &result) const
01370 {
01371
01372 const IProperty *prop;
01373 if (getPropertyByName (property_name, prop))
01374 {
01375 const CPropertyString *strProp = dynamic_cast<const CPropertyString *> (prop);
01376 if (strProp)
01377 {
01378 result = strProp->String;
01379 return true;
01380 }
01381 else
01382 {
01383 nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01384 }
01385 }
01386 return false;
01387 }
01388
01389
01390
01391 bool IPrimitive::getPropertyByName (const char *property_name, std::vector<std::string> *&result) const
01392 {
01393
01394 IProperty *prop;
01395 if (getPropertyByName (property_name, prop))
01396 {
01397 CPropertyStringArray *strProp = dynamic_cast<CPropertyStringArray *> (prop);
01398 if (strProp)
01399 {
01400 result = &(strProp->StringArray);
01401 return true;
01402 }
01403 else
01404 {
01405 nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01406 }
01407 }
01408 return false;
01409 }
01410
01411
01412
01413 bool IPrimitive::getPropertyByName (const char *property_name, const std::vector<std::string> *&result) const
01414 {
01415
01416 IProperty *prop;
01417 if (getPropertyByName (property_name, prop))
01418 {
01419 const CPropertyStringArray *strProp = dynamic_cast<const CPropertyStringArray *> (prop);
01420 if (strProp)
01421 {
01422 result = &(strProp->StringArray);
01423 return true;
01424 }
01425 else
01426 {
01427 nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01428 }
01429 }
01430 return false;
01431 }
01432
01433
01434
01435 bool IPrimitive::getPropertyByName (const char *property_name, NLMISC::CRGBA &result) const
01436 {
01437
01438 IProperty *prop;
01439 if (getPropertyByName (property_name, prop))
01440 {
01441 const CPropertyColor *colorProp = dynamic_cast<const CPropertyColor *> (prop);
01442 if (colorProp)
01443 {
01444 result = colorProp->Color;
01445 return true;
01446 }
01447 else
01448 {
01449 nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a color.", property_name);
01450 }
01451 }
01452 return false;
01453 }
01454
01455
01456
01457 bool IPrimitive::removeProperty (uint index)
01458 {
01459
01460 std::map<std::string, IProperty*>::iterator ite = _Properties.begin ();
01461 while (ite != _Properties.end ())
01462 {
01463 if (index == 0)
01464 {
01465 _Properties.erase (ite);
01466 return true;
01467 }
01468 index--;
01469 ite ++;
01470 }
01471 nlwarning ("NLLIGO::IPrimitive::removeProperty : invalid index (index : %d, size : %d).", index, _Properties.size ());
01472 return false;
01473 }
01474
01475
01476
01477 bool IPrimitive::removePropertyByName (const char *property_name)
01478 {
01479
01480 std::map<std::string, IProperty*>::iterator ite = _Properties.find (property_name);
01481 if (ite != _Properties.end ())
01482 {
01483 _Properties.erase (ite);
01484 return true;
01485 }
01486 return false;
01487 }
01488
01489
01490
01491 void IPrimitive::removeProperties ()
01492 {
01493 std::map<std::string, IProperty*>::iterator ite = _Properties.begin ();
01494 while (ite != _Properties.end ())
01495 {
01496 delete ite->second;
01497 ite++;
01498 }
01499 _Properties.clear ();
01500 }
01501
01502
01503
01504 bool IPrimitive::getChild (const IPrimitive *&result, uint childId) const
01505 {
01506 if (childId < _Children.size ())
01507 {
01508 result = _Children[childId];
01509 return true;
01510 }
01511 else
01512 {
01513 nlwarning ("NLLIGO::IPrimitive::getChild : invalid index (index : %d, size %d).", childId, _Children.size ());
01514 }
01515 return false;
01516 }
01517
01518
01519
01520 bool IPrimitive::getChild (IPrimitive *&result, uint childId)
01521 {
01522 if (childId < _Children.size ())
01523 {
01524 result = _Children[childId];
01525 return true;
01526 }
01527 else
01528 {
01529 nlwarning ("NLLIGO::IPrimitive::getChild : invalid index (index : %d, size %d).", childId, _Children.size ());
01530 }
01531 return false;
01532 }
01533
01534
01535
01536 bool IPrimitive::removeChild (IPrimitive *child)
01537 {
01538 uint childId;
01539 if (getChildId(childId, child))
01540 {
01541 return removeChild(childId);
01542 }
01543 else
01544 {
01545 nlwarning("NLLIGO::IPrimitive::removeChild : invalid child, can't remove (child : %p)", child);
01546 }
01547 return false;
01548 }
01549
01550
01551
01552 bool IPrimitive::removeChild (uint childId)
01553 {
01554 if (childId < _Children.size ())
01555 {
01556 delete _Children[childId];
01557 _Children.erase (_Children.begin()+childId);
01558 updateChildId (childId);
01559 return true;
01560 }
01561 else
01562 {
01563 nlwarning ("NLLIGO::IPrimitive::removeChild : invalid index (index : %d, size %d).", childId, _Children.size ());
01564 }
01565 return false;
01566 }
01567
01568
01569
01570 void IPrimitive::removeChildren ()
01571 {
01572
01573 for (uint i=0; i<_Children.size (); i++)
01574 {
01575 delete _Children[i];
01576 }
01577 _Children.clear ();
01578 }
01579
01580
01581
01582 bool IPrimitive::unlinkChild(IPrimitive *child)
01583 {
01584 uint childId;
01585 if (getChildId(childId, child))
01586 {
01587 child->onUnlinkFromParent();
01588 child->branchUnlink();
01589 _Children.erase (_Children.begin()+childId);
01590 updateChildId (childId);
01591 child->_Parent = NULL;
01592 child->_ChildId = 0;
01593 return true;
01594 }
01595 else
01596 {
01597 nlwarning("NLLIGO::IPrimitive::unlinkChild : invalid child, can't unlink (child : %p)", child);
01598 }
01599 return false;
01600 }
01601
01602
01603
01604 bool IPrimitive::insertChild (IPrimitive *primitive, uint index)
01605 {
01606
01607 if (index == AtTheEnd)
01608 index = _Children.size ();
01609
01610
01611 if (index>_Children.size ())
01612 return false;
01613
01614
01615 _Children.insert (_Children.begin () + index, primitive);
01616
01617
01618 updateChildId (index);
01619
01620
01621 primitive->_Parent = this;
01622
01623
01624 primitive->onLinkToParent();
01625 primitive->branchLink();
01626
01627 return true;
01628 }
01629
01630
01631
01632 IPrimitive::~IPrimitive ()
01633 {
01634
01635 removeChildren ();
01636
01637
01638 removeProperties ();
01639 }
01640
01641
01642 bool IPrimitive::checkProperty(const std::string &property_name) const
01643 {
01644 if (_Properties.find(property_name) == _Properties.end())
01645 return false;
01646 return true;
01647 }
01648
01649
01650
01651 bool IPrimitive::addPropertyByName (const char *property_name, IProperty *result)
01652 {
01653 bool inserted = _Properties.insert (std::map<std::string, IProperty*>::value_type (property_name, result)).second;
01654 if (inserted)
01655 {
01656 return true;
01657 }
01658 return false;
01659 }
01660
01661
01662
01663 bool IPrimitive::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config)
01664 {
01665
01666 _Properties.clear ();
01667
01668
01669 xmlNodePtr commentNode = CIXml::getFirstChildNode(xmlNode, XML_COMMENT_NODE);
01670 if (commentNode)
01671 {
01672 if (!CIXml::getContentString(_UnparsedProperties, commentNode))
01673 _UnparsedProperties = "";
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683 xmlNodePtr propNode;
01684 propNode = CIXml::getFirstChildNode (xmlNode, "PROPERTY");
01685 if (propNode)
01686 {
01687 do
01688 {
01689
01690 string name;
01691 if (GetNodeString (name, filename, propNode, "NAME"))
01692 {
01693
01694 string type;
01695 if (GetPropertyString (type, filename, propNode, "TYPE"))
01696 {
01697
01698 IProperty *property = NULL;
01699
01700
01701 if (type == "string")
01702 {
01703
01704 CPropertyString *propertyString = new CPropertyString;
01705 property = propertyString;
01706
01707
01708 if (!GetNodeString (propertyString->String, filename, propNode, "STRING"))
01709 {
01710 return false;
01711 }
01712 }
01713 else if (type == "string_array")
01714 {
01715
01716 CPropertyStringArray *propertyStringArray = new CPropertyStringArray;
01717 property = propertyStringArray;
01718
01719
01720 xmlNodePtr stringNode;
01721 propertyStringArray->StringArray.reserve (CIXml::countChildren (propNode, "STRING"));
01722 stringNode = CIXml::getFirstChildNode (propNode, "STRING");
01723 if (stringNode)
01724 {
01725 do
01726 {
01727
01728 string content;
01729 GetContentString (content, filename, stringNode);
01730 propertyStringArray->StringArray.push_back (content);
01731
01732 stringNode = CIXml::getNextChildNode (stringNode, "STRING");
01733 }
01734 while (stringNode);
01735 }
01736 }
01737 else if (type == "color")
01738 {
01739
01740 CPropertyColor *propertyColor= new CPropertyColor;
01741 property = propertyColor;
01742
01743
01744 xmlNodePtr colorNode;
01745 colorNode = CIXml::getFirstChildNode (xmlNode, "COLOR");
01746 string R, G, B, A;
01747 if (GetPropertyString (R, filename, colorNode, "R") &&
01748 GetPropertyString (G, filename, colorNode, "G") &&
01749 GetPropertyString (B, filename, colorNode, "B") &&
01750 GetPropertyString (A, filename, colorNode, "A"))
01751 {
01752 sint32 sR=0, sG=0, sB=0, sA=255;
01753 sR = atoi (R.c_str ());
01754 clamp (sR, 0, 255);
01755 sG = atoi (G.c_str ());
01756 clamp (sG, 0, 255);
01757 sB = atoi (B.c_str ());
01758 clamp (sB, 0, 255);
01759 sA = atoi (A.c_str ());
01760 clamp (sR, 0, 255);
01761 propertyColor->Color.R = (uint8)sR;
01762 propertyColor->Color.G = (uint8)sG;
01763 propertyColor->Color.B = (uint8)sB;
01764 propertyColor->Color.A = (uint8)sA;
01765 }
01766 else
01767 return false;
01768 }
01769
01770
01771 if (property == NULL)
01772 {
01773 XMLError (propNode, filename, "IPrimitive::read : Unknown property type (%s)", type.c_str ());
01774 return false;
01775 }
01776
01777
01778 _Properties.insert (std::map<std::string, IProperty*>::value_type (name, property));
01779 }
01780 else
01781 {
01782 return false;
01783 }
01784 }
01785 else
01786 {
01787 return false;
01788 }
01789
01790 propNode = CIXml::getNextChildNode (propNode, "PROPERTY");
01791 }
01792 while (propNode);
01793 }
01794
01795
01796 initDefaultValues (config);
01797
01798
01799 xmlNodePtr childNode;
01800 childNode = CIXml::getFirstChildNode (xmlNode, "CHILD");
01801 if (childNode)
01802 {
01803 do
01804 {
01805
01806 string type;
01807 if (GetPropertyString (type, filename, childNode, "TYPE"))
01808 {
01809
01810 if (type=="node")
01811 type="CPrimNode";
01812 if (type=="point")
01813 type="CPrimPoint";
01814 if (type=="path")
01815 type="CPrimPath";
01816 if (type=="zone")
01817 type="CPrimZone";
01818 if (type=="alias")
01819 type="CPrimAlias";
01820 IPrimitive *primitive = static_cast<IPrimitive *> (CClassRegistry::create (type));
01821
01822
01823 if (primitive == NULL)
01824 {
01825 XMLError (childNode, filename, "IPrimitive::read : Unknown primitive type (%s)", type.c_str ());
01826 return false;
01827 }
01828
01829
01830 primitive->read (childNode, filename, version, config);
01831
01832
01833 insertChild (primitive);
01834
01835 }
01836 else
01837 {
01838 return false;
01839 }
01840
01841 childNode = CIXml::getNextChildNode (childNode, "CHILD");
01842 }
01843 while (childNode);
01844 }
01845
01846 #ifdef NLLIGO_DEBUG
01847
01848 getPropertyByName("class", _DebugClassName);
01849 getPropertyByName("name", _DebugPrimitiveName);
01850 #endif
01851
01852 return true;
01853 }
01854
01855
01856
01857 void IPrimitive::initDefaultValues (CLigoConfig &config)
01858 {
01859
01860 const CPrimitiveClass *primitiveClass = config.getPrimitiveClass (*this);
01861 if (primitiveClass)
01862 {
01863
01864 uint count = primitiveClass->Parameters.size ();
01865 uint i;
01866 for (i=0; i<count; i++)
01867 {
01868 const CPrimitiveClass::CParameter ¶meter = primitiveClass->Parameters[i];
01869
01870
01871 IProperty *result;
01872 if (!getPropertyByName (parameter.Name.c_str(), result))
01873 {
01874
01875 if ((parameter.Type == CPrimitiveClass::CParameter::StringArray) || (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray))
01876 result = new CPropertyStringArray();
01877 else
01878 result = new CPropertyString();
01879 nlverify (addPropertyByName (parameter.Name.c_str(), result));
01880 }
01881 }
01882
01883
01884 for (i=0; i<count; i++)
01885 {
01886 const CPrimitiveClass::CParameter ¶meter = primitiveClass->Parameters[i];
01887
01888 CPropertyString *pString = NULL;
01889 CPropertyStringArray *pStringArray = NULL;
01890
01891 IProperty *result;
01892 nlverify (getPropertyByName (parameter.Name.c_str(), result));
01893 pString = dynamic_cast<CPropertyString*>(result);
01894 if (!pString)
01895 pStringArray = dynamic_cast<CPropertyStringArray*>(result);
01896
01897
01898 if (pString)
01899 {
01900
01901 if (pString->String.empty())
01902 {
01903
01904 pString->Default = true;
01905 parameter.getDefaultValue (pString->String, *this, *primitiveClass);
01906 }
01907 }
01908 else if (pStringArray)
01909 {
01910
01911 if (pStringArray->StringArray.empty())
01912 {
01913
01914 pStringArray->Default = true;
01915 parameter.getDefaultValue (pStringArray->StringArray, *this, *primitiveClass);
01916 }
01917 }
01918 }
01919 }
01920 }
01921
01922
01923
01924 void IPrimitive::write (xmlNodePtr xmlNode, const char *filename) const
01925 {
01926
01927
01928
01929
01930
01931 xmlSetProp (xmlNode, (const xmlChar*)"TYPE", (const xmlChar*)(const_cast<IPrimitive*> (this)->getClassName ().c_str ()));
01932
01933
01934 if (!_UnparsedProperties.empty())
01935 {
01936 xmlNodePtr commentNode = xmlNewComment((const xmlChar*)(_UnparsedProperties.c_str()));
01937 nlverify(commentNode);
01938 xmlAddChild(xmlNode, commentNode);
01939 }
01940
01941
01942 std::map<std::string, IProperty*>::const_iterator ite = _Properties.begin ();
01943 while (ite != _Properties.end ())
01944 {
01945
01946 if (!ite->second->Default)
01947 {
01948
01949 xmlNodePtr propNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PROPERTY", NULL);
01950 xmlNodePtr nameNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"NAME", NULL);
01951 xmlNodePtr textNode = xmlNewText ((const xmlChar *)(ite->first.c_str ()));
01952 xmlAddChild (nameNode, textNode);
01953
01954
01955 const CPropertyString *str = dynamic_cast<const CPropertyString *> (ite->second);
01956 if (str)
01957 {
01958
01959 xmlSetProp (propNode, (const xmlChar*)"TYPE", (const xmlChar*)"string");
01960
01961
01962 xmlNodePtr stringNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"STRING", NULL);
01963 xmlNodePtr textNode = xmlNewText ((const xmlChar *)(str->String.c_str ()));
01964 xmlAddChild (stringNode, textNode);
01965 }
01966 else
01967 {
01968
01969 const CPropertyStringArray *array = dynamic_cast<const CPropertyStringArray *> (ite->second);
01970 if (array)
01971 {
01972
01973 xmlSetProp (propNode, (const xmlChar*)"TYPE", (const xmlChar*)"string_array");
01974
01975
01976 for (uint i=0; i<array->StringArray.size (); i++)
01977 {
01978
01979 xmlNodePtr stringNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"STRING", NULL);
01980 xmlNodePtr textNode = xmlNewText ((const xmlChar *)(array->StringArray[i].c_str ()));
01981 xmlAddChild (stringNode, textNode);
01982 }
01983 }
01984 else
01985 {
01986
01987 const CPropertyColor *color = safe_cast<const CPropertyColor *> (ite->second);
01988
01989
01990 xmlSetProp (propNode, (const xmlChar*)"TYPE", (const xmlChar*)"color");
01991
01992
01993 xmlNodePtr colorNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"COLOR", NULL);
01994 xmlSetProp (colorNode, (const xmlChar*)"R", (const xmlChar*)toString (color->Color.R).c_str ());
01995 xmlSetProp (colorNode, (const xmlChar*)"G", (const xmlChar*)toString (color->Color.G).c_str ());
01996 xmlSetProp (colorNode, (const xmlChar*)"B", (const xmlChar*)toString (color->Color.B).c_str ());
01997 xmlSetProp (colorNode, (const xmlChar*)"A", (const xmlChar*)toString (color->Color.A).c_str ());
01998 }
01999 }
02000 }
02001
02002 ite++;
02003 }
02004
02005
02006 for (uint i=0; i<_Children.size (); i++)
02007 {
02008
02009 xmlNodePtr childNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"CHILD", NULL);
02010
02011
02012 _Children[i]->write (childNode, filename);
02013 }
02014 }
02015
02016
02017
02018 bool IPrimitive::getChildId (uint &childId, const IPrimitive *child) const
02019 {
02020 childId = child->_ChildId;
02021 return true;
02022 }
02023
02024
02025
02026 uint IPrimitive::getNumProperty () const
02027 {
02028 return _Properties.size ();
02029 }
02030
02031
02032
02033 std::string IPrimitive::getName() const
02034 {
02035 std::string ret;
02036 getPropertyByName("name", ret);
02037 return ret;
02038 }
02039
02040
02041
02042 const std::string &IPrimitive::getUnparsedProperties() const
02043 {
02044 return _UnparsedProperties;
02045 }
02046
02047
02048
02049 void IPrimitive::setUnparsedProperties(const std::string &unparsedProperties) const
02050 {
02051 _UnparsedProperties = unparsedProperties;
02052 }
02053
02054
02055
02056
02057
02058 CPrimAlias::CPrimAlias() :
02059 _Alias(0),
02060 _Container(NULL)
02061 {
02062 }
02063
02064 CPrimAlias::CPrimAlias(const CPrimAlias &other)
02065 : IPrimitive(other)
02066 {
02067
02068 _Container = NULL;
02069 _Alias = other._Alias;
02070 }
02071
02072 CPrimAlias::~CPrimAlias()
02073 {
02074 if (_Container)
02075 onBranchUnlink();
02076 }
02077
02078 void CPrimAlias::onBranchLink()
02079 {
02080 CPrimitiveContext &ctx = CPrimitiveContext::instance();
02081
02082 nlassert(ctx.CurrentPrimitive);
02083 nlassert(_Container == NULL || _Container == ctx.CurrentPrimitive);
02084
02085 _Container = ctx.CurrentPrimitive;
02086
02087
02088 _Alias = _Container->genAlias(this, _Alias);
02089 }
02090
02091 void CPrimAlias::onBranchUnlink()
02092 {
02093 nlassert(_Container != NULL);
02094 _Container->releaseAlias(this, _Alias);
02095 _Container = NULL;
02096
02097
02098 }
02099
02100 uint32 CPrimAlias::getAlias() const
02101 {
02102 return _Alias;
02103 }
02104
02105 uint32 CPrimAlias::getFullAlias() const
02106 {
02107 nlassert(_Container != NULL);
02108 return _Container->buildFullAlias(_Alias);
02109 }
02110
02111 void CPrimAlias::regenAlias()
02112 {
02113
02114 nlassert(_Container);
02115
02116 _Alias = _Container->genAlias(this, _Alias);
02117 }
02118
02119
02120
02121 bool CPrimAlias::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config)
02122 {
02123
02124 xmlNodePtr ptNode = CIXml::getFirstChildNode (xmlNode, "ALIAS");
02125 if (ptNode)
02126 {
02127 int val;
02128 if (ReadInt ("VALUE", val, filename, ptNode))
02129 {
02130 _Alias = uint32(val);
02131
02132
02134
02135
02137 }
02138 else
02139 {
02140
02141 nlwarning("CPrimAlias::read: Can't find xml property 'VALUE' in element <ALIAS>");
02142 return false;
02143 }
02144 }
02145 else
02146 {
02147
02148 nlwarning("CPrimAlias::read: Can't find xml element <ALIAS>");
02149 return false;
02150 }
02151
02152 return IPrimitive::read (xmlNode, filename, version, config);
02153 }
02154
02155 void CPrimAlias::write (xmlNodePtr xmlNode, const char *filename) const
02156 {
02157
02158 xmlNodePtr ptNode = xmlNewChild(xmlNode, NULL, (const xmlChar*)"ALIAS", NULL);
02159 WriteInt("VALUE", int(_Alias), ptNode);
02160
02161 IPrimitive::write (xmlNode, filename);
02162 }
02163
02164
02165 IPrimitive *CPrimAlias::copy () const
02166 {
02167
02168 CPrimAlias *pa = new CPrimAlias(*this);
02169
02170
02171
02172
02173
02174 return pa;
02175 }
02176
02177 void CPrimAlias::serial (NLMISC::IStream &f)
02178 {
02179 IPrimitive::serial(f);
02180
02181 f.serial(_Alias);
02182
02183
02184
02185
02186
02187
02188 }
02189
02190
02191
02192
02193
02194
02195 CPrimitives::CPrimitives () :
02196 _LigoConfig(NULL)
02197 {
02198
02199 _LastGeneratedAlias = 0;
02200 _AliasStaticPart = 0;
02201
02202 RootNode = static_cast<CPrimNode *> (CClassRegistry::create ("CPrimNode"));
02203
02204
02205 _LigoConfig = CPrimitiveContext::instance().CurrentLigoConfig;
02206 }
02207
02208
02209
02210 CPrimitives::CPrimitives (const CPrimitives &other)
02211 {
02212 operator =(other);
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224 }
02225
02226
02227
02228 CPrimitives::~CPrimitives ()
02229 {
02230 delete RootNode;
02231 }
02232
02233
02234
02235 uint32 CPrimitives::getAliasStaticPart()
02236 {
02237 return _AliasStaticPart;
02238 }
02239
02240
02241
02242 void CPrimitives::setAliasStaticPart(uint32 staticPart)
02243 {
02244 _AliasStaticPart = staticPart;
02245 }
02246
02247
02248
02249 uint32 CPrimitives::buildFullAlias(uint32 dynamicPart)
02250 {
02251 if (_LigoConfig)
02252 {
02253 return _LigoConfig->buildAlias(_AliasStaticPart, dynamicPart, true);
02254 }
02255 else
02256 return dynamicPart;
02257 }
02258
02259
02260
02261
02262 uint32 CPrimitives::genAlias(IPrimitive *prim, uint32 preferedAlias)
02263 {
02264 nlassert(_LigoConfig);
02265 uint32 ret;
02266
02267 if (preferedAlias != 0)
02268 {
02269
02270 nlassert(preferedAlias == (preferedAlias & _LigoConfig->getDynamicAliasMask()));
02271
02272 map<uint32, IPrimitive*>::iterator it(_AliasInUse.find(preferedAlias));
02273 if (it == _AliasInUse.end())
02274 {
02275
02276
02277 _AliasInUse.insert(make_pair(preferedAlias, prim));
02278 return preferedAlias;
02279 }
02280 else
02281 {
02282
02283 if (it->second == prim)
02284 {
02285
02286
02287 return preferedAlias;
02288 }
02289 }
02290 }
02291
02292
02293 uint32 mask = _LigoConfig->getDynamicAliasMask();
02294 nlassert(_AliasInUse.size() < mask);
02295
02296
02297 ++_LastGeneratedAlias;
02298
02299 _LastGeneratedAlias &= _LigoConfig->getDynamicAliasMask();
02300
02301 ret = _LastGeneratedAlias;
02302
02303 while (_AliasInUse.find(ret) != _AliasInUse.end())
02304 {
02305
02306
02307 ++_LastGeneratedAlias;
02308 _LastGeneratedAlias &= _LigoConfig->getDynamicAliasMask();
02309 ret = _LastGeneratedAlias;
02310 }
02311
02312
02313
02314 _AliasInUse.insert(make_pair(ret, prim));
02315
02316
02317 prim->onModifyPrimitive (*this);
02318
02319 return ret;
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347 void CPrimitives::releaseAlias(IPrimitive *prim, uint32 alias)
02348 {
02349
02350 nlassert(_LigoConfig);
02351
02352 nlassert(alias == (alias & _LigoConfig->getDynamicAliasMask()));
02353 std::map<uint32, IPrimitive*>::iterator it(_AliasInUse.find(alias));
02354
02355 nlassert(it != _AliasInUse.end());
02356
02357 if (it->second != prim)
02358 {
02359 nlwarning("CPrimitives::releaseAlias: The alias %u is own by another primitive !", alias);
02360 return;
02361 }
02362
02363
02364
02365 _AliasInUse.erase(it);
02366 }
02367
02368
02369
02370 void CPrimitives::forceAlias(CPrimAlias *prim, uint32 alias)
02371 {
02372
02373 nlassert(_LigoConfig);
02374
02375 nlassert(alias == (alias & _LigoConfig->getDynamicAliasMask()));
02376
02377
02378 prim->_Alias = alias;
02379
02380 std::map<uint32, IPrimitive*>::iterator it(_AliasInUse.find(alias));
02381 if (it != _AliasInUse.end() && it->second != prim)
02382 {
02383
02384 CPrimAlias *pa = static_cast<CPrimAlias*>(const_cast<IPrimitive*>(it->second));
02385
02386
02387 it->second = prim;
02388
02389
02390
02391 pa->regenAlias();
02392 }
02393 else
02394 {
02395
02396 _AliasInUse.insert(make_pair(alias, prim));
02397 }
02398
02399 }
02400
02401
02402
02403 uint32 CPrimitives::getLastGeneratedAlias()
02404 {
02405 return _LastGeneratedAlias;
02406 }
02407
02408
02409
02410 IPrimitive *CPrimitives::getPrimitiveByAlias(uint32 primAlias)
02411 {
02412
02413 uint32 staticAlias = _LigoConfig->getStaticAliasMask() & primAlias;
02414 staticAlias = staticAlias >> _LigoConfig->getDynamicAliasSize();
02415 if (staticAlias != _AliasStaticPart)
02416 return NULL;
02417
02418
02419 primAlias &= _LigoConfig->getDynamicAliasMask();
02420
02421 std::map<uint32, IPrimitive*>::const_iterator it(_AliasInUse.find(primAlias));
02422
02423 if (it != _AliasInUse.end())
02424 return it->second->getParent();
02425 else
02426 return NULL;
02427 }
02428
02429
02430
02431 void CPrimitives::buildPrimitiveWithAliasList(std::map<uint32, IPrimitive*> &result)
02432 {
02433 nlassert(_LigoConfig != NULL);
02434
02435 std::map<uint32, IPrimitive*>::iterator first(_AliasInUse.begin()), last(_AliasInUse.end());
02436 for (; first != last; ++first)
02437 {
02438 result.insert(make_pair(_LigoConfig->buildAlias(_AliasStaticPart, first->first), first->second->getParent()));
02439 }
02440 }
02441
02442
02443
02444 CPrimitives& CPrimitives::operator= (const CPrimitives &other)
02445 {
02446
02447
02448
02449 _AliasStaticPart = other._AliasStaticPart;
02450 _LastGeneratedAlias = other._LastGeneratedAlias;
02451
02452 _LigoConfig = CPrimitiveContext::instance().CurrentLigoConfig;
02453
02454 CPrimitives *temp = CPrimitiveContext::instance().CurrentPrimitive;
02455 CPrimitiveContext::instance().CurrentPrimitive = this;
02456
02457 RootNode = static_cast<CPrimNode *> (((IPrimitive*)other.RootNode)->copy ());
02458 RootNode->branchLink();
02459
02460 CPrimitiveContext::instance().CurrentPrimitive = temp;
02461
02462 return *this;
02463 }
02464
02465
02466
02467 bool CPrimitives::read (xmlNodePtr xmlNode, const char *filename, CLigoConfig &config)
02468 {
02469 nlassert (xmlNode);
02470
02471 _Filename = CFile::getFilename(filename);
02472 if (_LigoConfig)
02473 {
02474
02475 _AliasStaticPart = _LigoConfig->getFileStaticAliasMapping(CFile::getFilename(filename));
02476 }
02477
02478
02479 RootNode->removeChildren ();
02480 RootNode->removeProperties ();
02481
02482
02483 if (strcmp ((const char*)xmlNode->name, "PRIMITIVES") == 0)
02484 {
02485
02486 string versionName = "0";
02487 if (GetPropertyString (versionName, filename, xmlNode, "VERSION"))
02488 {
02489
02490 uint32 version = atoi (versionName.c_str ());
02491
02492
02493 if (version <= NLLIGO_PRIMITIVE_VERSION)
02494 {
02495
02496 xmlNode = GetFirstChildNode (xmlNode, filename, "ROOT_PRIMITIVE");
02497 if (xmlNode)
02498 {
02499 if (version > 0)
02500 {
02501 xmlNodePtr subNode = GetFirstChildNode(xmlNode, filename, "ALIAS");
02502 if (subNode)
02503 {
02504 uint temp;
02505 ReadUInt("LAST_GENERATED", temp, filename, subNode);
02506 _LastGeneratedAlias = temp;
02507 }
02508 else
02509 _LastGeneratedAlias = 0;
02510 }
02511 else
02512 _LastGeneratedAlias = 0;
02513
02514
02515 ((IPrimitive*)RootNode)->read (xmlNode, filename, version, config);
02516 }
02517 }
02518 else
02519 {
02520 Error (filename, "CPrimitives::read : Unknown file version (%d)", version);
02521 return false;
02522 }
02523 }
02524 else
02525 {
02526 return false;
02527 }
02528 }
02529 else
02530 {
02531 XMLError (xmlNode, filename, "This XML document is not a NeL primitive file");
02532 return false;
02533 }
02534
02535 return true;
02536 }
02537
02538
02539
02540 void CPrimitives::write (xmlDocPtr doc, const char *filename) const
02541 {
02542 nlassert (doc);
02543
02544
02545 xmlNodePtr primNode = xmlNewDocNode (doc, NULL, (const xmlChar*)"PRIMITIVES", NULL);
02546 xmlDocSetRootElement (doc, primNode);
02547
02548 write (primNode, filename);
02549 }
02550
02551
02552
02553 void CPrimitives::write (xmlNodePtr root, const char *filename) const
02554 {
02555 nlassert (root);
02556
02557
02558 xmlSetProp (root, (const xmlChar*)"VERSION", (const xmlChar*)toString (NLLIGO_PRIMITIVE_VERSION).c_str ());
02559
02560
02561 xmlNodePtr nameNode = xmlNewChild ( root, NULL, (const xmlChar*)"ROOT_PRIMITIVE", NULL);
02562 xmlNodePtr subNode = xmlNewChild ( nameNode, NULL, (const xmlChar*)"ALIAS", NULL);
02563 WriteUInt("LAST_GENERATED", _LastGeneratedAlias, subNode);
02564
02565
02566 ((IPrimitive*)RootNode)->write (nameNode, filename);
02567 }
02568
02569
02570
02571 void CPrimitives::serial(NLMISC::IStream &f)
02572 {
02573 uint currentVersion = NLLIGO_PRIMITIVE_VERSION;
02574 f.serialVersion(currentVersion);
02575
02576 if (currentVersion == 0)
02577 {
02578 f.serial(_LastGeneratedAlias);
02579 }
02580
02581 if (f.isReading())
02582 {
02583 RootNode->removeChildren ();
02584 RootNode->removeProperties ();
02585 }
02586 f.serialPolyPtr(RootNode);
02587 f.serial(_Filename);
02588 if (f.isReading() && _LigoConfig)
02589 {
02590 _AliasStaticPart = _LigoConfig->getFileStaticAliasMapping(_Filename);
02591 }
02592 }
02593
02594
02595
02596 void CPrimitives::convertAddPrimitive (IPrimitive *child, const IPrimitive *prim, bool hidden)
02597 {
02598
02599 IPrimitive *primitive = NULL;
02600
02601
02602 const CPrimPoint *oldPoint = dynamic_cast<const CPrimPoint *>(prim);
02603 if (oldPoint)
02604 {
02605
02606 CPrimPoint *point = static_cast<CPrimPoint *> (CClassRegistry::create ("CPrimPoint"));
02607 primitive = point;
02608
02609
02610 *point = *oldPoint;
02611 }
02612 else
02613 {
02614
02615 const CPrimPath *oldPath = dynamic_cast<const CPrimPath *>(prim);
02616 if (oldPath)
02617 {
02618
02619 CPrimPath *path = static_cast<CPrimPath *> (CClassRegistry::create ("CPrimPath"));
02620 primitive = path;
02621
02622
02623 *path = *oldPath;
02624 }
02625 else
02626 {
02627 const CPrimZone *oldZone = safe_cast<const CPrimZone *>(prim);
02628 if (oldZone)
02629 {
02630
02631 CPrimZone *zone = static_cast<CPrimZone *> (CClassRegistry::create ("CPrimZone"));
02632 primitive = zone;
02633
02634
02635 *zone = *oldZone;
02636 }
02637 }
02638 }
02639
02640
02641 if (primitive)
02642 {
02643
02644 CPropertyString *nameProp = new CPropertyString;
02645
02646
02647
02648 primitive->addPropertyByName ("name", nameProp);
02649
02650
02651 if (hidden)
02652 {
02653
02654 nameProp = new CPropertyString;
02655
02656
02657 primitive->addPropertyByName ("hidden", nameProp);
02658 }
02659
02660
02661 child->insertChild (primitive);
02662 }
02663 }
02664
02665
02666
02667 void CPrimitives::convertPrimitive (const IPrimitive *prim, bool hidden)
02668 {
02669
02670 uint numChildren = RootNode->getNumChildren ();
02671 uint j;
02672 for (j=0; j<numChildren; j++)
02673 {
02674 IPrimitive *child;
02675 nlverify (RootNode->getChild (child, j));
02676 const IProperty *prop;
02677 if (child->getPropertyByName ("name", prop))
02678 {
02679
02680 const CPropertyString *name = dynamic_cast<const CPropertyString *>(prop);
02681 if (name)
02682 {
02683
02684
02685
02686
02687
02688
02689 }
02690 }
02691 }
02692
02693
02694 if (j==numChildren)
02695 {
02696
02697 CPrimNode *primNode = static_cast<CPrimNode *> (CClassRegistry::create ("CPrimNode"));
02698
02699
02700 CPropertyString *nameProp = new CPropertyString;
02701
02702
02703
02704 primNode->addPropertyByName ("name", nameProp);
02705
02706
02707 RootNode->insertChild (primNode);
02708
02709
02710 convertAddPrimitive (primNode, prim, hidden);
02711 }
02712 }
02713
02714
02715
02716 void CPrimitives::convert (const CPrimRegion ®ion)
02717 {
02718
02719 RootNode->removeChildren ();
02720 RootNode->removeProperties ();
02721
02722
02723 uint i;
02724 for (i=0; i<region.VPoints.size (); i++)
02725 {
02726 convertPrimitive (&(region.VPoints[i]), region.VHidePoints[i]);
02727 }
02728 for (i=0; i<region.VPaths.size (); i++)
02729 {
02730 convertPrimitive (&(region.VPaths[i]), region.VHidePaths[i]);
02731 }
02732 for (i=0; i<region.VZones.size (); i++)
02733 {
02734 convertPrimitive (&(region.VZones[i]), region.VHideZones[i]);
02735 }
02736 }
02737
02738
02739
02740 CPrimitiveContext::CPrimitiveContext():
02741 CurrentLigoConfig(NULL),
02742 CurrentPrimitive(NULL)
02743 {
02744 }
02745
02746
02747 void Register ()
02748 {
02749 NLMISC_REGISTER_CLASS(CPropertyString);
02750 NLMISC_REGISTER_CLASS(CPropertyStringArray);
02751 NLMISC_REGISTER_CLASS(CPropertyColor);
02752 NLMISC_REGISTER_CLASS(CPrimNode);
02753 NLMISC_REGISTER_CLASS(CPrimPoint);
02754 NLMISC_REGISTER_CLASS(CPrimPath);
02755 NLMISC_REGISTER_CLASS(CPrimZone);
02756 NLMISC_REGISTER_CLASS(CPrimAlias);
02757 }
02758
02759
02760
02761 }
02762
02763