KiCad PCB EDA Suite
vrml2_switch.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Cirilo Bernardo <[email protected]>
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <iostream>
26 #include <sstream>
27 #include <wx/log.h>
28 
29 #include "vrml2_base.h"
30 #include "vrml2_switch.h"
31 #include "plugins/3dapi/ifsg_all.h"
32 
33 
35 {
37  whichChoice = -1;
38 }
39 
40 
42 {
44  m_Parent = aParent;
45  whichChoice = -1;
46 
47  if( nullptr != m_Parent )
48  m_Parent->AddChildNode( this );
49 }
50 
51 
53 {
54  wxLogTrace( traceVrmlPlugin,
55  wxT( " * [INFO] Destroying Switch node with %zu children, %zu"
56  "references, and %zu back pointers." ),
57  m_Children.size(), m_Refs.size(), m_BackPointers.size() );
58 }
59 
60 
62 {
63  // a Switch node is never dangling
64  return false;
65 }
66 
67 
68 bool WRL2SWITCH::Read( WRLPROC& proc, WRL2BASE* aTopNode )
69 {
70  /*
71  * Structure of a Switch node (p.113):
72  *
73  * Switch {
74  * exposedField MFNode choice []
75  * exposedField SFInt32 whichChoice -1
76  * }
77  */
78 
79  wxCHECK_MSG( aTopNode, false, wxT( "Invalid top node." ) );
80 
81  char tok = proc.Peek();
82 
83  if( proc.eof() )
84  {
85  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
86  " * [INFO] bad file format; unexpected eof %s." ),
87  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
88 
89  return false;
90  }
91 
92  if( '{' != tok )
93  {
94  wxLogTrace( traceVrmlPlugin,
95  wxT( "%s:%s:%d\n"
96  " * [INFO] bad file format; expecting '{' but got '%s' %s." ),
97  __FILE__, __FUNCTION__, __LINE__, tok, proc.GetFilePosition() );
98 
99  return false;
100  }
101 
102  proc.Pop();
103  std::string glob;
104 
105  while( true )
106  {
107  if( proc.Peek() == '}' )
108  {
109  proc.Pop();
110  break;
111  }
112 
113  if( !proc.ReadName( glob ) )
114  {
115  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
116  "%s" ),
117  __FILE__, __FUNCTION__, __LINE__ , proc.GetError() );
118 
119  return false;
120  }
121 
122  // expecting one of:
123  // choice
124  // whichChoice
125  if( !glob.compare( "whichChoice" ) )
126  {
127  if( !proc.ReadSFInt( whichChoice ) )
128  {
129  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
130  " * [INFO] invalid whichChoice %s\n"
131  " * [INFO] file: '%s'\n"
132  "%s" ),
133  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
134  proc.GetFileName(), proc.GetError() );
135 
136  return false;
137  }
138  }
139  else if( !glob.compare( "choice" ) )
140  {
141  if( !readChildren( proc, aTopNode ) )
142  return false;
143  }
144  else
145  {
146  wxLogTrace( traceVrmlPlugin,
147  wxT( "%s:%s:%d\n"
148  " * [INFO] invalid Switch %s.\n"
149  " * [INFO] file: '%s'\n" ),
150  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
151  proc.GetFileName() );
152 
153  return false;
154  }
155  } // while( true ) -- reading contents of Switch{}
156 
157  return true;
158 }
159 
160 
162 {
163  wxCHECK_MSG( aNode, false, wxT( "Invalid node." ) );
164 
165  // take possession if the node is dangling WRL2_SHAPE
166  if( WRL2NODES::WRL2_SHAPE == aNode->GetNodeType() && aNode->isDangling() )
167  {
168  WRL2NODE* np = aNode->GetParent();
169 
170  if( nullptr != np )
171  aNode->SetParent( this );
172 
173  if( !WRL2NODE::AddChildNode( aNode ) )
174  {
175  aNode->SetParent( nullptr );
176  return false;
177  }
178  }
179 
180  if( !WRL2NODE::AddRefNode( aNode ) )
181  return false;
182 
183  return true;
184 }
185 
186 
187 bool WRL2SWITCH::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
188 {
189  char tok = proc.Peek();
190 
191  if( proc.eof() )
192  {
193  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
194  " * [INFO] bad file format; unexpected eof %s." ),
195  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
196 
197  return false;
198  }
199 
200  WRL2NODE* child = nullptr;
201 
202  if( '[' != tok )
203  {
204  // since there are no delimiters we expect a single child
205  if( !aTopNode->ReadNode( proc, this, &child ) )
206  return false;
207 
208  if( nullptr != child )
209  choices.push_back( child );
210 
211  if( proc.Peek() == ',' )
212  proc.Pop();
213 
214  return true;
215  }
216 
217  proc.Pop();
218 
219  while( true )
220  {
221  if( proc.Peek() == ']' )
222  {
223  proc.Pop();
224  break;
225  }
226 
227  if( !aTopNode->ReadNode( proc, this, &child ) )
228  return false;
229 
230  if( nullptr != child )
231  choices.push_back( child );
232 
233  if( proc.Peek() == ',' )
234  proc.Pop();
235 
236  }
237 
238  return true;
239 }
240 
241 
243 {
244  wxLogTrace( traceVrmlPlugin,
245  wxT( " * [INFO] Translating Switch with %zu children, %zu references, and"
246  "%zu back pointers." ),
247  m_Children.size(), m_Refs.size(), m_BackPointers.size() );
248 
249  if( choices.empty() )
250  {
251  wxLogTrace( traceVrmlPlugin, " * [INFO] Switch translation: no choices." );
252 
253  return nullptr;
254  }
255 
256  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
257 
258  wxCHECK_MSG( aParent && ( ptype == S3D::SGTYPE_TRANSFORM ), nullptr,
259  wxString::Format( wxT( "Switch does not have a Transform parent (parent "
260  "ID: %d)." ), ptype ) );
261 
262  if( whichChoice < 0 || whichChoice >= (int)choices.size() )
263  {
264  wxLogTrace( traceVrmlPlugin,
265  wxT( " * [INFO] Switch translation: no choice (choices = %zu), "
266  "whichChoice = %d." ), choices.size(), whichChoice );
267 
268  return nullptr;
269  }
270 
271  WRL2NODES type = choices[whichChoice]->GetNodeType();
272 
273  switch( type )
274  {
279  break;
280 
281  default:
282  return nullptr;
283  }
284 
285  return choices[whichChoice]->TranslateToSG( aParent );
286 }
virtual bool SetParent(WRL2NODE *aParent, bool doUnlink=true)
Set the parent WRL2NODE of this object.
Definition: vrml2_node.cpp:339
void Pop(void)
Definition: wrlproc.cpp:2035
std::list< WRL2NODE * > m_Children
Definition: vrml2_node.h:174
bool AddRefNode(WRL2NODE *aNode) override
std::list< WRL2NODE * > m_Refs
Definition: vrml2_node.h:175
WRL2NODES m_Type
Definition: vrml2_node.h:170
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
collects header files for all SG* wrappers and the API
bool ReadNode(WRLPROC &proc, WRL2NODE *aParent, WRL2NODE **aNode)
Definition: vrml2_base.cpp:276
bool isDangling(void) override
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
bool readChildren(WRLPROC &proc, WRL2BASE *aTopNode)
WRL2NODE * m_Parent
Definition: vrml2_node.h:169
std::string GetFilePosition() const
Definition: wrlproc.cpp:1982
std::list< WRL2NODE * > m_BackPointers
Definition: vrml2_node.h:173
WRL2NODES GetNodeType(void) const
Definition: vrml2_node.cpp:204
char Peek(void)
Definition: wrlproc.cpp:2007
std::string GetFileName(void)
Definition: wrlproc.cpp:1995
The top node of a VRML2 model.
Definition: vrml2_base.h:59
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition: vrml.cpp:63
int whichChoice
Definition: vrml2_switch.h:53
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
SGTYPES
Definition: sg_types.h:34
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
virtual ~WRL2SWITCH()
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
virtual bool isDangling(void)=0
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:483
virtual bool AddChildNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:356
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:289
bool ReadSFInt(int &aSFInt32)
Definition: wrlproc.cpp:867
WRL2NODE * GetParent(void) const
Definition: vrml2_node.cpp:210
WRL2NODES
Definition: wrltypes.h:124
std::string GetError(void)
Definition: wrlproc.cpp:1960
virtual bool AddRefNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:383
bool eof(void)
Definition: wrlproc.cpp:1954
std::vector< WRL2NODE * > choices
Definition: vrml2_switch.h:54