1 /*
2  * Proto.h
3  *
4  * Copyright (C) 1999 Stephen F. White, 2005 J. "MUFTI" Scheurich
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file "COPYING" for details); if
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  */
21 
22 #pragma once
23 
24 # include "Array.h"
25 # include "Map.h"
26 # include "MyString.h"
27 # include "Node.h"
28 
29 #define INVALID_INDEX (-1)
30 
31 class Element;
32 class EventIn;
33 class EventOut;
34 class Field;
35 class ExposedField;
36 class FieldValue;
37 class Scene;
38 class Node;
39 
40 #include "ProtoMacros.h"
41 #include "StringArray.h"
42 #include "NodeList.h"
43 #include "InterfaceArray.h"
44 
45 class NodeScript;
46 class ScriptDialog;
47 
48 enum UrlSchemas {
49     URL_NULL,
50     URL_VRML97_AMENDMENT1,
51     URL_X3D,
52     URL_SCRIPTED_NODES,
53     URL_COVER,
54     URL_KAMBI,
55     URL_EXPORT_CONTAINER
56 };
57 
58 class RouteInfo {
59 public:
RouteInfo(Node * s,int out,Node * d,int in)60                     RouteInfo(Node *s, int out, Node *d, int in)
61                     { src = s; eventOut = out; dest = d; eventIn = in; }
RouteInfo()62                     RouteInfo()
63                     { src = NULL; eventOut = -1; dest = NULL; eventIn = -1; }
64 
65     Node           *src;
66     Node           *dest;
67     int             eventOut;
68     int             eventIn;
69 };
70 
71 
72 class Proto {
73 public:
74 
75     // unlike other nodes, script nodes need to change their Proto dynamically
76     friend class DynamicFieldsNode;
77 
78                           Proto(Scene *scene, const MyString &name);
79                           // create a Proto as a X3D/Cover extension
80                           Proto(Scene *scene, Proto *proto, int extensionFlag);
Proto()81                           Proto() {}
82     virtual              ~Proto();
83 
84     FieldIndex metadata;
85 
metadata_Field(void)86     int metadata_Field(void) const { return metadata; }
87 
88     void                  protoInitializer(Scene *scene, const MyString &name);
89 
isDynamicFieldsProto(void)90     virtual bool          isDynamicFieldsProto(void) { return false; }
91 
92     void                  finishEvents(void);
93 
94     bool                  avoidElement(Element *element, bool x3d);
95     bool                  avoidElement(Element *element, int flag);
96 
getType()97     virtual int           getType() const { return -1; }
getNodeClass()98     virtual int           getNodeClass() const { return CHILD_NODE; }
99 
100     bool                  matchNodeClass(int childType) const;
101 
102     virtual Node         *create(Scene *scene);
needUpdate(void)103     virtual bool          needUpdate(void) { return false; }
104 
getEventIn(int index)105     EventIn              *getEventIn(int index) const
106                              { return m_eventIns[index]; }
getEventOut(int index)107     EventOut             *getEventOut(int index) const
108                              { return m_eventOuts[index]; }
getField(int index)109     Field                *getField(int index) const { return m_fields[index]; }
getExposedField(int index)110     ExposedField         *getExposedField(int index) const
111                              { return m_exposedFields[index]; }
112     Element              *getElement(int elementType, int index) const;
113 
getNumFields()114     int                   getNumFields() const { return m_fields.size(); }
getNumEventIns()115     int                   getNumEventIns() const { return m_eventIns.size(); }
getNumEventOuts()116     int                   getNumEventOuts() const { return m_eventOuts.size(); }
getNumExposedFields()117     int                   getNumExposedFields() const
118                              { return m_exposedFields.size(); }
119 
120     int                   getExposedOfField(Field *field);
121     int                   getFieldOfExposed(ExposedField *field);
122 
123     int                   lookupEventIn(const MyString &name,
124                                         bool x3d = false) const;
125     int                   lookupEventOut(const MyString &name,
126                                          bool x3d = false) const;
127     int                   lookupField(const MyString &name,
128                                       bool x3d = false) const;
129     int                   lookupExposedField(const MyString &name,
130                                              bool x3d = false) const;
131 
132     int                   lookupIsEventIn(const char *name,
133                                           int elementType = -1) const;
134     int                   lookupIsExposedField(const char *name,
135                                                int elementType = -1) const;
136 
137     int                   lookupIsEventIn(Node *node, int eventIn,
138                                           int elementType = -1) const;
139     int                   lookupIsEventOut(Node *node, int eventOut,
140                                            int elementType = -1) const;
141     int                   lookupIsField(Node *node, int field) const;
142     int                   lookupIsExposedField(Node *node, int field) const;
143 
144     int                   getNumIsMSNodes(void) const;
145     Node                 *getIsMSNode(int numNode) const;
146     int                   getIsMSNodeField(int numNode) const;
147 
getName(bool x3d)148     virtual const MyString &getName(bool x3d) const { return m_name; }
149 
150     bool                  canWriteElement(Element *element, bool x3d) const;
151     int                   write(int filedes, int indent, int flags) const;
152     int                   writeEvents(int filedes, int indent, int flags) const;
153 
154     virtual int           writeCDeclaration(int filedes, int languageFlag);
155     int                   writeCDeclarationEventIn(int f, int i,
156                                                    int languageFlag);
157     int                   writeCDeclarationEventOut(int f, int i,
158                                                     int languageFlag);
159     int                   writeCDeclarationField(int f, int i,
160                                                  int languageFlag);
161     virtual int           writeCExtraFields(int f, int languageFlag);
162     int                   writeCConstructorField(int f, int i,
163                                                  int languageFlag);
164     int                   writeCCallTreeField(int f, int i,
165                                               const char *treeFunctionName,
166                                               int languageFlag,
167                                               const char *functionName = NULL,
168                                               bool useObject = false);
169 
170     void                  buildExportNames(const char *nodeName = NULL);
getClassName(void)171     const char           *getClassName(void)
172                              { return m_className; }
173 
174     MyString              buildCallbackClass(const char* name);
175     MyString              buildCallbackName(const char* name);
176 
getRenderCallbackClass(void)177     const char           *getRenderCallbackClass(void)
178                              { return m_renderCallbackClass; }
getRenderCallbackName(void)179     const char           *getRenderCallbackName(void)
180                              { return m_renderCallbackName; }
181 
getTreeRenderCallbackClass(void)182     const char           *getTreeRenderCallbackClass(void)
183                              { return m_treeRenderCallbackClass; }
getTreeRenderCallbackName(void)184     const char           *getTreeRenderCallbackName(void)
185                              { return m_treeRenderCallbackName; }
186 
getCreateNormalsCallbackClass(void)187     const char           *getCreateNormalsCallbackClass(void)
188                              { return m_createNormalsCallbackClass; }
getCreateNormalsCallbackName(void)189     const char           *getCreateNormalsCallbackName(void)
190                              { return m_createNormalsCallbackName; }
191 
getDoWithDataCallbackClass(void)192     const char           *getDoWithDataCallbackClass(void)
193                              { return m_doWithDataCallbackClass; }
getDoWithDataCallbackName(void)194     const char           *getDoWithDataCallbackName(void)
195                              { return m_doWithDataCallbackName; }
196 
getTreeDoWithDataCallbackClass(void)197     const char           *getTreeDoWithDataCallbackClass(void)
198                              { return m_treeDoWithDataCallbackClass; }
getTreeDoWithDataCallbackName(void)199     const char           *getTreeDoWithDataCallbackName(void)
200                              { return m_treeDoWithDataCallbackName; }
201 
getProcessEventCallbackClass(void)202     const char           *getProcessEventCallbackClass(void)
203                              { return m_processEventCallbackClass; }
getProcessEventCallbackName(void)204     const char           *getProcessEventCallbackName(void)
205                              { return m_processEventCallbackName; }
206 
translateField(int field)207     virtual int           translateField(int field) const { return field; }
208 
getCName(bool x3d)209     virtual const MyString &getCName(bool x3d) const { return m_cName; }
210 
211     int                   addElement(Element *element);
212     int                   addOrUpdateElement(Element *element);
213     int                   addField(Field *field);
214     int                   addExposedField(ExposedField *exposedField);
215 
216     void                  deleteElements(void);
217 
218     void                  define(Node *primaryNode, NodeList *nodes);
getNumNodes(void)219     int                   getNumNodes(void) { return m_protoNodes.size(); }
getNode(long i)220     Node                 *getNode(long i)
221                              {
222                              if (i >= m_protoNodes.size())
223                                  return NULL;
224                              return m_protoNodes[i];
225                              }
addNode(Node * node)226     void                  addNode(Node *node)
227                              {
228                              m_protoNodes.append(node);
229                              }
230     void                  removeNode(int i);
231     void                  removeFromIs(Node *node);
232     void                  compareToIsNodes(Node *node);
233     void                  addURLs(FieldValue *urls);
234     void                  addURLs(int urlSchema);
getURLs(void)235     FieldValue *          getURLs(void) { return m_urls; }
isInternUrl(void)236     bool                  isInternUrl(void) { return m_isInternUrl; }
237 
isX3dExtensionProto(void)238     bool                  isX3dExtensionProto(void)
239                              { return isExtensionProto(FF_X3D_ONLY); }
isCoverExtensionProto(void)240     bool                  isCoverExtensionProto(void)
241                              { return isExtensionProto(FF_COVER_ONLY); }
isKambiExtensionProto(void)242     bool                  isKambiExtensionProto(void)
243                              { return isExtensionProto(FF_KAMBI_ONLY); }
isX3domExtensionProto(void)244     bool                  isX3domExtensionProto(void)
245                              { return isExtensionProto(FF_X3DOM_ONLY); }
246     bool                  isExtensionProto(int flag);
247     bool                  isMismatchingProto(void);
getUrls(void)248     FieldValue           *getUrls(void) { return m_urls; }
isExternProto(void)249     bool                  isExternProto(void) { return m_urls != NULL; }
250     bool                  checkIsExtension(Element *element, int flag);
251 
isCoverProto(void)252     virtual bool          isCoverProto(void) { return false; }
isKambiProto(void)253     virtual bool          isKambiProto(void) { return false; }
isX3domProto(void)254     virtual bool          isX3domProto(void) { return false; }
isScriptedProto(void)255     virtual bool          isScriptedProto(void) { return false; }
isScriptedExternProto(void)256     virtual bool          isScriptedExternProto(void) { return false; }
isX3dInternalProto(void)257     virtual bool          isX3dInternalProto(void) { return false; }
258 
setScene(Scene * scene)259     void                  setScene(Scene *scene) { m_scene = scene; }
getScene(void)260     Scene                *getScene(void) { return m_scene; }
261 
262     void                  convert2X3d(void);
263     void                  convert2Vrml(void);
264 
isLoading(void)265     bool                  isLoading(void) { return m_loading; }
setLoading(bool flag)266     void                  setLoading(bool flag) { m_loading = flag; }
isLoaded(void)267     bool                  isLoaded(void)
268                              { return m_loaded && (m_protoNodes.size() > 0); }
setLoaded(bool flag)269     void                  setLoaded(bool flag) { m_loaded = flag; }
270 
isDefined(void)271     bool                  isDefined(void) { return m_defined; }
272 
setAppinfo(const MyString & appinfo)273     void                  setAppinfo(const MyString& appinfo)
274                              { m_appinfo = appinfo; }
getAppinfo()275     MyString              getAppinfo() const
276                              { return m_appinfo; }
setDocumentation(const MyString & documentation)277     void                  setDocumentation(const MyString& documentation)
278                              { m_documentation = documentation; }
getDocumentation()279     MyString              getDocumentation() const
280                              { return m_documentation; }
281 
isDynamicProto(void)282     bool                  isDynamicProto(void) { return m_dynamicProto; }
setDynamicProto(void)283     void                  setDynamicProto(void) { m_dynamicProto = true; }
284 
isMesh(void)285     virtual bool          isMesh(void) { return false; }
isExportTargetMesh(void)286     virtual bool          isExportTargetMesh(void) { return false; }
isWonderlandExported(void)287     virtual bool          isWonderlandExported(void)
288                              {
289                              if (isMesh())
290                                  return true;
291                              return false;
292                              }
293 
isWriteCDeclarationWritten()294     bool                  isWriteCDeclarationWritten()
295                               { return m_writeCDeclarationWritten; }
setWriteCDeclarationWritten(bool flag)296     void                  setWriteCDeclarationWritten(bool flag)
297                               { m_writeCDeclarationWritten = flag; }
298 
isInScene()299     bool                  isInScene()
300                               {
301 #ifdef HAVE_NULL_COMPARE
302                               if (this == NULL)
303                                   return false;
304 #endif
305                               return m_isInScene;
306                               }
setIsInScene(bool flag)307     void                  setIsInScene(bool flag) { m_isInScene = flag; }
308 
isDeclaredInRwd_h()309     virtual bool          isDeclaredInRwd_h() { return false; }
310 
isInUse(void)311     bool                  isInUse(void) { return m_inUse; }
setInUse(bool flag)312     void                  setInUse(bool flag) { m_inUse = flag; }
313 
fromProtoLibrary()314     bool                  fromProtoLibrary() { return m_fromProtoLibrary; }
setFromProtoLibrary()315     void                  setFromProtoLibrary() { m_fromProtoLibrary = true; }
316 
317     bool                  showFields(bool x3d);
showFields()318     virtual bool          showFields() { return false; }
319     bool                  hasNumbers4kids(void);
320 
getInterfaceData(void)321     InterfaceArray       *getInterfaceData(void)
322                               {
323                               return &m_interface;
324                               }
getInterfaceData(bool protoFlag)325     InterfaceArray       *getInterfaceData(bool protoFlag)
326                               {
327                               buildInterfaceData(protoFlag);
328                               return &m_interface;
329                               }
330     void                  buildInterfaceData(bool protoFlag);
331 
332     int                   addField(int fieldType, const MyString &name,
333                                    FieldValue *defaultValue = NULL,
334                                    FieldValue *min = NULL,
335                                    FieldValue *max = NULL);
336     int                   addExposedField(int fieldType, const MyString &name,
337                                           FieldValue *defaultValue = NULL,
338                                           FieldValue *min = NULL,
339                                           FieldValue *max = NULL,
340                                           const MyString &x3dName = "");
341     int                   addEventIn(int fieldType, const MyString &name);
342     int                   addEventOut(int fieldType, const MyString &name);
343 
getGraphPosition(float * x,float * y)344     void                  getGraphPosition(float *x, float *y) const
345                              { *x = m_graphX; *y = m_graphY; }
setGraphPosition(float x,float y)346     void                  setGraphPosition(float x, float y)
347                              { m_graphX = x; m_graphY = y; }
348 
getGraphSize(int * width,int * height)349     void                  getGraphSize(int *width, int *height) const
350                              { *width = m_graphWidth; *height = m_graphHeight; }
setGraphSize(int width,int height)351     void                  setGraphSize(int width, int height)
352                              { m_graphWidth = width; m_graphHeight = height; }
353     void                  deleteField(int i);
354     void                  deleteEventIn(int i);
355     void                  deleteEventOut(int i);
356     void                  deleteExposedField(int i);
357     void                  setIsNodeIndex(void);
358 
getUnitLength(void)359     double                getUnitLength(void) { return m_unitLength; }
getUnitAngle(void)360     double                getUnitAngle(void) { return m_unitAngle; }
361 
setUnitLength(double u)362     void                  setUnitLength(double u) { m_unitLength = u; }
setUnitAngle(double u)363     void                  setUnitAngle(double u) { m_unitAngle = u; }
364 
isCRouteSource(void)365     virtual bool          isCRouteSource(void) { return false; }
366 
hasTimeSensor(void)367     bool                  hasTimeSensor(void)
368                               { return m_hasTimeSensor; }
369 
specialInit(void)370     bool                  specialInit(void)
371                               {
372                               static bool init = true;
373                               if (init) {
374                                   init = false;
375                                   return true;
376                               }
377                               return false;
378                               }
379 
380 protected:
copy()381     Proto                *copy() const { return new Proto(*this); }
382     int                   addField(int fieldType, const MyString &name,
383                                    FieldValue *defaultValue, int nodeType);
384     int                   addField(int fieldType, const MyString &name,
385                                    FieldValue *defaultValue, int flags,
386                                    const char **strings);
387     int                   addEventIn(int fieldType, const MyString &name,
388                                      int flags);
389     int                   addEventIn(int fieldType, const MyString &name,
390                                      int flags, int field);
391     int                   addEventOut(int fieldType, const MyString &name,
392                                       int flags);
393     int                   addExposedField(int fieldType, const MyString &name,
394                                           FieldValue *defaultValue,
395                                           int nodeType,
396                                           const MyString &x3dName = "");
397     int                   addExposedField(int fieldType, const MyString &name,
398                                           FieldValue *defaultValue, int flags,
399                                           const char **strings);
400     int                   addExposedField(int fieldType, const MyString &name,
401                                           FieldValue *defaultValue,
402                                           FieldValue *min, FieldValue *max,
403                                           int nodeType, int flags,
404                                           const char **strings,
405                                           const MyString &x3dName);
406     int                   lookupSimpleEventIn(const MyString &name,
407                                               bool x3d) const;
408     int                   lookupSimpleEventOut(const MyString &name,
409                                                bool x3d) const;
410     void                  setFieldFlags(int index, int flags);
411 
412 protected:
413     Scene                *m_scene;
414     MyString              m_name;
415     MyArray<EventIn *>      m_eventIns;
416     MyArray<EventOut *>     m_eventOuts;
417     MyArray<Field *>        m_fields;
418     MyArray<ExposedField *> m_exposedFields;
419 
420     MyString              m_appinfo;
421     MyString              m_documentation;
422 
423     InterfaceArray        m_interface;
424 
425     bool                  m_writeCDeclarationWritten;
426     bool                  m_isInScene;
427 
428     bool                  m_showFieldsInit;
429     bool                  m_showFields;
430 
431     bool                  m_numbers4Kids;
432     bool                  m_numbers4KidsInit;
433 
434     // for PROTO's:
435     MyArray<Node *>       m_protoNodes;
436     int                   m_nodeIndex;
437     FieldValue           *m_urls;
438     bool                  m_isInternUrl;
439     bool                  m_loaded;
440     bool                  m_loading;
441     bool                  m_defined;
442     StringArray           m_nameOfFieldsWithDefaultValue;
443 
444     float                 m_graphX, m_graphY;
445     int                   m_graphWidth, m_graphHeight;
446 
447     MyString              m_cName;
448     MyString              m_className;
449 
450     MyString              m_renderCallbackClass;
451     MyString              m_renderCallbackName;
452 
453     MyString              m_treeRenderCallbackClass;
454     MyString              m_treeRenderCallbackName;
455 
456     MyString              m_createNormalsCallbackClass;
457     MyString              m_createNormalsCallbackName;
458 
459     MyString              m_doWithDataCallbackClass;
460     MyString              m_doWithDataCallbackName;
461 
462     MyString              m_treeDoWithDataCallbackClass;
463     MyString              m_treeDoWithDataCallbackName;
464 
465     MyString              m_processEventCallbackClass;
466     MyString              m_processEventCallbackName;
467 
468     bool                  m_dynamicProto;
469     bool                  m_inUse;
470 
471     bool                  m_fromProtoLibrary;
472     double                m_unitLength;
473     double                m_unitAngle;
474 
475     bool                  m_hasTimeSensor;
476 };
477 
478 #include "DynamicFieldsNode.h"
479 
480 class NodePROTO : public DynamicFieldsNode
481 {
482 public:
483                         NodePROTO(Scene *scene, Proto *proto);
484     void                createPROTO(bool copy = true);
485 
getX3dVersion(void)486     virtual int         getX3dVersion(void) const { return 0; }
487 
isPROTO(void)488     virtual bool        isPROTO(void) const { return true; }
489 
490     virtual int         write(int filedes, int indent, bool avoidUse);
491 
492     virtual int         writeXml(int filedes, int indent,
493                                  int containerField = -1,
494                                  bool avoidUse = false);
495 
writeFields(int filedes,int indent)496     virtual int         writeFields(int filedes, int indent)
497                             { return Node::writeFields(filedes, indent); }
498 
writeProto(int f)499     virtual int         writeProto(int f)  { return Node::writeProto(f); }
500 
writeCDynamicNodeCallback(int f,int languageFlag)501     virtual int         writeCDynamicNodeCallback(int f, int languageFlag)
502                         {
503                             return Node::writeCDynamicNodeCallback(f,
504                                        languageFlag);
505                         }
506 
507     virtual int         getType() const;
508     virtual int         getNodeClass() const;
509     virtual int         getProfile(void) const;
copy()510     virtual Node       *copy() const { return new NodePROTO(*this); }
511 
getPrimaryProto()512     virtual Proto      *getPrimaryProto() const
513                            { return m_indexedNodes[0]->getProto(); }
514 
515     virtual void        preDraw();
516     virtual void        draw();
517     virtual void        draw(int pass);
518 
519     virtual void        update();
520     virtual void        reInit(void);
521 
522     virtual FieldValue *getField(int index) const;
523     virtual void        setField(int index, FieldValue *value, int cf = -1);
524     void                receiveProtoEvent(int eventOut, double timestamp,
525                                          FieldValue *value);
526     virtual void        sendEvent(int eventOut, double timestamp,
527                                   FieldValue *value);
528     virtual void        receiveEvent(int eventIn, double timestamp,
529                                      FieldValue *value);
530     Node               *getIsNode(int nodeIndex);
531     void                appendToIndexedNodes(Node *node);
getNumIndexedNodes(void)532     int                 getNumIndexedNodes(void)
533                             { return m_indexedNodes.size(); }
getIndexedNode(int i)534     Node               *getIndexedNode(int i) { return m_indexedNodes[i]; }
isJoint(void)535     virtual bool        isJoint(void) { return m_jointRotationField != -1; }
isHumanoid(void)536     virtual bool        isHumanoid(void) { return m_isHumanoid; }
537     virtual void        drawHandles(void);
538     virtual int         countPolygons(void);
539     virtual int         countPrimitives(void);
540     virtual int         countPolygons1Sided(void);
541     virtual int         countPolygons2Sided(void);
542     virtual Vec3f       getHandle(int handle, int *constraint, int *field);
543     virtual void        setHandle(int handle, const Vec3f &v);
544     virtual void        transform();
545     virtual bool        isEXTERNPROTO(void);
546     void                getComponentsInBranch(DoWithNodeCallback callback,
547                                               void *data);
548     virtual bool        canWriteAc3d();
549     virtual int         writeAc3d(int filedes, int indent);
550     virtual void        handleAc3dMaterial(ac3dMaterialCallback callback,
551                                            Scene* scene);
552     virtual int         writeRib(int filedes, int indent);
553 
554     virtual bool        canWriteCattGeo();
555     virtual int         writeCattGeo(int filedes, int indent);
556 
hasProtoNodes(void)557     virtual bool        hasProtoNodes(void)
558                             { return m_indexedNodes.size() > 0; }
559     Node               *getProtoRoot(void);
560 
getProtoNode(int i)561     Node               *getProtoNode(int i) { return m_nodes.get(i); }
getNumProtoNodes(void)562     int                 getNumProtoNodes(void) { return m_nodes.size(); }
563 
isLoaded(void)564     bool                isLoaded(void)
565                              { return getProto()->isLoaded() &&
566                                       (m_indexedNodes.size() > 0); }
567 
showFields()568     virtual bool        showFields() { return true; }
569 
570 protected:
571     NodeList            m_nodes;
572     MyArray<Node *>     m_indexedNodes;
573     int                 m_jointRotationField;
574     bool                m_isHumanoid;
575 };
576 
577 typedef MyArray<Proto *>  ProtoArray;
578 int getMaskedNodeClass(int nodeClass);
579 bool matchNodeClass(int nodeType, int childType, bool repeat = true);
580 
581 class WonderlandExportProto : public Proto {
582 public:
WonderlandExportProto(Scene * scene,const char * name)583                         WonderlandExportProto(Scene *scene, const char *name) :
584                                               Proto(scene, name) {}
585 
isWonderlandExported(void)586     virtual bool        isWonderlandExported(void) { return true; }
587 };
588 
589