Author: eudoxos
Date: 2009-02-20 23:56:45 +0100 (Fri, 20 Feb 2009)
New Revision: 1674

Modified:
   trunk/core/GeometricalModel.hpp
   trunk/core/MetaBody.hpp
   trunk/core/Omega.cpp
   trunk/core/Omega.hpp
   trunk/gui/py/PythonUI.cpp
   trunk/lib/factory/ClassFactory.cpp
   trunk/lib/factory/ClassFactory.hpp
   trunk/lib/factory/DynLibManager.cpp
   trunk/lib/factory/DynLibManager.hpp
   trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp
   trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp
   trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.cpp
   trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.hpp
   
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
Log:
1. removed persistentInteraction from most places; they are still present in 
MetaBody, but not serialized any more, most importantly (avoids warnings) and 
not GL-drawn.
2. Plugin loading loginc completely changes, the underlying macro YADE_PLUGIN 
has still the same interface. We used __attribute__((constructor)), 
__attribute__((visibility("internal"))) and anonymous namespace magic to get 
there. This will make it possible to put multiple plugins to a single shared 
library without touching the source, only fiddling with SConscript's.
3. PythonUI is interactive by default (it was not?? weird.)


Modified: trunk/core/GeometricalModel.hpp
===================================================================
--- trunk/core/GeometricalModel.hpp     2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/core/GeometricalModel.hpp     2009-02-20 22:56:45 UTC (rev 1674)
@@ -9,7 +9,7 @@
 #pragma once
 
 #include<yade/lib-base/yadeWm3Extra.hpp>
-#include <Wm3Vector3.h>
+#include<Wm3Vector3.h>
 #include<yade/lib-base/yadeWm3.hpp>
 #include<yade/lib-serialization/Serializable.hpp>
 #include<yade/lib-multimethods/Indexable.hpp>

Modified: trunk/core/MetaBody.hpp
===================================================================
--- trunk/core/MetaBody.hpp     2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/core/MetaBody.hpp     2009-02-20 22:56:45 UTC (rev 1674)
@@ -57,7 +57,6 @@
                (initializers)
                (bodies)
                (transientInteractions)
-               (persistentInteractions)
                (physicalActions)
                (miscParams)
                (dispParams)

Modified: trunk/core/Omega.cpp
===================================================================
--- trunk/core/Omega.cpp        2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/core/Omega.cpp        2009-02-20 22:56:45 UTC (rev 1674)
@@ -164,8 +164,7 @@
        return 
(dynlibs[className].baseClasses.find(baseClassName)!=dynlibs[className].baseClasses.end());
 }
 
-void Omega::scanPlugins()
-{
+void Omega::scanPlugins(){
        FOREACH(string dld,preferences->dynlibDirectories) 
ClassFactory::instance().addBaseDirectory(dld);
        vector<string> dynlibsList;
        FOREACH(string si, preferences->dynlibDirectories){
@@ -177,54 +176,28 @@
                        if (!filesystem::is_directory(*di) && 
filesystem::exists(*di) && filesystem::extension(*di)!=".a" &&
                                
ClassFactory::instance().libNameToSystemName(ClassFactory::instance().systemNameToLibName(filesystem::basename(pth)))==(pth.leaf())){
                                filesystem::path 
name(filesystem::basename(pth));
-                               // warning: this can produce invalid name (too 
short).
-                               // 0-length names are dumped directly
-                               // names 0<length<4 should fail assertion in 
DynLibManager::systemNameToLibName
-                               // the whole loading "logic" should be 
rewritten from scratch...
                                if(name.leaf().length()<1) continue; // filter 
out 0-length filenames
-                               if(dynlibsList.size()==0 || 
ClassFactory::instance().systemNameToLibName(name.leaf())!=dynlibsList.back()) {
-                                       LOG_DEBUG("Added plugin: 
"<<si<<"/"<<pth.leaf()<<".");
-                                       
dynlibsList.push_back(ClassFactory::instance().systemNameToLibName(name.leaf()));
+                               string plugin=name.leaf();
+                               
if(!ClassFactory::instance().load(ClassFactory::instance().systemNameToLibName(plugin))){
+                                       string 
err=ClassFactory::instance().lastError();
+                                       if(err.find(": undefined symbol: 
")!=std::string::npos){
+                                               size_t pos=err.rfind(":");      
assert(pos!=std::string::npos);
+                                               std::string sym(err,pos+2); //2 
removes ": " from the beginning
+                                               int status=0; char* 
demangled_sym=abi::__cxa_demangle(sym.c_str(),0,0,&status);
+                                               LOG_FATAL(plugin<<": undefined 
symbol `"<<demangled_sym<<"'"); LOG_FATAL(plugin<<": "<<err); 
LOG_FATAL("Bailing out.");
+                                       }
+                                       else {
+                                               LOG_FATAL(plugin<<": "<<err<<" 
."); /* leave space to not to confuse c++filt */ LOG_FATAL("Bailing out.");
+                                       }
+                                       abort();
                                }
-                               else LOG_DEBUG("Possible plugin discarded: 
"<<si<<"/"<<name.leaf()<<".");
-                       } else LOG_DEBUG("File not considered a plugin: 
"<<pth.leaf()<<".");
-               }
-       }
-
-       bool allLoaded = true;
-       vector<string> dynlibsClassList; // dynlibsList holds filenames, this 
holds classes defined inside (may be different if using yadePuginClasses)
-       FOREACH(string dll, dynlibsList){
-               bool thisLoaded = ClassFactory::instance().load(dll);
-               if (!thisLoaded){
-                       string err=ClassFactory::instance().lastError();
-                       // HACK
-                       if(err.find("cannot open shared object file: No such 
file or directory")!=std::string::npos){
-                               LOG_INFO("Attempted to load nonexistent file; 
since this may be due to bad algorithm of filename construction, we pretend 
everything is OK (original error: `"<<err<<"').");
-                               thisLoaded=true;
                        }
-                       else if(err.find(": undefined symbol: 
")!=std::string::npos){
-                               size_t pos=err.rfind(":");
-                               assert(pos!=std::string::npos);
-                               std::string sym(err,pos+2); //2 removes ": " 
from the beginning
-                               int status=0;
-                               char* 
demangled_sym=abi::__cxa_demangle(sym.c_str(),0,0,&status);
-                               LOG_FATAL("Undefined symbol 
`"<<demangled_sym<<"' ("<<err<<").");
-                       }
-                       else LOG_ERROR("Error loading Library `"<<dll<<"': 
"<<err<<" ."); // leave space to not to confuse c++filt
+                       else LOG_DEBUG("File not considered a plugin: 
"<<pth.leaf()<<".");
                }
-               else { // no error
-                       if 
(ClassFactory::instance().lastPluginClasses().size()==0){ // regular plugin, 
one class per file
-                               dynlibsClassList.push_back(dll);
-                               LOG_DEBUG("Plugin "<<dll<<": loaded default 
class "<<dll<<".");
-                       } else {// if plugin defines yadePluginClasses (has 
multiple classes), insert these into dynLibsList
-                               vector<string> 
css=ClassFactory::instance().lastPluginClasses();
-                               for(size_t i=0; i<css.size();i++) { 
dynlibsClassList.push_back(css[i]); LOG_DEBUG("Plugin "<<dll<<": loaded 
explicit class "<<css[i]<<".");  }
-                       }
-               }
-               allLoaded &= thisLoaded;
        }
-       if(!allLoaded) { LOG_FATAL("Error loading a plugin (see above; run with 
-v to see more), bailing out."); abort(); }
-       buildDynlibDatabase(dynlibsClassList);
+       list<string>& plugins(ClassFactory::instance().pluginClasses);
+       plugins.sort(); plugins.unique();
+       buildDynlibDatabase(vector<string>(plugins.begin(),plugins.end()));
 }
 
 void Omega::loadSimulationFromStream(std::istream& stream){

Modified: trunk/core/Omega.hpp
===================================================================
--- trunk/core/Omega.hpp        2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/core/Omega.hpp        2009-02-20 22:56:45 UTC (rev 1674)
@@ -80,6 +80,7 @@
                ptime                            msStartingPauseTime;
                time_duration                    simulationPauseDuration;
                string                           simulationFileName;
+
                void buildDynlibDatabase(const vector<string>& dynlibsList); // 
FIXME - maybe in ClassFactory ?
 
                map<string,string> memSavedSimulations;

Modified: trunk/gui/py/PythonUI.cpp
===================================================================
--- trunk/gui/py/PythonUI.cpp   2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/gui/py/PythonUI.cpp   2009-02-20 22:56:45 UTC (rev 1674)
@@ -15,7 +15,7 @@
 struct termios PythonUI::tios, PythonUI::tios_orig;
 string PythonUI::runScript;
 bool PythonUI::stopAfter=false;
-bool PythonUI::nonInteractive=true;
+bool PythonUI::nonInteractive=false;
 vector<string> PythonUI::scriptArgs;
 
 PythonUI* PythonUI::self=NULL;

Modified: trunk/lib/factory/ClassFactory.cpp
===================================================================
--- trunk/lib/factory/ClassFactory.cpp  2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/lib/factory/ClassFactory.cpp  2009-02-20 22:56:45 UTC (rev 1674)
@@ -10,6 +10,8 @@
 
 #include "ClassFactory.hpp"
 
+#include<boost/algorithm/string/regex.hpp>
+
 CREATE_LOGGER(ClassFactory);
 
 class Factorable;
@@ -123,3 +125,21 @@
        return dlm.systemNameToLibName(name);
 }
 
+
+void ClassFactory::registerPluginClasses(const char* fileAndClasses[]){
+       assert(fileAndClasses[0]!=NULL); // must be file name
+       // only filename given, no classes names explicitly
+       if(fileAndClasses[1]==NULL){
+               /* strip leading path (if any; using / as path separator) and 
strip one suffix (if any) to get the contained class name */
+               string 
heldClass=boost::algorithm::replace_regex_copy(string(fileAndClasses[0]),boost::regex("^(.*/)?(.*?)(\\.[^.]*)?$"),string("\\2"));
+               LOG_DEBUG("Plugin "<<fileAndClasses[0]<<", class 
"<<heldClass<<" (deduced)");
+               pluginClasses.push_back(heldClass); // last item with 
everything up to last / take off and .suffix strip
+       }
+       else {
+               for(int i=1; fileAndClasses[i]!=NULL; i++){
+                       LOG_DEBUG("Plugin "<<fileAndClasses[0]<<", class 
"<<fileAndClasses[i]);
+                       pluginClasses.push_back(fileAndClasses[i]);
+               }
+       }
+}
+

Modified: trunk/lib/factory/ClassFactory.hpp
===================================================================
--- trunk/lib/factory/ClassFactory.hpp  2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/lib/factory/ClassFactory.hpp  2009-02-20 22:56:45 UTC (rev 1674)
@@ -11,9 +11,10 @@
 #pragma once
 
 
-#include <map>
-#include <string>
-#include <iostream>
+#include<map>
+#include<string>
+#include<list>
+#include<iostream>
 
 #ifndef  __GXX_EXPERIMENTAL_CXX0X__
 #      include<boost/shared_ptr.hpp>
@@ -141,8 +142,10 @@
 
                bool load(const string& name);
                std::string lastError();
-               vector<string> lastPluginClasses(){ return 
dlm.lastPluginClasses; }
 
+               void registerPluginClasses(const char* fileAndClasses[]);
+               list<string> pluginClasses;
+
                string libNameToSystemName(const string& name);
                string systemNameToLibName(const string& name);
 
@@ -155,3 +158,11 @@
 };
 
 
+/*! Macro defining what classes can be found in this plugin -- must always be 
used in the respective .cpp file. If left empty, filename will be used to 
deduce that.
+ *
+ * Note:
+ *     1. Visibility must be set to "internal" (or "protected") so that other 
plugins' init will not shadow this one and all of them get properly executed.
+ *     2. The function must be enclosed in its own anonymous namespace, 
otherwise there will be clashes (liker errors) if more files with YADE_PLUGIN 
are linked together.
+ */
+#define YADE_PLUGIN(...) namespace{ __attribute__((constructor)) 
__attribute__((visibility("internal"))) void registerThisPluginClasses(void){ 
const char* info[]={__FILE__ , ##__VA_ARGS__ , NULL}; 
ClassFactory::instance().registerPluginClasses(info);} }
+

Modified: trunk/lib/factory/DynLibManager.cpp
===================================================================
--- trunk/lib/factory/DynLibManager.cpp 2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/lib/factory/DynLibManager.cpp 2009-02-20 22:56:45 UTC (rev 1674)
@@ -50,84 +50,31 @@
 }
 
 
-/*Factory DynLibManager::resolve(const string libName, const string symb )
-{
-       if (isLoaded(libName))
-       {
-               string tmpSymb;
-               tmpSymb = symb;
-               tmpSymb.push_back('_');
-               tmpSymb.append(libName);
-               
-               #ifdef WIN32
-                       void * sym = (void*)GetProcAddress(handles[libName], 
tmpSymb);
-                       if (sym==NULL)
-                               error();
-                       return (Factory)sym;
-               #else
-                       void * sym = dlsym(handles[libName], tmpSymb.data());
-               
-                       if (error())  
-                               return NULL;
-                       else
-                               return (Factory)sym;
-               #endif
-       }
-       else
-       {
-               return NULL;
-       }
-}*/
-
-
 bool DynLibManager::loadFromDirectoryList (const string& libName )
 {
-       lastPluginClasses.clear();
-
        if (libName.empty()) return false;
-
        string libFileName = libNameToSystemName(libName);
-
        string baseDir = findLibDir(libName);
-
        string fullLibName;
        if (baseDir.length()==0) return load(libFileName,libName);
        else return load(baseDir+"/"+libFileName,libName);
-       
 }
 
 
 bool DynLibManager::load (const string& fullLibName, const string& libName )
 {
-       lastPluginClasses.clear();
-
        if (libName.empty() || fullLibName.empty()){
                LOG_ERROR("Empty filename for library `"<<libName<<"'.");
                return false;
        }
-       /*if(!filesystem::exists(fullLibName)){
-               LOG_ERROR("Trying to load library `"<<libName<<"' from 
nonexistent file `"<<fullLibName<<"'?! (still returning success)");
-               return true;
-       }*/
-
 #ifdef WIN32
        if (isLoaded(libName)) return true;
        HINSTANCE handle = LoadLibraryA(fullLibName.c_str());
 #else
        void * handle = dlopen(fullLibName.data(), RTLD_NOW);
 #endif
-
        if (!handle) return !error();
-
        handles[libName] = handle;
-
-#ifndef WIN32
-       char**yadePluginClasses=(char**)dlsym(handle, "yadePluginClasses");
-       // errors are ignored, since definition of this sybol is optional
-       if(!dlerror()){ for(int i=0; yadePluginClasses[i]!=NULL && 
strlen(yadePluginClasses[i])>0; i++){
-               lastPluginClasses.push_back(yadePluginClasses[i]); 
LOG_DEBUG("Pushed back `"<<yadePluginClasses[i]<<"'."); }
-       }
-#endif
        return true;
 }
 

Modified: trunk/lib/factory/DynLibManager.hpp
===================================================================
--- trunk/lib/factory/DynLibManager.hpp 2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/lib/factory/DynLibManager.hpp 2009-02-20 22:56:45 UTC (rev 1674)
@@ -27,12 +27,7 @@
 
 using namespace std;
 
-/*! Macro defining what classes can be found in this plugin -- must always be 
used in the respective .cpp file.
 
-If left empty, filename will be used to deduce that.
-*/
-#define YADE_PLUGIN(...) const char* yadePluginClasses[]={ __VA_ARGS__ "", 
NULL };
-
 class DynLibManager 
 {
        private :
@@ -62,7 +57,6 @@
                string systemNameToLibName(const string& name);
                string findLibDir(const string& name);
                string lastError();
-               vector<string> lastPluginClasses;
                DECLARE_LOGGER;
 
        private :

Modified: trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp  
2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp  
2009-02-20 22:56:45 UTC (rev 1674)
@@ -18,7 +18,6 @@
 
 PersistentSAPCollider::PersistentSAPCollider() : BroadInteractor()
 {
-       noTransientIfPersistentExists=false;
        haveDistantTransient=false;
 
        nbObjects=0;
@@ -185,7 +184,6 @@
        const shared_ptr<Interaction>& 
interaction=transientInteractions->find(body_id_t(id1),body_id_t(id2));
        bool found=(interaction!=0);//Bruno's Hack
        // if there is persistent interaction, we will not create transient one!
-       bool foundPersistent = noTransientIfPersistentExists ? 
(persistentInteractions->find(body_id_t(id1),body_id_t(id2))!=0) : false;
        
        // test if the AABBs of the spheres number "id1" and "id2" are 
overlapping
        int offset1=3*id1, offset2=3*id2;
@@ -205,7 +203,7 @@
        // inserts the pair p=(id1,id2) if the two AABB overlaps and if p does 
not exists in the overlappingBB
        //if((id1==0 && id2==1) || (id1==1 && id2==0)) LOG_DEBUG("Processing #0 
#1");
        //if(interaction&&!interaction->isReal){ LOG_DEBUG("Unreal interaction 
#"<<id1<<"=#"<<id2<<" (overlap="<<overlap<<", 
haveDistantTransient="<<haveDistantTransient<<")");}
-       if(overlap && !found && !foundPersistent){
+       if(overlap && !found){
                //LOG_DEBUG("Creating interaction #"<<id1<<"=#"<<id2);
                transientInteractions->insert(body_id_t(id1),body_id_t(id2));
        }

Modified: trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp  
2009-02-20 19:21:34 UTC (rev 1673)
+++ trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp  
2009-02-20 22:56:45 UTC (rev 1674)
@@ -58,7 +58,6 @@
                // collection of AABB that are in interaction
                //protected : vector< set<unsigned int> > overlappingBB;
                shared_ptr<InteractionContainer> transientInteractions;
-               shared_ptr<InteractionContainer> persistentInteractions;
                /// upper right corner of the AABB of the objects =>  for 
spheres = center[i]-radius
                vector<Real> maxima;
 
@@ -97,14 +96,11 @@
                /// return true if BoundingVolume is in potential interaction
                bool probeBoundingVolume(const BoundingVolume& bv);
 
-               //! When creating transient interaction, look first if a 
persistent link between the pair in question exists; in that case, skip it.
-               bool noTransientIfPersistentExists;
                //! Don't break transient interaction once bodies don't overlap 
anymore; material law will be responsible for breaking it.
                bool haveDistantTransient;
 
                void registerAttributes(){
                        BroadInteractor::registerAttributes();
-                       REGISTER_ATTRIBUTE(noTransientIfPersistentExists);
                        REGISTER_ATTRIBUTE(haveDistantTransient);
                }
 

Modified: 
trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.cpp
===================================================================
--- 
trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.cpp    
    2009-02-20 19:21:34 UTC (rev 1673)
+++ 
trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.cpp    
    2009-02-20 22:56:45 UTC (rev 1674)
@@ -117,8 +117,6 @@
                        // look if the pair (id1,id2) already exists in the 
overleppingBB collection
                        const shared_ptr<Interaction>& 
interaction=transientInteractions->find ( body_id_t ( id1 ),body_id_t ( id2 ) );
                        bool found= ( interaction!=0 );//Bruno's Hack
-                       // if there is persistent interaction, we will not 
create transient one!
-                       //bool foundPersistent = noTransientIfPersistentExists 
? ( persistentInteractions->find ( body_id_t ( id1 ),body_id_t ( id2 ) ) !=0 ) 
: false;
 
                        // inserts the pair p=(id1,id2) if the two AABB 
overlaps and if p does not exists in the overlappingBB
                        if ( !found )

Modified: 
trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.hpp
===================================================================
--- 
trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.hpp    
    2009-02-20 19:21:34 UTC (rev 1673)
+++ 
trunk/pkg/common/Engine/StandAloneEngine/PersistentTriangulationCollider.hpp    
    2009-02-20 22:56:45 UTC (rev 1674)
@@ -71,7 +71,6 @@
                // collection of AABB that are in interaction
                //protected : vector< set<unsigned int> > overlappingBB;
                shared_ptr<InteractionContainer> transientInteractions;
-               shared_ptr<InteractionContainer> persistentInteractions;
                /// upper right corner of the AABB of the objects =>  for 
spheres = center[i]-radius
                vector<Real> maxima;
 

Modified: 
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
===================================================================
--- 
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
    2009-02-20 19:21:34 UTC (rev 1673)
+++ 
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
    2009-02-20 22:56:45 UTC (rev 1674)
@@ -380,15 +380,6 @@
 
 void OpenGLRenderingEngine::renderInteractionGeometry(const 
shared_ptr<MetaBody>& rootBody){   
        {
-               boost::mutex::scoped_lock 
lock(rootBody->persistentInteractions->drawloopmutex);
-               FOREACH(const shared_ptr<Interaction>& I, 
*rootBody->persistentInteractions){
-                       if(!I->interactionGeometry) continue;
-                       const shared_ptr<Body>& 
b1=Body::byId(I->getId1(),rootBody), b2=Body::byId(I->getId2(),rootBody);
-                       
if(!(b1->physicalParameters->isDisplayed||b2->physicalParameters->isDisplayed)) 
continue;
-                       glPushMatrix(); 
interactionGeometryDispatcher(I->interactionGeometry,I,b1,b2,Interaction_wire); 
glPopMatrix();
-               }
-       }
-       {
                boost::mutex::scoped_lock 
lock(rootBody->transientInteractions->drawloopmutex);
                FOREACH(const shared_ptr<Interaction>& I, 
*rootBody->transientInteractions){
                        if(!I->interactionGeometry) continue;
@@ -402,15 +393,6 @@
 
 void OpenGLRenderingEngine::renderInteractionPhysics(const 
shared_ptr<MetaBody>& rootBody){    
        {
-               boost::mutex::scoped_lock 
lock(rootBody->persistentInteractions->drawloopmutex);
-               FOREACH(const shared_ptr<Interaction>& I, 
*rootBody->persistentInteractions){
-                       if(!I->interactionPhysics) continue;
-                       const shared_ptr<Body>& 
b1=Body::byId(I->getId1(),rootBody), b2=Body::byId(I->getId2(),rootBody);
-                       
if(!(b1->physicalParameters->isDisplayed||b2->physicalParameters->isDisplayed)) 
continue;
-                       glPushMatrix(); 
interactionPhysicsDispatcher(I->interactionPhysics,I,b1,b2,Interaction_wire); 
glPopMatrix();
-               }
-       }
-       {
                boost::mutex::scoped_lock 
lock(rootBody->transientInteractions->drawloopmutex);
                FOREACH(const shared_ptr<Interaction>& I, 
*rootBody->transientInteractions){
                        if(!I->interactionPhysics) continue;


_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to