Warning, /include/Geant4/tools/sg/node is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_sg_node
0005 #define tools_sg_node
0006
0007 #include "field"
0008 #include "search_action"
0009 #include "write_action"
0010 #include "read_action"
0011 #include "get_matrix_action"
0012 #include "node_desc"
0013
0014 #include "../forit"
0015
0016 namespace tools {
0017 namespace sg {
0018 class render_action;
0019 class pick_action;
0020 class bbox_action;
0021 class event_action;
0022 class visible_action;
0023 }}
0024
0025 namespace tools {
0026 namespace sg {
0027
0028 class node {
0029 public:
0030 TOOLS_SCLASS(tools::sg::node)
0031 //public:
0032 // static bool is_a(const std::string& a_class) {return rcmp(a_class,s_class());}
0033 // in a derived class:
0034 // static bool is_a(const std::string& a_class) {
0035 // if(rcmp(a_class,s_class())) return true;
0036 // return parent::is_a(a_class);
0037 // }
0038 virtual void* cast(const std::string& a_class) const {
0039 if(void* p = cmp_cast<node>(this,a_class)) return p;
0040 return 0;
0041 }
0042 virtual const std::string& s_cls() const = 0;
0043 public:
0044 virtual node* copy() const = 0;
0045
0046 virtual unsigned int cls_version() const {return 1;}
0047
0048 virtual const desc_fields& node_desc_fields() const {
0049 static const desc_fields s_v;
0050 return s_v;
0051 }
0052
0053 virtual void render(render_action&) {}
0054 virtual void pick(pick_action&) {}
0055 virtual void bbox(bbox_action&) {}
0056 virtual void search(search_action& a_action) {
0057 if(a_action.what()==search_action::search_node_of_class) {
0058 if(void* p = cast(a_action.sclass())) {
0059 a_action.add_obj(p);
0060 if(a_action.stop_at_first()) a_action.set_done(true);
0061 }
0062 } else if(a_action.what()==search_action::search_path_to_node) {
0063 if(this==a_action.node()){
0064 a_action.path_push(this); //ending node in the path.
0065 a_action.set_done(true);
0066 }
0067 } else if(a_action.what()==search_action::search_path_to_node_of_class) {
0068 if(cast(a_action.sclass())) {
0069 search_action::path_t path = a_action.path();
0070 path.push_back(this);
0071 a_action.add_path(path);
0072 if(a_action.stop_at_first()) a_action.set_done(true);
0073 }
0074 }
0075 }
0076 virtual void get_matrix(get_matrix_action& a_action) {
0077 if(this==a_action.node()){
0078 a_action.set_found_model(a_action.model_matrix());
0079 a_action.set_done(true);
0080 }
0081 }
0082 virtual bool write(write_action& a_action) {
0083 if(!a_action.beg_node(*this)) return false;
0084 if(!write_fields(a_action)) return false;
0085 if(!a_action.end_node(*this)) return false;
0086 return true;
0087 }
0088 virtual void event(event_action&) {}
0089 virtual bool read(read_action& a_action) {return read_fields(a_action);}
0090 virtual void is_visible(visible_action&) {}
0091
0092 virtual void protocol_one_fields(std::vector<field*>& a_fields) const {a_fields = m_fields;}
0093
0094 virtual bool draw_in_frame_buffer() const {return false;} // marker nodes return true.
0095 public:
0096 virtual bool touched() { //virtual for plotter.
0097 tools_vforcit(field*,m_fields,it) {
0098 if((*it)->touched()) return true;
0099 }
0100 return false;
0101 }
0102 virtual void reset_touched() {
0103 tools_vforcit(field*,m_fields,it) (*it)->reset_touched();
0104 }
0105 public:
0106 node()
0107 {
0108 #ifdef TOOLS_MEM
0109 mem::increment(s_class().c_str());
0110 #endif
0111 }
0112 virtual ~node(){
0113 #ifdef TOOLS_MEM
0114 mem::decrement(s_class().c_str());
0115 #endif
0116 }
0117 protected:
0118 node(const node&)
0119 {
0120 #ifdef TOOLS_MEM
0121 mem::increment(s_class().c_str());
0122 #endif
0123 }
0124 node& operator=(const node&){
0125 return *this;
0126 }
0127 protected:
0128 void add_field(field* a_field) {
0129 m_fields.push_back(a_field); //it does not take ownerhship.
0130 }
0131 //TOOLS_CLASS_STRING(fields_end) //for write_bsg, sg::rbsg
0132 bool write_fields(write_action& a_action) {
0133
0134 check_fields(a_action.out()); //costly.
0135 //dump_field_descs(a_action.out());
0136
0137 unsigned int index = 0;
0138 tools_vforcit(field*,m_fields,it) {
0139 if(!(*it)->write(a_action.buffer())) {
0140 a_action.out() << "node::write_fields :"
0141 << " for field index " << index
0142 << " and field class " << (*it)->s_cls()
0143 << " of node class " << s_cls()
0144 << " : field.write() failed" << "."
0145 << std::endl;
0146 return false;
0147 }
0148 index++;
0149 }
0150 return true;
0151 }
0152
0153 bool read_fields(read_action& a_action) { //used in protocol-2.
0154 node_desc rndesc;
0155 if(!a_action.get_node_desc(s_cls(),rndesc)) {
0156 a_action.out() << "tools::node::read_fields :"
0157 << " for node class " << s_cls()
0158 << " : read_action.get_node_desc() failed."
0159 << std::endl;
0160 return false;
0161 }
0162 //Whatever the current node fields, we must read all rndesc.fields() :
0163 tools_vforcit(field_desc,rndesc.fields(),it) {
0164 const field_desc& fdesc = *it;
0165
0166 field* fd = find_field(fdesc);
0167 if(!fd) {
0168 a_action.out() << "tools::node::read_fields :"
0169 << " for node class " << s_cls()
0170 << " : field desc name " << fdesc.name()
0171 << " : field desc class " << fdesc.cls()
0172 << " : field desc offset " << fdesc.offset()
0173 << " : field not found."
0174 << "."
0175 << std::endl;
0176 //#define TOOLS_NODE_DEBUG_READ_FIELD
0177 #ifdef TOOLS_NODE_DEBUG_READ_FIELD
0178 check_fields(a_action.out()); //costly.
0179 dump_field_descs(a_action.out());
0180 {a_action.out() << "read field descs of node class " << s_cls() << " :" << std::endl;
0181 tools_vforcit(field_desc,rndesc.fields(),itr) {
0182 a_action.out() << "name " << (*itr).name()
0183 << ", class " << (*itr).cls()
0184 << ", offset " << (*itr).offset()
0185 << std::endl;
0186 }}
0187 {a_action.out() << "m_fields of node class " << s_cls() << " :" << std::endl;
0188 tools_vforcit(field*,m_fields,itm) {
0189 a_action.out() << "field class " << (*itm)->s_cls()
0190 << ", found offset " << field_offset(*itm)
0191 << std::endl;
0192 }}
0193 ::exit(0);
0194 #endif
0195 fd = a_action.field_factory().create(fdesc.cls());
0196 if(!fd) {
0197 a_action.out() << "tools::node::read_fields :"
0198 << " for node class " << s_cls()
0199 << " : field desc class " << fdesc.cls()
0200 << " : can't create generic field."
0201 << "."
0202 << std::endl;
0203 return false;
0204 }
0205 } /*else {
0206 a_action.out() << "debug : tools::node::read_fields :"
0207 << " for node class " << s_cls()
0208 << " : field desc class " << fdesc.cls()
0209 << " : field desc offset " << fdesc.offset()
0210 << " : field found."
0211 << "."
0212 << std::endl;
0213 }*/
0214
0215 if(!fd->read(a_action.buffer())) {
0216 a_action.out() << "tools::node::read_fields :"
0217 << " for node class " << s_cls()
0218 << " : and field class " << fd->s_cls()
0219 << " : field read() failed."
0220 << std::endl;
0221 return false;
0222 }
0223 //fd->dump(a_action.out());
0224 }
0225
0226 //NOTE : if some current node fields had not been found
0227 // in rndesc.fields(), they catch the default value
0228 // of the node fields.
0229
0230 return true;
0231 }
0232 public:
0233 void touch() {
0234 if(m_fields.empty()) return;
0235 m_fields.front()->touch();
0236 }
0237 /*
0238 bool equal(const node& a_node) const {
0239 if(m_fields.size()!=a_node.m_fields.size()) return false;
0240 std::vector<field*>::iterator it = m_fields.begin();
0241 std::vector<field*>::iterator ait = a_node.m_fields.begin();
0242 for(;it!=m_fields.end();++it,++ait) {
0243 if(!(*it)->equal(*(*ait))) return false;
0244 }
0245 return true;
0246 }
0247 */
0248 public:
0249 field& field_from_desc(const field_desc& a_desc) const {
0250 //WARNING : touchy.
0251 return *((field*)((char*)this+a_desc.offset()));
0252 }
0253 void dump_field_descs(std::ostream& a_out) const {
0254 a_out << "field descs of node class " << s_cls() << " :" << std::endl;
0255 const std::vector<field_desc>& fds = node_desc_fields();
0256 tools_vforcit(field_desc,fds,itd) {
0257 a_out << "name " << (*itd).name()
0258 << ", class " << (*itd).cls()
0259 << ", offset " << (*itd).offset()
0260 << std::endl;
0261 }
0262 }
0263 field* find_field_by_name(const std::string& a_name) const {
0264 // a_name is of the form <class>.<field>. For example for color on sg::text, there are :
0265 // tools::sg::back_area.color
0266 // tools::sg::text.color
0267 const std::vector<field_desc>& fds = node_desc_fields();
0268 tools_vforcrit(field_desc,fds,it) {
0269 if((*it).name()==a_name) {
0270 tools_vforcit(field*,m_fields,itf) {
0271 if(field_offset(*itf)==(*it).offset()) return (*itf);
0272 }
0273 }
0274 }
0275 return 0;
0276 }
0277 protected:
0278 field_desc::offset_t field_offset(const field* a_field) const {
0279 //WARNING : touchy.
0280 return ((char*)(a_field)-(char*)(this));
0281 }
0282
0283 field* find_field(const field_desc& a_rdesc) const {
0284 const std::vector<field_desc>& fds = node_desc_fields();
0285 tools_vforcit(field_desc,fds,it) {
0286 if((*it).name()==a_rdesc.name()) {
0287 tools_vforcit(field*,m_fields,itf) {
0288 //::printf("debug : find_field : look : %s\n",field_name(*(*it)).c_str());
0289 if(field_offset(*itf)==(*it).offset()) return (*itf);
0290 }
0291 }
0292 }
0293 return 0;
0294 }
0295
0296 void check_fields(std::ostream& a_out) const {
0297 const std::vector<field_desc>& fds = node_desc_fields();
0298 tools_vforcit(field*,m_fields,it) {
0299 bool found = false;
0300 tools_vforcit(field_desc,fds,itd) {
0301 if( ((*itd).offset()==field_offset(*it)) &&
0302 ((*itd).cls()==(*it)->s_cls())
0303 ){
0304 found = true;
0305 break;
0306 }
0307 }
0308 if(!found) {
0309 a_out << "tools::sg::node::check_fields :"
0310 << " WARNING : node of class " << s_cls()
0311 << " has bad fields description."
0312 << std::endl;
0313 }
0314 }
0315 }
0316 private:
0317 std::vector<field*> m_fields;
0318 };
0319
0320 }}
0321
0322 #include "../HEADER"
0323
0324 #define TOOLS_NODE(a__class,a__sclass,a__parent)\
0325 TOOLS_HEADER(a__class,a__sclass,a__parent)\
0326 virtual tools::sg::node* copy() const {return new a__class(*this);}
0327
0328 #define TOOLS_NODE_NO_CAST(a__class,a__sclass,a__parent)\
0329 private:\
0330 typedef a__parent parent;\
0331 public:\
0332 TOOLS_SCLASS(a__sclass)\
0333 public:\
0334 virtual const std::string& s_cls() const {return s_class();}\
0335 virtual tools::sg::node* copy() const {return new a__class(*this);}
0336
0337 #define TOOLS_NODE_T(a__T,a__class,a__sclass,a__parent)\
0338 private:\
0339 typedef a__parent parent;\
0340 public:\
0341 static const std::string& s_class() {\
0342 static const std::string s_v(std::string(#a__class)+"<"+a__T::s_class()+">");\
0343 return s_v;\
0344 }\
0345 static void check_class_name() {a__class<a__T>::s_class();}\
0346 public:\
0347 virtual const std::string& s_cls() const {return s_class();}\
0348 virtual tools::sg::node* copy() const {return new a__class(*this);}\
0349 public:\
0350 virtual void* cast(const std::string& a_class) const {\
0351 if(void* p = tools::cmp_cast<a__class>(this,a_class)) return p;\
0352 return parent::cast(a_class);\
0353 }
0354
0355 #define TOOLS_NODE_VT2(a__T1,a__T2,a__class,a__sclass,a__parent)\
0356 private:\
0357 typedef a__parent parent;\
0358 public:\
0359 static const std::string& s_class() {\
0360 static const std::string s_v(std::string(#a__class)+"<"+a__T1::s_class()+","+a__T2::s_class()+">");\
0361 return s_v;\
0362 }\
0363 static void check_class_name() {a__class<a__T1,a__T2>::s_class();}\
0364 public:\
0365 virtual const std::string& s_cls() const {return s_class();}\
0366 /*virtual tools::sg::node* copy() const {return new a__class(*this);}*/\
0367 public:\
0368 virtual void* cast(const std::string& a_class) const {\
0369 if(void* p = tools::cmp_cast<a__class>(this,a_class)) return p;\
0370 return parent::cast(a_class);\
0371 }
0372
0373 #endif