fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Material / Base / OSGChunkMaterial.cpp
blob8d39e23add843d7c46cbc6796d52feea8e8a1caf
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright(C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include "OSGGL.h"
50 #include "OSGState.h"
51 #include "OSGMaterialDrawable.h"
53 #include "OSGChunkMaterial.h"
54 #include "OSGChunkBlock.h"
56 OSG_USING_NAMESPACE
58 // Documentation for this class is emited in the
59 // OSGChunkMaterialBase.cpp file.
60 // To modify it, please change the .fcd file (OSGChunkMaterial.fcd) and
61 // regenerate the base file.
63 /***************************************************************************\
64 * Class methods *
65 \***************************************************************************/
67 /*-------------------------------------------------------------------------*\
68 - private -
69 \*-------------------------------------------------------------------------*/
71 void ChunkMaterial::initMethod(InitPhase ePhase)
73 Inherited::initMethod(ePhase);
76 /***************************************************************************\
77 * Instance methods *
78 \***************************************************************************/
80 /*------------- constructors & destructors --------------------------------*/
82 ChunkMaterial::ChunkMaterial(void) :
83 Inherited()
87 ChunkMaterial::ChunkMaterial(const ChunkMaterial &source) :
88 Inherited(source)
92 ChunkMaterial::~ChunkMaterial(void)
96 void ChunkMaterial::pushToChunks(StateChunk * const value)
98 if(value == NULL)
99 return;
101 editMField(ChunksFieldMask, _mfChunks);
103 _mfChunks.push_back(value);
106 #if 0
107 void ChunkMaterial::assignChunks (const MFUnrecStateChunkPtr &value)
109 MFUnrecStateChunkPtr::const_iterator elemIt =
110 value.begin();
111 MFUnrecStateChunkPtr::const_iterator elemEnd =
112 value.end ();
114 static_cast<ChunkMaterial *>(this)->clearChunks();
116 while(elemIt != elemEnd)
118 this->pushToChunks(*elemIt);
120 ++elemIt;
123 #endif
125 void ChunkMaterial::removeFromChunks(UInt32 uiIndex)
127 if(uiIndex < _mfChunks.size())
129 editMField(ChunksFieldMask, _mfChunks);
132 MFUnrecStateChunkPtr::iterator fieldIt = _mfChunks.begin_nc();
134 fieldIt += uiIndex;
137 _mfChunks.erase(uiIndex);
139 if(uiIndex < _mfSlots.size())
141 editMField(SlotsFieldMask, _mfSlots );
143 MFInt32::iterator slotIt = _mfSlots.begin();
145 slotIt += uiIndex;
147 _mfSlots.erase(slotIt);
152 void ChunkMaterial::removeFromChunksByObj(StateChunk * const value)
154 Int32 iElemIdx = _mfChunks.findIndex(value);
156 if(iElemIdx != -1)
158 editMField(ChunksFieldMask, _mfChunks);
161 MFUnrecStateChunkPtr::iterator fieldIt = _mfChunks.begin_nc();
163 fieldIt += iElemIdx;
166 _mfChunks.erase(iElemIdx);
168 if(iElemIdx < Int32(_mfSlots.size()))
170 editMField(SlotsFieldMask, _mfSlots );
172 MFInt32::iterator slotIt = _mfSlots.begin();
174 slotIt += iElemIdx;
176 _mfSlots.erase(slotIt);
181 void ChunkMaterial::replaceChunk(UInt32 uiIndex,
182 StateChunk * const value )
184 if(uiIndex < _mfChunks.size() && value != NULL)
186 editMField(ChunksFieldMask, _mfChunks);
188 _mfChunks.replace(uiIndex, value);
193 void ChunkMaterial::changed(ConstFieldMaskArg whichField,
194 UInt32 origin,
195 BitVector details)
197 Inherited::changed(whichField, origin, details);
201 /*-------------------------- your_category---------------------------------*/
203 /*! Add the given chunk to the material. It is possible to specify
204 which slot this chunk should be associated with. See \ref StateChunkClass
205 for a general description of the slots concept. The default slot is
206 State::AutoSlotReplace.
209 bool ChunkMaterial::addChunk(StateChunk *chunk, Int32 slot)
211 if(chunk == NULL)
212 return false;
214 if(slot != State::AutoSlotReplace)
216 editMField(SlotsFieldMask, _mfSlots);
218 while(_mfSlots.size() < _mfChunks.size())
219 _mfSlots.push_back(State::AutoSlotReplace);
222 editMField(ChunksFieldMask, _mfChunks);
224 _mfChunks.push_back(chunk);
226 if(slot != State::AutoSlotReplace)
228 editMField(SlotsFieldMask, _mfSlots);
230 _mfSlots.push_back(slot);
233 return true;
236 /*! Remove the given chunk from the material. If the slot is not
237 State::AutoSlotReplace, only the given slot will be searched and
238 removed if found. Returns true if the chunk couldn't be found. */
240 bool ChunkMaterial::subChunk(StateChunk *chunk, Int32 slot)
242 UInt32 i;
244 const ChunkMaterial *pThis = this;
246 for(i = 0; i < _mfChunks.size(); ++i)
248 if(pThis->_mfChunks[i] == chunk &&
249 ((i < _mfSlots.size() && pThis->_mfSlots[i] == slot) ||
250 slot == State::AutoSlotReplace))
252 editMField(ChunksFieldMask, _mfChunks);
254 _mfChunks.erase(i);
256 if(i < _mfSlots.size())
258 editMField(SlotsFieldMask, _mfSlots);
260 _mfSlots.erase(_mfSlots.begin() + i);
263 return false;
267 SWARNING << "ChunkMaterial::subChunk(" << this << ") has no chunk "
268 << chunk << " with slot " << slot << std::endl;
270 return true;
273 /*! Add the given chunk to the material at a certain index. It is possible to
274 specify which slot this chunk should be associated with.
275 See \ref StateChunkClass for a general description of the slots concept.
276 The default slot is State::AutoSlotReplace. */
278 bool ChunkMaterial::insertChunk(StateChunk *chunk, UInt32 chunkIndex, Int32 slot)
280 if(chunk == NULL)
281 return false;
283 // push back chunk
284 if(chunkIndex >= _mfChunks.size())
285 return addChunk(chunk, slot);
287 if(slot != State::AutoSlotReplace)
289 editMField(SlotsFieldMask, _mfSlots);
291 while(_mfSlots.size() < chunkIndex+1)
292 _mfSlots.push_back(State::AutoSlotReplace);
294 _mfSlots.insert(_mfSlots.begin()+chunkIndex, slot);
296 else
298 if(_mfSlots.size() > chunkIndex)
300 editMField(SlotsFieldMask, _mfSlots);
302 _mfSlots.insert(_mfSlots.begin()+chunkIndex, slot);
306 editMField(ChunksFieldMask, _mfChunks);
308 _mfChunks.insert(_mfChunks.begin_nc() + chunkIndex, chunk);
310 return true;
313 /*! Retrieve slot information from the given chunk. Returns false if the
314 chunk couldn't be found. */
316 bool ChunkMaterial::getChunkSlot(StateChunk *chunk, Int32 &slot) const
318 if(chunk == NULL)
319 return false;
321 Int32 chunkIndex = this->find(chunk);
323 if(chunkIndex < 0)
324 return false;
326 if(Int32(_mfSlots.size()) <= chunkIndex)
327 slot = State::AutoSlotReplace;
328 else
329 slot = _mfSlots[chunkIndex];
331 return true;
334 /*! Update slot information for the given chunk. Returns false if the
335 chunk couldn't be found. */
337 bool ChunkMaterial::setChunkSlot(StateChunk *chunk, Int32 slot)
339 if(chunk == NULL)
340 return false;
342 Int32 chunkIndex = this->find(chunk);
344 if(chunkIndex < 0)
345 return false;
347 editMField(SlotsFieldMask, _mfSlots);
349 while(Int32(_mfSlots.size()) <= chunkIndex)
350 _mfSlots.push_back(State::AutoSlotReplace);
352 _mfSlots[chunkIndex] = slot;
354 return true;
357 /*! Search the list of chunks for the given chunk. Returns its index, -1
358 if the chunk is not used in the material.
361 Int32 ChunkMaterial::find(StateChunk *chunk) const
363 UInt32 i;
365 for(i = 0; i < _mfChunks.size(); ++i)
367 if(_mfChunks[i] == chunk)
368 return i;
371 return -1;
374 /*! Search the list of chunks for a chunk of the given type and the given
375 slot. If slot is State::AutoSlotReplace, all slots are searched and the
376 first found chunk is returned.
377 For searching a specific chunk with a AutoSlotReplace slot,
378 the slot parameter is interpreted as a index.
381 StateChunk *ChunkMaterial::find(const FieldContainerType &type,
382 Int32 slot) const
384 UInt32 index = 0;
386 for(UInt32 i = 0; i < _mfChunks.size(); ++i)
388 StateChunk *p = _mfChunks[i];
390 Int32 s = State::AutoSlotReplace;
392 if(i < getMFSlots()->size())
393 s = getSlots(i);
395 if(s == State::AutoSlotReplace)
396 s = index;
398 if(p->getType() == type)
400 if(slot == State::AutoSlotReplace || slot == s)
401 return (p);
403 ++index;
407 return NULL;
410 #if 0
411 bool ChunkMaterial::operator==(const ChunkMaterial &other) const
413 return Inherited::operator==(other);
415 #endif
417 void ChunkMaterial::clearChunks(void)
419 editMField(ChunksFieldMask, _mfChunks);
420 editMField(SlotsFieldMask, _mfSlots );
422 _mfChunks.clear();
423 _mfSlots .clear();
426 void ChunkMaterial::fill(ChunkBlock *pBlock)
428 if(pBlock == NULL)
429 return;
431 pBlock->clearChunks();
433 const MFUnrecStateChunkPtr *chunks = this->getMFChunks();
434 const MFInt32 *slots = this->getMFSlots ();
436 for(SizeT i = 0; i < chunks->size(); ++i)
438 int slot = i < slots->size() ?
439 (*slots)[i] :
440 State::AutoSlotReplace;
442 StateChunk *chunk = (*chunks)[i];
444 if(chunk != NULL)
445 pBlock->addChunk(chunk, slot);
450 /*! Add chunks to the given state. Needed for ordering in the drived
451 materials.
454 void ChunkMaterial::addChunks(State *state) const
456 UInt32 i;
458 for(i = 0; i < _mfChunks.size(); ++i)
460 state->addChunk(_mfChunks[i],
461 (i < _mfSlots.size()) ? _mfSlots[i]
462 : State::AutoSlotReplace);
466 /*! Rebuild the internal State. Just collects the chunks in the State.
469 void ChunkMaterial::rebuildState(void)
471 FDEBUG(("ChunkMat::rebuild state\n"));
473 if(_pState != NULL)
475 _pState->clearChunks();
477 else
479 _pState = State::createLocal();
481 _pState->setDefaultSortKey(this->getId());
485 _pState->setCoreGLChunkLimit(_sfCoreGLChunkLimit.getValue());
486 _pState->setTransparencyMode(_sfTransparencyMode.getValue());
488 addChunks(_pState);
491 /*! Check if the Material (i.e. any of its chunks) is transparent..
494 bool ChunkMaterial::isTransparent(void) const
496 Int32 tm = getTransparencyMode();
498 if(tm != Material::TransparencyAutoDetection)
500 return (tm == Material::TransparencyForceTransparent);
503 bool returnValue = false;
505 MFChunksType::const_iterator chunksIt = _mfChunks.begin();
506 MFChunksType::const_iterator chunksEnd = _mfChunks.end ();
508 for(; chunksIt != chunksEnd && returnValue == false; ++chunksIt)
510 returnValue = (*chunksIt)->isTransparent();
513 return returnValue;
516 /*------------------------------- dump ----------------------------------*/
518 void ChunkMaterial::dump( UInt32 OSG_CHECK_ARG(uiIndent),
519 const BitVector OSG_CHECK_ARG(bvFlags )) const
521 SLOG << "ChunkMaterial at " << this << std::endl;
522 SLOG << "Chunks: " << std::endl;
524 UInt32 i;
526 for(i = 0; i < _mfChunks.size(); ++i)
528 SLOG << _mfChunks[i] << " "
529 << static_cast<Int32>((i < _mfSlots.size())
530 ? _mfSlots[i]
531 : State::AutoSlotReplace)
532 << std::endl;