Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 2 // See the file tools.license for terms. 3 3 4 #ifndef tools_sg_node 4 #ifndef tools_sg_node 5 #define tools_sg_node 5 #define tools_sg_node 6 6 7 #include "field" 7 #include "field" 8 #include "search_action" 8 #include "search_action" 9 #include "write_action" 9 #include "write_action" 10 #include "read_action" 10 #include "read_action" 11 #include "get_matrix_action" 11 #include "get_matrix_action" 12 #include "node_desc" 12 #include "node_desc" 13 13 14 #include "../forit" 14 #include "../forit" 15 15 16 namespace tools { 16 namespace tools { 17 namespace sg { 17 namespace sg { 18 class render_action; 18 class render_action; 19 class pick_action; 19 class pick_action; 20 class bbox_action; 20 class bbox_action; 21 class event_action; 21 class event_action; 22 class visible_action; 22 class visible_action; 23 }} 23 }} 24 24 25 namespace tools { 25 namespace tools { 26 namespace sg { 26 namespace sg { 27 27 28 class node { 28 class node { 29 public: 29 public: 30 TOOLS_SCLASS(tools::sg::node) 30 TOOLS_SCLASS(tools::sg::node) 31 //public: 31 //public: 32 // static bool is_a(const std::string& a_clas 32 // static bool is_a(const std::string& a_class) {return rcmp(a_class,s_class());} 33 // in a derived class: 33 // in a derived class: 34 // static bool is_a(const std::string& a_clas 34 // static bool is_a(const std::string& a_class) { 35 // if(rcmp(a_class,s_class())) return true; 35 // if(rcmp(a_class,s_class())) return true; 36 // return parent::is_a(a_class); 36 // return parent::is_a(a_class); 37 // } 37 // } 38 virtual void* cast(const std::string& a_clas 38 virtual void* cast(const std::string& a_class) const { 39 if(void* p = cmp_cast<node>(this,a_class)) 39 if(void* p = cmp_cast<node>(this,a_class)) return p; 40 return 0; 40 return 0; 41 } 41 } 42 virtual const std::string& s_cls() const = 0 42 virtual const std::string& s_cls() const = 0; 43 public: 43 public: 44 virtual node* copy() const = 0; 44 virtual node* copy() const = 0; 45 45 46 virtual unsigned int cls_version() const {re 46 virtual unsigned int cls_version() const {return 1;} 47 47 48 virtual const desc_fields& node_desc_fields( 48 virtual const desc_fields& node_desc_fields() const { 49 static const desc_fields s_v; 49 static const desc_fields s_v; 50 return s_v; 50 return s_v; 51 } 51 } 52 52 53 virtual void render(render_action&) {} 53 virtual void render(render_action&) {} 54 virtual void pick(pick_action&) {} 54 virtual void pick(pick_action&) {} 55 virtual void bbox(bbox_action&) {} 55 virtual void bbox(bbox_action&) {} 56 virtual void search(search_action& a_action) 56 virtual void search(search_action& a_action) { 57 if(a_action.what()==search_action::search_ 57 if(a_action.what()==search_action::search_node_of_class) { 58 if(void* p = cast(a_action.sclass())) { 58 if(void* p = cast(a_action.sclass())) { 59 a_action.add_obj(p); 59 a_action.add_obj(p); 60 if(a_action.stop_at_first()) a_action. 60 if(a_action.stop_at_first()) a_action.set_done(true); 61 } 61 } 62 } else if(a_action.what()==search_action:: 62 } else if(a_action.what()==search_action::search_path_to_node) { 63 if(this==a_action.node()){ 63 if(this==a_action.node()){ 64 a_action.path_push(this); //ending nod 64 a_action.path_push(this); //ending node in the path. 65 a_action.set_done(true); 65 a_action.set_done(true); 66 } 66 } 67 } else if(a_action.what()==search_action:: 67 } else if(a_action.what()==search_action::search_path_to_node_of_class) { 68 if(cast(a_action.sclass())) { 68 if(cast(a_action.sclass())) { 69 search_action::path_t path = a_action. 69 search_action::path_t path = a_action.path(); 70 path.push_back(this); 70 path.push_back(this); 71 a_action.add_path(path); 71 a_action.add_path(path); 72 if(a_action.stop_at_first()) a_action. 72 if(a_action.stop_at_first()) a_action.set_done(true); 73 } 73 } 74 } 74 } 75 } 75 } 76 virtual void get_matrix(get_matrix_action& a 76 virtual void get_matrix(get_matrix_action& a_action) { 77 if(this==a_action.node()){ 77 if(this==a_action.node()){ 78 a_action.set_found_model(a_action.model_ 78 a_action.set_found_model(a_action.model_matrix()); 79 a_action.set_done(true); 79 a_action.set_done(true); 80 } 80 } 81 } 81 } 82 virtual bool write(write_action& a_action) { 82 virtual bool write(write_action& a_action) { 83 if(!a_action.beg_node(*this)) return false 83 if(!a_action.beg_node(*this)) return false; 84 if(!write_fields(a_action)) return false; 84 if(!write_fields(a_action)) return false; 85 if(!a_action.end_node(*this)) return false 85 if(!a_action.end_node(*this)) return false; 86 return true; 86 return true; 87 } 87 } 88 virtual void event(event_action&) {} 88 virtual void event(event_action&) {} 89 virtual bool read(read_action& a_action) {re 89 virtual bool read(read_action& a_action) {return read_fields(a_action);} 90 virtual void is_visible(visible_action&) {} 90 virtual void is_visible(visible_action&) {} 91 91 92 virtual void protocol_one_fields(std::vector 92 virtual void protocol_one_fields(std::vector<field*>& a_fields) const {a_fields = m_fields;} 93 93 94 virtual bool draw_in_frame_buffer() const {r 94 virtual bool draw_in_frame_buffer() const {return false;} // marker nodes return true. 95 public: 95 public: 96 virtual bool touched() { //virtual for plott 96 virtual bool touched() { //virtual for plotter. 97 tools_vforcit(field*,m_fields,it) { 97 tools_vforcit(field*,m_fields,it) { 98 if((*it)->touched()) return true; 98 if((*it)->touched()) return true; 99 } 99 } 100 return false; 100 return false; 101 } 101 } 102 virtual void reset_touched() { 102 virtual void reset_touched() { 103 tools_vforcit(field*,m_fields,it) (*it)->r 103 tools_vforcit(field*,m_fields,it) (*it)->reset_touched(); 104 } 104 } 105 public: 105 public: 106 node() 106 node() 107 { 107 { 108 #ifdef TOOLS_MEM 108 #ifdef TOOLS_MEM 109 mem::increment(s_class().c_str()); 109 mem::increment(s_class().c_str()); 110 #endif 110 #endif 111 } 111 } 112 virtual ~node(){ 112 virtual ~node(){ 113 #ifdef TOOLS_MEM 113 #ifdef TOOLS_MEM 114 mem::decrement(s_class().c_str()); 114 mem::decrement(s_class().c_str()); 115 #endif 115 #endif 116 } 116 } 117 protected: 117 protected: 118 node(const node&) 118 node(const node&) 119 { 119 { 120 #ifdef TOOLS_MEM 120 #ifdef TOOLS_MEM 121 mem::increment(s_class().c_str()); 121 mem::increment(s_class().c_str()); 122 #endif 122 #endif 123 } 123 } 124 node& operator=(const node&){ 124 node& operator=(const node&){ 125 return *this; 125 return *this; 126 } 126 } 127 protected: 127 protected: 128 void add_field(field* a_field) { 128 void add_field(field* a_field) { 129 m_fields.push_back(a_field); //it does not 129 m_fields.push_back(a_field); //it does not take ownerhship. 130 } 130 } 131 //TOOLS_CLASS_STRING(fields_end) //for write 131 //TOOLS_CLASS_STRING(fields_end) //for write_bsg, sg::rbsg 132 bool write_fields(write_action& a_action) { 132 bool write_fields(write_action& a_action) { 133 133 134 check_fields(a_action.out()); //costly. 134 check_fields(a_action.out()); //costly. 135 //dump_field_descs(a_action.out()); 135 //dump_field_descs(a_action.out()); 136 136 137 unsigned int index = 0; 137 unsigned int index = 0; 138 tools_vforcit(field*,m_fields,it) { 138 tools_vforcit(field*,m_fields,it) { 139 if(!(*it)->write(a_action.buffer())) { 139 if(!(*it)->write(a_action.buffer())) { 140 a_action.out() << "node::write_fields 140 a_action.out() << "node::write_fields :" 141 << " for field index " 141 << " for field index " << index 142 << " and field class " 142 << " and field class " << (*it)->s_cls() 143 << " of node class " << 143 << " of node class " << s_cls() 144 << " : field.write() fa 144 << " : field.write() failed" << "." 145 << std::endl; 145 << std::endl; 146 return false; 146 return false; 147 } 147 } 148 index++; 148 index++; 149 } 149 } 150 return true; 150 return true; 151 } 151 } 152 152 153 bool read_fields(read_action& a_action) { // 153 bool read_fields(read_action& a_action) { //used in protocol-2. 154 node_desc rndesc; 154 node_desc rndesc; 155 if(!a_action.get_node_desc(s_cls(),rndesc) 155 if(!a_action.get_node_desc(s_cls(),rndesc)) { 156 a_action.out() << "tools::node::read_fie 156 a_action.out() << "tools::node::read_fields :" 157 << " for node class " << 157 << " for node class " << s_cls() 158 << " : read_action.get_no 158 << " : read_action.get_node_desc() failed." 159 << std::endl; 159 << std::endl; 160 return false; 160 return false; 161 } 161 } 162 //Whatever the current node fields, we mus 162 //Whatever the current node fields, we must read all rndesc.fields() : 163 tools_vforcit(field_desc,rndesc.fields(),i 163 tools_vforcit(field_desc,rndesc.fields(),it) { 164 const field_desc& fdesc = *it; 164 const field_desc& fdesc = *it; 165 165 166 field* fd = find_field(fdesc); 166 field* fd = find_field(fdesc); 167 if(!fd) { 167 if(!fd) { 168 a_action.out() << "tools::node::read_f 168 a_action.out() << "tools::node::read_fields :" 169 << " for node class " < 169 << " for node class " << s_cls() 170 << " : field desc name 170 << " : field desc name " << fdesc.name() 171 << " : field desc class 171 << " : field desc class " << fdesc.cls() 172 << " : field desc offse 172 << " : field desc offset " << fdesc.offset() 173 << " : field not found. 173 << " : field not found." 174 << "." 174 << "." 175 << std::endl; 175 << std::endl; 176 //#define TOOLS_NODE_DEBUG_READ_FIELD 176 //#define TOOLS_NODE_DEBUG_READ_FIELD 177 #ifdef TOOLS_NODE_DEBUG_READ_FIELD 177 #ifdef TOOLS_NODE_DEBUG_READ_FIELD 178 check_fields(a_action.out()); //costly 178 check_fields(a_action.out()); //costly. 179 dump_field_descs(a_action.out()); 179 dump_field_descs(a_action.out()); 180 {a_action.out() << "read field descs of 180 {a_action.out() << "read field descs of node class " << s_cls() << " :" << std::endl; 181 tools_vforcit(field_desc,rndesc.fields 181 tools_vforcit(field_desc,rndesc.fields(),itr) { 182 a_action.out() << "name " << (*itr). 182 a_action.out() << "name " << (*itr).name() 183 << ", class " << (*itr).cls() 183 << ", class " << (*itr).cls() 184 << ", offset " << (*itr).offse 184 << ", offset " << (*itr).offset() 185 << std::endl; 185 << std::endl; 186 }} 186 }} 187 {a_action.out() << "m_fields of node cl 187 {a_action.out() << "m_fields of node class " << s_cls() << " :" << std::endl; 188 tools_vforcit(field*,m_fields,itm) { 188 tools_vforcit(field*,m_fields,itm) { 189 a_action.out() << "field class " << 189 a_action.out() << "field class " << (*itm)->s_cls() 190 << ", found offset " << field_ 190 << ", found offset " << field_offset(*itm) 191 << std::endl; 191 << std::endl; 192 }} 192 }} 193 ::exit(0); 193 ::exit(0); 194 #endif 194 #endif 195 fd = a_action.field_factory().create(f 195 fd = a_action.field_factory().create(fdesc.cls()); 196 if(!fd) { 196 if(!fd) { 197 a_action.out() << "tools::node::read 197 a_action.out() << "tools::node::read_fields :" 198 << " for node class " 198 << " for node class " << s_cls() 199 << " : field desc cla 199 << " : field desc class " << fdesc.cls() 200 << " : can't create g 200 << " : can't create generic field." 201 << "." 201 << "." 202 << std::endl; 202 << std::endl; 203 return false; 203 return false; 204 } 204 } 205 } /*else { 205 } /*else { 206 a_action.out() << "debug : tools::node << 206 a_action.out() << "debug : inlib::node::read_fields :" 207 << " for node class " < 207 << " for node class " << s_cls() 208 << " : field desc class 208 << " : field desc class " << fdesc.cls() 209 << " : field desc offse 209 << " : field desc offset " << fdesc.offset() 210 << " : field found." 210 << " : field found." 211 << "." 211 << "." 212 << std::endl; 212 << std::endl; 213 }*/ 213 }*/ 214 214 215 if(!fd->read(a_action.buffer())) { 215 if(!fd->read(a_action.buffer())) { 216 a_action.out() << "tools::node::read_f 216 a_action.out() << "tools::node::read_fields :" 217 << " for node class " < 217 << " for node class " << s_cls() 218 << " : and field class 218 << " : and field class " << fd->s_cls() 219 << " : field read() fai 219 << " : field read() failed." 220 << std::endl; 220 << std::endl; 221 return false; 221 return false; 222 } 222 } 223 //fd->dump(a_action.out()); 223 //fd->dump(a_action.out()); 224 } 224 } 225 225 226 //NOTE : if some current node fields had n 226 //NOTE : if some current node fields had not been found 227 // in rndesc.fields(), they catch th 227 // in rndesc.fields(), they catch the default value 228 // of the node fields. 228 // of the node fields. 229 229 230 return true; 230 return true; 231 } 231 } 232 public: 232 public: 233 void touch() { 233 void touch() { 234 if(m_fields.empty()) return; 234 if(m_fields.empty()) return; 235 m_fields.front()->touch(); 235 m_fields.front()->touch(); 236 } 236 } 237 /* 237 /* 238 bool equal(const node& a_node) const { 238 bool equal(const node& a_node) const { 239 if(m_fields.size()!=a_node.m_fields.size() 239 if(m_fields.size()!=a_node.m_fields.size()) return false; 240 std::vector<field*>::iterator it = m_field 240 std::vector<field*>::iterator it = m_fields.begin(); 241 std::vector<field*>::iterator ait = a_node 241 std::vector<field*>::iterator ait = a_node.m_fields.begin(); 242 for(;it!=m_fields.end();++it,++ait) { 242 for(;it!=m_fields.end();++it,++ait) { 243 if(!(*it)->equal(*(*ait))) return false; 243 if(!(*it)->equal(*(*ait))) return false; 244 } 244 } 245 return true; 245 return true; 246 } 246 } 247 */ 247 */ 248 public: 248 public: 249 field& field_from_desc(const field_desc& a_d 249 field& field_from_desc(const field_desc& a_desc) const { 250 //WARNING : touchy. 250 //WARNING : touchy. 251 return *((field*)((char*)this+a_desc.offse 251 return *((field*)((char*)this+a_desc.offset())); 252 } 252 } 253 void dump_field_descs(std::ostream& a_out) c 253 void dump_field_descs(std::ostream& a_out) const { 254 a_out << "field descs of node class " << s 254 a_out << "field descs of node class " << s_cls() << " :" << std::endl; 255 const std::vector<field_desc>& fds = node_ 255 const std::vector<field_desc>& fds = node_desc_fields(); 256 tools_vforcit(field_desc,fds,itd) { 256 tools_vforcit(field_desc,fds,itd) { 257 a_out << "name " << (*itd).name() 257 a_out << "name " << (*itd).name() 258 << ", class " << (*itd).cls() 258 << ", class " << (*itd).cls() 259 << ", offset " << (*itd).offset() 259 << ", offset " << (*itd).offset() 260 << std::endl; 260 << std::endl; 261 } 261 } 262 } 262 } 263 field* find_field_by_name(const std::string& 263 field* find_field_by_name(const std::string& a_name) const { 264 // a_name is of the form <class>.<field>. 264 // a_name is of the form <class>.<field>. For example for color on sg::text, there are : 265 // tools::sg::back_area.color 265 // tools::sg::back_area.color 266 // tools::sg::text.color 266 // tools::sg::text.color 267 const std::vector<field_desc>& fds = node_ 267 const std::vector<field_desc>& fds = node_desc_fields(); 268 tools_vforcrit(field_desc,fds,it) { 268 tools_vforcrit(field_desc,fds,it) { 269 if((*it).name()==a_name) { 269 if((*it).name()==a_name) { 270 tools_vforcit(field*,m_fields,itf) { 270 tools_vforcit(field*,m_fields,itf) { 271 if(field_offset(*itf)==(*it).offset( 271 if(field_offset(*itf)==(*it).offset()) return (*itf); 272 } 272 } 273 } 273 } 274 } 274 } 275 return 0; 275 return 0; 276 } 276 } 277 protected: 277 protected: 278 field_desc::offset_t field_offset(const fiel 278 field_desc::offset_t field_offset(const field* a_field) const { 279 //WARNING : touchy. 279 //WARNING : touchy. 280 return ((char*)(a_field)-(char*)(this)); 280 return ((char*)(a_field)-(char*)(this)); 281 } 281 } 282 282 283 field* find_field(const field_desc& a_rdesc) 283 field* find_field(const field_desc& a_rdesc) const { 284 const std::vector<field_desc>& fds = node_ 284 const std::vector<field_desc>& fds = node_desc_fields(); 285 tools_vforcit(field_desc,fds,it) { 285 tools_vforcit(field_desc,fds,it) { 286 if((*it).name()==a_rdesc.name()) { 286 if((*it).name()==a_rdesc.name()) { 287 tools_vforcit(field*,m_fields,itf) { 287 tools_vforcit(field*,m_fields,itf) { 288 //::printf("debug : find_field : l 288 //::printf("debug : find_field : look : %s\n",field_name(*(*it)).c_str()); 289 if(field_offset(*itf)==(*it).offset( 289 if(field_offset(*itf)==(*it).offset()) return (*itf); 290 } 290 } 291 } 291 } 292 } 292 } 293 return 0; 293 return 0; 294 } 294 } 295 295 296 void check_fields(std::ostream& a_out) const 296 void check_fields(std::ostream& a_out) const { 297 const std::vector<field_desc>& fds = node_ 297 const std::vector<field_desc>& fds = node_desc_fields(); 298 tools_vforcit(field*,m_fields,it) { 298 tools_vforcit(field*,m_fields,it) { 299 bool found = false; 299 bool found = false; 300 tools_vforcit(field_desc,fds,itd) { 300 tools_vforcit(field_desc,fds,itd) { 301 if( ((*itd).offset()==field_offset(*it 301 if( ((*itd).offset()==field_offset(*it)) && 302 ((*itd).cls()==(*it)->s_cls()) 302 ((*itd).cls()==(*it)->s_cls()) 303 ){ 303 ){ 304 found = true; 304 found = true; 305 break; 305 break; 306 } 306 } 307 } 307 } 308 if(!found) { 308 if(!found) { 309 a_out << "tools::sg::node::check_field 309 a_out << "tools::sg::node::check_fields :" 310 << " WARNING : node of class " < 310 << " WARNING : node of class " << s_cls() 311 << " has bad fields description. 311 << " has bad fields description." 312 << std::endl; 312 << std::endl; 313 } 313 } 314 } 314 } 315 } 315 } 316 private: 316 private: 317 std::vector<field*> m_fields; 317 std::vector<field*> m_fields; 318 }; 318 }; 319 319 320 }} 320 }} 321 321 322 #include "../HEADER" 322 #include "../HEADER" 323 323 324 #define TOOLS_NODE(a__class,a__sclass,a__paren 324 #define TOOLS_NODE(a__class,a__sclass,a__parent)\ 325 TOOLS_HEADER(a__class,a__sclass,a__parent)\ 325 TOOLS_HEADER(a__class,a__sclass,a__parent)\ 326 virtual tools::sg::node* copy() const {retur 326 virtual tools::sg::node* copy() const {return new a__class(*this);} 327 327 328 #define TOOLS_NODE_NO_CAST(a__class,a__sclass, 328 #define TOOLS_NODE_NO_CAST(a__class,a__sclass,a__parent)\ 329 private:\ 329 private:\ 330 typedef a__parent parent;\ 330 typedef a__parent parent;\ 331 public:\ 331 public:\ 332 TOOLS_SCLASS(a__sclass)\ 332 TOOLS_SCLASS(a__sclass)\ 333 public:\ 333 public:\ 334 virtual const std::string& s_cls() const {re 334 virtual const std::string& s_cls() const {return s_class();}\ 335 virtual tools::sg::node* copy() const {retur 335 virtual tools::sg::node* copy() const {return new a__class(*this);} 336 336 337 #define TOOLS_NODE_T(a__T,a__class,a__sclass,a 337 #define TOOLS_NODE_T(a__T,a__class,a__sclass,a__parent)\ 338 private:\ 338 private:\ 339 typedef a__parent parent;\ 339 typedef a__parent parent;\ 340 public:\ 340 public:\ 341 static const std::string& s_class() {\ 341 static const std::string& s_class() {\ 342 static const std::string s_v(std::string(# 342 static const std::string s_v(std::string(#a__class)+"<"+a__T::s_class()+">");\ 343 return s_v;\ 343 return s_v;\ 344 }\ 344 }\ 345 static void check_class_name() {a__class<a__ 345 static void check_class_name() {a__class<a__T>::s_class();}\ 346 public:\ 346 public:\ 347 virtual const std::string& s_cls() const {re 347 virtual const std::string& s_cls() const {return s_class();}\ 348 virtual tools::sg::node* copy() const {retur 348 virtual tools::sg::node* copy() const {return new a__class(*this);}\ 349 public:\ 349 public:\ 350 virtual void* cast(const std::string& a_clas 350 virtual void* cast(const std::string& a_class) const {\ 351 if(void* p = tools::cmp_cast<a__class>(thi 351 if(void* p = tools::cmp_cast<a__class>(this,a_class)) return p;\ 352 return parent::cast(a_class);\ 352 return parent::cast(a_class);\ 353 } 353 } 354 354 355 #define TOOLS_NODE_VT2(a__T1,a__T2,a__class,a_ 355 #define TOOLS_NODE_VT2(a__T1,a__T2,a__class,a__sclass,a__parent)\ 356 private:\ 356 private:\ 357 typedef a__parent parent;\ 357 typedef a__parent parent;\ 358 public:\ 358 public:\ 359 static const std::string& s_class() {\ 359 static const std::string& s_class() {\ 360 static const std::string s_v(std::string(# 360 static const std::string s_v(std::string(#a__class)+"<"+a__T1::s_class()+","+a__T2::s_class()+">");\ 361 return s_v;\ 361 return s_v;\ 362 }\ 362 }\ 363 static void check_class_name() {a__class<a__ 363 static void check_class_name() {a__class<a__T1,a__T2>::s_class();}\ 364 public:\ 364 public:\ 365 virtual const std::string& s_cls() const {re 365 virtual const std::string& s_cls() const {return s_class();}\ 366 /*virtual tools::sg::node* copy() const {ret 366 /*virtual tools::sg::node* copy() const {return new a__class(*this);}*/\ 367 public:\ 367 public:\ 368 virtual void* cast(const std::string& a_clas 368 virtual void* cast(const std::string& a_class) const {\ 369 if(void* p = tools::cmp_cast<a__class>(thi 369 if(void* p = tools::cmp_cast<a__class>(this,a_class)) return p;\ 370 return parent::cast(a_class);\ 370 return parent::cast(a_class);\ 371 } 371 } 372 372 373 #endif 373 #endif