KiCad PCB EDA Suite
x3d_shape.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) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
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 
26 #include <iostream>
27 #include <sstream>
28 #include <wx/xml/xml.h>
29 #include <wx/log.h>
30 #include "x3d_ops.h"
31 #include "x3d_shape.h"
32 #include "plugins/3dapi/ifsg_all.h"
33 
34 
36 {
37  m_Type = X3D_SHAPE;
38  appearance = nullptr;
39  geometry = nullptr;
40 }
41 
42 
44 {
45  m_Type = X3D_SHAPE;
46  appearance = nullptr;
47  geometry = nullptr;
48 
49  if( nullptr != aParent )
50  {
51  X3DNODES ptype = aParent->GetNodeType();
52 
53  if( X3D_TRANSFORM == ptype || X3D_SWITCH == ptype )
54  m_Parent = aParent;
55  }
56 
57  if( nullptr != m_Parent )
58  m_Parent->AddChildNode( this );
59 }
60 
61 
63 {
64  wxLogTrace( traceVrmlPlugin,
65  wxT( " * [INFO] Destroying Shape with %zu children, %zu references, "
66  "%and ul back pointers." ),
67  m_Children.size(), m_Refs.size(), m_BackPointers.size() );
68 }
69 
70 
71 bool X3DSHAPE::Read( wxXmlNode* aNode, X3DNODE* aTopNode, X3D_DICT& aDict )
72 {
73  if( nullptr == aTopNode || nullptr == aNode )
74  return false;
75 
76  if( nullptr != appearance || nullptr != geometry )
77  return false;
78 
79  m_Dict = &aDict;
80  wxXmlAttribute* prop;
81 
82  for( prop = aNode->GetAttributes(); prop != nullptr; prop = prop->GetNext() )
83  {
84  const wxString& pname = prop->GetName();
85 
86  if( pname == "DEF" )
87  {
88  m_Name = prop->GetValue();
89  m_Dict->AddName( m_Name, this );
90  }
91  }
92 
93  for( wxXmlNode* child = aNode->GetChildren(); child != nullptr; child = child->GetNext() )
94  {
95  wxString name = child->GetName();
96 
97  if( name == "Appearance" && nullptr == appearance )
98  X3D::ReadAppearance( child, this, aDict );
99  else if( name == "IndexedFaceSet" && nullptr == geometry )
100  X3D::ReadIndexedFaceSet( child, this, aDict );
101  }
102 
103  if( nullptr == appearance || nullptr == geometry )
104  return false;
105 
106  if( !SetParent( aTopNode ) )
107  return false;
108 
109  return true;
110 }
111 
112 
113 bool X3DSHAPE::SetParent( X3DNODE* aParent, bool doUnlink )
114 {
115  if( aParent == m_Parent )
116  return true;
117 
118  if( nullptr != aParent )
119  {
120  X3DNODES nt = aParent->GetNodeType();
121 
122  if( nt != X3D_SWITCH && nt != X3D_TRANSFORM )
123  return false;
124  }
125 
126  if( nullptr != m_Parent && doUnlink )
127  m_Parent->unlinkChildNode( this );
128 
129  m_Parent = aParent;
130 
131  if( nullptr != m_Parent )
132  m_Parent->AddChildNode( this );
133 
134  return true;
135 }
136 
137 
139 {
140  if( nullptr == aNode )
141  return false;
142 
143  X3DNODES tchild = aNode->GetNodeType();
144 
145  if( X3D_APPEARANCE != tchild && X3D_INDEXED_FACE_SET != tchild )
146  return false;
147 
148  std::list< X3DNODE* >::iterator sC = m_Children.begin();
149  std::list< X3DNODE* >::iterator eC = m_Children.end();
150 
151  while( sC != eC )
152  {
153  if( *sC == aNode )
154  return false;
155 
156  ++sC;
157  }
158 
159  if( X3D_APPEARANCE == tchild )
160  {
161  if( nullptr == appearance )
162  {
163  m_Children.push_back( aNode );
164  appearance = aNode;
165  }
166  else
167  {
168  return false;
169  }
170  }
171  else
172  {
173  if( nullptr == geometry )
174  {
175  m_Children.push_back( aNode );
176  geometry = aNode;
177  }
178  else
179  {
180  return false;
181  }
182  }
183 
184  if( aNode->GetParent() != this )
185  aNode->SetParent( this );
186 
187  return true;
188 }
189 
190 
192 {
193  if( nullptr == aNode )
194  return false;
195 
196  X3DNODES tchild = aNode->GetNodeType();
197 
198  if( X3D_APPEARANCE != tchild && X3D_INDEXED_FACE_SET != tchild )
199  return false;
200 
201  std::list< X3DNODE* >::iterator sR = m_Refs.begin();
202  std::list< X3DNODE* >::iterator eR = m_Refs.end();
203 
204  while( sR != eR )
205  {
206  if( *sR == aNode )
207  return false;
208 
209  ++sR;
210  }
211 
212  if( X3D_APPEARANCE == tchild )
213  {
214  if( nullptr == appearance )
215  {
216  m_Refs.push_back( aNode );
217  aNode->addNodeRef( this );
218  appearance = aNode;
219  }
220  else
221  {
222  return false;
223  }
224  }
225  else
226  {
227  if( nullptr == geometry )
228  {
229  m_Refs.push_back( aNode );
230  aNode->addNodeRef( this );
231  geometry = aNode;
232  }
233  else
234  {
235  return false;
236  }
237  }
238 
239  return true;
240 }
241 
242 
244 {
245  if( nullptr == geometry || nullptr == appearance )
246  return nullptr;
247 
248  wxLogTrace( traceVrmlPlugin,
249  wxT( " * [INFO] Translating Shape with %zu children, %zu references, "
250  "and %zu back pointers." ),
251  m_Children.size(), m_Refs.size(), m_BackPointers.size() );
252 
253  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
254 
255  wxCHECK_MSG( aParent && ( ptype == S3D::SGTYPE_TRANSFORM ), nullptr,
256  wxString::Format( wxT( "Shape does not have a Transform parent (parent ID: %d)" ),
257  ptype ) );
258 
259  if( m_sgNode )
260  {
261  if( nullptr != aParent )
262  {
263  if( nullptr == S3D::GetSGNodeParent( m_sgNode )
264  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
265  {
266  return nullptr;
267  }
268  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
269  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
270  {
271  return nullptr;
272  }
273  }
274 
275  return m_sgNode;
276  }
277 
278  IFSG_SHAPE shNode( aParent );
279 
280  SGNODE* pShape = shNode.GetRawPtr();
281  SGNODE* pGeom = geometry->TranslateToSG( pShape );
282  SGNODE* pApp = appearance->TranslateToSG( pShape );
283 
284  if( nullptr == pApp || nullptr == pGeom )
285  {
286  if( pGeom )
287  {
288  IFSG_FACESET tmp( false );
289  tmp.Attach( pGeom );
290  tmp.Destroy();
291  }
292 
293  if( pApp )
294  {
295  IFSG_APPEARANCE tmp( false );
296  tmp.Attach( pApp );
297  tmp.Destroy();
298  }
299 
300  shNode.Destroy();
301  return nullptr;
302  }
303 
304  m_sgNode = shNode.GetRawPtr();
305 
306  return m_sgNode;
307 }
308 
309 
310 void X3DSHAPE::unlinkChildNode( const X3DNODE* aNode )
311 {
312  if( nullptr == aNode )
313  return;
314 
315  if( aNode == appearance )
316  appearance = nullptr;
317  else if( aNode == geometry )
318  geometry = nullptr;
319 
320  X3DNODE::unlinkChildNode( aNode );
321 }
322 
323 
324 void X3DSHAPE::unlinkRefNode( const X3DNODE* aNode )
325 {
326  if( nullptr == aNode )
327  return;
328 
329  if( aNode == appearance )
330  appearance = nullptr;
331  else if( aNode == geometry )
332  geometry = nullptr;
333 
334  X3DNODE::unlinkRefNode( aNode );
335 }
bool AddRefNode(X3DNODE *aNode) override
Definition: x3d_shape.cpp:191
virtual bool SetParent(X3DNODE *aParent, bool doUnlink=true)=0
Set the parent X3DNODE of this object.
bool ReadIndexedFaceSet(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:155
std::list< X3DNODE * > m_BackPointers
Definition: x3d_base.h:163
bool Attach(SGNODE *aNode) override
Function Attach associates a given SGNODE* with this wrapper.
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
Definition: x3d_shape.cpp:243
X3DNODES m_Type
Definition: x3d_base.h:160
X3DNODE * GetParent(void) const
Return a pointer to the parent node of this object or NULL if the object has no parent (ie.
Definition: x3d_base.cpp:190
wxString m_Name
Definition: x3d_base.h:168
X3DNODE * appearance
Definition: x3d_shape.h:56
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:492
void addNodeRef(X3DNODE *aNode)
Add a pointer to a node which references, but does not own, this node.
Definition: x3d_base.cpp:142
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
collects header files for all SG* wrappers and the API
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:65
bool Attach(SGNODE *aNode) override
Function Attach associates a given SGNODE* with this wrapper.
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:501
std::list< X3DNODE * > m_Children
Definition: x3d_base.h:164
The base class of all X3D nodes.
Definition: x3d_base.h:74
virtual void unlinkRefNode(const X3DNODE *aNode)
Remove pointers to a referenced node; it is invoked by the referenced node upon destruction to ensure...
Definition: x3d_base.cpp:122
bool SetParent(X3DNODE *aParent, bool doUnlink=true) override
Set the parent X3DNODE of this object.
Definition: x3d_shape.cpp:113
bool ReadAppearance(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:117
virtual SGNODE * TranslateToSG(SGNODE *aParent)=0
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:510
bool Read(wxXmlNode *aNode, X3DNODE *aTopNode, X3D_DICT &aDict) override
Definition: x3d_shape.cpp:71
virtual bool AddChildNode(X3DNODE *aNode)=0
X3DNODES GetNodeType(void) const
Return the type of this node instance.
Definition: x3d_base.cpp:184
virtual void unlinkChildNode(const X3DNODE *aNode)
Remove references to an owned child; it is invoked by the child upon destruction to ensure that the p...
Definition: x3d_base.cpp:102
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition: vrml.cpp:63
bool AddName(const wxString &aName, X3DNODE *aNode)
Definition: x3d_base.cpp:35
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
SGNODE * m_sgNode
Definition: x3d_base.h:169
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:483
X3DNODE * m_Parent
Definition: x3d_base.h:159
const char * name
Definition: DXF_plotter.cpp:56
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:40
bool AddChildNode(X3DNODE *aNode) override
Definition: x3d_shape.cpp:138
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
Definition: ifsg_node.cpp:55
X3DNODES
Definition: x3d_base.h:59
X3D_DICT * m_Dict
Definition: x3d_base.h:161
virtual void unlinkChildNode(const X3DNODE *aNode) override
Remove references to an owned child; it is invoked by the child upon destruction to ensure that the p...
Definition: x3d_shape.cpp:310
virtual ~X3DSHAPE()
Definition: x3d_shape.cpp:62
virtual void unlinkRefNode(const X3DNODE *aNode) override
Remove pointers to a referenced node; it is invoked by the referenced node upon destruction to ensure...
Definition: x3d_shape.cpp:324
X3DNODE * geometry
Definition: x3d_shape.h:57
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:40
std::list< X3DNODE * > m_Refs
Definition: x3d_base.h:165