csplugincommon/rendermanager/operations.h
Go to the documentation of this file.00001 /* 00002 Copyright (C) 2007-2008 by Marten Svanfeldt 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_OPERATIONS_H__ 00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_OPERATIONS_H__ 00021 00027 #include "csplugincommon/rendermanager/rendertree.h" 00028 #include "csutil/set.h" 00029 #include "csutil/compositefunctor.h" 00030 00031 namespace CS 00032 { 00033 namespace RenderManager 00034 { 00035 //-- Tags for information about operations 00037 struct OperationUnordered {}; 00039 struct OperationNumbered {}; 00041 struct OperationUnorderedParallel {}; 00043 struct OperationNumberedParallel {}; 00044 00045 00046 namespace Implementation 00047 { 00052 template<typename IterationObject> 00053 struct NoOperationBlock 00054 { 00055 void Reset () const 00056 {} 00057 00058 bool operator() (IterationObject) const 00059 { 00060 return false; 00061 } 00062 }; 00063 00068 template<typename IterationObject> 00069 struct OnceOperationBlock 00070 { 00071 void Reset () 00072 { 00073 objectSet.Empty (); 00074 } 00075 00076 bool operator() (IterationObject obj) 00077 { 00078 if (objectSet.In (obj)) 00079 return true; 00080 00081 objectSet.AddNoTest (obj); 00082 return false; 00083 } 00084 00085 csSet<IterationObject> objectSet; 00086 }; 00087 00092 template<typename IterationObject> 00093 struct OnceOperationBlockRef 00094 { 00095 OnceOperationBlockRef (csSet<IterationObject>& set) 00096 : objectSet (set) 00097 {} 00098 00099 void Reset () 00100 { 00101 objectSet.Empty (); 00102 } 00103 00104 bool operator() (IterationObject obj) 00105 { 00106 if (objectSet.In (obj)) 00107 return true; 00108 00109 objectSet.AddNoTest (obj); 00110 return false; 00111 } 00112 00113 csSet<IterationObject>& objectSet; 00114 }; 00115 00120 #if defined (CS_COMPILER_MSVC) && _MSC_VER < 1310 00121 template<typename Fn, typename OperationBlock> 00122 struct OperationCallerWorkAround 00123 { 00124 00128 template<typename Type> 00129 struct OperationCaller {}; 00130 00134 template<> 00135 struct OperationCaller<OperationUnordered> 00136 { 00137 OperationCaller (Fn& fn, OperationBlock& block) 00138 : function (fn), block (block) 00139 {} 00140 00141 template<typename ObjectType> 00142 void operator() (const ObjectType& context) 00143 { 00144 if (!block (context)) 00145 function (context); 00146 } 00147 00148 Fn& function; 00149 OperationBlock block; 00150 }; 00151 00155 template<> 00156 struct OperationCaller<OperationNumbered> 00157 { 00158 OperationCaller (Fn& fn, OperationBlock& block) 00159 : function (fn), block (block), index (0) 00160 {} 00161 00162 template<typename ObjectType> 00163 void operator() (const ObjectType& context) 00164 { 00165 if (!block (context)) 00166 function (index, context); 00167 index++; 00168 } 00169 00170 Fn& function; 00171 OperationBlock block; 00172 size_t index; 00173 }; 00174 00175 00176 00180 template<> 00181 struct OperationCaller<OperationUnorderedParallel> 00182 { 00183 OperationCaller (Fn& fn, OperationBlock& block) 00184 : function (fn), block (block) 00185 {} 00186 00187 template<typename ObjectType> 00188 void operator() (const ObjectType& context) 00189 { 00190 if (!block (context)) 00191 function (context); 00192 } 00193 00194 Fn& function; 00195 OperationBlock block; 00196 }; 00197 00201 template<> 00202 struct OperationCaller<OperationNumberedParallel> 00203 { 00204 OperationCaller (Fn& fn, OperationBlock& block) 00205 : function (fn), block (block), index (0) 00206 {} 00207 00208 template<typename ObjectType> 00209 void operator() (const ObjectType& context) 00210 { 00211 if (!block (context)) 00212 function (index, context); 00213 index++; 00214 } 00215 00216 Fn& function; 00217 OperationBlock block; 00218 size_t index; 00219 }; 00220 00221 00222 }; 00223 00224 template<typename Fn, typename OperationBlock, typename Type> 00225 struct OperationCaller : 00226 public OperationCallerWorkAround<Fn, OperationBlock>::OperationCaller<Type> 00227 { 00228 OperationCaller (Fn& fn, OperationBlock& block) 00229 : OperationCallerWorkAround<Fn, OperationBlock>::OperationCaller<Type> (fn, block) 00230 {} 00231 }; 00232 #else 00233 00236 template<typename Fn, typename OperationBlock, typename Type> 00237 struct OperationCaller 00238 {}; 00239 00243 template<typename Fn, typename OperationBlock> 00244 struct OperationCaller<Fn, OperationBlock, OperationUnordered> 00245 { 00246 OperationCaller (Fn& fn, OperationBlock& block) 00247 : function (fn), block (block) 00248 {} 00249 00250 template<typename ObjectType> 00251 void operator() (const ObjectType& context) 00252 { 00253 if (!block (context)) 00254 function (context); 00255 } 00256 00257 Fn& function; 00258 OperationBlock block; 00259 }; 00260 00264 template<typename Fn, typename OperationBlock> 00265 struct OperationCaller<Fn, OperationBlock, OperationNumbered> 00266 { 00267 OperationCaller (Fn& fn, OperationBlock& block) 00268 : function (fn), block (block), index (0) 00269 {} 00270 00271 template<typename ObjectType> 00272 void operator() (const ObjectType& context) 00273 { 00274 if (!block (context)) 00275 function (index, context); 00276 index++; 00277 } 00278 00279 Fn& function; 00280 OperationBlock block; 00281 size_t index; 00282 }; 00283 00287 template<typename Fn, typename OperationBlock> 00288 struct OperationCaller<Fn, OperationBlock, OperationUnorderedParallel> 00289 { 00290 OperationCaller (Fn& fn, OperationBlock& block) 00291 : function (fn), block (block) 00292 {} 00293 00294 template<typename ObjectType> 00295 void operator() (const ObjectType& context) 00296 { 00297 if (!block (context)) 00298 function (context); 00299 } 00300 00301 Fn& function; 00302 OperationBlock block; 00303 }; 00304 00308 template<typename Fn, typename OperationBlock> 00309 struct OperationCaller<Fn, OperationBlock, OperationNumberedParallel> 00310 { 00311 OperationCaller (Fn& fn, OperationBlock& block) 00312 : function (fn), block (block), index (0) 00313 {} 00314 00315 template<typename ObjectType> 00316 void operator() (const ObjectType& context) 00317 { 00318 if (!block (context)) 00319 function (index, context); 00320 index++; 00321 } 00322 00323 Fn& function; 00324 OperationBlock block; 00325 size_t index; 00326 }; 00327 00328 #endif 00329 00330 // Helper lookups.. oh god save me from this code... 00331 template<typename Traits1, typename Traits2> 00332 struct OperationTraitsCombiner 00333 { 00334 // Invalid combination 00335 }; 00336 00337 template<> 00338 struct OperationTraitsCombiner<OperationUnordered, OperationUnordered> 00339 { 00340 typedef OperationUnordered Result; 00341 }; 00342 00343 template<> 00344 struct OperationTraitsCombiner<OperationNumbered, OperationNumbered> 00345 { 00346 typedef OperationNumbered Result; 00347 }; 00348 00349 template<> 00350 struct OperationTraitsCombiner<OperationUnorderedParallel, OperationUnorderedParallel> 00351 { 00352 typedef OperationUnorderedParallel Result; 00353 }; 00354 00355 template<> 00356 struct OperationTraitsCombiner<OperationNumberedParallel, OperationNumberedParallel> 00357 { 00358 typedef OperationNumberedParallel Result; 00359 }; 00360 00361 template<> 00362 struct OperationTraitsCombiner<OperationUnorderedParallel, OperationUnordered> 00363 { 00364 typedef OperationUnordered Result; 00365 }; 00366 template<> 00367 struct OperationTraitsCombiner<OperationUnordered, OperationUnorderedParallel> 00368 { 00369 typedef OperationUnordered Result; 00370 }; 00371 00372 template<> 00373 struct OperationTraitsCombiner<OperationNumberedParallel, OperationNumbered> 00374 { 00375 typedef OperationNumbered Result; 00376 }; 00377 template<> 00378 struct OperationTraitsCombiner<OperationNumbered, OperationNumberedParallel> 00379 { 00380 typedef OperationNumbered Result; 00381 }; 00382 } 00383 00388 template<typename T> 00389 struct OperationTraits 00390 { 00391 typedef OperationUnordered Ordering; 00392 }; 00393 00395 00398 template<typename Fn1, typename Fn2> 00399 struct OperationTraits<CS::Meta::CompositeFunctorType2<Fn1, Fn2> > 00400 { 00401 typedef typename Implementation::OperationTraitsCombiner< 00402 typename OperationTraits<Fn1>::Ordering, typename OperationTraits<Fn2>::Ordering 00403 >::Result Ordering; 00404 }; 00405 00409 template<typename Fn1, typename Fn2, typename Fn3> 00410 struct OperationTraits<CS::Meta::CompositeFunctorType3<Fn1, Fn2, Fn3> > 00411 { 00412 typedef typename Implementation::OperationTraitsCombiner< 00413 typename OperationTraits<Fn1>::Ordering, typename OperationTraits<Fn2>::Ordering 00414 >::Result Ordering1; 00415 00416 typedef typename Implementation::OperationTraitsCombiner< 00417 Ordering1, typename OperationTraits<Fn3>::Ordering 00418 >::Result Ordering; 00419 }; 00421 00422 00424 00429 template<typename RenderTree, typename Fn> 00430 void ForEachContext (RenderTree& tree, Fn& fn) 00431 { 00432 // Iterate over all contexts, calling the functor for each one 00433 typename RenderTree::ContextNodeArrayIteratorType it = tree.GetContextIterator (); 00434 00435 Implementation::NoOperationBlock<typename RenderTree::ContextNode*> noBlock; 00436 // Helper object for calling function 00437 Implementation::OperationCaller< 00438 Fn, 00439 Implementation::NoOperationBlock<typename RenderTree::ContextNode*>, 00440 typename OperationTraits<Fn>::Ordering 00441 > caller (fn, noBlock); 00442 00443 while (it.HasNext ()) 00444 { 00445 typename RenderTree::ContextNode* context = it.Next (); 00446 CS_ASSERT_MSG("Null context encountered, should not be possible", context); 00447 00448 caller (context); 00449 } 00450 } 00451 00456 template<typename RenderTree, typename Fn, typename Blocker> 00457 void ForEachContext (RenderTree& tree, Fn& fn, Blocker& block) 00458 { 00459 // Iterate over all contexts, calling the functor for each one 00460 typename RenderTree::ContextNodeArrayIteratorType it = tree.GetContextIterator (); 00461 00462 // Helper object for calling function 00463 Implementation::OperationCaller< 00464 Fn, 00465 Blocker, 00466 typename OperationTraits<Fn>::Ordering 00467 > caller (fn, block); 00468 00469 while (it.HasNext ()) 00470 { 00471 typename RenderTree::ContextNode* context = it.Next (); 00472 CS_ASSERT_MSG("Null context encountered, should not be possible", context); 00473 00474 caller (context); 00475 } 00476 } 00477 00482 template<typename RenderTree, typename Fn> 00483 void ForEachContextReverse (RenderTree& tree, Fn& fn) 00484 { 00485 // Iterate over all contexts, calling the functor for each one 00486 typename RenderTree::ContextNodeArrayReverseIteratorType it = tree.GetReverseContextIterator (); 00487 00488 Implementation::NoOperationBlock<typename RenderTree::ContextNode*> noBlock; 00489 // Helper object for calling function 00490 Implementation::OperationCaller< 00491 Fn, 00492 Implementation::NoOperationBlock<typename RenderTree::ContextNode*>, 00493 typename OperationTraits<Fn>::Ordering 00494 > caller (fn, noBlock); 00495 00496 while (it.HasNext ()) 00497 { 00498 typename RenderTree::ContextNode* context = it.Next (); 00499 CS_ASSERT_MSG("Null context encountered, should not be possible", context); 00500 00501 caller (context); 00502 } 00503 } 00504 00509 template<typename RenderTree, typename Fn, typename Blocker> 00510 void ForEachContextReverse (RenderTree& tree, Fn& fn, Blocker& block) 00511 { 00512 // Iterate over all contexts, calling the functor for each one 00513 typename RenderTree::ContextNodeArrayIteratorType it = tree.GetReverseContextIterator (); 00514 00515 // Helper object for calling function 00516 Implementation::OperationCaller< 00517 Fn, 00518 Blocker, 00519 typename OperationTraits<Fn>::Ordering 00520 > caller (fn, block); 00521 00522 while (it.HasNext ()) 00523 { 00524 typename RenderTree::ContextNode* context = it.Next (); 00525 CS_ASSERT_MSG("Null context encountered, should not be possible", context); 00526 00527 caller (context); 00528 } 00529 } 00530 00532 00534 00538 template<typename ContextType, typename Fn> 00539 void ForEachMeshNode (ContextType& context, Fn& fn) 00540 { 00541 typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetIterator (); 00542 00543 Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*> noBlock; 00544 // Helper object for calling function 00545 Implementation::OperationCaller< 00546 Fn, 00547 Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*>, 00548 typename OperationTraits<Fn>::Ordering 00549 > caller (fn, noBlock); 00550 00551 while (it.HasNext ()) 00552 { 00553 typename ContextType::TreeType::MeshNode* node = it.Next (); 00554 CS_ASSERT_MSG("Null node encountered, should not be possible", node); 00555 00556 caller (node); 00557 } 00558 } 00559 00564 template<typename ContextType, typename Fn, typename Blocker> 00565 void ForEachMeshNode (ContextType& context, Fn& fn, Blocker& blocker) 00566 { 00567 typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetIterator (); 00568 00569 // Helper object for calling function 00570 Implementation::OperationCaller< 00571 Fn, 00572 Blocker, 00573 typename OperationTraits<Fn>::Ordering 00574 > caller (fn, blocker); 00575 00576 while (it.HasNext ()) 00577 { 00578 typename ContextType::TreeType::MeshNode* node = it.Next (); 00579 CS_ASSERT_MSG("Null node encountered, should not be possible", node); 00580 00581 caller (node); 00582 } 00583 } 00584 00589 template<typename ContextType, typename Fn> 00590 void ForEachMeshNodeReverse (ContextType& context, Fn& fn) 00591 { 00592 typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetReverseIterator (); 00593 00594 Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*> noBlock; 00595 // Helper object for calling function 00596 Implementation::OperationCaller< 00597 Fn, 00598 Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*>, 00599 typename OperationTraits<Fn>::Ordering 00600 > caller (fn, noBlock); 00601 00602 while (it.HasNext ()) 00603 { 00604 typename ContextType::TreeType::MeshNode* node = it.Next (); 00605 CS_ASSERT_MSG("Null node encountered, should not be possible", node); 00606 00607 caller (node); 00608 } 00609 } 00610 00615 template<typename ContextType, typename Fn, typename Blocker> 00616 void ForEachMeshNodeReverse (ContextType& context, Fn& fn, Blocker& blocker) 00617 { 00618 typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetReverseIterator (); 00619 00620 // Helper object for calling function 00621 Implementation::OperationCaller< 00622 Fn, 00623 Blocker, 00624 typename OperationTraits<Fn>::Ordering 00625 > caller (fn, blocker); 00626 00627 while (it.HasNext ()) 00628 { 00629 typename ContextType::TreeType::MeshNode* node = it.Next (); 00630 CS_ASSERT_MSG("Null node encountered, should not be possible", node); 00631 00632 caller (node); 00633 } 00634 } 00635 00636 namespace Implementation 00637 { 00638 template<typename ContextType, typename MeshFn, typename Blocker> 00639 struct MeshContextTraverser 00640 { 00641 MeshContextTraverser (MeshFn& fn, Blocker& blocker) 00642 : fn (fn), blocker (blocker) 00643 {} 00644 00645 void operator() (ContextType* context) 00646 { 00647 ForEachMeshNode (*context, fn, blocker); 00648 } 00649 00650 MeshFn& fn; 00651 Blocker& blocker; 00652 }; 00653 } 00654 00656 00657 00658 00659 00661 00665 template<typename RenderTree> 00666 class SingleMeshContextNumbering 00667 { 00668 public: 00669 SingleMeshContextNumbering () 00670 : meshIndex (0) 00671 {} 00672 00673 void operator () (size_t, typename RenderTree::MeshNode* node) 00674 { 00675 for (size_t i = 0; i < node->meshes.GetSize(); ++i) 00676 { 00677 node->meshes[i].contextLocalId = meshIndex++; 00678 } 00679 } 00680 00681 private: 00682 size_t meshIndex; 00683 }; 00684 00685 template<typename RenderTree> 00686 struct OperationTraits<SingleMeshContextNumbering<RenderTree> > 00687 { 00688 typedef OperationNumbered Ordering; 00689 }; 00691 00692 } 00693 } 00694 00695 00696 00697 #endif
Generated for Crystal Space 2.0 by doxygen 1.6.1