CMS 3D CMS Logo

Ig3DBaseModel.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
00002 
00003 #include "Iguana/GLModels/interface/Ig3DBaseModel.h"
00004 #include "Iguana/GLModels/interface/Ig3DBaseModelEvent.h"
00005 #include "Iguana/GLModels/interface/Ig3DBaseRep.h"
00006 #include <Inventor/nodes/SoSelection.h>
00007 #include <Inventor/nodes/SoSeparator.h>
00008 #include <Inventor/actions/SoSearchAction.h>
00009 #include <Inventor/SoPath.h>
00010 #include <classlib/utils/DebugAids.h>
00011 #include <algorithm>
00012 
00013 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00014 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00015 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00016 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00017 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00018 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00019 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00020 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00021 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00022 
00023 Ig3DBaseModel::Ig3DBaseModel (IgState   *state)
00024     : m_state (state),
00025       m_sceneGraph (new SoSelection),
00026       m_attachPoint (0)
00027 {
00028     // ASSERT ("attachPoint is the scene graph or within it");
00029     m_sceneGraph->ref ();
00030     m_sceneGraph->setName ("IGUANA_SCENE_GRAPH_V2");
00031     Ig3DBaseRep *rep = new Ig3DBaseRep (this, 0, 0, new SoSeparator);
00032     ASSERT (m_attachPoint == rep);
00033 }
00034 
00035 Ig3DBaseModel::~Ig3DBaseModel (void)
00036 { m_sceneGraph->unref (); }
00037 
00039 IgState *
00040 Ig3DBaseModel::state (void) const
00041 { return m_state; }
00042 
00044 void
00045 Ig3DBaseModel::listen (EventType /* event */, const Listener &listener)
00046 { m_listeners.push_back (listener); }
00047 
00048 void
00049 Ig3DBaseModel::unlisten (EventType /* event */, const Listener &listener)
00050 {
00051     Listeners::iterator pos = std::find (m_listeners.begin (),
00052                                          m_listeners.end(),
00053                                          listener);
00054     ASSERT (pos != m_listeners.end ());
00055     m_listeners.erase (pos);
00056 }
00057 
00058 void
00059 Ig3DBaseModel::changed (void)
00060 {
00061     Ig3DBaseModelEvent event (this);
00062     for (Listeners::iterator pos = m_listeners.begin ();
00063          pos != m_listeners.end (); ++pos)
00064         (*pos) (event);
00065 }
00066 
00068 Ig3DBaseRep *
00069 Ig3DBaseModel::lookup (SoGroup *node) const
00070 { ASSERT (false); return dynamic_cast<Ig3DBaseRep *> (node); }
00071 
00073 void
00074 Ig3DBaseModel::add (Ig3DBaseRep *rep)
00075 {
00076     ASSERT (rep);
00077 
00078     if (! m_attachPoint)
00079     {
00080         // Initialising: creating the root rep.
00081         ASSERT (m_sceneGraph->getNumChildren () == 0);
00082         m_sceneGraph->addChild (m_attachPoint = rep);
00083     }
00084     else
00085     {
00086         ASSERT (m_attachPoint->findChild (rep) == -1);
00087         m_attachPoint->addChild (rep);
00088         changed ();
00089     }
00090 }
00091 
00092 void
00093 Ig3DBaseModel::remove (Ig3DBaseRep *rep, bool search /* = false */)
00094 {
00095     ASSERT (rep);
00096     // Be conservative -- the rep has no way of knowing it has been
00097     // added to a model or to a parent.
00098     int index;
00099     if ((index = m_attachPoint->findChild (rep)) != -1)
00100         m_attachPoint->removeChild (index);
00101 
00102     if (search)
00103     {
00104         // NB: The object rep can be attached in only one place.  We
00105         // end up here if the rep is being deleted via its object
00106         // going away and the rep doesn't know where it belongs to,
00107         // asking us to do the hard work.
00108         //
00109         // Find the parent.  Since this is a rep, the parent must
00110         // always be a rep (a separator) and not hidden inside
00111         // switches.  It might have been in the attach point but we
00112         // already removed that one, so we know the path must be at
00113         // least two levels.
00114         SoSearchAction searcher;
00115         searcher.setNode (rep);
00116         searcher.apply (m_attachPoint);
00117 
00118         if (searcher.getPath ())
00119         {
00120             ASSERT (searcher.getPath ()->getLength () > 1);
00121             SoNode *parent = searcher.getPath ()->getNodeFromTail (1);
00122             ASSERT (parent && parent->isOfType(SoSeparator::getClassTypeId()));
00123             SoSeparator *p = static_cast<SoSeparator *> (parent);
00124             p->removeChild (rep);
00125         }
00126     }
00127 
00128     changed ();
00129 }
00130 
00131 void
00132 Ig3DBaseModel::change (Ig3DBaseRep *rep)
00133 {
00134     ASSERT (rep);
00135     changed ();
00136 }
00137 
00139 SoGroup *
00140 Ig3DBaseModel::sceneGraph (void) const
00141 { return m_sceneGraph; }
00142 
00143 Ig3DBaseRep *
00144 Ig3DBaseModel::attachPoint (void) const
00145 { return m_attachPoint; }
00146 
00148 SbString
00149 Ig3DBaseModel::encode (const std::string &name)
00150 {
00151     // Encode names so that they use valid OpenInventor characters and
00152     // thre rest is escaped as `_X<hex code>', and decode them when
00153     // reading in the files.
00154     static const char   hexdigits []     = "0123456789abcdef";
00155     std::string         result;
00156 
00157     if (! SbName::isBaseNameStartChar (name [0]))
00158     {
00159         result += '_';
00160     }
00161         
00162     for (std::string::size_type i = 0; i < name.size (); ++i)
00163         if (SbName::isBaseNameChar (name[i]))
00164             result.append (1, name[i]);
00165         else if (i > 0 && SbName::isBaseNameStartChar (name[i]))
00166             result.append (1, name[i]);
00167         else
00168         {
00169 #           if UCHAR_MAX != 255 || CHAR_BIT != 8
00170 #             error expected 8-bit characters
00171 #           endif
00172             result += '_';
00173             result += 'X';
00174             result += hexdigits [((unsigned char) name[i]>>4)&0xf];
00175             result += hexdigits [(unsigned char) name[i]&0xf];
00176         }
00177 
00178     return result.c_str ();
00179 }
00180 
00181 std::string
00182 Ig3DBaseModel::decode (const std::string &name)
00183 {
00184     // Encode names so that they use valid OpenInventor characters and
00185     // thre rest is escaped as `_X<hex code>', and decode them when
00186     // reading in the files.
00187     static const char   hexdigits []     = "0123456789abcdef";
00188     std::string         result;
00189     const char          *first;
00190     const char          *second;
00191 
00192     for (std::string::size_type i = 0; i < name.size (); ++i)
00193         if (name[i] != '_'
00194             || i > name.size () - 4
00195             || name[i+1] != 'X'
00196             || !(first = strchr (hexdigits, name[i+2]))
00197             || !(second = strchr (hexdigits, name[i+3])))
00198             result.append (1, name[i]);
00199         else
00200         {
00201 #           if UCHAR_MAX != 255 || CHAR_BIT != 8
00202 #             error expected 8-bit characters
00203 #           endif
00204             unsigned int code = ((unsigned) (first - hexdigits) << 4)
00205                                 + ((unsigned) (second - hexdigits));
00206             ASSERT (code <= UCHAR_MAX);
00207             result += static_cast<char> (code);
00208             i += 3;
00209         }
00210 
00211     return result;
00212 }
00213 
00214 std::string
00215 Ig3DBaseModel::decode (const SbName &name)
00216 { return decode (std::string (name.getString ())); }

Generated on Tue Jun 9 17:38:42 2009 for CMSSW by  doxygen 1.5.4