Added support for FreeCAD VRML files
This commit is contained in:
parent
97d4c33a9f
commit
c798f8b545
|
@ -486,3 +486,23 @@ bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||||
|
|
||||||
return aParent->AddRefNode( aChild );
|
return aParent->AddRefNode( aChild );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||||
|
{
|
||||||
|
if( NULL == aParent || NULL == aChild )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return aParent->AddChildNode( aChild );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
|
||||||
|
{
|
||||||
|
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
aObject->AssociateWrapper( aRefPtr );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ namespace S3D
|
||||||
SGLIB_API S3D::SGTYPES GetSGNodeType( SGNODE* aNode );
|
SGLIB_API S3D::SGTYPES GetSGNodeType( SGNODE* aNode );
|
||||||
SGLIB_API SGNODE* GetSGNodeParent( SGNODE* aNode );
|
SGLIB_API SGNODE* GetSGNodeParent( SGNODE* aNode );
|
||||||
SGLIB_API bool AddSGNodeRef( SGNODE* aParent, SGNODE* aChild );
|
SGLIB_API bool AddSGNodeRef( SGNODE* aParent, SGNODE* aChild );
|
||||||
|
SGLIB_API bool AddSGNodeChild( SGNODE* aParent, SGNODE* aChild );
|
||||||
|
SGLIB_API void AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function CalcTriNorm
|
* Function CalcTriNorm
|
||||||
|
|
|
@ -19,6 +19,7 @@ add_library( s3d_plugin_vrml MODULE
|
||||||
v2/vrml2_norms.cpp
|
v2/vrml2_norms.cpp
|
||||||
v2/vrml2_color.cpp
|
v2/vrml2_color.cpp
|
||||||
v2/vrml2_box.cpp
|
v2/vrml2_box.cpp
|
||||||
|
v2/vrml2_switch.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} )
|
target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} )
|
||||||
|
|
|
@ -369,10 +369,18 @@ SGNODE* WRL2APPEARANCE::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
{
|
{
|
||||||
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode )
|
if( NULL != aParent )
|
||||||
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
|
|
@ -33,11 +33,13 @@
|
||||||
#include "vrml2_norms.h"
|
#include "vrml2_norms.h"
|
||||||
#include "vrml2_color.h"
|
#include "vrml2_color.h"
|
||||||
#include "vrml2_box.h"
|
#include "vrml2_box.h"
|
||||||
|
#include "vrml2_switch.h"
|
||||||
#include "plugins/3dapi/ifsg_all.h"
|
#include "plugins/3dapi/ifsg_all.h"
|
||||||
|
|
||||||
|
|
||||||
WRL2BASE::WRL2BASE() : WRL2NODE()
|
WRL2BASE::WRL2BASE() : WRL2NODE()
|
||||||
{
|
{
|
||||||
|
m_useInline = false;
|
||||||
m_Type = WRL2_BASE;
|
m_Type = WRL2_BASE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +63,44 @@ bool WRL2BASE::SetParent( WRL2NODE* aParent )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL2BASE::SetEnableInline( bool enable )
|
||||||
|
{
|
||||||
|
m_useInline = enable;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL2BASE::GetEnableInline( void )
|
||||||
|
{
|
||||||
|
return m_useInline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL2BASE::AddInlineData( const std::string& aName, WRL2INLINE* aObject )
|
||||||
|
{
|
||||||
|
std::map< std::string, WRL2INLINE* >::iterator dp = m_inlineModels.find( aName );
|
||||||
|
// XXX;
|
||||||
|
// qwerty;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL2BASE::GetInlineData( const std::string& aName, WRL2INLINE* aObject )
|
||||||
|
{
|
||||||
|
// XXX;
|
||||||
|
// qwerty;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL2BASE::DelInlineData( const std::string& aName, WRL2INLINE* aObject )
|
||||||
|
{
|
||||||
|
// XXX;
|
||||||
|
// qwerty;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string WRL2BASE::GetName( void )
|
std::string WRL2BASE::GetName( void )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_VRML2
|
#ifdef DEBUG_VRML2
|
||||||
|
@ -508,6 +548,13 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WRL2_SWITCH:
|
||||||
|
|
||||||
|
if( !readSwitch( proc, aParent, aNode ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case WRL2_TRANSFORM:
|
case WRL2_TRANSFORM:
|
||||||
case WRL2_GROUP:
|
case WRL2_GROUP:
|
||||||
|
|
||||||
|
@ -549,7 +596,6 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
|
||||||
case WRL2_SOUND:
|
case WRL2_SOUND:
|
||||||
case WRL2_SPHERESENSOR:
|
case WRL2_SPHERESENSOR:
|
||||||
case WRL2_SPOTLIGHT:
|
case WRL2_SPOTLIGHT:
|
||||||
case WRL2_SWITCH:
|
|
||||||
case WRL2_TEXT:
|
case WRL2_TEXT:
|
||||||
case WRL2_TEXTURECOORDINATE:
|
case WRL2_TEXTURECOORDINATE:
|
||||||
case WRL2_TEXTURETRANSFORM:
|
case WRL2_TEXTURETRANSFORM:
|
||||||
|
@ -775,13 +821,62 @@ bool WRL2BASE::readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL2BASE::readSwitch( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
|
||||||
|
{
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = NULL;
|
||||||
|
|
||||||
|
WRL2SWITCH* np = new WRL2SWITCH( aParent );
|
||||||
|
|
||||||
|
if( !np->Read( proc, this ) )
|
||||||
|
{
|
||||||
|
delete np;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = (WRL2NODE*) np;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
{
|
{
|
||||||
if( m_Children.empty() )
|
if( m_Children.empty() )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
|
||||||
|
|
||||||
|
if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML2
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] WRL2BASE does not have a Transform parent (parent ID: ";
|
||||||
|
std::cerr << ptype << ")\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
|
{
|
||||||
|
if( NULL != aParent )
|
||||||
|
{
|
||||||
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
}
|
||||||
|
|
||||||
IFSG_TRANSFORM topNode( aParent );
|
IFSG_TRANSFORM topNode( aParent );
|
||||||
|
|
||||||
|
@ -815,6 +910,7 @@ SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WRL2_TRANSFORM:
|
case WRL2_TRANSFORM:
|
||||||
|
case WRL2_SWITCH:
|
||||||
|
|
||||||
if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr(), calcNormals ) )
|
if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr(), calcNormals ) )
|
||||||
test = true;
|
test = true;
|
||||||
|
|
|
@ -45,9 +45,12 @@
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "vrml2_node.h"
|
#include "vrml2_node.h"
|
||||||
|
|
||||||
|
class SGNODE;
|
||||||
|
class WRL2INLINE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class WRL2BASE
|
* Class WRL2BASE
|
||||||
|
@ -56,6 +59,8 @@
|
||||||
class WRL2BASE : public WRL2NODE
|
class WRL2BASE : public WRL2NODE
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
bool m_useInline;
|
||||||
|
|
||||||
// handle cases of USE / DEF
|
// handle cases of USE / DEF
|
||||||
bool implementUse( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
bool implementUse( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
||||||
bool implementDef( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
bool implementDef( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
||||||
|
@ -69,6 +74,9 @@ private:
|
||||||
bool readNorms( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
bool readNorms( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
||||||
bool readColor( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
bool readColor( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
||||||
bool readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
bool readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
||||||
|
bool readSwitch( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
|
||||||
|
|
||||||
|
std::map< std::string, WRL2INLINE* > m_inlineModels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -79,6 +87,15 @@ public:
|
||||||
WRL2BASE();
|
WRL2BASE();
|
||||||
virtual ~WRL2BASE();
|
virtual ~WRL2BASE();
|
||||||
|
|
||||||
|
// function to enable/disable Inline{} expansion
|
||||||
|
void SetEnableInline( bool enable );
|
||||||
|
bool GetEnableInline( void );
|
||||||
|
|
||||||
|
// functions to manipulate Inline{} objects
|
||||||
|
SGNODE* AddInlineData( const std::string& aName, WRL2INLINE* aObject );
|
||||||
|
SGNODE* GetInlineData( const std::string& aName, WRL2INLINE* aObject );
|
||||||
|
void DelInlineData( const std::string& aName, WRL2INLINE* aObject );
|
||||||
|
|
||||||
// function to read entire VRML file
|
// function to read entire VRML file
|
||||||
bool Read( WRLPROC& proc );
|
bool Read( WRLPROC& proc );
|
||||||
|
|
||||||
|
|
|
@ -228,10 +228,18 @@ SGNODE* WRL2BOX::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
{
|
{
|
||||||
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode )
|
if( NULL != aParent )
|
||||||
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
|
|
@ -578,10 +578,18 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
{
|
{
|
||||||
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode )
|
if( NULL != aParent )
|
||||||
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
|
|
@ -305,10 +305,18 @@ SGNODE* WRL2MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
{
|
{
|
||||||
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode )
|
if( NULL != aParent )
|
||||||
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
|
|
@ -235,10 +235,11 @@ bool WRL2NODE::SetName( const std::string& aName )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: NOTE: in VRML2 the '-' is invalid; however there are some bad models which contain '-' in
|
// The characters '+' and '-' are not allowed in names as per the VRML2 specification;
|
||||||
// a name and many VRML parsers seem to accept them. In VRML1 the '-' is allowed.
|
// however many parsers accept them and many bad generators use them so the rules
|
||||||
|
// have been relaxed here.
|
||||||
// #define BAD_CHARS1 "\"\'#+,-.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
|
// #define BAD_CHARS1 "\"\'#+,-.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
|
||||||
#define BAD_CHARS1 "\"\'#+,.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
|
#define BAD_CHARS1 "\"\'#,.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
|
||||||
#define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
|
#define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
|
||||||
|
|
||||||
if( std::string::npos != aName.find_first_of( BAD_CHARS1 )
|
if( std::string::npos != aName.find_first_of( BAD_CHARS1 )
|
||||||
|
@ -396,6 +397,8 @@ bool WRL2NODE::AddRefNode( WRL2NODE* aNode )
|
||||||
{
|
{
|
||||||
if( *sR == aNode )
|
if( *sR == aNode )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
++sR;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Refs.push_back( aNode );
|
m_Refs.push_back( aNode );
|
||||||
|
|
|
@ -65,9 +65,13 @@ WRL2SHAPE::~WRL2SHAPE()
|
||||||
|
|
||||||
bool WRL2SHAPE::isDangling( void )
|
bool WRL2SHAPE::isDangling( void )
|
||||||
{
|
{
|
||||||
// this node is dangling unless it has a parent of type WRL2_TRANSFORM
|
// this node is dangling unless it has a parent of type:
|
||||||
|
// WRL2_TRANSFORM
|
||||||
|
// WRL2_SWITCH
|
||||||
|
|
||||||
if( NULL == m_Parent || m_Parent->GetNodeType() != WRL2_TRANSFORM )
|
if( NULL == m_Parent
|
||||||
|
|| ( m_Parent->GetNodeType() != WRL2_TRANSFORM
|
||||||
|
&& m_Parent->GetNodeType() != WRL2_SWITCH ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -332,10 +336,18 @@ SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
{
|
{
|
||||||
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode )
|
if( NULL != aParent )
|
||||||
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
|
|
@ -0,0 +1,324 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "vrml2_base.h"
|
||||||
|
#include "vrml2_switch.h"
|
||||||
|
#include "plugins/3dapi/ifsg_all.h"
|
||||||
|
|
||||||
|
|
||||||
|
WRL2SWITCH::WRL2SWITCH() : WRL2NODE()
|
||||||
|
{
|
||||||
|
m_Type = WRL2_SWITCH;
|
||||||
|
whichChoice = -1;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL2SWITCH::WRL2SWITCH( WRL2NODE* aParent ) : WRL2NODE()
|
||||||
|
{
|
||||||
|
m_Type = WRL2_SWITCH;
|
||||||
|
m_Parent = aParent;
|
||||||
|
whichChoice = -1;
|
||||||
|
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL2SWITCH::~WRL2SWITCH()
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
|
||||||
|
std::cerr << " * [INFO] Destroying Transform with " << m_Children.size();
|
||||||
|
std::cerr << " children, " << m_Refs.size() << " references and ";
|
||||||
|
std::cerr << m_BackPointers.size() << " backpointers\n";
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL2SWITCH::isDangling( void )
|
||||||
|
{
|
||||||
|
// a Switch node is never dangling
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// functions inherited from WRL2NODE
|
||||||
|
bool WRL2SWITCH::Read( WRLPROC& proc, WRL2BASE* aTopNode )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Structure of a Switch node (p.113):
|
||||||
|
*
|
||||||
|
* Switch {
|
||||||
|
* exposedField MFNode choice []
|
||||||
|
* exposedField SFInt32 whichChoice -1
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( NULL == aTopNode )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML2
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] aTopNode is NULL\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t line, column;
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
|
||||||
|
char tok = proc.Peek();
|
||||||
|
|
||||||
|
if( proc.eof() )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad file format; unexpected eof at line ";
|
||||||
|
std::cerr << line << ", column " << column << "\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( '{' != tok )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad file format; expecting '{' but got '" << tok;
|
||||||
|
std::cerr << "' at line " << line << ", column " << column << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc.Pop();
|
||||||
|
std::string glob;
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
if( proc.Peek() == '}' )
|
||||||
|
{
|
||||||
|
proc.Pop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !proc.ReadName( glob ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expecting one of:
|
||||||
|
// choice
|
||||||
|
// whichChoice
|
||||||
|
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
|
||||||
|
if( !glob.compare( "whichChoice" ) )
|
||||||
|
{
|
||||||
|
if( !proc.ReadSFInt( whichChoice ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] invalid whichChoice at line " << line << ", column ";
|
||||||
|
std::cerr << column << "\n";
|
||||||
|
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
|
||||||
|
std::cerr << " * [INFO] message: '" << proc.GetError() << "'\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( !glob.compare( "choice" ) )
|
||||||
|
{
|
||||||
|
if( !readChildren( proc, aTopNode ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad Switch at line " << line << ", column ";
|
||||||
|
std::cerr << column << "\n";
|
||||||
|
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // while( true ) -- reading contents of Switch{}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL2SWITCH::AddRefNode( WRL2NODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML2
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL passed as node pointer\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !WRL2NODE::AddRefNode( aNode ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// take possession if the node is dangling WRL2_SHAPE
|
||||||
|
|
||||||
|
if( WRL2_SHAPE == aNode->GetNodeType() && aNode->isDangling() )
|
||||||
|
{
|
||||||
|
WRL2NODE* np = aNode->GetParent();
|
||||||
|
|
||||||
|
if( NULL != np )
|
||||||
|
aNode->SetParent( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL2SWITCH::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
|
||||||
|
{
|
||||||
|
size_t line, column;
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
|
||||||
|
char tok = proc.Peek();
|
||||||
|
|
||||||
|
if( proc.eof() )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad file format; unexpected eof at line ";
|
||||||
|
std::cerr << line << ", column " << column << "\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRL2NODE* child = NULL;
|
||||||
|
|
||||||
|
if( '[' != tok )
|
||||||
|
{
|
||||||
|
// since there are no delimeters we expect a single child
|
||||||
|
if( !aTopNode->ReadNode( proc, this, &child ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( NULL != child )
|
||||||
|
choices.push_back( child );
|
||||||
|
|
||||||
|
if( proc.Peek() == ',' )
|
||||||
|
proc.Pop();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc.Pop();
|
||||||
|
std::string glob;
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
if( proc.Peek() == ']' )
|
||||||
|
{
|
||||||
|
proc.Pop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aTopNode->ReadNode( proc, this, &child ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( NULL != child )
|
||||||
|
choices.push_back( child );
|
||||||
|
|
||||||
|
if( proc.Peek() == ',' )
|
||||||
|
proc.Pop();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL2SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
|
||||||
|
std::cerr << " * [INFO] Translating Switch with " << m_Children.size();
|
||||||
|
std::cerr << " children, " << m_Refs.size() << " references and ";
|
||||||
|
std::cerr << m_BackPointers.size() << " backpointers\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( choices.empty() )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
|
||||||
|
std::cerr << " * [INFO] Switch translation: no choices\n";
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
|
||||||
|
|
||||||
|
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML2
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] Transform does not have a Transform parent (parent ID: ";
|
||||||
|
std::cerr << ptype << ")\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( whichChoice < 0 || whichChoice >= (int)choices.size() )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
|
||||||
|
std::cerr << " * [INFO] Switch translation: no choice (choices = ";
|
||||||
|
std::cerr << choices.size() << "), whichChoice = " << whichChoice << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRL2NODES type = choices[whichChoice]->GetNodeType();
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case WRL2_SHAPE:
|
||||||
|
case WRL2_SWITCH:
|
||||||
|
case WRL2_INLINE:
|
||||||
|
case WRL2_TRANSFORM:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return choices[whichChoice]->TranslateToSG( aParent, calcNormals );
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file vrml2_switch.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VRML2_SWITCH_H
|
||||||
|
#define VRML2_SWITCH_H
|
||||||
|
|
||||||
|
#include "vrml2_node.h"
|
||||||
|
|
||||||
|
class WRL2BASE;
|
||||||
|
class SGNODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WRL2SWITCH
|
||||||
|
*/
|
||||||
|
class WRL2SWITCH : public WRL2NODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int whichChoice;
|
||||||
|
std::vector< WRL2NODE* > choices;
|
||||||
|
|
||||||
|
bool readChildren( WRLPROC& proc, WRL2BASE* aTopNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// functions inherited from WRL2NODE
|
||||||
|
bool isDangling( void );
|
||||||
|
|
||||||
|
public:
|
||||||
|
WRL2SWITCH();
|
||||||
|
WRL2SWITCH( WRL2NODE* aNode );
|
||||||
|
virtual ~WRL2SWITCH();
|
||||||
|
|
||||||
|
// functions inherited from WRL2NODE
|
||||||
|
bool Read( WRLPROC& proc, WRL2BASE* aTopNode );
|
||||||
|
bool AddRefNode( WRL2NODE* aNode );
|
||||||
|
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VRML2_SWITCH_H
|
|
@ -314,6 +314,9 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
|
||||||
if( !aTopNode->ReadNode( proc, this, NULL ) )
|
if( !aTopNode->ReadNode( proc, this, NULL ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if( proc.Peek() == ',' )
|
||||||
|
proc.Pop();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,6 +333,10 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
|
||||||
|
|
||||||
if( !aTopNode->ReadNode( proc, this, NULL ) )
|
if( !aTopNode->ReadNode( proc, this, NULL ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if( proc.Peek() == ',' )
|
||||||
|
proc.Pop();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -338,6 +345,12 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
|
||||||
|
|
||||||
SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
{
|
{
|
||||||
|
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
|
||||||
|
std::cerr << " * [INFO] Translating Transform with " << m_Children.size();
|
||||||
|
std::cerr << " children, " << m_Refs.size() << " references and ";
|
||||||
|
std::cerr << m_BackPointers.size() << " backpointers\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
if( m_Children.empty() && m_Refs.empty() )
|
if( m_Children.empty() && m_Refs.empty() )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -356,10 +369,18 @@ SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
|
||||||
if( m_sgNode )
|
if( m_sgNode )
|
||||||
{
|
{
|
||||||
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode )
|
if( NULL != aParent )
|
||||||
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
|
||||||
{
|
{
|
||||||
return NULL;
|
if( NULL == S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
|
||||||
|
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_sgNode;
|
return m_sgNode;
|
||||||
|
@ -371,7 +392,11 @@ SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
std::list< WRL2NODE* >::iterator eC = m_Children.end();
|
std::list< WRL2NODE* >::iterator eC = m_Children.end();
|
||||||
WRL2NODES type;
|
WRL2NODES type;
|
||||||
|
|
||||||
// Include only Shape and Transform nodes in a Transform node
|
// Include only the following in a Transform node:
|
||||||
|
// Shape
|
||||||
|
// Switch
|
||||||
|
// Transform
|
||||||
|
// Inline
|
||||||
bool test = false; // set to true if there are any subnodes for display
|
bool test = false; // set to true if there are any subnodes for display
|
||||||
|
|
||||||
for( int i = 0; i < 2; ++i )
|
for( int i = 0; i < 2; ++i )
|
||||||
|
@ -383,6 +408,8 @@ SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
case WRL2_SHAPE:
|
case WRL2_SHAPE:
|
||||||
|
case WRL2_SWITCH:
|
||||||
|
case WRL2_INLINE:
|
||||||
case WRL2_TRANSFORM:
|
case WRL2_TRANSFORM:
|
||||||
|
|
||||||
if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) )
|
if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) )
|
||||||
|
|
|
@ -197,6 +197,9 @@ SCENEGRAPH* Load( char const* aFileName )
|
||||||
#endif
|
#endif
|
||||||
WRL2BASE* bp = new WRL2BASE;
|
WRL2BASE* bp = new WRL2BASE;
|
||||||
|
|
||||||
|
// allow Inline{} files to be included
|
||||||
|
bp->SetEnableInline( true );
|
||||||
|
|
||||||
if( !bp->Read( proc ) )
|
if( !bp->Read( proc ) )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
|
@ -113,9 +113,10 @@ bool WRLPROC::Open( const std::string& aFileName )
|
||||||
// backslash
|
// backslash
|
||||||
// XXX: NOTE: badchars should include '-' but due to my bad model naming scheme
|
// XXX: NOTE: badchars should include '-' but due to my bad model naming scheme
|
||||||
// in the VRML model generator, I have allowed '-'. Other VRML parsers seem to
|
// in the VRML model generator, I have allowed '-'. Other VRML parsers seem to
|
||||||
// accept '-'.
|
// accept '-'. FreeCAD produces names with '+' in them so '+' has been allowed
|
||||||
|
// as well; '+' is not even valid for VRML1.
|
||||||
//m_badchars = "'\"#,.+-[]\\{}";
|
//m_badchars = "'\"#,.+-[]\\{}";
|
||||||
m_badchars = "'\"#,.+[]\\{}";
|
m_badchars = "'\"#,.[]\\{}";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +306,8 @@ bool WRLPROC::ReadName( std::string& aName )
|
||||||
while( m_buf[m_linepos] > 0x20 && m_linepos < ssize )
|
while( m_buf[m_linepos] > 0x20 && m_linepos < ssize )
|
||||||
{
|
{
|
||||||
if( '[' == m_buf[m_linepos] || '{' == m_buf[m_linepos]
|
if( '[' == m_buf[m_linepos] || '{' == m_buf[m_linepos]
|
||||||
|| '.' == m_buf[m_linepos] || '#' == m_buf[m_linepos] )
|
|| '.' == m_buf[m_linepos] || '#' == m_buf[m_linepos]
|
||||||
|
|| ',' == m_buf[m_linepos] )
|
||||||
{
|
{
|
||||||
if( !aName.empty() )
|
if( !aName.empty() )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue