From e08c0de68fd4aaf325b50fbb7516368a1516eef0 Mon Sep 17 00:00:00 2001 From: Cirilo Bernardo Date: Tue, 22 Dec 2015 17:02:33 +1100 Subject: [PATCH] Work in progress: VRML2 parser --- plugins/3d/vrml/CMakeLists.txt | 1 + plugins/3d/vrml/v2/vrml2_base.cpp | 253 ++++++++++++++++--------- plugins/3d/vrml/v2/vrml2_base.h | 30 ++- plugins/3d/vrml/v2/vrml2_node.cpp | 125 ++++++++++-- plugins/3d/vrml/v2/vrml2_node.h | 17 +- plugins/3d/vrml/v2/vrml2_transform.cpp | 159 ++++++++++++++++ plugins/3d/vrml/v2/vrml2_transform.h | 59 ++++++ plugins/3d/vrml/v2/wrlproc.cpp | 150 ++++++++++----- plugins/3d/vrml/v2/wrlproc.h | 16 +- 9 files changed, 629 insertions(+), 181 deletions(-) create mode 100644 plugins/3d/vrml/v2/vrml2_transform.cpp create mode 100644 plugins/3d/vrml/v2/vrml2_transform.h diff --git a/plugins/3d/vrml/CMakeLists.txt b/plugins/3d/vrml/CMakeLists.txt index ebd0de4815..533a4bec9e 100644 --- a/plugins/3d/vrml/CMakeLists.txt +++ b/plugins/3d/vrml/CMakeLists.txt @@ -5,6 +5,7 @@ add_library( s3d_plugin_vrml MODULE v2/wrlproc.cpp v2/vrml2_node.cpp v2/vrml2_base.cpp + v2/vrml2_transform.cpp ) target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} ) diff --git a/plugins/3d/vrml/v2/vrml2_base.cpp b/plugins/3d/vrml/v2/vrml2_base.cpp index bbba4f26c6..fd4975e2b4 100644 --- a/plugins/3d/vrml/v2/vrml2_base.cpp +++ b/plugins/3d/vrml/v2/vrml2_base.cpp @@ -24,7 +24,7 @@ #include #include "vrml2_base.h" -#include "vrml2_helpers.h" +#include "vrml2_transform.h" WRL2BASE::WRL2BASE() : WRL2NODE() @@ -36,17 +36,6 @@ WRL2BASE::WRL2BASE() : WRL2NODE() WRL2BASE::~WRL2BASE() { - std::list< WRL2NODE* >::iterator sC = m_Children.begin(); - std::list< WRL2NODE* >::iterator eC = m_Children.end(); - - while( sC != eC ) - { - (*sC)->SetParent( NULL ); - delete (*sC); - ++sC; - } - - m_Children.clear(); return; } @@ -63,70 +52,18 @@ bool WRL2BASE::SetParent( WRL2NODE* aParent ) } -WRL2NODE* WRL2BASE::FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ) -{ - if( aNodeName.empty() ) - return NULL; - - if( !m_Name.compare( aNodeName ) ) - return this; - - FIND_NODE( aNodeName, m_Children, this ); - - return NULL; -} - - -bool WRL2BASE::AddRefNode( WRL2NODE* aNode ) -{ - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [BUG] attempting to add reference node to WRL2BASE\n"; - #endif - - return false; -} - - -bool WRL2BASE::AddChildNode( WRL2NODE* aNode ) -{ - if( aNode->GetNodeType() == WRL2_BASE ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << " * [BUG] attempting to add a base node to another base node\n"; - #endif - return false; - } - - std::list< WRL2NODE* >::iterator sC = m_Children.begin(); - std::list< WRL2NODE* >::iterator eC = m_Children.end(); - - while( sC != eC ) - { - if( *sC == aNode ) - return false; - } - - aNode->SetParent( this ); - m_Children.push_back( aNode ); - - return true; -} - - -const char* WRL2BASE::GetName( void ) +std::string WRL2BASE::GetName( void ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; std::cerr << " * [BUG] attempting to extract name from virtual base node\n"; #endif - return NULL; - return NULL; + + return std::string( "" ); } -bool WRL2BASE::SetName(const char *aName) +bool WRL2BASE::SetName( const std::string& aName ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; @@ -180,7 +117,7 @@ bool WRL2BASE::Read( WRLPROC& proc ) WRL2NODE* node = NULL; - while( !readNode( proc, this, node ) ); + while( !ReadNode( proc, this, &node ) ); if( proc.eof() ) return true; @@ -195,8 +132,18 @@ bool WRL2BASE::isDangling( void ) } -bool WRL2BASE::implementUse( WRLPROC& proc, WRL2NODE* aParent ) +bool WRL2BASE::implementUse( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) { + if( NULL == aNode ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] invalid node handle (NULL)\n"; + #endif + + return false; + } + if( !aParent ) { #ifdef DEBUG @@ -207,6 +154,7 @@ bool WRL2BASE::implementUse( WRLPROC& proc, WRL2NODE* aParent ) return false; } + *aNode = NULL; std::string glob; if( !proc.ReadName( glob ) ) @@ -244,18 +192,72 @@ bool WRL2BASE::implementUse( WRLPROC& proc, WRL2NODE* aParent ) return false; } + *aNode = ref; + return true; } -bool WRL2BASE::implementDef( WRLPROC& proc, WRL2NODE* aParent ) -{ - // XXX - TO BE IMPLEMENTED - return false; -} - - -bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) +bool WRL2BASE::implementDef( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) +{ + if( NULL == aNode ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] invalid node handle (NULL)\n"; + #endif + + return false; + } + + if( NULL == aParent ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] invalid parent pointer (NULL)\n"; + #endif + + return false; + } + + *aNode = NULL; + + std::string glob; + + if( !proc.ReadName( glob ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + size_t line, column; + proc.GetFilePosData( line, column ); + + if( ReadNode( proc, aParent, aNode ) ) + { + if( *aNode && !(*aNode)->SetName( glob ) ) + { + #ifdef DEBUG + size_t line, column; + proc.GetFilePosData( line, column ); + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad formatting (invalid name) at line"; + std::cerr << line << ", column " << column << "\n"; + #endif + + return false; + } + } + + return true; +} + + +bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) { if( NULL == aNode ) { @@ -280,7 +282,6 @@ bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) *aNode = NULL; std::string glob; - bool hasComma = false; WRL2NODES ntype; if( !proc.ReadName( glob ) ) @@ -305,7 +306,7 @@ bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) // a typical pattern. if( !glob.compare( "USE" ) ) { - if( !implementUse( aParent ) ) + if( !implementUse( proc, aParent, aNode ) ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; @@ -320,8 +321,17 @@ bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) if( !glob.compare( "DEF" ) ) { - // XXX - implement - implementDef( aParent ); + if( !implementDef( proc, aParent, aNode ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + return true; } if( !glob.compare( "PROTO" ) ) @@ -370,6 +380,8 @@ bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) } ntype = getNodeTypeID( glob ); + size_t line = 0; + size_t column = 0; switch( ntype ) { @@ -377,52 +389,68 @@ bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) // items to be implemented: // case WRL2_APPEARANCE: - // note: + // XXX - IMPLEMENT break; case WRL2_BOX: + // XXX - IMPLEMENT break; case WRL2_COLOR: + // XXX - IMPLEMENT break; case WRL2_CONE: + // XXX - IMPLEMENT break; case WRL2_COORDINATE: + // XXX - IMPLEMENT break; case WRL2_CYLINDER: + // XXX - IMPLEMENT break; case WRL2_ELEVATIONGRID: + // XXX - IMPLEMENT break; case WRL2_EXTRUSION: + // XXX - IMPLEMENT break; case WRL2_INDEXEDFACESET: + // XXX - IMPLEMENT break; case WRL2_MATERIAL: + // XXX - IMPLEMENT break; case WRL2_NORMAL: + // XXX - IMPLEMENT break; case WRL2_SHAPE: + // XXX - IMPLEMENT break; case WRL2_SPHERE: + // XXX - IMPLEMENT break; case WRL2_TRANSFORM: case WRL2_GROUP: + + if( !readTransform( proc, aParent, aNode ) ) + return false; + break; - // - // items not implemented or for optional future implementation: - // + // + // items not implemented or for optional future implementation: + // case WRL2_ANCHOR: case WRL2_AUDIOCLIP: case WRL2_BACKGROUND: @@ -463,10 +491,57 @@ bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) case WRL2_VISIBILITYSENSOR: case WRL2_WORLDINFO: case WRL2_INVALID: - default: // any nodes which may have been defined via PROTO/EXTERNPROTO + default: + + proc.GetFilePosData( line, column ); + + if( !proc.DiscardNode() ) + { + #ifdef DEBUG + std::cerr << proc.GetError() << "\n"; + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] could not discard node at line " << line; + std::cerr << ", column " << column << "\n"; + #endif + + return false; + } + break; } - // XXX - TO BE IMPLEMENTED - return NULL; + return true; +} + + +bool WRL2BASE::readTransform( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) +{ + if( NULL != aNode ) + *aNode = NULL; + + WRL2TRANSFORM* np = new WRL2TRANSFORM( aParent ); + + if( !np->Read( proc, this ) ) + { + delete np; + return false; + } + + if( NULL != aNode ) + *aNode = (WRL2NODE*) np; + + return true; +} + + +bool WRL2BASE::Read( WRLPROC& proc, WRL2BASE* aTopNode ) +{ + // this function makes no sense in the base node + #ifdef DEBUG + std::cerr << proc.GetError() << "\n"; + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] this method must never be invoked on a WR2BASE object\n"; + #endif + + return false; } diff --git a/plugins/3d/vrml/v2/vrml2_base.h b/plugins/3d/vrml/v2/vrml2_base.h index cac2ed9251..389361f6db 100644 --- a/plugins/3d/vrml/v2/vrml2_base.h +++ b/plugins/3d/vrml/v2/vrml2_base.h @@ -48,11 +48,6 @@ #include "vrml2_node.h" -// BUG: there are no referenced nodes; however it is indeed -// possible for the BASE node to have reference nodes, for example: -// DEF BLAH Transform{} -// USE BLAH -// The code must be adjusted to respond to unlink requests and addNodeRef requests /** * Class WRL2BASE @@ -60,9 +55,6 @@ */ class WRL2BASE : public WRL2NODE { -protected: - std::list< WRL2NODE* > m_Children; // nodes owned by this node - public: // functions inherited from WRL2NODE @@ -71,26 +63,28 @@ public: bool isDangling( void ); // handle cases of USE / DEF - bool implementUse( WRLPROC& proc, WRL2NODE* aParent ); - bool implementDef( WRLPROC& proc, WRL2NODE* aParent ); + bool implementUse( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); + bool implementDef( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); - // read in a VRML node - bool readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); + bool readTransform( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); public: WRL2BASE(); virtual ~WRL2BASE(); + // function to read entire VRML file + bool Read( WRLPROC& proc ); + + // read in a VRML node + bool ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); + // overrides - virtual const char* GetName( void ); - virtual bool SetName(const char *aName); + virtual std::string GetName( void ); + virtual bool SetName( const std::string& aName ); // functions inherited from WRL2NODE - bool Read( WRLPROC& proc ); + bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); bool SetParent( WRL2NODE* aParent ); - WRL2NODE* FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ); - bool AddRefNode( WRL2NODE* aNode ); - bool AddChildNode( WRL2NODE* aNode ); }; #endif // VRML2_BASE_H diff --git a/plugins/3d/vrml/v2/vrml2_node.cpp b/plugins/3d/vrml/v2/vrml2_node.cpp index e55f5f0aa4..8be18d0056 100644 --- a/plugins/3d/vrml/v2/vrml2_node.cpp +++ b/plugins/3d/vrml/v2/vrml2_node.cpp @@ -29,8 +29,9 @@ #include #include #include -#include "vrml2_node.h" +#include "vrml2_node.h" +#include "vrml2_helpers.h" static std::set< std::string > badNames; @@ -139,6 +140,18 @@ WRL2NODE::~WRL2NODE() ++sBP; } + m_Refs.clear(); + std::list< WRL2NODE* >::iterator sC = m_Children.begin(); + std::list< WRL2NODE* >::iterator eC = m_Children.end(); + + while( sC != eC ) + { + (*sC)->SetParent( NULL ); + delete (*sC); + ++sC; + } + + m_Children.clear(); return; } @@ -189,20 +202,14 @@ WRL2NODE* WRL2NODE::GetParent( void ) } -const char* WRL2NODE::GetName( void ) +std::string WRL2NODE::GetName( void ) { - return m_Name.c_str(); + return m_Name; } -bool WRL2NODE::SetName(const char *aName) +bool WRL2NODE::SetName( const std::string& aName ) { - if( NULL == aName || '\0' == aName[0] ) - { - m_Name.clear(); - return true; - } - std::set< std::string >::iterator item = badNames.find( aName ); if( item != badNames.end() ) @@ -224,12 +231,11 @@ bool WRL2NODE::SetName(const char *aName) return false; } - std::string tmpstr( aName ); #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" - if( std::string::npos != tmpstr.find_first_of( BAD_CHARS1 ) - || std::string::npos != tmpstr.find_first_of( BAD_CHARS2 ) ) + if( std::string::npos != aName.find_first_of( BAD_CHARS1 ) + || std::string::npos != aName.find_first_of( BAD_CHARS2 ) ) { #ifdef DEBUG std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; @@ -272,3 +278,96 @@ std::string WRL2NODE::GetError( void ) { return m_error; } + + +WRL2NODE* WRL2NODE::FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ) +{ + if( aNodeName.empty() ) + return NULL; + + if( !m_Name.compare( aNodeName ) ) + return this; + + FIND_NODE( aNodeName, m_Children, this ); + + return NULL; +} + + +bool WRL2NODE::SetParent( WRL2NODE* aParent ) +{ + if( aParent == m_Parent ) + return true; + + if( NULL != m_Parent ) + m_Parent->unlinkChildNode( this ); + + m_Parent = aParent; + + if( NULL != m_Parent ) + m_Parent->AddChildNode( this ); + + return true; +} + + +bool WRL2NODE::AddChildNode( WRL2NODE* aNode ) +{ + if( aNode->GetNodeType() == WRL2_BASE ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to add a base node to another node\n"; + #endif + return false; + } + + std::list< WRL2NODE* >::iterator sC = m_Children.begin(); + std::list< WRL2NODE* >::iterator eC = m_Children.end(); + + while( sC != eC ) + { + if( *sC == aNode ) + return false; + } + + aNode->SetParent( this ); + m_Children.push_back( aNode ); + + return true; +} + + +bool WRL2NODE::AddRefNode( WRL2NODE* aNode ) +{ + if( NULL == aNode ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] NULL passed as node pointer\n"; + #endif + return false; + } + + if( aNode->GetNodeType() == WRL2_BASE ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to add a base node ref to another base node\n"; + #endif + return false; + } + + std::list< WRL2NODE* >::iterator sR = m_Refs.begin(); + std::list< WRL2NODE* >::iterator eR = m_Refs.end(); + + while( sR != eR ) + { + if( *sR == aNode ) + return false; + } + + m_Refs.push_back( aNode ); + + return true; +} diff --git a/plugins/3d/vrml/v2/vrml2_node.h b/plugins/3d/vrml/v2/vrml2_node.h index 024e504e3e..849ff2322b 100644 --- a/plugins/3d/vrml/v2/vrml2_node.h +++ b/plugins/3d/vrml/v2/vrml2_node.h @@ -48,6 +48,7 @@ #include "wrlproc.h" +class WRL2BASE; /** * Class WRL2NODE @@ -61,6 +62,8 @@ protected: std::string m_Name; // name to use for referencing the node by name std::list< WRL2NODE* > m_BackPointers; // nodes which hold a reference to this + std::list< WRL2NODE* > m_Children; // nodes owned by this node + std::list< WRL2NODE* > m_Refs; // nodes referenced by this node std::string m_error; public: @@ -122,7 +125,7 @@ public: virtual ~WRL2NODE(); // read data via the given file processor - virtual bool Read( WRLPROC& proc ) = 0; + virtual bool Read( WRLPROC& proc, WRL2BASE* aTopNode ) = 0; /** * Function GetNodeType @@ -146,10 +149,10 @@ public: * the given node is not allowed to be a parent to * the derived object. */ - virtual bool SetParent( WRL2NODE* aParent ) = 0; + virtual bool SetParent( WRL2NODE* aParent ); - virtual const char* GetName( void ); - virtual bool SetName(const char *aName); + virtual std::string GetName( void ); + virtual bool SetName( const std::string& aName ); const char* GetNodeTypeName( WRL2NODES aNodeType ) const; @@ -162,11 +165,11 @@ public: * @param aCaller is a pointer to the node invoking this function * @return is a valid node pointer on success, otherwise NULL */ - virtual WRL2NODE* FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ) = 0; + virtual WRL2NODE* FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ); - virtual bool AddRefNode( WRL2NODE* aNode ) = 0; + bool AddChildNode( WRL2NODE* aNode ); - virtual bool AddChildNode( WRL2NODE* aNode ) = 0; + virtual bool AddRefNode( WRL2NODE* aNode ); std::string GetError( void ); }; diff --git a/plugins/3d/vrml/v2/vrml2_transform.cpp b/plugins/3d/vrml/v2/vrml2_transform.cpp new file mode 100644 index 0000000000..51fe3f8e9d --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_transform.cpp @@ -0,0 +1,159 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + +#include "vrml2_transform.h" + + +WRL2TRANSFORM::WRL2TRANSFORM() : WRL2NODE() +{ + m_Type = WRL2_TRANSFORM; + return; +} + + +WRL2TRANSFORM::WRL2TRANSFORM( WRL2NODE* aParent ) : WRL2NODE() +{ + m_Type = WRL2_TRANSFORM; + m_Parent = aParent; + return; +} + + +WRL2TRANSFORM::~WRL2TRANSFORM() +{ + return; +} + + +void WRL2TRANSFORM::unlinkChildNode( const WRL2NODE* aNode ) +{ + // XXX - TO BE IMPLEMENTED +} + +void WRL2TRANSFORM::unlinkRefNode( const WRL2NODE* aNode ) +{ + // XXX - TO BE IMPLEMENTED +} + + +bool WRL2TRANSFORM::isDangling( void ) +{ + // XXX - TO BE IMPLEMENTED + return false; +} + + +// functions inherited from WRL2NODE +bool WRL2TRANSFORM::Read( WRLPROC& proc, WRL2BASE* aTopNode ) +{ + /* + * Structure of a Transform node (p.120): + * + * Transform { + * eventIn MFNode addChildren + * eventIn MFNode removeChildren + * exposedField SFVec3f center 0 0 0 + * exposedField MFNode children [] + * exposedField SFRotation rotation 0 0 1 0 + * exposedField SFVec3f scale 1 1 1 + * exposedField SFRotation ScaleOrientation 0 0 1 0 + * exposedField SFVec3f translation 0 0 0 + * field SFVec3f bboxCenter 0 0 0 + * field SFVec3f bboxSize 0 0 0 + * } + */ + + // XXX - TO BE IMPLEMENTED + // XXX - at the moment this is half-assed code; it needs to be checked and expanded + + size_t line, column; + proc.GetFilePosData( line, column ); + + char tok = proc.Peek(); + + if( '\0' != tok ) + proc.GetFilePosData( line, column ); + + if( '{' != tok ) + { + #ifdef DEBUG + 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() == '}' ) + + if( !proc.ReadName( glob ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + } + + // XXX - TO BE IMPLEMENTED + return false; +} + + +bool WRL2TRANSFORM::AddRefNode( WRL2NODE* aNode ) +{ + if( NULL == aNode ) + { + #ifdef DEBUG + 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; +} diff --git a/plugins/3d/vrml/v2/vrml2_transform.h b/plugins/3d/vrml/v2/vrml2_transform.h new file mode 100644 index 0000000000..9bdbd5e643 --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_transform.h @@ -0,0 +1,59 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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_transform.h + */ + + +#ifndef VRML2_TRANSFORM_H +#define VRML2_TRANSFORM_H + +#include +#include + +#include "vrml2_base.h" + +/** + * Class WRL2TRANSFORM + */ +class WRL2TRANSFORM : public WRL2NODE +{ +public: + + // functions inherited from WRL2NODE + void unlinkChildNode( const WRL2NODE* aNode ); + void unlinkRefNode( const WRL2NODE* aNode ); + bool isDangling( void ); + +public: + WRL2TRANSFORM(); + WRL2TRANSFORM( WRL2NODE* aNode ); + virtual ~WRL2TRANSFORM(); + + // functions inherited from WRL2NODE + bool Read( WRLPROC& proc, WRL2BASE* aTopNode ); + bool AddRefNode( WRL2NODE* aNode ); +}; + +#endif // VRML2_TRANSFORM_H diff --git a/plugins/3d/vrml/v2/wrlproc.cpp b/plugins/3d/vrml/v2/wrlproc.cpp index d6beb6b602..6d53844dda 100644 --- a/plugins/3d/vrml/v2/wrlproc.cpp +++ b/plugins/3d/vrml/v2/wrlproc.cpp @@ -192,7 +192,7 @@ bool WRLPROC::getRawLine( void ) } -bool WRLPROC::eatSpace( void ) +bool WRLPROC::EatSpace( void ) { if( m_linepos >= m_buf.size() ) m_buf.clear(); @@ -240,7 +240,7 @@ bool WRLPROC::ReadGlob( std::string& aGlob, bool* hasComma ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -278,7 +278,7 @@ bool WRLPROC::ReadName( std::string& aName ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -333,7 +333,7 @@ bool WRLPROC::ReadName( std::string& aName ) bool WRLPROC::DiscardNode( void ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -365,7 +365,7 @@ bool WRLPROC::DiscardNode( void ) while( lvl > 0 ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -448,7 +448,7 @@ bool WRLPROC::DiscardNode( void ) bool WRLPROC::DiscardList( void ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -480,7 +480,7 @@ bool WRLPROC::DiscardList( void ) while( lvl > 0 ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -572,7 +572,7 @@ bool WRLPROC::ReadString( std::string& aSFString ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << "invalid VRML file; expecting string at line " << ifline << " but found nothing"; @@ -671,7 +671,7 @@ bool WRLPROC::ReadString( std::string& aSFString ) bool WRLPROC::ReadSFBool( bool& aSFBool ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; size_t fileline = m_fileline; @@ -752,7 +752,7 @@ bool WRLPROC::ReadSFFloat( float& aSFFloat, bool* hasComma ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -817,7 +817,7 @@ bool WRLPROC::ReadSFInt( int& aSFInt32, bool* hasComma ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -894,7 +894,7 @@ bool WRLPROC::ReadSFRotation( WRLROTATION& aSFRotation, bool* hasComma ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -984,7 +984,7 @@ bool WRLPROC::ReadSFVec2f( WRLVEC2F& aSFVec2f, bool* hasComma ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1073,7 +1073,7 @@ bool WRLPROC::ReadSFVec3f( WRLVEC3F& aSFVec3f, bool* hasComma ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1157,7 +1157,7 @@ bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1184,7 +1184,7 @@ bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString ) return false; } - if( m_linepos >= m_buf.size() && !eatSpace() ) + if( m_linepos >= m_buf.size() && !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1231,7 +1231,7 @@ bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString ) return false; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1249,7 +1249,7 @@ bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString ) aMFString.push_back( lstr ); - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1283,7 +1283,7 @@ bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1310,7 +1310,7 @@ bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1348,7 +1348,7 @@ bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1371,7 +1371,7 @@ bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1391,7 +1391,7 @@ bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor ) lcomma = true; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1437,7 +1437,7 @@ bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1464,7 +1464,7 @@ bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1502,7 +1502,7 @@ bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1525,7 +1525,7 @@ bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1535,7 +1535,7 @@ bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat ) lcomma = true; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1581,7 +1581,7 @@ bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1608,7 +1608,7 @@ bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1646,7 +1646,7 @@ bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1669,7 +1669,7 @@ bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1679,7 +1679,7 @@ bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 ) lcomma = true; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1725,7 +1725,7 @@ bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1752,7 +1752,7 @@ bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1790,7 +1790,7 @@ bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1813,7 +1813,7 @@ bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1823,7 +1823,7 @@ bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ) lcomma = true; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1869,7 +1869,7 @@ bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -1896,7 +1896,7 @@ bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -1934,7 +1934,7 @@ bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1957,7 +1957,7 @@ bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -1967,7 +1967,7 @@ bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ) lcomma = true; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -2013,7 +2013,7 @@ bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; // if the text is the start of a comment block, clear the buffer and loop @@ -2040,7 +2040,7 @@ bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -2078,7 +2078,7 @@ bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) while( true ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -2101,7 +2101,7 @@ bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) if( !lcomma ) { - if( !eatSpace() ) + if( !EatSpace() ) return false; if( ']' == m_buf[m_linepos] ) @@ -2111,7 +2111,7 @@ bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) lcomma = true; } - if( !eatSpace() ) + if( !EatSpace() ) { std::ostringstream ostr; ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; @@ -2159,3 +2159,57 @@ std::string WRLPROC::GetError( void ) { return m_error; } + + +bool WRLPROC::GetFilePosData( size_t& line, size_t& column ) +{ + if( !m_file.is_open() ) + { + line = 0; + column = 0; + return false; + } + + line = m_fileline; + column = m_linepos; + + return true; +} + + +char WRLPROC::Peek( void ) +{ + if( !m_file.is_open() ) + { + std::ostringstream ostr; + ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; + ostr << " * [BUG] no open file"; + m_error = ostr.str(); + + return '\0'; + } + + if( !EatSpace() ) + { + if( m_error.empty() ) + { + std::ostringstream ostr; + ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; + ostr << " * [INFO] failed to read data from file\n"; + m_error = ostr.str(); + } + + return false; + } + + return m_buf[m_linepos]; +} + + +void WRLPROC::Pop( void ) +{ + if( m_linepos < m_buf.size() ) + ++m_linepos; + + return; +} diff --git a/plugins/3d/vrml/v2/wrlproc.h b/plugins/3d/vrml/v2/wrlproc.h index 1e1085f5b8..3942d97e22 100644 --- a/plugins/3d/vrml/v2/wrlproc.h +++ b/plugins/3d/vrml/v2/wrlproc.h @@ -56,11 +56,6 @@ private: // parameters are updated as appropriate. bool getRawLine( void ); - // eatSpace discards all leading white space from the current m_linepos - // and continues until a non-empty line is found which contains non-blank - // characters - bool eatSpace( void ); - public: WRLPROC(); ~WRLPROC(); @@ -72,9 +67,18 @@ public: // return the VRML Version WRLVERSION GetVRMLType( void ); - std::string GetError( void ); // helper routines + std::string GetError( void ); + bool GetFilePosData( size_t& line, size_t& column ); + // eatSpace discards all leading white space from the current m_linepos + // and continues until a non-empty line is found which contains non-blank + // characters + bool EatSpace( void ); + // Peek returns the next non-white char in the file or '\0' on failure + char Peek( void ); + // Pop removes the current char from the buffer + void Pop( void ); // read up to the next whitespace or comma bool ReadGlob( std::string& aGlob, bool* hasComma = NULL );