1 /*
2  * NodeSwitch.cpp
3  *
4  * Copyright (C) 1999 Stephen F. White
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 #include <stdio.h>
23 #include "stdafx.h"
24 
25 #include "NodeSwitch.h"
26 #include "Proto.h"
27 #include "Scene.h"
28 #include "FieldValue.h"
29 #include "MFNode.h"
30 #include "SFInt32.h"
31 
ProtoSwitch(Scene * scene)32 ProtoSwitch::ProtoSwitch(Scene *scene)
33   : WonderlandExportProto(scene, "Switch")
34 {
35     bboxCenter.set(
36           addField(SFVEC3F, "bboxCenter", new SFVec3f(0.0f, 0.0f, 0.0f)));
37     setFieldFlags(bboxCenter, FF_X3D_ONLY);
38     bboxSize.set(
39           addField(SFVEC3F, "bboxSize", new SFVec3f(-1.0f, -1.0f, -1.0f),
40                    new SFFloat(-1.0f)));
41     setFieldFlags(bboxSize, FF_X3D_ONLY);
42     choice.set(
43           addExposedField(MFNODE, "choice", new MFNode(), CHILD_NODE,
44                           "children"));
45     whichChoice.set(
46           addExposedField(SFINT32, "whichChoice", new SFInt32(-1),
47                           new SFInt32(-1)));
48 
49     render.set(
50         addExposedField(SFBOOL, "render", new SFBool(true)));
51     setFieldFlags(render, FF_X3DOM_ONLY);
52 
53     addEventIn(MFNODE, "addChildren", FF_X3D_ONLY);
54     addEventIn(MFNODE, "removeChildren", FF_X3D_ONLY);
55 }
56 
57 Node *
create(Scene * scene)58 ProtoSwitch::create(Scene *scene)
59 {
60     return new NodeSwitch(scene, this);
61 }
62 
NodeSwitch(Scene * scene,Proto * def)63 NodeSwitch::NodeSwitch(Scene *scene, Proto *def)
64   : Node(scene, def)
65 {
66 }
67 
accountWhich()68 int NodeSwitch::accountWhich()
69 {
70     NodeList *choiceList = choice()->getValues();
71 
72     int which = whichChoice()->getValue();
73 
74     int whichCount = 0;
75     for (long i = 0; i < choiceList->size(); i++)
76         if (choiceList->get(i)->getType() != VRML_COMMENT) {
77             if (whichCount == which)
78                 return i;
79             else
80                 whichCount++;
81         }
82     return which;
83 }
84 
85 void
preDraw()86 NodeSwitch::preDraw()
87 {
88     NodeList *choiceList = choice()->getValues();
89 
90     int which = accountWhich();
91 
92     if (which < 0 || which >= (int)choiceList->size()) return;
93 
94     choiceList->get(which)->preDraw();
95 }
96 
97 void
draw(int pass)98 NodeSwitch::draw(int pass)
99 {
100     NodeList *choiceList = choice()->getValues();
101 
102     int which = accountWhich();
103 
104     if (which < 0 || which >= (int)choiceList->size()) return;
105 
106     glPushName(choice_Field());
107     glPushName(which);
108     choiceList->get(which)->draw(pass);
109     glPopName();
110     glPopName();
111 }
112 
113 void
flip(int index)114 NodeSwitch::flip(int index)
115 {
116     if (m_scene->isX3d())
117         bboxCenter()->flip(index);
118     choice()->flip(index);
119 }
120 
121 void
swap(int fromTo)122 NodeSwitch::swap(int fromTo)
123 {
124     if (m_scene->isX3d()) {
125         bboxCenter()->swap(fromTo);
126         bboxSize()->swap(fromTo);
127     }
128     choice()->swap(fromTo);
129 }
130 
131 // writing of file formats, which do not support switch-like constructs:
132 // if a valid choice is selected, write this choice, else write all in choice field
133 
134 int
writeAc3d(int filedes,int indent)135 NodeSwitch::writeAc3d(int filedes, int indent)
136 {
137     int which = accountWhich();
138     if (which < 0 || which >= (int)choice()->getValues()->size())
139         return choice()->writeAc3d(filedes, indent);
140     return choice()->getValues()->get(which)->writeAc3d(filedes, indent);
141 }
142 
143 int
writeRib(int filedes,int indent)144 NodeSwitch::writeRib(int filedes, int indent)
145 {
146     int which = accountWhich();
147     if (which > -1 && which < (int)choice()->getValues()->size())
148         return choice()->getValues()->get(which)->writeRib(filedes, indent);
149     return 0;
150 }
151 
152 int
writeCattGeo(int filedes,int indent)153 NodeSwitch::writeCattGeo(int filedes, int indent)
154 {
155     int which = accountWhich();
156     if (which < 0 || which >= (int)choice()->getValues()->size())
157         return choice()->getValues()->writeCattGeo(this, filedes, indent);
158     NodeList tempNode(choice()->getValue(which));
159     // The following is a dangerous construct.
160     // Works only, cause writeCattGeo gets only things like name, scene etc. from node
161     return tempNode.writeCattGeo(this, filedes, indent);
162 }
163 
164