KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vrml1_base.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 The 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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <iostream>
22#include <sstream>
23#include <wx/log.h>
24
25#include "vrml1_base.h"
26#include "vrml1_group.h"
27#include "vrml1_separator.h"
28#include "vrml1_material.h"
29#include "vrml1_matbinding.h"
30#include "vrml1_coords.h"
31#include "vrml1_switch.h"
32#include "vrml1_faceset.h"
33#include "vrml1_transform.h"
34#include "vrml1_shapehints.h"
36
37
39{
42 return;
43}
44
45
47{
48 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] Destroying virtual base node." ) );
49
50 cancelDict();
51}
52
53
54bool WRL1BASE::SetParent( WRL1NODE* aParent, bool /* doUnlink */ )
55{
56 wxCHECK_MSG( false, false, wxT( "Attempt to set parent on WRL1BASE node." ) );
57}
58
59
60std::string WRL1BASE::GetName( void )
61{
62 wxCHECK_MSG( false, std::string( "" ),
63 wxT( "Attempt to extract name from virtual base node." ) );
64}
65
66
67bool WRL1BASE::SetName( const std::string& aName )
68{
69 wxCHECK_MSG( false, false, wxT( "Attempt to set name on virtual base node." ) );
70}
71
72
74{
75 wxCHECK_MSG( proc.GetVRMLType() == WRLVERSION::VRML_V1, false,
76 wxT( "No open file or file is not a VRML1 file" ) );
77
78 // Note: according to the VRML1 specification, a file may contain
79 // only one grouping node at the top level. The following code
80 // supports non-conformant VRML1 files by processing all top level
81 // nodes as if the vrml1_base were the equivalent of a vrml1_separator
82
83 while( proc.Peek() )
84 {
85 if( !ReadNode( proc, this, nullptr ) )
86 {
87 wxLogTrace( traceVrmlPlugin,
88 wxT( "%s:%s:%d\n * [INFO] bad file format; unexpected eof %s" ),
89 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
90
91 return false;
92 }
93 }
94
95 if( !proc.eof() )
96 {
97 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n%s" ),
98 __FILE__, __FUNCTION__, __LINE__, proc.GetError() );
99
100 return false;
101 }
102
103 return true;
104}
105
106
107bool WRL1BASE::implementUse( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
108{
109 if( nullptr != aNode )
110 *aNode = nullptr;
111
112 wxCHECK_MSG( aParent, false, wxT( "Invoked with invalid parent." ) );
113
114 std::string glob;
115
116 if( !proc.ReadName( glob ) )
117 {
118 wxLogTrace( traceVrmlPlugin, wxT( "%s" ), proc.GetError() );
119
120 return false;
121 }
122
123 WRL1NODE* ref = aParent->FindNode( glob );
124
125 // return 'true' - the file may be defective but it may still be somewhat OK
126 if( nullptr == ref )
127 {
128 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n * [INFO] node '%s' not found." ),
129 __FILE__, __FUNCTION__, __LINE__, glob );
130
131 return true;
132 }
133
134 if( !aParent->AddRefNode( ref ) )
135 {
136 wxLogTrace( traceVrmlPlugin,
137 wxT( "%s:%s:%d\n * [INFO] failed to add node '%s' (%s) to parent of type %s." ),
138 __FILE__, __FUNCTION__, __LINE__, glob,
139 ref->GetNodeTypeName( ref->GetNodeType() ),
140 aParent->GetNodeTypeName( aParent->GetNodeType() ) );
141
142 return false;
143 }
144
145 if( nullptr != aNode )
146 *aNode = ref;
147
148 return true;
149}
150
151
152bool WRL1BASE::implementDef( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
153{
154 if( nullptr != aNode )
155 *aNode = nullptr;
156
157 wxCHECK_MSG( nullptr != aParent, false, wxT( "Invalid parent pointer." ) );
158
159 std::string glob;
160 WRL1NODE* lnode = nullptr;
161
162 if( !proc.ReadName( glob ) )
163 {
164 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n%s" ),
165 __FILE__, __FUNCTION__, __LINE__, proc.GetError() );
166
167 return false;
168 }
169
170 if( ReadNode( proc, aParent, &lnode ) )
171 {
172 if( nullptr != aNode )
173 *aNode = lnode;
174
175 if( lnode && !lnode->SetName( glob ) )
176 {
177 wxLogTrace( traceVrmlPlugin,
178 wxT( "%s:%s:%d\n * [INFO] bad formatting (invalid name) %s." ),
179 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
180
181 return false;
182 }
183
184 if( !m_dictionary )
185 return false;
186
187 m_dictionary->AddName( glob, lnode );
188
189 return true;
190 }
191
192 return false;
193}
194
195
196bool WRL1BASE::ReadNode( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
197{
198 // This function reads a node and stores a pointer to it in aNode.
199 // A value 'true' is returned if a node is successfully read or,
200 // if the node is not supported, successfully discarded. Callers
201 // must always check the value of aNode when the function returns
202 // 'true' since it will be NULL if the node type is not supported.
203
204 if( nullptr != aNode )
205 *aNode = nullptr;
206
207 wxCHECK_MSG( aParent, false, wxT( "Invalid parent pointer." ) );
208
209 std::string glob;
210 WRL1NODES ntype;
211
212 if( !proc.ReadName( glob ) )
213 {
214 if( !proc.eof() )
215 {
216 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n%s" ),
217 __FILE__, __FUNCTION__, __LINE__, proc.GetError() );
218 }
219
220 return false;
221 }
222
223 // Process node name:
224 // the names encountered at this point should be one of the
225 // built-in node names or one of:
226 // DEF, USE
227 if( !glob.compare( "USE" ) )
228 {
229 if( !implementUse( proc, aParent, aNode ) )
230 return false;
231
232 return true;
233 }
234
235 if( !glob.compare( "DEF" ) )
236 {
237 if( !implementDef( proc, aParent, aNode ) )
238 return false;
239
240 return true;
241 }
242
243 ntype = getNodeTypeID( glob );
244
245 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] Processing node '%s' ID: %d." ), glob, ntype );
246
247 switch( ntype )
248 {
250 if( !readGroup( proc, aParent, aNode ) )
251 return false;
252
253 break;
254
256 if( !readSeparator( proc, aParent, aNode ) )
257 return false;
258
259 break;
260
262 if( !readSwitch( proc, aParent, aNode ) )
263 return false;
264
265 break;
266
268 if( !readMaterial( proc, aParent, aNode ) )
269 return false;
270
271 break;
272
274 if( !readMatBinding( proc, aParent, aNode ) )
275 return false;
276
277 break;
278
280 if( !readCoords( proc, aParent, aNode ) )
281 return false;
282
283 break;
284
286 if( !readFaceSet( proc, aParent, aNode ) )
287 return false;
288
289 break;
290
295 if( !readTransform( proc, aParent, aNode ) )
296 return false;
297
298 break;
299
301 if( !readShapeHints( proc, aParent, aNode ) )
302 return false;
303
304 break;
305
306 //
307 // items not implemented or for optional future implementation:
308 //
309 default:
310 if( !proc.DiscardNode() )
311 {
312 wxLogTrace( traceVrmlPlugin,
313 wxT( "%s:%s:%d\n * [INFO] could not discard node %s." ),
314 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
315
316 return false;
317 }
318 else
319 {
320 wxLogTrace( traceVrmlPlugin,
321 wxT( " * [INFO] discarded node '%s' %s (currently unsupported)." ),
322 glob, proc.GetFilePosition() );
323 }
324
325 break;
326 }
327
328 return true;
329}
330
331
332bool WRL1BASE::Read( WRLPROC& proc, WRL1BASE* aTopNode )
333{
334 wxCHECK_MSG( false, false, wxT( "This method must never be invoked on a WRL1BASE object" ) );
335}
336
337
338bool WRL1BASE::readGroup( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
339{
340 if( nullptr != aNode )
341 *aNode = nullptr;
342
343 WRL1GROUP* np = new WRL1GROUP( m_dictionary, aParent );
344
345 if( !np->Read( proc, this ) )
346 {
347 delete np;
348 return false;
349 }
350
351 if( nullptr != aNode )
352 *aNode = (WRL1NODE*) np;
353
354 return true;
355}
356
357
358bool WRL1BASE::readSeparator( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
359{
360 if( nullptr != aNode )
361 *aNode = nullptr;
362
363 WRL1SEPARATOR* np = new WRL1SEPARATOR( m_dictionary, aParent );
364
365 if( !np->Read( proc, this ) )
366 {
367 delete np;
368 return false;
369 }
370
371 if( nullptr != aNode )
372 *aNode = (WRL1NODE*) np;
373
374 return true;
375}
376
377
378bool WRL1BASE::readSwitch( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
379{
380 WRL1SWITCH* np = new WRL1SWITCH( m_dictionary, aParent );
381
382 if( !np->Read( proc, this ) )
383 {
384 delete np;
385 return false;
386 }
387
388 if( nullptr != aNode )
389 *aNode = (WRL1NODE*) np;
390
391 return true;
392}
393
394
395bool WRL1BASE::readMaterial( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
396{
397 if( nullptr != aNode )
398 *aNode = nullptr;
399
400 WRL1MATERIAL* np = new WRL1MATERIAL( m_dictionary, aParent );
401
402 if( !np->Read( proc, this ) )
403 {
404 delete np;
405 return false;
406 }
407
408 if( nullptr != aNode )
409 *aNode = (WRL1NODE*) np;
410
411 return true;
412}
413
414
415bool WRL1BASE::readMatBinding( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
416{
417 if( nullptr != aNode )
418 *aNode = nullptr;
419
420 WRL1MATBINDING* np = new WRL1MATBINDING( m_dictionary, aParent );
421
422 if( !np->Read( proc, this ) )
423 {
424 delete np;
425 return false;
426 }
427
428 if( nullptr != aNode )
429 *aNode = (WRL1NODE*) np;
430
431 return true;
432}
433
434
435bool WRL1BASE::readCoords( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
436{
437 if( nullptr != aNode )
438 *aNode = nullptr;
439
440 WRL1COORDS* np = new WRL1COORDS( m_dictionary, aParent );
441
442 if( !np->Read( proc, this ) )
443 {
444 delete np;
445 return false;
446 }
447
448 if( nullptr != aNode )
449 *aNode = (WRL1NODE*) np;
450
451 return true;
452}
453
454
455bool WRL1BASE::readFaceSet( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
456{
457 if( nullptr != aNode )
458 *aNode = nullptr;
459
460 WRL1FACESET* np = new WRL1FACESET( m_dictionary, aParent );
461
462 if( !np->Read( proc, this ) )
463 {
464 delete np;
465 return false;
466 }
467
468 if( nullptr != aNode )
469 *aNode = (WRL1NODE*) np;
470
471 return true;
472}
473
474
475bool WRL1BASE::readTransform( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
476{
477 if( nullptr != aNode )
478 *aNode = nullptr;
479
480 WRL1TRANSFORM* np = new WRL1TRANSFORM( m_dictionary, aParent );
481
482 if( !np->Read( proc, this ) )
483 {
484 delete np;
485 return false;
486 }
487
488 if( nullptr != aNode )
489 *aNode = (WRL1NODE*) np;
490
491 return true;
492}
493
494
495bool WRL1BASE::readShapeHints( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
496{
497 if( nullptr != aNode )
498 *aNode = nullptr;
499
500 WRL1SHAPEHINTS* np = new WRL1SHAPEHINTS( m_dictionary, aParent );
501
502 if( !np->Read( proc, this ) )
503 {
504 delete np;
505 return false;
506 }
507
508 if( nullptr != aNode )
509 *aNode = (WRL1NODE*) np;
510
511 return true;
512}
513
514
516{
517 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] Translating VRML1 Base with %zu items." ),
518 m_Items.size() );
519
520 if( m_Items.empty() )
521 return nullptr;
522
523 if( m_Items.size() == 1 )
524 return ( *m_Items.begin() )->TranslateToSG( nullptr, nullptr );
525
526 // Note: according to the VRML1 specification, a file may contain
527 // only one grouping node at the top level. The following code
528 // supports non-conformant VRML1 files.
529
530 m_current.Init();
531
532 IFSG_TRANSFORM txNode( true );
533 bool hasContent = false;
534
535 std::list< WRL1NODE* >::iterator sI = m_Items.begin();
536 std::list< WRL1NODE* >::iterator eI = m_Items.end();
537
538 SGNODE* node = txNode.GetRawPtr();
539
540 while( sI != eI )
541 {
542 if( nullptr != (*sI)->TranslateToSG( node, &m_current ) )
543 hasContent = true;
544
545 ++sI;
546 }
547
548 if( !hasContent )
549 {
550 txNode.Destroy();
551 return nullptr;
552 }
553
554 return node;
555}
SGNODE * GetRawPtr(void) noexcept
Return the raw internal SGNODE pointer.
Definition ifsg_node.cpp:61
void Destroy(void)
Delete the object held by this wrapper.
Definition ifsg_node.cpp:51
The wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH.
The base class of all Scene Graph nodes.
Definition sg_node.h:71
bool readMaterial(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool implementUse(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool readMatBinding(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool readFaceSet(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool readCoords(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool ReadNode(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool readTransform(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool readShapeHints(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
virtual std::string GetName(void) override
bool SetParent(WRL1NODE *aParent, bool doUnlink=true) override
Set the parent WRL1NODE of this object.
bool readGroup(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool readSwitch(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
SGNODE * TranslateToSG(SGNODE *aParent, WRL1STATUS *sp) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
virtual bool SetName(const std::string &aName) override
virtual ~WRL1BASE()
bool implementDef(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool Read(WRLPROC &proc)
bool readSeparator(WRLPROC &proc, WRL1NODE *aParent, WRL1NODE **aNode)
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
WRL1NODE(NAMEREGISTER *aDictionary)
WRL1NODES m_Type
Definition vrml1_node.h:223
WRL1NODES getNodeTypeID(const std::string &aNodeName)
Return the ID based on the given aNodeName or WRL1_INVALID (WRL1_END) if no such node name exists.
std::list< WRL1NODE * > m_Items
Definition vrml1_node.h:229
NAMEREGISTER * m_dictionary
Definition vrml1_node.h:242
virtual WRL1NODE * FindNode(const std::string &aNodeName)
Search the tree of linked nodes and returns a reference to the current node with the given name.
void cancelDict(void)
WRL1STATUS m_current
Definition vrml1_node.h:232
virtual bool AddRefNode(WRL1NODE *aNode)
virtual bool SetName(const std::string &aName)
const char * GetNodeTypeName(WRL1NODES aNodeType) const
WRL1NODES GetNodeType(void) const
Return the type of this node instance.
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
char Peek(void)
Definition wrlproc.cpp:2003
WRLVERSION GetVRMLType(void)
Definition wrlproc.cpp:226
std::string GetError(void)
Definition wrlproc.cpp:1956
bool eof(void)
Definition wrlproc.cpp:1950
bool ReadName(std::string &aName)
Definition wrlproc.cpp:285
std::string GetFilePosition() const
Definition wrlproc.cpp:1978
bool DiscardNode(void)
Definition wrlproc.cpp:364
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition vrml.cpp:59
collects header files for all SG* wrappers and the API
WRL1NODES
Definition wrltypes.h:52
@ WRL1_SEPARATOR
Definition wrltypes.h:78
@ WRL1_INDEXEDFACESET
Definition wrltypes.h:63
@ WRL1_COORDINATE3
Definition wrltypes.h:57
@ WRL1_TRANSLATION
Definition wrltypes.h:87
@ WRL1_GROUP
Definition wrltypes.h:62
@ WRL1_BASE
Definition wrltypes.h:53
@ WRL1_TRANSFORM
Definition wrltypes.h:86
@ WRL1_MATERIALBINDING
Definition wrltypes.h:68
@ WRL1_MATERIAL
Definition wrltypes.h:67
@ WRL1_SHAPEHINTS
Definition wrltypes.h:79
@ WRL1_SWITCH
Definition wrltypes.h:82
@ WRL1_ROTATION
Definition wrltypes.h:76
@ WRL1_SCALE
Definition wrltypes.h:77