Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/3dsmaxExport/LEXIExporter/SharedUtilities/Sources/DDObject.cpp @ 45

Last change on this file since 45 was 6, checked in by anonymous, 18 years ago

=…

File size: 33.0 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of LEXIExporter
4
5Copyright 2006 NDS Limited
6
7Author(s):
8Lasse Tassing
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "StdAfx.h"
26
27#define NOTIFY_CHANGE(x) \
28        m_bChanged=true; \
29        for(unsigned _iNotify=0;_iNotify<m_lListeners.size();_iNotify++) \
30                m_lListeners[_iNotify]->OnChanged(this, x);
31
32// Constructor
33CDDObject::CDDObject(void)
34{
35        m_iRefCount=1;
36        m_bChanged=false;
37
38}
39
40// Private destructor - use Release() to free object
41CDDObject::~CDDObject(void)
42{
43        Clear();       
44}
45
46// Clear object of all mappings
47void CDDObject::Clear(void)
48{
49        // Get list of elements
50        fastvector< const CDDBase * > lList=m_mData.data();
51
52        unsigned i=0;
53        try 
54        {
55                // Release all elements
56                for(i=0;i<lList.size();i++)
57                        lList[i]->Release();
58        } catch(...)
59        {
60                LOGDEBUG "Caught exception while releasing object %d, %X", i, lList[i]);
61        }
62
63        // Clear map
64        m_mData.clear();
65        m_bChanged=true;       
66}
67
68// Remove a specific mapping
69void CDDObject::RemoveData(const char *pszID)
70{
71        const CDDBase *pItem;
72        if(m_mData.find(pszID,pItem))
73        {
74                pItem->Release();               
75                m_mData.erase(pszID);
76                NOTIFY_CHANGE(pszID);
77        }
78}
79
80// Check if object has been changed
81bool CDDObject::HasChanged(bool bResetChange, bool bRecurse)
82{
83        bool bRet=m_bChanged;
84
85        // If this object has not changed, we check others
86        if(!bRet && bRecurse)
87        {
88                fastvector< const CDDBase * > lObjects=m_mData.data();
89                for(unsigned i=0;i<lObjects.size();i++)
90                {
91                        if(lObjects[i]->GetType()==DD_OBJECT)
92                        {
93                                // Check sub object
94                                CDDObject *pSub=(CDDObject *)lObjects[i];
95                                if(pSub->HasChanged(bResetChange, true))
96                                {
97                                        // Object has changed, we do not need to check any further
98                                        bRet=true;
99                                        break;
100                                }
101                        }
102                        else if(lObjects[i]->GetType()==DD_OBJLIST)
103                        {
104                                const CDDObjectList *pDDList=static_cast<const CDDObjectList *>(lObjects[i]);
105                                for(unsigned iSub=0;iSub<pDDList->m_lList.size();iSub++)
106                                {
107                                        // Intentionally cast const away, since we have to be able to reset change flag
108                                        if(((CDDObject*)pDDList->m_lList[iSub])->HasChanged(bResetChange, true))
109                                        {
110                                                // Object has changed, we do not need to check any further
111                                                bRet=true;
112                                                break;
113                                        }
114                                }
115                                // If any of the sub objects was marked, we do not need to check any other objects
116                                if(bRet) break;
117                        }
118                }
119        }
120
121        if(bResetChange) m_bChanged=false;
122        return bRet;
123}
124
125// Deserialize from data stream
126void CDDObject::FromDataStream(CDataStream *pStream, bool bAppend)
127{
128        // Free header and optionally clear existing keys       
129        if(!bAppend) Clear();
130
131        int iKeyCount=pStream->GetInt();
132        if(!iKeyCount) return;
133
134        for(int iKey=0;iKey<iKeyCount;iKey++)
135        {
136                EDDType eType=(EDDType)pStream->GetInt();
137                const char *pszKey=pStream->GetString();
138                const CDDBase *pOldItem;
139
140                switch(eType)
141                {
142                        case DD_OBJECT:
143                                {
144                                CDDObject *pNewDD=new CDDObject;
145                                pNewDD->FromDataStream(pStream, true);                         
146                m_mData.map(pszKey, pNewDD, pOldItem);                         
147                                } break;
148                        case DD_OBJLIST:
149                                {
150                                int iCount=pStream->GetInt();
151                                CDDObjectList *pDDList=new CDDObjectList;
152                                for(int iSubDD=0;iSubDD<iCount;iSubDD++)
153                                {
154                                        CDDObject *pNew=new CDDObject;
155                                        pNew->FromDataStream(pStream, true);
156                                        pDDList->m_lList.push_back(pNew);
157                                }
158                                m_mData.map(pszKey, pDDList, pOldItem);
159                                } break;
160                        case DD_INT:
161                                m_mData.map(pszKey, new CDDInt(pStream->GetInt()), pOldItem);                           
162                                break;
163                        case DD_INTLIST:
164                                {
165                                int iCount=pStream->GetInt();
166                                int *pValues=new int[iCount];
167                                for(int i=0;i<iCount;i++)       pValues[i]=pStream->GetInt();                           
168                                m_mData.map(pszKey, new CDDIntList(iCount, pValues), pOldItem);
169                                } break;
170                        case DD_FLOAT:
171                                m_mData.map(pszKey, new CDDFloat(pStream->GetFloat()), pOldItem);                               
172                                break;
173                        case DD_FLOATLIST:
174                                {
175                                int iCount=pStream->GetInt();
176                                float *pfValues=new float[iCount];
177                                for(int i=0;i<iCount;i++)       pfValues[i]=pStream->GetFloat();
178                                m_mData.map(pszKey, new CDDFloatList(iCount, pfValues), pOldItem);
179                                } break;
180                        case DD_STRING:
181                                {
182                                m_mData.map(pszKey, new CDDString(pStream->GetString()), pOldItem);
183                                } break;
184                        case DD_STRINGLIST:
185                                {
186                                vector<faststring> lList;
187                                int iCount=pStream->GetInt();
188                                for(int iS=0;iS<iCount;iS++)
189                                {
190                                        faststring s=pStream->GetString();
191                                        lList.push_back(s);
192                                }
193                                m_mData.map(pszKey, new CDDStringList(lList));
194                                } break;
195                        case DD_BINARY:
196                                {
197                                unsigned iSize;
198                                const void *pData=pStream->GetBinary(iSize);                           
199                                m_mData.map(pszKey, new CDDBinary(pData, iSize), pOldItem);
200                                } break;
201                        case DD_VEC3:
202                                {
203                                float fX = pStream->GetFloat();
204                                float fY = pStream->GetFloat();
205                                float fZ = pStream->GetFloat();
206                                m_mData.map(pszKey, new CDDVec3(fX, fY, fZ), pOldItem);                         
207                                } break;
208                        case DD_VEC3LIST:
209                                {
210                                int iCount = pStream->GetInt();
211                                CVec3* pValues = new CVec3[iCount];
212                                for(int i = 0;i < iCount; i++)
213                                {
214                                        pValues[i].x = pStream->GetFloat();
215                                        pValues[i].y = pStream->GetFloat();
216                                        pValues[i].z = pStream->GetFloat();
217                                }
218                                m_mData.map(pszKey, new CDDVec3List(iCount, pValues), pOldItem);
219                                } break;
220                        case DD_BOOL:
221                                m_mData.map(pszKey, new CDDBool(pStream->GetBool()), pOldItem);                         
222                                break;
223                        case DD_VEC2:
224                                {
225                                float fX = pStream->GetFloat();
226                                float fY = pStream->GetFloat();
227                                m_mData.map(pszKey, new CDDVec2(fX, fY), pOldItem);                             
228                                } break;
229                        case DD_VEC4:
230                                {
231                                float fX = pStream->GetFloat();
232                                float fY = pStream->GetFloat();
233                                float fZ = pStream->GetFloat();
234                                float fW = pStream->GetFloat();
235                                m_mData.map(pszKey, new CDDVec4(fX, fY, fZ, fW), pOldItem);                             
236                                } break;
237                        case DD_VEC4LIST:
238                                {
239                                int iCount = pStream->GetInt();
240                                CVec4* pValues = new CVec4[iCount];
241                                for(int i = 0;i < iCount; i++)
242                                {
243                                        pValues[i].x = pStream->GetFloat();
244                                        pValues[i].y = pStream->GetFloat();
245                                        pValues[i].z = pStream->GetFloat();
246                                        pValues[i].w = pStream->GetFloat();
247                                }
248                                m_mData.map(pszKey, new CDDVec4List(iCount, pValues), pOldItem);
249                                } break;
250                        case DD_MATRIX:
251                                {
252                                float mat[16];
253                                for(unsigned int x = 0; x < 16; x++) mat[x] = pStream->GetFloat();
254                                m_mData.map(pszKey, new CDDMatrix(mat), pOldItem);
255                                } break;
256                        case DD_MATRIXLIST:
257                                {
258                                int iCount = pStream->GetInt();
259                                CMatrix* pValues = new CMatrix[iCount];
260                                for(int i = 0;i < iCount; i++)
261                                {
262                                        float* pMat = (float*)pValues[i].mat;
263                                        for(unsigned int x = 0; x < 16; x++) pMat[x] = pStream->GetFloat();
264                                }
265                                m_mData.map(pszKey, new CDDMatrixList(iCount, pValues), pOldItem);
266                                } break;
267                        default:
268                                LOGWARNING "Got invalid type in FromDataStream: %d", eType);
269                                continue;
270                }
271        }
272        m_bChanged=true;
273}
274
275void CDDObject::ToDataStream(CDataStream *pStream) const
276{
277        // Get list of elements
278        fastvector< fastmap<const CDDBase *>::SDataPair > lList=m_mData.iterate();
279
280        // DDObject "header"); 
281        pStream->AddInt(lList.size());
282        for(unsigned i=0;i<lList.size();i++)
283        {               
284                const CDDBase *pItem=lList[i].Data;
285                EDDType eType=pItem->GetType();
286                pStream->AddInt(eType);
287                pStream->AddString(lList[i].pszKey);           
288                switch(eType)
289                {
290                        case DD_OBJECT:
291                                ((CDDObject*)pItem)->ToDataStream(pStream);
292                                break;
293                        case DD_OBJLIST:
294                                {
295                                CDDObjectList *pList=(CDDObjectList*)pItem;
296                                pStream->AddInt(pList->m_lList.size());
297                                for(unsigned i=0;i<pList->m_lList.size();i++)
298                                        pList->m_lList[i]->ToDataStream(pStream);
299                                } break;
300                        case DD_INT:
301                                pStream->AddInt(((CDDInt*)(pItem))->m_iValue);
302                                break;
303                        case DD_INTLIST:
304                                {
305                                CDDIntList *pList=(CDDIntList*)pItem;
306                                pStream->AddInt(pList->m_iCount);
307                                for(int i=0;i<pList->m_iCount;i++)      pStream->AddInt(pList->m_pValues[i]);
308                                } break;
309                        case DD_FLOAT:
310                                pStream->AddFloat(((CDDFloat*)(pItem))->m_fValue);
311                                break;
312                        case DD_FLOATLIST:
313                                {
314                                CDDFloatList *pList=(CDDFloatList*)pItem;
315                                pStream->AddInt(pList->m_iCount);
316                                for(int i=0;i<pList->m_iCount;i++)      pStream->AddFloat(pList->m_pValues[i]);
317                                } break;
318                        case DD_STRING:
319                                pStream->AddString(((CDDString*)(pItem))->m_sValue);
320                                break;
321                        case DD_STRINGLIST:
322                                {
323                                CDDStringList *pList=(CDDStringList*)pItem;
324                                pStream->AddInt(pList->m_Value.size());
325                                for(unsigned iS=0;iS<pList->m_Value.size();iS++)
326                                        pStream->AddString(pList->m_Value[iS].c_str());
327                                } break;
328                        case DD_VEC3:
329                                {
330                                const CDDVec3* pVec3 = (const CDDVec3*)pItem;
331                                pStream->AddFloat(pVec3->m_Vec.x);
332                                pStream->AddFloat(pVec3->m_Vec.y);
333                                pStream->AddFloat(pVec3->m_Vec.z);
334                                } break;
335                        case DD_VEC3LIST:
336                                {
337                                CDDVec3List* pList = (CDDVec3List*)pItem;
338                                pStream->AddInt(pList->m_iCount);
339                                for(int i = 0; i < pList->m_iCount; i++)
340                                {
341                                        pStream->AddFloat(pList->m_pValues[i].x);
342                                        pStream->AddFloat(pList->m_pValues[i].y);
343                                        pStream->AddFloat(pList->m_pValues[i].z);
344                                }
345                                } break;
346                        case DD_BOOL:
347                                pStream->AddBool(((CDDBool*)(pItem))->m_bValue);
348                                break;
349                        case DD_VEC2:
350                                {
351                                const CDDVec2* pVec2 = (const CDDVec2*)pItem;
352                                pStream->AddFloat(pVec2->m_Vec.x);
353                                pStream->AddFloat(pVec2->m_Vec.y);
354                                } break;
355                        case DD_VEC4:
356                                {
357                                const CDDVec4* pVec4 = (const CDDVec4*)pItem;
358                                pStream->AddFloat(pVec4->m_Vec.x);
359                                pStream->AddFloat(pVec4->m_Vec.y);
360                                pStream->AddFloat(pVec4->m_Vec.z);
361                                pStream->AddFloat(pVec4->m_Vec.w);
362                                } break;
363                        case DD_VEC4LIST:
364                                {
365                                CDDVec4List* pList = (CDDVec4List*)pItem;
366                                pStream->AddInt(pList->m_iCount);
367                                for(int i = 0; i < pList->m_iCount; i++)
368                                {
369                                        pStream->AddFloat(pList->m_pValues[i].x);
370                                        pStream->AddFloat(pList->m_pValues[i].y);
371                                        pStream->AddFloat(pList->m_pValues[i].z);
372                                        pStream->AddFloat(pList->m_pValues[i].w);
373                                }
374                                } break;
375                        case DD_MATRIX:
376                                {
377                                const CDDMatrix* pMatrix = (const CDDMatrix*)pItem;
378                                const float* pMat = (const float*)pMatrix->m_Matrix.mat;
379                                for(unsigned int x = 0; x < 16; x++) pStream->AddFloat(pMat[x]);
380                                } break;
381                        case DD_MATRIXLIST:
382                                {
383                                CDDMatrixList* pList = (CDDMatrixList*)pItem;
384                                pStream->AddInt(pList->m_iCount);
385                                for(int i = 0; i < pList->m_iCount; i++)
386                                {
387                                        const CMatrix& Mat = pList->m_pValues[i];
388                                        const float* pMat = (const float*)Mat.mat;
389                                        for(unsigned int x = 0; x < 16; x++) pStream->AddFloat(pMat[x]);
390                                }
391                                } break;
392
393                        case DD_BINARY:
394                                {
395                                } break;
396                }
397        }
398}
399
400void CDDObject::Dump(ELogLevel eLogLevel) const
401{
402        // Get list of elements
403        fastvector< fastmap<const CDDBase *>::SDataPair > lList=m_mData.iterate();
404
405        // DDObject "header");
406        LOGCUSTOM eLogLevel, "Dumping DDObject");
407        for(unsigned i=0;i<lList.size();i++)
408        {               
409                const CDDBase *pItem=lList[i].Data;
410                EDDType eType=pItem->GetType();
411                                               
412                switch(eType)
413                {
414                        case DD_OBJECT:
415                                LOGCUSTOM eLogLevel, "%s=(ddobject) {", lList[i].pszKey);                                                       
416                                ((CDDObject*)pItem)->Dump(eLogLevel);
417                                LOGCUSTOM eLogLevel, "}; // end DDObject");                                                     
418                                break;
419                        case DD_OBJLIST:
420                                {
421                                LOGCUSTOM eLogLevel, "%s=(ddlist):", lList[i].pszKey);                                                 
422                                CDDObjectList *pList=((CDDObjectList*)pItem);
423                                for(unsigned j=0;j<pList->m_lList.size();j++)
424                                {
425                                        LOGCUSTOM eLogLevel, " //List, object=%d", j);
426                                        pList->m_lList[j]->Dump(eLogLevel);
427                                }
428                                } break;
429                        case DD_INT:
430                                LOGCUSTOM eLogLevel, "%s=(int)%d;", lList[i].pszKey, ((CDDInt*)(pItem))->m_iValue);                             
431                                break;
432                        case DD_INTLIST:
433                                {
434                                LOGCUSTOM eLogLevel, "%s=(intlist);", lList[i].pszKey);                                                 
435                                } break;
436                        case DD_FLOAT:
437                                LOGCUSTOM eLogLevel, "%s=(float)%f;", lList[i].pszKey, ((CDDFloat*)(pItem))->m_fValue);                         
438                                break;
439                        case DD_FLOATLIST:
440                                {                               
441                                LOGCUSTOM eLogLevel, "%s=(floatlist);", lList[i].pszKey);                                                       
442                                } break;
443                        case DD_STRINGLIST:
444                                {
445                                LOGCUSTOM eLogLevel, "%s=(stringlist):", lList[i].pszKey);                                                     
446                                CDDStringList *pList=((CDDStringList*)pItem);
447                                for(unsigned j=0;j<pList->m_Value.size();j++)
448                                        LOGCUSTOM eLogLevel, "%s", pList->m_Value[j].c_str());
449                                }break;
450                        case DD_STRING:
451                                LOGCUSTOM eLogLevel, "%s=(string)\"%s\";", lList[i].pszKey, ((CDDString*)(pItem))->m_sValue);                                                   
452                                break;
453                        case DD_VEC3:
454                                {
455                                const CDDVec3* pVec3 = (const CDDVec3*)pItem;
456                                LOGCUSTOM eLogLevel, "%s=(vec3)%f|%f|%f;", lList[i].pszKey, pVec3->m_Vec.x, pVec3->m_Vec.y, pVec3->m_Vec.z);
457                                } break;
458                        case DD_VEC3LIST:
459                                {                               
460                                LOGCUSTOM eLogLevel, "%s=(vec3list);", lList[i].pszKey);                                                       
461                                } break;
462                        case DD_BOOL:
463                                LOGCUSTOM eLogLevel, "%s=(bool)%s;", lList[i].pszKey, ((CDDBool*)(pItem))->m_bValue ? "true" : "false");
464                                break;
465                }
466        }
467}
468
469// Save object as ASCII
470void CDDObject::SaveASCII(const char *pszFile) const
471{
472        HANDLE hFile=CreateFile(pszFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
473        if(hFile==INVALID_HANDLE_VALUE) return;
474
475        faststring sOut="";
476        BuildString(sOut);
477       
478        DWORD dwBytesWritten;
479        WriteFile(hFile, sOut.c_str(), sOut.size(), &dwBytesWritten, NULL);
480        CloseHandle(hFile);
481        return;
482}
483
484void CDDObject::BuildString(faststring &strout) const
485{
486        char buffer[8192];
487
488        // Get list of elements
489        fastvector< fastmap<const CDDBase *>::SDataPair > lList=m_mData.iterate();
490
491        //
492        for(unsigned i=0;i<lList.size();i++)
493        {               
494                const CDDBase *pItem=lList[i].Data;
495                EDDType eType=pItem->GetType();
496                strout.add(lList[i].pszKey);
497                                               
498                switch(eType)
499                {
500                        case DD_OBJECT:
501                                strout.add("=(ddobject) {\r\n");                               
502                                ((CDDObject*)pItem)->BuildString(strout);
503                                strout.add("};\r\n");
504                                break;
505                        case DD_OBJLIST:
506                                {
507                                strout.add("=(ddlist) {");
508                                CDDObjectList *pList=(CDDObjectList*)pItem;                             
509                                for(unsigned i=0;i<pList->m_lList.size();i++)
510                                {
511                                        strout.add((i>0 ? ",{\r\n" : "{\r\n"));
512                                        pList->m_lList[i]->BuildString(strout);
513                                        strout.add("}");
514                                }
515                                strout.add("};\r\n");
516                                } break;
517                        case DD_INT:
518                                _snprintf(buffer, 8192, "=(int)%d;\r\n", ((CDDInt*)(pItem))->m_iValue);
519                                strout.add(buffer);                             
520                                break;
521                        case DD_INTLIST:
522                                {
523                                strout.add("=(intlist) {");
524                                CDDIntList *pList=(CDDIntList*)pItem;                           
525                                for(int i=0;i<pList->m_iCount;i++)     
526                                {
527                                        _snprintf(buffer, 8192, "%s%d", (i>0 ? ", " : ""), pList->m_pValues[i]);
528                                }
529                                strout.add("};\r\n");
530                                } break;
531                        case DD_FLOAT:
532                                _snprintf(buffer, 8192, "=(float)%f;\r\n", ((CDDFloat*)(pItem))->m_fValue);
533                                strout.add(buffer);     
534                                break;
535                        case DD_FLOATLIST:
536                                {                               
537                                strout.add("=(floatlist) {");
538                                CDDFloatList *pList=(CDDFloatList*)pItem;                               
539                                for(int i=0;i<pList->m_iCount;i++)     
540                                {
541                                        _snprintf(buffer, 8192, "%s%.2f", (i>0 ? ", " : ""), pList->m_pValues[i]);
542                                        strout.add(buffer);
543                                }
544                                strout.add("};\r\n");
545                                } break;
546                        case DD_STRING:
547                                strout.add("=(string)\"");
548                                strout.add(((CDDString*)(pItem))->m_sValue);
549                                strout.add("\";\r\n");                         
550                                break;
551                        case DD_STRINGLIST:
552                                {
553                                strout.add("=(stringlist) {\r\n");
554                                vector<faststring> &lList=((CDDStringList*)pItem)->m_Value;
555                                for(unsigned i=0;i<lList.size();i++)   
556                                {
557                                        _snprintf(buffer, 8192, "%s\"%s\"\r\n", (i>0 ? ", " : ""), lList[i].c_str());
558                                        strout.add(buffer);
559                                }
560                                strout.add("};\r\n");
561                                } break;
562                        case DD_VEC3:
563                                {
564                                const CDDVec3* pVec3 = (const CDDVec3*)pItem;
565                                _snprintf(buffer, 8192, "=(vec3)%f|%f|%f;\r\n", pVec3->m_Vec.x, pVec3->m_Vec.y, pVec3->m_Vec.z);
566                                strout.add(buffer);     
567                                } break;
568                        case DD_VEC3LIST:
569                                {                               
570                                strout.add("=(vec3list) {");
571                                const CDDVec3List* pList = (const CDDVec3List*)pItem;
572                                for(int i = 0;i < pList->m_iCount; i++)
573                                {
574                                        const CVec3& Vec3 = pList->m_pValues[i];
575                                        _snprintf(buffer, 8192, "%s%f|%f|%f", (i>0 ? ", " : ""), Vec3.x, Vec3.y, Vec3.z);
576                                        strout.add(buffer);
577                                }
578                                strout.add("};\r\n");
579                                } break;
580                        case DD_BOOL:
581                                _snprintf(buffer, 8192, "=(bool)%s;\r\n", ((CDDBool*)(pItem))->m_bValue ? "true" : "false");
582                                strout.add(buffer);                             
583                                break;
584                        case DD_VEC2:
585                                {
586                                const CDDVec2* pVec2 = (const CDDVec2*)pItem;
587                                _snprintf(buffer, 8192, "=(vec2)%f|%f;\r\n", pVec2->m_Vec.x, pVec2->m_Vec.y);
588                                strout.add(buffer);     
589                                } break;
590                        case DD_VEC4:
591                                {
592                                const CDDVec4* pVec4 = (const CDDVec4*)pItem;
593                                _snprintf(buffer, 8192, "=(vec4)%f|%f|%f|%f;\r\n", pVec4->m_Vec.x, pVec4->m_Vec.y, pVec4->m_Vec.z, pVec4->m_Vec.w);
594                                strout.add(buffer);     
595                                } break;
596                        case DD_VEC4LIST:
597                                {                               
598                                strout.add("=(vec4list) {");
599                                const CDDVec4List* pList = (const CDDVec4List*)pItem;
600                                for(int i = 0;i < pList->m_iCount; i++)
601                                {
602                                        const CVec4& Vec4 = pList->m_pValues[i];
603                                        _snprintf(buffer, 8192, "%s%f|%f|%f|%f", (i>0 ? ", " : ""), Vec4.x, Vec4.y, Vec4.z, Vec4.w);
604                                        strout.add(buffer);
605                                }
606                                strout.add("};\r\n");
607                                } break;
608                        case DD_MATRIX:
609                                {
610                                const CDDMatrix* pMat = (const CDDMatrix*)pItem;
611                                _snprintf(buffer, 8192, "=(matrix)");
612                                const float* pMatFloats = (const float*)pMat->m_Matrix.mat;
613                                for(unsigned int x = 0; x < 16; x++) _snprintf(buffer + strlen(buffer), 8192 - strlen(buffer), "%s%f", x ? "|" : "", pMatFloats[x]);
614                                _snprintf(buffer + strlen(buffer), 8192 - strlen(buffer), ";\r\n");
615                                strout.add(buffer);     
616                                } break;
617                        case DD_MATRIXLIST:
618                                {                               
619                                strout.add("=(matrixlist) {");
620                                const CDDMatrixList* pList = (const CDDMatrixList*)pItem;
621                                for(int i = 0;i < pList->m_iCount; i++)
622                                {
623                                        const CMatrix& Mat = pList->m_pValues[i];
624                                        _snprintf(buffer, 8192, "%s", (i>0 ? ", " : ""));
625                                        const float* pMatFloats = (const float*)Mat.mat;
626                                        for(unsigned int x = 0; x < 16; x++) _snprintf(buffer + strlen(buffer), 8192 - strlen(buffer), "%s%f", x ? "|" : "", pMatFloats[x]);
627                                        strout.add(buffer);
628                                }
629                                strout.add("};\r\n");
630                                } break;
631                }
632        }
633}
634
635// Merge this DDObject and another one
636void CDDObject::MergeWith(const CDDObject *pOther, bool bOverwrite)
637{
638        fastvector< fastmap< const CDDBase* >::SDataPair > lDataList=pOther->m_mData.iterate();
639
640        // Copy data
641        for(unsigned i=0;i<lDataList.size();i++)
642        {
643                if(lDataList[i].Data)
644                {
645                        CDDBase *pClone=lDataList[i].Data->Clone();
646                        if(pClone) 
647                        {
648                                // Check if we want to overwrite
649                                if(bOverwrite)
650                                {
651                                        const CDDBase *pOldItem=NULL;
652
653                                        // This map function will overwrite, if data exists and pOldItem will be valid
654                                        m_mData.map(lDataList[i].pszKey, pClone, pOldItem);
655                                        if(pOldItem) pOldItem->Release();
656                                        continue;
657                                }
658
659                                // If the item exists already, we skip the clone
660                                const CDDBase *pTemp;                   
661                                if(m_mData.find(lDataList[i].pszKey, pTemp)) 
662                                {
663                                        pClone->Release();
664                                        continue;
665                                }
666
667                                // Insert item
668                                m_mData.map(lDataList[i].pszKey, pClone);
669                        }
670                }
671        }       
672        m_bChanged=true;
673}
674
675// Make a new object, containing all changed or added keys,
676// compared to pOther.
677CDDObject *CDDObject::BuildChanges(const CDDObject *pOther) const
678{
679        CDDObject *pChanges=NULL; //new CDDObject;
680        fastvector<const char *>        lKeys=m_mData.keys();
681        for(unsigned iKey=0;iKey<lKeys.size();iKey++)
682        {
683                const CDDBase *pSrc, *pCompare=NULL;           
684                m_mData.find(lKeys[iKey], pSrc);
685                if(!pOther->m_mData.find(lKeys[iKey], pCompare) || pSrc->GetType()!=pCompare->GetType())
686                {
687                        if(!pChanges) pChanges=new CDDObject;
688                        pChanges->m_mData.map(lKeys[iKey], pSrc->Clone());
689                        continue;
690                }
691                bool bChanged=false;
692                switch(pSrc->GetType())
693                {
694                        case DD_OBJECT:
695                                {
696                                // Compare object and insert compared object
697                                CDDObject *pComp=((CDDObject*)pSrc)->BuildChanges((CDDObject*)pCompare);
698                                if(pComp) 
699                                {
700                                        if(!pChanges) pChanges=new CDDObject;
701                                        pChanges->m_mData.map(lKeys[iKey], pComp);             
702                                }
703                                } break;
704                        case DD_OBJLIST:
705                                {
706                                fastvector<const CDDObject *> &lSrcList=((CDDObjectList*)pSrc)->m_lList;
707                                fastvector<const CDDObject *> &lDstList=((CDDObjectList*)pCompare)->m_lList;
708                                if(lSrcList.size()!=lDstList.size())
709                                {
710                                        if(!pChanges) pChanges=new CDDObject;
711                                        pChanges->m_mData.map(lKeys[iKey], pCompare);   
712                                        pCompare->AddRef();
713                                } else
714                                {
715                                        for(unsigned i=0;i<lSrcList.size();i++)
716                                        {
717                                                CDDObject *pComp=lSrcList[i]->BuildChanges(lDstList[i]);
718                                                if(pComp)
719                                                {
720                                                        pComp->Release();
721                                                        if(!pChanges) pChanges=new CDDObject;
722                                                        pChanges->m_mData.map(lKeys[iKey], pCompare);           
723                                                        pCompare->AddRef();
724                                                        break;
725                                                }
726                                        }
727                                }
728                                } break;
729                        case DD_INT:
730                                if(((CDDInt*)(pSrc))->m_iValue!=((CDDInt*)(pCompare))->m_iValue) bChanged=true;
731                                break;
732                        case DD_INTLIST:
733                                break;
734                        case DD_FLOAT:
735                                if(((CDDFloat*)(pSrc))->m_fValue!=((CDDFloat*)(pCompare))->m_fValue) bChanged=true;
736                                break;
737                        case DD_FLOATLIST:
738                                break;
739                        case DD_STRING:
740                                if(strcmp(((CDDString*)(pSrc))->m_sValue,((CDDString*)(pCompare))->m_sValue)!=0) bChanged=true;
741                                break;
742                        case DD_STRINGLIST:
743                                {
744                                CDDStringList *pSrcList=(CDDStringList*)pSrc;
745                                CDDStringList *pCmpList=(CDDStringList*)pCompare;
746                                if(pSrcList->m_Value.size()!=pCmpList->m_Value.size()) bChanged=true;
747                                else
748                                {
749                                        for(unsigned iS=0;iS<pSrcList->m_Value.size();iS++)
750                                                if(pSrcList->m_Value[iS].compare(pCmpList->m_Value[iS])!=0) 
751                                                {
752                                                        bChanged=true;
753                                                        break;
754                                                }
755                                }
756                                } break;
757                        case DD_BINARY:
758                                break;
759                        case DD_VEC3:
760                                {
761                                const CDDVec3* pVec3S = (const CDDVec3*)pSrc;
762                                const CDDVec3* pVec3C = (const CDDVec3*)pCompare;
763                                if(memcmp(&pVec3S->m_Vec, &pVec3C->m_Vec, sizeof(CVec3))) bChanged = true;
764                                } break;
765                        case DD_VEC3LIST:
766                                break;
767                        case DD_BOOL:
768                                if(((CDDBool*)(pSrc))->m_bValue != ((CDDBool*)(pCompare))->m_bValue) bChanged = true;
769                                break;
770                        case DD_VEC2:
771                                {
772                                const CDDVec2* pVec2S = (const CDDVec2*)pSrc;
773                                const CDDVec2* pVec2C = (const CDDVec2*)pCompare;
774                                if(memcmp(&pVec2S->m_Vec, &pVec2C->m_Vec, sizeof(CVec2))) bChanged = true;
775                                } break;
776                        case DD_VEC4:
777                                {
778                                const CDDVec4* pVec4S = (const CDDVec4*)pSrc;
779                                const CDDVec4* pVec4C = (const CDDVec4*)pCompare;
780                                if(memcmp(&pVec4S->m_Vec, &pVec4C->m_Vec, sizeof(CVec4))) bChanged = true;
781                                } break;
782                        case DD_MATRIX:
783                                {
784                                const CDDMatrix* pMatS = (const CDDMatrix*)pSrc;
785                                const CDDMatrix* pMatC = (const CDDMatrix*)pCompare;
786                                if(memcmp(&pMatS->m_Matrix, &pMatC->m_Matrix, sizeof(CMatrix))) bChanged = true;
787                                } break;
788                        case DD_MATRIXLIST:
789                                break;
790                }
791                if(bChanged)
792                {
793                        if(!pChanges) pChanges=new CDDObject;
794                        pChanges->m_mData.map(lKeys[iKey], pSrc->Clone());             
795                }
796        }
797        return pChanges;
798}
799
800// Create a clone of the object instance
801CDDBase* CDDObject::Clone(void) const
802{
803        CDDObject *pClone=new CDDObject;
804        fastvector< fastmap< const CDDBase* >::SDataPair > lDataList=m_mData.iterate();
805
806        // Clone data
807        for(unsigned i=0;i<lDataList.size();i++)
808        {
809                if(lDataList[i].Data)
810                {
811                        pClone->m_mData.map(lDataList[i].pszKey, lDataList[i].Data->Clone());
812                }
813        }
814        return pClone;
815}
816
817// Set notifier instance. Use this to get notified when object data changes
818void CDDObject::AddNotifier(IDDNotify *pNotifier)
819{
820        m_lListeners.push_back(pNotifier);     
821}
822void CDDObject::RemoveNotifier(IDDNotify *pNotifier)
823{
824        for(unsigned i=0;i<m_lListeners.size();i++)
825        {
826                if(m_lListeners[i]==pNotifier)
827                {
828                        m_lListeners.erase(i);
829                        break;
830                }
831        }       
832}
833
834// Query Functions
835// ---------------
836
837// Retrieve a list of keys
838fastvector<const char *> CDDObject::GetKeyNames(void) const
839{
840        return m_mData.keys();
841}
842
843// Find out which type of data a key holds (DDUnknown if not found)
844EDDType CDDObject::GetKeyType(const char *pszID) const
845{
846        const CDDBase *pItem;
847        if(m_mData.find(pszID,pItem))
848        {
849                return pItem->GetType();
850        }
851        return DD_UNKNOWN;
852}
853
854// Get integer data
855int     CDDObject::GetInt(const char *pszID, int iDefValue) const
856{
857        const CDDBase *pItem;
858        if(m_mData.find(pszID,pItem))
859        {
860#ifdef GET_CHECK_TYPE
861                if(pItem->GetType()==DD_INT)
862#endif
863                        return ((const CDDInt*)(pItem))->m_iValue;             
864        }
865        return iDefValue;
866}
867// Get a list of integers
868int *CDDObject::GetIntList(const char *pszID, int &iElemCount) const
869{
870        const CDDBase *pItem;
871        if(m_mData.find(pszID,pItem))
872        {
873#ifdef GET_CHECK_TYPE
874                if(pItem->GetType()!=DD_INTLIST) return NULL;
875#endif
876                iElemCount=((const CDDIntList*)(pItem))->m_iCount;
877                return ((const CDDIntList*)(pItem))->m_pValues;         
878        }
879        return NULL;
880}
881
882// Get floating point data
883float CDDObject::GetFloat(const char *pszID, float fDefValue) const
884{
885        const CDDBase *pItem;
886        if(m_mData.find(pszID,pItem))
887        {
888#ifdef GET_CHECK_TYPE
889                if(pItem->GetType()==DD_FLOAT)
890#endif
891                return ((const CDDFloat*)(pItem))->m_fValue;           
892        }
893        return fDefValue;
894}
895// Get a list of floats
896float *CDDObject::GetFloatList(const char *pszID, int &iElemCount) const
897{
898        const CDDBase *pItem;
899        if(m_mData.find(pszID,pItem))
900        {
901#ifdef GET_CHECK_TYPE
902                if(pItem->GetType()!=DD_FLOATLIST) return NULL;
903#endif
904                iElemCount=((const CDDFloatList*)(pItem))->m_iCount;
905                return ((const CDDFloatList*)(pItem))->m_pValues;               
906        }
907        return NULL;
908}
909
910// Get string data
911const char *CDDObject::GetString(const char *pszID, const char *pszDefault) const
912{
913        const CDDBase *pItem;
914        if(m_mData.find(pszID,pItem))
915        {
916#ifdef GET_CHECK_TYPE
917                if(pItem->GetType()==DD_STRING)
918#endif
919                return ((const CDDString*)(pItem))->m_sValue;           
920        }
921        return pszDefault;
922}
923
924// Get string data
925vector<faststring> CDDObject::GetStringList(const char *pszID) const
926{
927        const CDDBase *pItem;
928        if(m_mData.find(pszID,pItem))
929        {
930#ifdef GET_CHECK_TYPE
931                if(pItem->GetType()==DD_STRINGLIST)
932#endif
933                return ((const CDDStringList*)(pItem))->m_Value;               
934        }
935        vector<faststring> lEmpty;
936        return lEmpty;
937}
938
939// Get a DDObject
940CDDObject* CDDObject::GetDDObject(const char *pszID) const
941{
942        const CDDBase *pItem;
943        if(m_mData.find(pszID,pItem))
944        {
945#ifdef GET_CHECK_TYPE
946                if(pItem->GetType()==DD_OBJECT)
947#endif
948                return (CDDObject*)(pItem);             
949        }
950        return NULL;
951}
952
953// Get a DDObject List
954fastvector<const CDDObject*> CDDObject::GetDDList(const char *pszID) const
955{
956        fastvector<const CDDObject*> lEmpty;
957        const CDDBase *pItem;
958        if(m_mData.find(pszID,pItem))
959        {
960#ifdef GET_CHECK_TYPE
961                if(pItem->GetType()!=DD_OBJLIST) return lEmpty;
962#endif
963                return ((const CDDObjectList*)(pItem))->m_lList;               
964        }
965        return lEmpty;
966}
967
968// Get binary data
969const void *CDDObject::GetBinary(const char *pszID, int &iByteLength) const
970{
971        const CDDBase *pItem;
972        if(m_mData.find(pszID,pItem))
973        {
974#ifdef GET_CHECK_TYPE
975                if(pItem->GetType()!=DD_BINARY) return NULL;
976#endif
977                iByteLength=((const CDDBinary*)(pItem))->m_iSize;
978                return ((const CDDBinary*)(pItem))->m_pData;           
979        }
980        return NULL;
981}
982
983// Get vec3 data
984CVec3 CDDObject::GetVec3(const char *pszID, const CVec3& vDefValue) const
985{
986        const CDDBase *pItem;
987        if(m_mData.find(pszID,pItem))
988        {
989#ifdef GET_CHECK_TYPE
990                if(pItem->GetType()==DD_VEC3)
991#endif
992                return ((const CDDVec3*)(pItem))->m_Vec;
993        }
994        return vDefValue;
995}
996// Get a list of vec3's
997CVec3* CDDObject::GetVec3List(const char *pszID, int &iElemCount) const
998{
999        const CDDBase *pItem;
1000        if(m_mData.find(pszID,pItem))
1001        {
1002#ifdef GET_CHECK_TYPE
1003                if(pItem->GetType()!=DD_VEC3LIST) return NULL;
1004#endif
1005                iElemCount=((const CDDVec3List*)(pItem))->m_iCount;
1006                return ((const CDDVec3List*)(pItem))->m_pValues;               
1007        }
1008        return NULL;
1009}
1010
1011// Get boolean data
1012bool CDDObject::GetBool(const char *pszID, bool bDefValue) const
1013{
1014        const CDDBase *pItem;
1015        if(m_mData.find(pszID,pItem))
1016        {
1017#ifdef GET_CHECK_TYPE
1018                if(pItem->GetType()==DD_BOOL)
1019#endif
1020                        return ((const CDDBool*)(pItem))->m_bValue;             
1021        }
1022        return bDefValue;
1023}
1024
1025// Get vec2 data
1026CVec2 CDDObject::GetVec2(const char *pszID, const CVec2& vDefValue) const
1027{
1028        const CDDBase *pItem;
1029        if(m_mData.find(pszID,pItem))
1030        {
1031#ifdef GET_CHECK_TYPE
1032                if(pItem->GetType()==DD_VEC2)
1033#endif
1034                return ((const CDDVec2*)(pItem))->m_Vec;
1035        }
1036        return vDefValue;
1037}
1038
1039// Get vec4 data
1040CVec4 CDDObject::GetVec4(const char *pszID, const CVec4& vDefValue) const
1041{
1042        const CDDBase *pItem;
1043        if(m_mData.find(pszID,pItem))
1044        {
1045#ifdef GET_CHECK_TYPE
1046                if(pItem->GetType()==DD_VEC4)
1047#endif
1048                return ((const CDDVec4*)(pItem))->m_Vec;
1049        }
1050        return vDefValue;
1051}
1052// Get a list of vec4's
1053CVec4* CDDObject::GetVec4List(const char *pszID, int &iElemCount) const
1054{
1055        const CDDBase *pItem;
1056        if(m_mData.find(pszID,pItem))
1057        {
1058#ifdef GET_CHECK_TYPE
1059                if(pItem->GetType()!=DD_VEC4LIST) return NULL;
1060#endif
1061                iElemCount=((const CDDVec4List*)(pItem))->m_iCount;
1062                return ((const CDDVec4List*)(pItem))->m_pValues;               
1063        }
1064        return NULL;
1065}
1066
1067// Get matrix data
1068CMatrix CDDObject::GetMatrix(const char *pszID, const CMatrix& mDefValue) const
1069{
1070        const CDDBase *pItem;
1071        if(m_mData.find(pszID,pItem))
1072        {
1073#ifdef GET_CHECK_TYPE
1074                if(pItem->GetType()==DD_MATRIX)
1075#endif
1076                return ((const CDDMatrix*)(pItem))->m_Matrix;
1077        }
1078        return mDefValue;
1079}
1080// Get a list of matrices
1081CMatrix* CDDObject::GetMatrixList(const char *pszID, int &iElemCount) const
1082{
1083        const CDDBase *pItem;
1084        if(m_mData.find(pszID,pItem))
1085        {
1086#ifdef GET_CHECK_TYPE
1087                if(pItem->GetType()!=DD_MATRIXLIST) return NULL;
1088#endif
1089                iElemCount=((const CDDMatrixList*)(pItem))->m_iCount;
1090                return ((const CDDMatrixList*)(pItem))->m_pValues;             
1091        }
1092        return NULL;
1093}
1094
1095// Data Store functions
1096// ---------------------------
1097
1098// Store integer       
1099void CDDObject::SetInt(const char *pszID, int iData)
1100{
1101        const CDDBase *pOld=NULL;
1102        m_mData.map(pszID, new CDDInt(iData), pOld);
1103        if(pOld) pOld->Release();
1104        m_bChanged=true;
1105        NOTIFY_CHANGE(pszID);   
1106}
1107// Set a list of integers
1108void CDDObject::SetIntList(const char *pszID, const int *pValues, int iCount)
1109{
1110        const CDDBase *pOld=NULL;
1111        m_mData.map(pszID, new CDDIntList(pValues, iCount), pOld);
1112        if(pOld) pOld->Release();
1113        m_bChanged=true;
1114        NOTIFY_CHANGE(pszID);
1115}
1116void CDDObject::SetIntList(const char *pszID, fastvector<int> &lList)
1117{
1118        SetIntList(pszID, &lList[0], lList.size());
1119}
1120
1121// Store float 
1122void CDDObject::SetFloat(const char *pszID, float fData)
1123{
1124        const CDDBase *pOld=NULL;
1125        m_mData.map(pszID, new CDDFloat(fData), pOld);
1126        if(pOld) pOld->Release();
1127        NOTIFY_CHANGE(pszID);   
1128
1129}
1130// Set a list of floats
1131void CDDObject::SetFloatList(const char *pszID, const float *pValues, int iCount)
1132{
1133        const CDDBase *pOld=NULL;
1134        m_mData.map(pszID, new CDDFloatList(pValues, iCount), pOld);
1135        if(pOld) pOld->Release();
1136        NOTIFY_CHANGE(pszID);   
1137
1138}
1139void CDDObject::SetFloatList(const char *pszID, fastvector<float> &lList)
1140{
1141        SetFloatList(pszID, &lList[0], lList.size());
1142}
1143
1144// Store string
1145void CDDObject::SetString(const char *pszID, const char *pszData)
1146{
1147        const CDDBase *pOld=NULL;
1148        m_mData.map(pszID, new CDDString(pszData), pOld);
1149        if(pOld) pOld->Release();
1150        NOTIFY_CHANGE(pszID);   
1151
1152}
1153
1154// Store stringlist
1155void CDDObject::SetStringList(const char *pszID, vector<faststring> &lList)
1156{
1157        const CDDBase *pOld=NULL;
1158        m_mData.map(pszID, new CDDStringList(lList), pOld);
1159        if(pOld) pOld->Release();
1160        NOTIFY_CHANGE(pszID);   
1161
1162}
1163
1164// Store DDObject
1165void CDDObject::SetDDObject(const char *pszID, const CDDObject *pObj)
1166{
1167        const CDDBase *pOld=NULL;
1168        pObj->AddRef();
1169        m_mData.map(pszID, pObj, pOld);
1170        if(pOld) pOld->Release();
1171        NOTIFY_CHANGE(pszID);
1172
1173}
1174
1175// Store DDObject List
1176void CDDObject::SetDDList(const char *pszID, fastvector<const CDDObject *> &lList, bool bAddRef)
1177{
1178        const CDDBase *pOld=NULL;
1179        m_mData.map(pszID, new CDDObjectList(lList, bAddRef), pOld);   
1180        if(pOld) pOld->Release();
1181        NOTIFY_CHANGE(pszID);
1182
1183}
1184
1185// Set a list of floats
1186void CDDObject::SetBinary(const char *pszID, const void *pData, unsigned iSize)
1187{
1188        const CDDBase *pOld=NULL;
1189        m_mData.map(pszID, new CDDBinary(pData, (int)iSize), pOld);
1190        if(pOld) pOld->Release();
1191        NOTIFY_CHANGE(pszID);
1192
1193}
1194
1195// Store vec3
1196void CDDObject::SetVec3(const char *pszID, const CVec3& vVec)
1197{
1198        const CDDBase *pOld=NULL;
1199        m_mData.map(pszID, new CDDVec3(vVec.x, vVec.y, vVec.z), pOld);
1200        if(pOld) pOld->Release();
1201        NOTIFY_CHANGE(pszID);
1202
1203}
1204// Set a list of vec3's
1205void CDDObject::SetVec3List(const char *pszID, const CVec3* pValues, int iCount)
1206{
1207        const CDDBase *pOld=NULL;
1208        m_mData.map(pszID, new CDDVec3List(pValues, iCount), pOld);
1209        if(pOld) pOld->Release();
1210        NOTIFY_CHANGE(pszID);
1211
1212}
1213
1214// Store boolean
1215void CDDObject::SetBool(const char *pszID, bool bData)
1216{
1217        const CDDBase *pOld=NULL;
1218        m_mData.map(pszID, new CDDBool(bData), pOld);
1219        if(pOld) pOld->Release();
1220        NOTIFY_CHANGE(pszID);
1221
1222}
1223
1224// Store vec2
1225void CDDObject::SetVec2(const char *pszID, const CVec2& vVec)
1226{
1227        const CDDBase *pOld=NULL;
1228        m_mData.map(pszID, new CDDVec2(vVec.x, vVec.y), pOld);
1229        if(pOld) pOld->Release();
1230        NOTIFY_CHANGE(pszID);
1231
1232}
1233
1234// Store vec4
1235void CDDObject::SetVec4(const char *pszID, const CVec4& vVec)
1236{
1237        const CDDBase *pOld=NULL;
1238        m_mData.map(pszID, new CDDVec4(vVec.x, vVec.y, vVec.z, vVec.w), pOld);
1239        if(pOld) pOld->Release();
1240        NOTIFY_CHANGE(pszID);
1241
1242}
1243// Set a list of vec4's
1244void CDDObject::SetVec4List(const char *pszID, const CVec4* pValues, int iCount)
1245{
1246        const CDDBase *pOld=NULL;
1247        m_mData.map(pszID, new CDDVec4List(pValues, iCount), pOld);
1248        if(pOld) pOld->Release();
1249        NOTIFY_CHANGE(pszID);
1250
1251}
1252
1253// Store matrix
1254void CDDObject::SetMatrix(const char *pszID, const CMatrix& mMat)
1255{
1256        const CDDBase *pOld=NULL;
1257        m_mData.map(pszID, new CDDMatrix((const float*)mMat.mat), pOld);
1258        if(pOld) pOld->Release();
1259        NOTIFY_CHANGE(pszID);
1260
1261}
1262// Set a list of matrices
1263void CDDObject::SetMatrixList(const char *pszID, const CMatrix* pValues, int iCount)
1264{
1265        const CDDBase *pOld=NULL;
1266        m_mData.map(pszID, new CDDMatrixList(pValues, iCount), pOld);
1267        if(pOld) pOld->Release();
1268        NOTIFY_CHANGE(pszID);
1269}
1270
1271
1272
Note: See TracBrowser for help on using the repository browser.