ATLAS Offline Software
Loading...
Searching...
No Matches
VP1ExtraSepLayerHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "VP1Base/VP1Msg.h"
7#include <Inventor/C/errors/debugerror.h>
8#include <Inventor/nodes/SoSeparator.h>
9#include <Inventor/nodes/SoMaterial.h>
10#include <map>
11#include <iostream>
12
13//____________________________________________________________________
15public:
16
19
20 SoSeparator * topsep;
21 const int limitpersep;
22 std::map<SoNode*,SoSeparator*> nodes2extrasep;//We dont do any special refcounting here.
23
24 //For notifications:
26
27 //For addNodeUnderMaterial:
28 std::map<SoMaterial*,std::pair<SoSeparator*,VP1ExtraSepLayerHelper*> > mat2sepandhelper;
29};
30
31
32//____________________________________________________________________
34: m_d(new Imp(topsep,numberOfNodesPerExtraSep))
35{
36 m_d->topsep->ref();
37}
38
39//____________________________________________________________________
41{
42 std::map<SoMaterial*,std::pair<SoSeparator*,VP1ExtraSepLayerHelper*> >::iterator it, itE = m_d->mat2sepandhelper.end();
43 for (it = m_d->mat2sepandhelper.begin();it!=itE;++it) {
44 delete it->second.second;
45 it->second.first->unref();
46 }
47 m_d->topsep->removeAllChildren();
48 m_d->topsep->unref();
49 delete m_d; m_d=0;
50}
51
52
53//____________________________________________________________________
55{
56 assert(m_d->nodes2extrasep.find(node)==m_d->nodes2extrasep.end());
57 if (VP1Msg::verbose()) {
58 if (m_d->nodes2extrasep.find(node)!=m_d->nodes2extrasep.end())
59 VP1Msg::message("VP1ExtraSepLayerHelper::addNode ERROR: Node already added!");
60 }
61
62 if (m_d->topsep->getNumChildren()==0) {
63 SoSeparator * sep = new SoSeparator;
64 if (VP1Msg::verbose())
65 sep->setName("SepHelperInternalSep");
66 sep->renderCaching.setValue(SoSeparator::ON);
67 sep->boundingBoxCaching.setValue(SoSeparator::ON);
68 sep->addChild(node);
69 m_d->topsep->addChild(sep);
70 m_d->nodes2extrasep[node]=sep;
71 return;
72 }
73
74 //Try to retrieve the last of the extra separators, and see if it still has room:
75 assert(m_d->topsep->getChild(m_d->topsep->getNumChildren()-1)->getTypeId().isDerivedFrom(SoSeparator::getClassTypeId()));
76 SoSeparator * lastsep = static_cast<SoSeparator*>(m_d->topsep->getChild(m_d->topsep->getNumChildren()-1));
77 if (lastsep->getNumChildren()<m_d->limitpersep) {
78 lastsep->addChild(node);
79 m_d->nodes2extrasep[node]=lastsep;
80 return;
81 }
82
83 //Add a new sep and return.
84 SoSeparator * sep = new SoSeparator;
85 if (VP1Msg::verbose())
86 sep->setName("SepHelperInternalSep");
87 sep->renderCaching.setValue(SoSeparator::ON);
88 sep->boundingBoxCaching.setValue(SoSeparator::ON);
89 sep->addChild(node);
90 m_d->topsep->addChild(sep);
91 m_d->nodes2extrasep[node]=sep;
92}
93
94//____________________________________________________________________
96{
97 assert(m_d->nodes2extrasep.find(node)!=m_d->nodes2extrasep.end());
98 if (VP1Msg::verbose()) {
99 if (m_d->nodes2extrasep.find(node)==m_d->nodes2extrasep.end())
100 VP1Msg::message("VP1ExtraSepLayerHelper::removeNode ERROR: Node not added previously!");
101 }
102
103 //Find extrasep and lastsep:
104 SoSeparator * extrasep = m_d->nodes2extrasep[node];
105 assert(extrasep->findChild(node)>-1);
106 assert(m_d->topsep->getChild(m_d->topsep->getNumChildren()-1)->getTypeId()==SoSeparator::getClassTypeId());
107 SoSeparator * lastsep = static_cast<SoSeparator*>(m_d->topsep->getChild(m_d->topsep->getNumChildren()-1));
108 assert(lastsep->getNumChildren()>0);
109
110 //First, remove the node:
111 node->ref();
112 extrasep->removeChild(node);
113 node->unref();
114 m_d->nodes2extrasep.erase(m_d->nodes2extrasep.find(node));
115
116 //Do we need to move a node from the last separator into the separator?
117 if (lastsep!=extrasep&&lastsep->getNumChildren()>0) {
118 SoNode * othernode = lastsep->getChild(lastsep->getNumChildren()-1);
119 othernode->ref();
120 lastsep->removeChild(othernode);
121 extrasep->addChild(othernode);
122 othernode->unref();
123 m_d->nodes2extrasep[othernode] = extrasep;
124 }
125
126 //Do we need to remove the last separator?
127 if (lastsep->getNumChildren()==0) {
128 lastsep->ref();
129 m_d->topsep->removeChild(lastsep);
130 lastsep->unref();
131 }
132}
133
134//____________________________________________________________________
136{
137 ++(m_d->largechangessave);
138 m_d->topsep->enableNotify(false);
139 //We "sterilise" the extra separators and the extra sep helpers
140 //also.
141
142 //Thus, we disable notifications on all children of topsep, and we
143 //call largeChangesBegin on all internal sephelpers.
144
145 int n = m_d->topsep->getNumChildren();
146 for (int i = 0; i < n; ++i)
147 m_d->topsep->getChild(i)->enableNotify(false);
148
149 std::map<SoMaterial*,std::pair<SoSeparator*,VP1ExtraSepLayerHelper*> >::iterator it, itE = m_d->mat2sepandhelper.end();
150 for (it = m_d->mat2sepandhelper.begin(); it!=itE;++it)
151 it->second.second->largeChangesBegin();
152
153}
154
155//____________________________________________________________________
157{
158 if (m_d->largechangessave<=0)
159 return;
160 if (--(m_d->largechangessave)!=0)
161 return;
162
163 std::map<SoMaterial*,std::pair<SoSeparator*,VP1ExtraSepLayerHelper*> >::iterator it, itE = m_d->mat2sepandhelper.end();
164 for (it = m_d->mat2sepandhelper.begin(); it!=itE;++it)
165 it->second.second->largeChangesEnd();
166
167 int n = m_d->topsep->getNumChildren();
168 for (int i = 0; i < n; ++i) {
169 m_d->topsep->getChild(i)->enableNotify(true);
170 m_d->topsep->getChild(i)->touch();
171 }
172
173 m_d->topsep->enableNotify(true);
174 m_d->topsep->touch();
175}
176
177//____________________________________________________________________
179{
180 return m_d->topsep;
181}
182
183//____________________________________________________________________
185{
186 return m_d->limitpersep;
187}
188
189//____________________________________________________________________
190void VP1ExtraSepLayerHelper::addNodeUnderMaterial( SoNode * node, SoMaterial * mat )
191{
192 VP1Msg::messageVerbose("VP1ExtraSepLayerHelper::addNodeUnderMaterial()");
193
194 std::map<SoMaterial*,std::pair<SoSeparator*,VP1ExtraSepLayerHelper*> >::iterator it = m_d->mat2sepandhelper.find(mat);
195 if (it==m_d->mat2sepandhelper.end()) {
196
197 SoSeparator * matsep = new SoSeparator;
198 if (VP1Msg::verbose())
199 matsep->setName("SepHelperInternalSep_MatSep");
200 matsep->ref();
201 matsep->addChild(mat);
202 SoSeparator * sep = new SoSeparator;
203 if (VP1Msg::verbose())
204 sep->setName("SepHelperInternalSep_InternalSepHelperTop");
205 matsep->addChild(sep);
206 VP1ExtraSepLayerHelper * mathelper = new VP1ExtraSepLayerHelper(sep,m_d->limitpersep);
207 m_d->mat2sepandhelper[mat] = std::pair<SoSeparator*,VP1ExtraSepLayerHelper*>(matsep,mathelper);
208 mathelper->addNode(node);
209 addNode(matsep);
210 } else {
211 it->second.second->addNode(node);
212 }
213}
214
215//____________________________________________________________________
217{
218 std::map<SoMaterial*,std::pair<SoSeparator*,VP1ExtraSepLayerHelper*> >::iterator it = m_d->mat2sepandhelper.find(mat);
219 if (it==m_d->mat2sepandhelper.end())
220 return;
221 it->second.second->removeNode(node);
222 if (it->second.second->topSeparator()->getNumChildren()==0) {
223 //No more use for this material apparently:
224 removeNode(it->second.first);
225 it->second.first->unref();
226 m_d->mat2sepandhelper.erase(it);
227 }
228}
229
230//____________________________________________________________________
231void VP1ExtraSepLayerHelper::moveNodeToNewMaterial(SoNode*node,SoMaterial* oldmat,SoMaterial* newmat)
232{
235}
std::map< SoMaterial *, std::pair< SoSeparator *, VP1ExtraSepLayerHelper * > > mat2sepandhelper
Imp(SoSeparator *topsep, int numberOfNodesPerExtraSep)
std::map< SoNode *, SoSeparator * > nodes2extrasep
void removeNodeUnderMaterial(SoNode *, SoMaterial *)
void moveNodeToNewMaterial(SoNode *, SoMaterial *oldmat, SoMaterial *newmat)
VP1ExtraSepLayerHelper(SoSeparator *topsep, int numberOfNodesPerExtraSep=32)
void addNodeUnderMaterial(SoNode *, SoMaterial *)
SoSeparator * topSeparator() const
static void messageVerbose(const QString &)
Definition VP1Msg.cxx:84
static bool verbose()
Definition VP1Msg.h:31
static void message(const QString &, IVP1System *sys=0)
Definition VP1Msg.cxx:30
Definition node.h:24