mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-20 20:51:42 +00:00
+ Removed glm source from kicad tree (Maciej / Cirilo)
+ Added renderer for 3D model preview (Mario) + Added 3d_cache including name resolver and modifications to 3D model dialogs (Cirilo)
This commit is contained in:
parent
ab7350bf2d
commit
69cc788e8e
3d-viewer
3d_cache
3d_cache.cpp3d_cache.h3d_cache_wrapper.cpp3d_cache_wrapper.h3d_filename_resolver.cpp3d_filename_resolver.h3d_info.h3d_plugin_manager.cpp3d_plugin_manager.hCMakeLists.txtREADMEansidecl.h
3d_canvas.hdialogs
3d_cache_dialogs.cpp3d_cache_dialogs.hdialog_config_3dpath.cppdialog_config_3dpath.hdialog_select_3dmodel.cppdialog_select_3dmodel.hpanel_prev_model.cpppanel_prev_model.h
md5.cppmd5.hsg
CMakeLists.txtapi_sg_node.cppapi_sg_transform.cppifsg_all.hifsg_api.cppifsg_api.hifsg_appearance.cppifsg_appearance.hifsg_colorindex.cppifsg_colorindex.hifsg_colors.cppifsg_colors.hifsg_coordindex.cppifsg_coordindex.hifsg_coords.cppifsg_coords.hifsg_defs.hifsg_faceset.cppifsg_faceset.hifsg_index.cppifsg_index.hifsg_node.cppifsg_node.hifsg_normalindex.cppifsg_normalindex.hifsg_normals.cppifsg_normals.hifsg_shape.cppifsg_shape.hifsg_transform.cppifsg_transform.hscenegraph.cppscenegraph.hsg_api.hsg_appearance.cppsg_appearance.hsg_base.cppsg_base.hsg_colorindex.cppsg_colorindex.hsg_colors.cppsg_colors.hsg_coordindex.cppsg_coordindex.hsg_coords.cppsg_coords.hsg_faceset.cppsg_faceset.hsg_helpers.cppsg_helpers.hsg_index.cppsg_index.hsg_node.cppsg_node.hsg_normals.cppsg_normals.hsg_shape.cppsg_shape.hsg_types.h
str_rsort.htestmd5.cpp3d_canvas
3d_draw.cpp3d_draw_board_body.cpp3d_material.h3d_math
3d_mesh_model.cpp3d_mesh_model.h3d_model_viewer
3d_read_mesh.cpp3d_rendering
3d_render_ogl_legacy
c3d_render_createscene_ogl_legacy.cppc3d_render_ogl_legacy.cppc3d_render_ogl_legacy.hc_ogl_3dmodel.cppc_ogl_3dmodel.hclayer_triangles.cppclayer_triangles.hogl_legacy_utils.cppogl_legacy_utils.h
3d_render_raytracing
accelerators
cfrustum.hcmaterial.hhitinfo.hray.cppray.hraypacket.hshapes2D
cbbox2d.cppcbbox2d.hcfilledcircle2d.hcobject2d.cppcobject2d.hcpolygon2d.hcpolygon4pts2d.hcring2d.hcroundsegment2d.cppcroundsegment2d.hctriangle2d.h
shapes3D
3d_xv3d
CBBox.cppCMakeLists.txtcommon_ogl
vrml_aux.hCMakeModules
common
cvpcb
include
gal/opengl
glm
core
_detail.hpp_fixes.hpp_swizzle.hpp_swizzle_func.hpp_vectorize.hppdummy.cppfunc_common.hppfunc_common.inlfunc_exponential.hppfunc_exponential.inlfunc_geometric.hppfunc_geometric.inlfunc_integer.hppfunc_integer.inlfunc_matrix.hppfunc_matrix.inlfunc_noise.hppfunc_noise.inlfunc_packing.hppfunc_packing.inlfunc_trigonometric.hppfunc_trigonometric.inlfunc_vector_relational.hppfunc_vector_relational.inlhint.hppintrinsic_common.hppintrinsic_common.inlintrinsic_exponential.hppintrinsic_exponential.inlintrinsic_geometric.hppintrinsic_geometric.inlintrinsic_matrix.hppintrinsic_matrix.inlintrinsic_trigonometric.hppintrinsic_trigonometric.inlintrinsic_vector_relational.hppintrinsic_vector_relational.inlsetup.hpptype.hpptype_float.hpptype_gentype.hpptype_gentype.inltype_half.hpptype_half.inltype_int.hpptype_mat.hpptype_mat.inltype_mat2x2.hpptype_mat2x2.inltype_mat2x3.hpptype_mat2x3.inltype_mat2x4.hpptype_mat2x4.inltype_mat3x2.hpptype_mat3x2.inltype_mat3x3.hpptype_mat3x3.inltype_mat3x4.hpptype_mat3x4.inltype_mat4x2.hpptype_mat4x2.inltype_mat4x3.hpptype_mat4x3.inltype_mat4x4.hpptype_mat4x4.inltype_size.hpptype_vec.hpptype_vec.inltype_vec1.hpptype_vec1.inltype_vec2.hpptype_vec2.inltype_vec3.hpptype_vec3.inltype_vec4.hpptype_vec4.inl
ext.hppglm.hppgtc
constants.hppconstants.inlepsilon.hppepsilon.inlhalf_float.hpphalf_float.inlmatrix_access.hppmatrix_access.inlmatrix_integer.hppmatrix_inverse.hppmatrix_inverse.inlmatrix_transform.hppmatrix_transform.inlnoise.hppnoise.inlquaternion.hppquaternion.inlrandom.hpprandom.inlreciprocal.hppreciprocal.inlswizzle.hppswizzle.inltype_precision.hpptype_precision.inltype_ptr.hpptype_ptr.inlulp.hppulp.inl
gtx
associated_min_max.hppassociated_min_max.inlbit.hppbit.inlclosest_point.hppclosest_point.inlcolor_cast.hppcolor_cast.inlcolor_space.hppcolor_space.inlcolor_space_YCoCg.hppcolor_space_YCoCg.inlcompatibility.hppcompatibility.inlcomponent_wise.hppcomponent_wise.inlconstants.hppepsilon.hppeuler_angles.hppeuler_angles.inlextend.hppextend.inlextented_min_max.hppextented_min_max.inlfast_exponential.hppfast_exponential.inlfast_square_root.hppfast_square_root.inlfast_trigonometry.hppfast_trigonometry.inlgradient_paint.hppgradient_paint.inlhanded_coordinate_space.hpphanded_coordinate_space.inlinertia.hppinertia.inlint_10_10_10_2.hppint_10_10_10_2.inlinteger.hppinteger.inlintersect.hppintersect.inllog_base.hpplog_base.inlmatrix_cross_product.hppmatrix_cross_product.inlmatrix_interpolation.hppmatrix_interpolation.inlmatrix_major_storage.hppmatrix_major_storage.inlmatrix_operation.hppmatrix_operation.inlmatrix_query.hppmatrix_query.inlmixed_product.hppmixed_product.inlmultiple.hppmultiple.inlnoise.hppnorm.hppnorm.inlnormal.hppnormal.inlnormalize_dot.hppnormalize_dot.inlnumber_precision.hppnumber_precision.inlocl_type.hppocl_type.inloptimum_pow.hppoptimum_pow.inlorthonormalize.hpporthonormalize.inlperpendicular.hppperpendicular.inlpolar_coordinates.hpppolar_coordinates.inlprojection.hppprojection.inlquaternion.hppquaternion.inlrandom.hppraw_data.hppraw_data.inlreciprocal.hpprotate_vector.hpprotate_vector.inlsimd_mat4.hppsimd_mat4.inlsimd_vec4.hppsimd_vec4.inlspline.hppspline.inlstd_based_type.hppstd_based_type.inlstring_cast.hppstring_cast.inltransform.hpptransform.inltransform2.hpptransform2.inlulp.hppunsigned_int.hppunsigned_int.inlvec1.hppvec1.inlvector_access.hppvector_access.inlvector_angle.hppvector_angle.inlvector_query.hppvector_query.inlverbose_operator.hppverbose_operator.inlwrap.hppwrap.inl
virtrev
plugins
project.hpcbnew
CMakeLists.txt
dialogs
dialog_edit_module_for_BoardEditor.cppdialog_edit_module_for_BoardEditor.hdialog_edit_module_for_BoardEditor_base.cppdialog_edit_module_for_BoardEditor_base.fbpdialog_edit_module_for_BoardEditor_base.hdialog_edit_module_for_Modedit.cppdialog_edit_module_for_Modedit.hdialog_edit_module_for_Modedit_base.cppdialog_edit_module_for_Modedit_base.fbpdialog_edit_module_for_Modedit_base.h
plugins
622
3d-viewer/3d_cache/3d_cache.cpp
Normal file
622
3d-viewer/3d_cache/3d_cache.cpp
Normal file
@ -0,0 +1,622 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <fstream>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <wx/filename.h>
|
||||
#include <wx/utils.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "md5.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_info.h"
|
||||
#include "sg/scenegraph.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "sg/ifsg_api.h"
|
||||
|
||||
|
||||
#define CACHE_CONFIG_NAME wxT( "cache.cfg" )
|
||||
|
||||
|
||||
|
||||
static const wxString md5ToWXString( const unsigned char* aMD5Sum )
|
||||
{
|
||||
unsigned char uc;
|
||||
unsigned char tmp;
|
||||
char md5[33];
|
||||
int j = 0;
|
||||
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
uc = aMD5Sum[i];
|
||||
tmp = uc / 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
md5[j++] = tmp;
|
||||
tmp = uc % 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
md5[j++] = tmp;
|
||||
}
|
||||
|
||||
md5[j] = 0;
|
||||
|
||||
return wxString::FromUTF8Unchecked( md5 );
|
||||
}
|
||||
|
||||
|
||||
static bool md5matches( const unsigned char* md5a, const unsigned char* md5b )
|
||||
{
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
if( md5a[i] != md5b[i] )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool isMD5null( const unsigned char* aMD5Sum )
|
||||
{
|
||||
if( NULL == aMD5Sum )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] NULL passed for aMD5Sum\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
if( 0 != aMD5Sum[i] )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
class S3D_CACHE_ENTRY
|
||||
{
|
||||
private:
|
||||
// prohibit assignment and default copy constructor
|
||||
S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
|
||||
S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
|
||||
|
||||
wxString m_CacheBaseName; // base name of cache file (an MD5 sum)
|
||||
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetMD5( const unsigned char* aMD5Sum );
|
||||
const wxString GetCacheBaseName( void );
|
||||
|
||||
unsigned char md5sum[16];
|
||||
SCENEGRAPH* sceneData;
|
||||
};
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
|
||||
{
|
||||
sceneData = NULL;
|
||||
memset( md5sum, 0, 16 );
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||
{
|
||||
if( NULL != sceneData )
|
||||
delete sceneData;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE_ENTRY::SetMD5( const unsigned char* aMD5Sum )
|
||||
{
|
||||
if( NULL == aMD5Sum )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] NULL passed for aMD5Sum\n";
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( md5sum, aMD5Sum, 16 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||
{
|
||||
if( m_CacheBaseName.empty() )
|
||||
m_CacheBaseName = md5ToWXString( md5sum );
|
||||
|
||||
return m_CacheBaseName;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE::S3D_CACHE()
|
||||
{
|
||||
m_DirtyCache = false;
|
||||
m_FNResolver = new S3D_FILENAME_RESOLVER;
|
||||
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
S3D_CACHE::~S3D_CACHE()
|
||||
{
|
||||
FlushCache();
|
||||
|
||||
if( m_FNResolver )
|
||||
delete m_FNResolver;
|
||||
|
||||
if( m_Plugins )
|
||||
delete m_Plugins;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||
{
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
// the model cannot be found; we cannot proceed
|
||||
std::cout << " * [3D model] could not find model '";
|
||||
std::cout << aModelFile.ToUTF8() << "'\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check cache if file is already loaded
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
if( mi != m_CacheMap.end() )
|
||||
return mi->second->sceneData;
|
||||
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
return checkCache( full3Dpath );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName )
|
||||
{
|
||||
unsigned char md5sum[16];
|
||||
|
||||
if( !getMD5( aFileName, md5sum ) || m_CacheDir.empty() )
|
||||
{
|
||||
// just in case we can't get an MD5 sum (for example, on access issues)
|
||||
// or we do not have a configured cache file directory, we create an
|
||||
// entry to prevent further attempts at loading the file
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] duplicate entry in map file; key = ";
|
||||
std::cerr << aFileName.ToUTF8() << "\n";
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " * [3D Model] [0] added cached name '" << aFileName.ToUTF8() << "'\n";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] duplicate entry in map file; key = ";
|
||||
std::cerr << aFileName.ToUTF8() << "\n";
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " * [3D Model] [1] added cached name '" << aFileName.ToUTF8() << "'\n";
|
||||
}
|
||||
|
||||
ep->SetMD5( md5sum );
|
||||
|
||||
wxString bname = ep->GetCacheBaseName();
|
||||
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( wxFileName::FileExists( cachename ) )
|
||||
{
|
||||
loadCacheData( ep );
|
||||
return ep->sceneData;
|
||||
}
|
||||
|
||||
ep->sceneData = m_Plugins->Load3DModel( aFileName );
|
||||
|
||||
return ep->sceneData;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::getMD5( const wxString& aFileName, unsigned char* aMD5Sum )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] empty filename\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aMD5Sum )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] NULL pointer passed for aMD5Sum\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
|
||||
if( !fp )
|
||||
{
|
||||
std::cerr << " * [3dmodel] could not open file '" << aFileName.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct md5_ctx msum;
|
||||
md5_init_ctx( &msum );
|
||||
int res = md5_stream( fp, aMD5Sum );
|
||||
fclose( fp );
|
||||
|
||||
if( 0 != res )
|
||||
{
|
||||
std::cerr << " * [3dmodel] md5 calculation failed on file '" << aFileName.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
wxString bname = aCacheItem->GetCacheBaseName();
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
std::cerr << " * [3D model] cannot load cached model; no md5 hash available\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
std::cerr << " * [3D model] cannot load cached model; config directory unknown\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
// determine if the file exists and is a regular file
|
||||
struct stat info;
|
||||
|
||||
if( stat( fname.ToUTF8(), &info ) )
|
||||
return false;
|
||||
|
||||
if( !S_ISREG( info.st_mode ) )
|
||||
{
|
||||
std::cerr << " * [3D model] path exists but is not a regular file: '";
|
||||
std::cerr << fname.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
#warning NOT IMPLEMENTED
|
||||
// XXX - proceed with loading the cache data
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( NULL == aCacheItem )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * NULL passed for aCacheItem\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * aCacheItem has no valid scene data\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString bname = aCacheItem->GetCacheBaseName();
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
std::cerr << " * [3D model] cannot load cached model; no md5 hash available\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
std::cerr << " * [3D model] cannot load cached model; config directory unknown\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( wxFileName::Exists( fname ) )
|
||||
{
|
||||
// determine if the file is a regular file
|
||||
struct stat info;
|
||||
|
||||
if( stat( fname.ToUTF8(), &info ) )
|
||||
return false;
|
||||
|
||||
if( !S_ISREG( info.st_mode ) )
|
||||
{
|
||||
std::cerr << " * [3D model] path exists but is not a regular file: '";
|
||||
std::cerr << fname.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// the file already exists on disk; just exit
|
||||
return true;
|
||||
}
|
||||
|
||||
#warning NOT IMPLEMENTED
|
||||
// XXX - proceed with saving the cache data
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
{
|
||||
if( !m_ConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir( aConfigDir, "" );
|
||||
cfgdir.Normalize();
|
||||
|
||||
if( cfgdir.DirExists() )
|
||||
{
|
||||
m_ConfigDir = cfgdir.GetPath();
|
||||
|
||||
// inform the file resolver of the config directory
|
||||
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * could not set 3D Config Directory on filename resolver\n";
|
||||
std::cerr << " * config directory: '" << m_ConfigDir.ToUTF8() << "'\n";
|
||||
}
|
||||
|
||||
cfgdir.AppendDir( wxT( "cache" ) );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * failed to create 3D cache directory\n";
|
||||
std::cerr << " * cache directory: '";
|
||||
std::cerr << cfgdir.GetPath().ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheDir = cfgdir.GetPathWithSep();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||
{
|
||||
if( !m_ConfigDir.empty() || !createDefault )
|
||||
return m_ConfigDir;
|
||||
|
||||
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
|
||||
// code coupling; ideally the instantiating code should call
|
||||
// Set3DConfigDir() to set the directory rather than relying on this
|
||||
// directory remaining the same in future KiCad releases.
|
||||
wxFileName cfgpath;
|
||||
|
||||
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
|
||||
// Unix: ~ (the home directory)
|
||||
// Windows: "C:\Documents and Settings\username\Application Data"
|
||||
// Mac: ~/Library/Preferences
|
||||
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
|
||||
|
||||
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
|
||||
wxString envstr;
|
||||
|
||||
if( !wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) || envstr.IsEmpty() )
|
||||
{
|
||||
// XDG_CONFIG_HOME is not set, so use the fallback
|
||||
cfgpath.AppendDir( wxT( ".config" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Override the assignment above with XDG_CONFIG_HOME
|
||||
cfgpath.AssignDir( envstr );
|
||||
}
|
||||
#endif
|
||||
|
||||
cfgpath.AppendDir( wxT( "kicad" ) );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * failed to create 3D configuration directory\n";
|
||||
return wxT( "" );
|
||||
}
|
||||
|
||||
if( Set3DConfigDir( cfgpath.GetPath() ) )
|
||||
return m_ConfigDir;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||
{
|
||||
m_CacheMap.clear();
|
||||
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
delete *sL;
|
||||
++sL;
|
||||
}
|
||||
|
||||
m_CacheList.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_CACHE::GetProjectDir( void )
|
||||
{
|
||||
return m_FNResolver->GetProjectDir();
|
||||
}
|
||||
|
||||
|
||||
S3D_FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
|
||||
{
|
||||
return m_FNResolver;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||
{
|
||||
return m_Plugins->GetFileFilters();
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::FlushCache( void )
|
||||
{
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
|
||||
std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
|
||||
|
||||
while( sCL != eCL )
|
||||
{
|
||||
delete *sCL;
|
||||
++sCL;
|
||||
}
|
||||
|
||||
m_CacheList.clear();
|
||||
ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::ClosePlugins( void )
|
||||
{
|
||||
if( NULL != m_Plugins )
|
||||
m_Plugins->ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// notes:
|
||||
// 1. aModelEntry:
|
||||
// + rotation: degrees, model space X, Y, Z; rotations are specified in sequence
|
||||
//
|
||||
S3DMODEL* S3D_CACHE::Prepare( S3D_INFO const* aModelEntry,
|
||||
const SGPOINT& aRotation, const SGPOINT& aOffset )
|
||||
{
|
||||
SCENEGRAPH* sp = Load( aModelEntry->filename );
|
||||
|
||||
if( !sp )
|
||||
return NULL;
|
||||
|
||||
// create a single transform entity to apply to the models
|
||||
glm::dmat4 t0 = glm::translate( glm::dvec3( 25.4 * aModelEntry->offset.x, 25.4 * aModelEntry->offset.y,
|
||||
25.4 * aModelEntry->offset.z ) );
|
||||
|
||||
glm::dmat4 rX = glm::rotate( aModelEntry->rotation.x, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
||||
glm::dmat4 rY = glm::rotate( -aModelEntry->rotation.y, glm::dvec3( 0.0, 1.0, 0.0 ) );
|
||||
glm::dmat4 rZ = glm::rotate( aModelEntry->rotation.z, glm::dvec3( 0.0, 0.0, 1.0 ) );
|
||||
|
||||
glm::dmat4 s0 = glm::scale( glm::dvec3( aModelEntry->scale.x, aModelEntry->scale.y,
|
||||
aModelEntry->scale.z ) );
|
||||
|
||||
glm::dmat4 m0 = rZ * rY * rX * s0 * t0;
|
||||
|
||||
rX = glm::rotate( aRotation.x, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
||||
rY = glm::rotate( aRotation.y, glm::dvec3( 0.0, 1.0, 0.0 ) );
|
||||
rZ = glm::rotate( aRotation.z, glm::dvec3( 0.0, 0.0, 1.0 ) );
|
||||
|
||||
glm::dmat4 t1 = glm::translate( glm::dvec3( aOffset.x, aOffset.y, aOffset.z ) );
|
||||
|
||||
glm::dmat4 m1 = t1 * rZ * rY * rX * m0;
|
||||
|
||||
return S3D::Prepare( sp, &m1 );
|
||||
}
|
214
3d-viewer/3d_cache/3d_cache.h
Normal file
214
3d-viewer/3d_cache/3d_cache.h
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 3d_cache.h
|
||||
* defines the display data cache manager for 3D models
|
||||
*/
|
||||
|
||||
#ifndef CACHE_3D_H
|
||||
#define CACHE_3D_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "3d_info.h"
|
||||
#include <3d_rendering/c3dmodel.h>
|
||||
|
||||
|
||||
class S3D_CACHE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class S3D_PLUGIN_MANAGER;
|
||||
struct S3D_INFO;
|
||||
|
||||
|
||||
class S3D_CACHE
|
||||
{
|
||||
private:
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
|
||||
/// mapping of file names to cache names and data
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString > m_CacheMap;
|
||||
|
||||
/// object to resolve file names
|
||||
S3D_FILENAME_RESOLVER* m_FNResolver;
|
||||
|
||||
/// plugin manager
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
|
||||
/// set true if the cache needs to be updated
|
||||
bool m_DirtyCache;
|
||||
|
||||
/// 3D cache directory
|
||||
wxString m_CacheDir;
|
||||
|
||||
/// base configuration path for 3D items
|
||||
wxString m_ConfigDir;
|
||||
|
||||
/// current KiCad project dir
|
||||
wxString m_ProjDir;
|
||||
|
||||
/**
|
||||
* Function checkCache
|
||||
* searches the cache list for the given filename and retrieves
|
||||
* the cache data; a cache entry is created if one does not
|
||||
* already exist
|
||||
*
|
||||
* @param aFileName [in] is a partial or full file path; a partial path is accepted
|
||||
* so that a cached model may be used in cases where the user has moved or deleted
|
||||
* the original model file.
|
||||
* @param aModelEntry [in, out] is the model entry for which we are retrieving
|
||||
* scene data.
|
||||
* @param aMD5Sum [in] is an optional MD5 sum; if this parameter is supplied and its value
|
||||
* differs from the cached file then the function will fail and the flag aMD5Mismatch
|
||||
* will be set to true. If the parameter is not supplied then the cache model is used
|
||||
* if available and with no regard to the MD5 sum.
|
||||
* @param aMD5Mismatch [out] if the function succeeds then this flag is set to false;
|
||||
* the flag is set true if aMD5Sum is specified and differs from the cached object's
|
||||
* md5sum.
|
||||
* @return on success a pointer to a SCENEGRAPH, otherwise NULL
|
||||
*/
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Function getMD5
|
||||
* calculates the MD5 hash of the given file
|
||||
*
|
||||
* @param aFileName [in] is a fully qualified path to the model file
|
||||
* @param aMD5Sum [out] is a 16-byte character array to hold the MD5 hash
|
||||
* @return true if the md5 hash was calculated; otherwise false
|
||||
*/
|
||||
bool getMD5( const wxString& aFileName, unsigned char* aMD5Sum );
|
||||
|
||||
// load scene data from a cache file
|
||||
bool loadCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// save scene data to a cache file
|
||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* Sets the configuration directory to be used by the
|
||||
* model manager for storing 3D model manager configuration
|
||||
* data and the model cache. The config directory may only be
|
||||
* set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use
|
||||
* for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Function Get3DConfigDir
|
||||
* returns the current 3D configuration directory on
|
||||
* success, otherwise it returns wxEmptyString. If the
|
||||
* directory was not previously set via Set3DConfigDir()
|
||||
* then a default is used which is based on kicad's
|
||||
* configuration directory code as of September 2015.
|
||||
*/
|
||||
wxString Get3DConfigDir( bool createDefault = false );
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current project's working directory; this
|
||||
* affects the model search path
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
/**
|
||||
* Function GetProjectDir
|
||||
* returns the current project's working directory
|
||||
*/
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function Load
|
||||
* attempts to load the scene data for a model; it will consult the
|
||||
* internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins.
|
||||
*
|
||||
* @param aModelFile [in] is the partial or full path to the model to be loaded
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
* The model may fail to load if, for example, the plugin does not
|
||||
* support rendering of the 3D model.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||
|
||||
S3D_FILENAME_RESOLVER* GetResolver( void );
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters retrieved from the plugins;
|
||||
* this will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/**
|
||||
* Function FlushCache
|
||||
* frees all data in the cache and closes all plugins
|
||||
*/
|
||||
void FlushCache( void );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* unloads plugins to free memory
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function Prepare
|
||||
* attempts to load the scene data for a model and to translate it
|
||||
* into an S3D_MODEL structure for display by a renderer
|
||||
*
|
||||
* @param aModelEntry is the structure containing the model name,
|
||||
* scale, offset, and rotation. Note that by kicad convention the
|
||||
* operations are Offset-Scale-Rotation, the Y value of the offset
|
||||
* is negative (Left-hand coordinate system), and the units of the
|
||||
* offset is inches. Application of the Offset, Scale. Rotation
|
||||
* within the aModelEntry structure places the model into a nominal
|
||||
* (0, 0, 0) position and orientation. Final positioning of the
|
||||
* model instance is determined by the aOffset, aAxis, and aAngle
|
||||
* parameters.
|
||||
* @ aRotation is a X, Y, Z rotation to calculate the final orientation
|
||||
* of the model instance
|
||||
* @param aOffset is an offset to apply to obtain the final position
|
||||
* of the model instance; this offset is applied after the aAxis/aAngle
|
||||
* orientation in the common Rotation-Scale-Translation order of transforms.
|
||||
*/
|
||||
S3DMODEL* Prepare( S3D_INFO const* aModelEntry,
|
||||
const SGPOINT& aRotation, const SGPOINT& aOffset );
|
||||
};
|
||||
|
||||
#endif // CACHE_3D_H
|
66
3d-viewer/3d_cache/3d_cache_wrapper.cpp
Normal file
66
3d-viewer/3d_cache/3d_cache_wrapper.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <common.h>
|
||||
#include "3d_cache_wrapper.h"
|
||||
|
||||
|
||||
CACHE_WRAPPER::CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CACHE_WRAPPER::~CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
||||
{
|
||||
CACHE_WRAPPER* cw = (CACHE_WRAPPER*) GetElem( ELEM_3DCACHE );
|
||||
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
// check that we get the expected type of object or NULL
|
||||
wxASSERT( !cw || cache );
|
||||
|
||||
if( !cw )
|
||||
{
|
||||
cw = new CACHE_WRAPPER;
|
||||
cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
SetElem( ELEM_3DCACHE, cw );
|
||||
updateProjDir = true;
|
||||
}
|
||||
|
||||
if( updateProjDir )
|
||||
cache->SetProjectDir( GetProjectPath() );
|
||||
|
||||
return cache;
|
||||
}
|
37
3d-viewer/3d_cache/3d_cache_wrapper.h
Normal file
37
3d-viewer/3d_cache/3d_cache_wrapper.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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
|
||||
*/
|
||||
|
||||
#ifndef CACHE_WRAPPER_3D_H
|
||||
#define CACHE_WRAPPER_3D_H
|
||||
|
||||
#include <project.h>
|
||||
#include "3d_cache.h"
|
||||
|
||||
class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM
|
||||
{
|
||||
public:
|
||||
CACHE_WRAPPER();
|
||||
virtual ~CACHE_WRAPPER();
|
||||
};
|
||||
|
||||
#endif // CACHE_WRAPPER_3D_H
|
457
3d-viewer/3d_cache/3d_filename_resolver.cpp
Normal file
457
3d-viewer/3d_cache/3d_filename_resolver.cpp
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include "3d_filename_resolver.h"
|
||||
|
||||
#define S3D_RESOLVER_CONFIG wxT( "3Dresolver.cfg" )
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
|
||||
{
|
||||
if( aConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir( aConfigDir, "" );
|
||||
cfgdir.Normalize();
|
||||
|
||||
if( false == cfgdir.DirExists() )
|
||||
return false;
|
||||
|
||||
m_ConfigDir = cfgdir.GetPath();
|
||||
createPathList();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChanged )
|
||||
{
|
||||
if( aProjDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName projdir( aProjDir, "" );
|
||||
projdir.Normalize();
|
||||
|
||||
if( false == projdir.DirExists() )
|
||||
return false;
|
||||
|
||||
wxString path = projdir.GetPath();
|
||||
|
||||
if( flgChanged )
|
||||
*flgChanged = false;
|
||||
|
||||
if( m_Paths.empty() )
|
||||
{
|
||||
m_Paths.push_back( path );
|
||||
|
||||
if( flgChanged )
|
||||
*flgChanged = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_Paths.front().Cmp( path ) )
|
||||
{
|
||||
m_Paths.pop_front();
|
||||
m_Paths.push_front( path );
|
||||
m_NameMap.clear();
|
||||
|
||||
if( flgChanged )
|
||||
*flgChanged = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cout << " * [INFO] changed project dir to " << m_Paths.front().ToUTF8() << "\n";
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_FILENAME_RESOLVER::GetProjectDir( void )
|
||||
{
|
||||
if( m_Paths.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_Paths.front();
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::createPathList( void )
|
||||
{
|
||||
if( !m_Paths.empty() )
|
||||
return true;
|
||||
|
||||
wxString kmod;
|
||||
|
||||
// add the current working directory as the first entry by
|
||||
// default; since CWD is not necessarily what we really want,
|
||||
// the user may change this later with a call to SetProjectDir()
|
||||
|
||||
if( !addPath( wxFileName::GetCwd() ) )
|
||||
m_Paths.push_back( wxEmptyString );
|
||||
|
||||
if( wxGetEnv( wxT( "KISYS3DMOD" ), &kmod ) )
|
||||
addPath( kmod );
|
||||
|
||||
if( !m_ConfigDir.empty() )
|
||||
readPathList();
|
||||
|
||||
if( m_Paths.empty() )
|
||||
return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << " * [3D model] search paths:\n";
|
||||
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
std::cout << " + '" << (*sPL).ToUTF8() << "'\n";
|
||||
++sPL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< wxString >& aPathList )
|
||||
{
|
||||
while( m_Paths.size() > 1 )
|
||||
m_Paths.pop_back();
|
||||
|
||||
size_t nI = aPathList.size();
|
||||
|
||||
for( size_t i = 0; i < nI; ++i )
|
||||
addPath( aPathList[i] );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << "* S3D_FILENAME_RESOLVER::UpdatePathList()\n";
|
||||
std::cerr << "NItems: " << aPathList.size() << "\n";
|
||||
|
||||
for( size_t i = 0; i < aPathList.size(); ++i )
|
||||
std::cerr << "Item #" << i << ": " << aPathList[i].ToUTF8() << "\n";
|
||||
#endif
|
||||
|
||||
return writePathList();
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
return wxEmptyString;
|
||||
|
||||
if( m_Paths.empty() )
|
||||
createPathList();
|
||||
|
||||
// first attempt to use the name as specified:
|
||||
wxString aResolvedName;
|
||||
wxString fname = aFileName;
|
||||
|
||||
#ifdef _WIN32
|
||||
// translate from KiCad's internal UNIX-like path to MSWin paths
|
||||
fname.Replace( wxT( "/" ), wxT( "\\" ) );
|
||||
#endif
|
||||
|
||||
if( checkRealPath( fname, aResolvedName ) )
|
||||
return aResolvedName;
|
||||
|
||||
// look up the filename in the internal filename map
|
||||
std::map< wxString, wxString, S3D::rsort_wxString >::iterator mi;
|
||||
mi = m_NameMap.find( fname );
|
||||
|
||||
if( mi != m_NameMap.end() )
|
||||
return mi->second;
|
||||
|
||||
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
wxFileName fpath( wxFileName::DirName( *sPL ) );
|
||||
wxFileName filename( fname );
|
||||
|
||||
// we can only attempt a search if the filename is incomplete
|
||||
if( filename.IsRelative() )
|
||||
{
|
||||
wxString fullPath = fpath.GetPathWithSep() + fname;
|
||||
|
||||
if( checkRealPath( fullPath, aResolvedName ) )
|
||||
return aResolvedName;
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
std::cerr << " * [3D Model] filename could not be resolved: '";
|
||||
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::checkRealPath( const wxString& aFileName,
|
||||
wxString& aResolvedName )
|
||||
{
|
||||
aResolvedName.clear();
|
||||
wxFileName fname( aFileName );
|
||||
fname.Normalize();
|
||||
|
||||
if( !fname.FileExists() )
|
||||
return false;
|
||||
|
||||
aResolvedName = fname.GetFullPath();
|
||||
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, aResolvedName ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::addPath( const wxString& aPath )
|
||||
{
|
||||
if( aPath.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName path( aPath, "" );
|
||||
path.Normalize();
|
||||
|
||||
if( !path.DirExists() )
|
||||
{
|
||||
std::cerr << " * [3D Model] invalid path: '" << path.GetPath().ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString pname = path.GetPath();
|
||||
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
if( !pname.Cmp( *sPL ) )
|
||||
return true;
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
m_Paths.push_back( pname );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::readPathList( void )
|
||||
{
|
||||
if( m_ConfigDir.empty() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * 3D configuration directory is unknown\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
wxFileName cfgpath( m_ConfigDir, S3D_RESOLVER_CONFIG );
|
||||
cfgpath.Normalize();
|
||||
wxString cfgname = cfgpath.GetFullPath();
|
||||
|
||||
size_t nitems = m_Paths.size();
|
||||
|
||||
std::ifstream cfgFile;
|
||||
std::string cfgLine;
|
||||
|
||||
if( !wxFileName::Exists( cfgname ) )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * no 3D configuration file: '";
|
||||
std::cerr << cfgname.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
cfgFile.open( cfgname.ToUTF8() );
|
||||
|
||||
if( !cfgFile.is_open() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * could not open configuration file '" << cfgname.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
int lineno = 0;
|
||||
bool mod = false; // set to true if there are non-existent paths in the file
|
||||
|
||||
while( cfgFile.good() )
|
||||
{
|
||||
cfgLine.clear();
|
||||
std::getline( cfgFile, cfgLine );
|
||||
++lineno;
|
||||
|
||||
if( cfgLine.empty() )
|
||||
{
|
||||
if( cfgFile.eof() )
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string::size_type spos = cfgLine.find_first_of( '"', 0 );
|
||||
|
||||
if( std::string::npos == spos )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * bad config entry in config file '" << cfgname.ToUTF8() << "'\n";
|
||||
std::cerr << " line " << lineno << " [missing opening quote mark]\n";
|
||||
}
|
||||
|
||||
cfgLine.erase( 0, spos + 1 );
|
||||
|
||||
spos = cfgLine.find_last_of( '"' );
|
||||
|
||||
if( std::string::npos == spos )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * bad config entry in config file '" << cfgname.ToUTF8() << "'\n";
|
||||
std::cerr << " line " << lineno << " [missing closing quote mark]\n";
|
||||
}
|
||||
|
||||
cfgLine.erase( spos );
|
||||
|
||||
if( !addPath( cfgLine ) )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * bad config entry in config file '" << cfgname.ToUTF8() << "'\n";
|
||||
std::cerr << " line " << lineno << " [not a valid path]: '";
|
||||
std::cerr << cfgLine << "'\n";
|
||||
mod = true;
|
||||
}
|
||||
}
|
||||
|
||||
cfgFile.close();
|
||||
|
||||
if( mod )
|
||||
writePathList();
|
||||
|
||||
if( m_Paths.size() != nitems )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_FILENAME_RESOLVER::writePathList( void )
|
||||
{
|
||||
if( m_ConfigDir.empty() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * 3D configuration directory is unknown\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_Paths.empty() || 1 == m_Paths.size() )
|
||||
return false;
|
||||
|
||||
wxString cfgname = m_ConfigDir + S3D_RESOLVER_CONFIG;
|
||||
std::ofstream cfgFile;
|
||||
|
||||
cfgFile.open( cfgname.ToUTF8(), std::ios_base::trunc );
|
||||
|
||||
if( !cfgFile.is_open() )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * could not open configuration file '" << cfgname.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
// the first entry is the current project dir; we never add a project dir
|
||||
// to the path list in the configuration file
|
||||
++sPL;
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
cfgFile << "\"" << (*sPL).ToUTF8() << "\"\n";
|
||||
++sPL;
|
||||
}
|
||||
|
||||
bool bad = cfgFile.bad();
|
||||
cfgFile.close();
|
||||
|
||||
if( bad )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
||||
{
|
||||
wxString fname = aFullPathName;
|
||||
|
||||
if( m_Paths.empty() )
|
||||
createPathList();
|
||||
|
||||
std::list< wxString >::const_iterator sL = m_Paths.begin();
|
||||
std::list< wxString >::const_iterator eL = m_Paths.end();
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
wxFileName fpath( *sL, "" );
|
||||
wxString fps = fpath.GetPathWithSep();
|
||||
|
||||
if( std::string::npos != fname.find( fps ) )
|
||||
{
|
||||
fname = fname.substr( fps.size() );
|
||||
|
||||
#ifdef _WIN32
|
||||
fname.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||
#endif
|
||||
|
||||
return fname;
|
||||
}
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
return fname;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::list< wxString >* S3D_FILENAME_RESOLVER::GetPaths( void )
|
||||
{
|
||||
return &m_Paths;
|
||||
}
|
165
3d-viewer/3d_cache/3d_filename_resolver.h
Normal file
165
3d-viewer/3d_cache/3d_filename_resolver.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 3d_filename_resolver.h
|
||||
* provides an extensible class to resolve 3D model paths. Initially
|
||||
* the legacy behavior will be implemented and an incomplete path
|
||||
* would be checked against the project directory or the KISYS3DMOD
|
||||
* environment variable. In the future a configurable set of search
|
||||
* paths may be specified.
|
||||
*/
|
||||
|
||||
#ifndef FILENAME_RESOLVER_3D_H
|
||||
#define FILENAME_RESOLVER_3D_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
|
||||
|
||||
class S3D_FILENAME_RESOLVER
|
||||
{
|
||||
private:
|
||||
wxString m_ConfigDir; // 3D configuration directory
|
||||
std::list< wxString > m_Paths; // list of base paths to search from
|
||||
// mapping of (short) file names to resolved names
|
||||
std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
|
||||
|
||||
/**
|
||||
* Function checkRealPath
|
||||
* checks if a file exists, is a regular file, and retrieves
|
||||
* the canonical name and extension.
|
||||
*
|
||||
* @param aFileName [in] is the file name and path to be checked
|
||||
* @param aResolvedName [out] is the canonical resolved filename
|
||||
* @param aFileExtension [out] is the file's extension string
|
||||
* @return true if the file was found and is a regular file
|
||||
*/
|
||||
bool checkRealPath( const wxString& aFileName, wxString& aResolvedName );
|
||||
|
||||
/**
|
||||
* Function createPathList
|
||||
* builds the path list using available information such as
|
||||
* KISYS3DMOD and the 3d_path_list configuration file. Invalid
|
||||
* paths are silently discarded and removed from the configuration
|
||||
* file.
|
||||
*
|
||||
* @return true if at least one valid path was found
|
||||
*/
|
||||
bool createPathList( void );
|
||||
|
||||
/**
|
||||
* Function addPath
|
||||
* checks that a path is valid and adds it to the search list
|
||||
*
|
||||
* @param aPath is the path to be checked and added
|
||||
* @return true if aPath is valid
|
||||
*/
|
||||
bool addPath( const wxString& aPath );
|
||||
|
||||
/**
|
||||
* Function readPathList
|
||||
* reads a list of path names from a configuration file
|
||||
*
|
||||
* @return true if a file was found and contained at least
|
||||
* one valid path
|
||||
*/
|
||||
bool readPathList( void );
|
||||
|
||||
/**
|
||||
* Function writePathList
|
||||
* writes the current path list to a configuration file
|
||||
*
|
||||
* @return true if the path list was not empty and was
|
||||
* successfully written to the configuration file
|
||||
*/
|
||||
bool writePathList( void );
|
||||
|
||||
public:
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* sets the user's configuration directory
|
||||
* for 3D models.
|
||||
*
|
||||
* @param aConfigDir
|
||||
* @return true if the call succeeds (directory exists)
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current KiCad project directory as the first
|
||||
* entry in the model path list
|
||||
*
|
||||
* @param aProjDir is the current project directory
|
||||
* @param flgChanged, if specified, is set to true if the directory actually changed
|
||||
* @return true if the call succeeds
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
|
||||
/**
|
||||
* Function UpdatePathList
|
||||
* clears the current path list and substitutes the given path
|
||||
* list, updating the path configuration file on success.
|
||||
*/
|
||||
bool UpdatePathList( std::vector< wxString >& aPathList );
|
||||
|
||||
/**
|
||||
* Function ResolvePath
|
||||
* determines the full path of the given file name. In the future
|
||||
* remote files may be supported, in which case it is best to
|
||||
* require a full URI in which case ResolvePath should check that
|
||||
* the URI conforms to RFC-2396 and related documents and copies
|
||||
* aFileName into aResolvedName if the URI is valid.
|
||||
*/
|
||||
wxString ResolvePath( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Function ShortenPath
|
||||
* produces a relative path based on the existing
|
||||
* search directories or returns the same path if
|
||||
* the path is not a superset of an existing search path.
|
||||
*
|
||||
* @param aFullPathName is an absolute path to shorten
|
||||
* @return the shortened path or aFullPathName
|
||||
*/
|
||||
wxString ShortenPath( const wxString& aFullPathName );
|
||||
|
||||
/**
|
||||
* Function GetPaths
|
||||
* returns a pointer to the internal path list; the items in:load
|
||||
*
|
||||
* the list can be used to set up the list of search paths
|
||||
* available to a 3D file browser.
|
||||
*
|
||||
* @return pointer to the internal path list
|
||||
*/
|
||||
const std::list< wxString >* GetPaths( void );
|
||||
};
|
||||
|
||||
#endif // FILENAME_RESOLVER_3D_H
|
52
3d-viewer/3d_cache/3d_info.h
Normal file
52
3d-viewer/3d_cache/3d_info.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* 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 3d_info.h
|
||||
* defines the basic data associated with a single 3D model.
|
||||
*/
|
||||
|
||||
#ifndef INFO_3D_H
|
||||
#define INFO_3D_H
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <3d_cache/sg/sg_base.h>
|
||||
|
||||
|
||||
struct S3D_INFO
|
||||
{
|
||||
SGPOINT scale; ///< scaling factors for the 3D footprint shape
|
||||
SGPOINT rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||
SGPOINT offset; ///< an offset (unit = inch) for the 3D shape
|
||||
// note: the models are treated in a peculiar fashion since it is the
|
||||
// SCALE which is applied first, followed by the ROTATION and finally
|
||||
// the TRANSLATION/Offset (S-R-T). The usual order of operations is T-R-S.
|
||||
|
||||
wxString filename; ///< The 3D shape filename in 3D library
|
||||
};
|
||||
|
||||
#endif // INFO_3D_H
|
602
3d-viewer/3d_cache/3d_plugin_manager.cpp
Normal file
602
3d-viewer/3d_cache/3d_plugin_manager.cpp
Normal file
@ -0,0 +1,602 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <utility>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/config.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/filename.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#include <3d_plugin_manager.h>
|
||||
#include <plugins/3d/3d_plugin.h>
|
||||
#include <3d_cache/sg/scenegraph.h>
|
||||
|
||||
class S3D_PLUGIN_ITEM
|
||||
{
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HMODULE m_dlHandle;
|
||||
#else
|
||||
void* m_dlHandle; // handle to the opened plugin
|
||||
#endif
|
||||
|
||||
S3D_PLUGIN* m_plugin; // pointer to an instance
|
||||
wxString m_pluginName; // plugin name
|
||||
|
||||
public:
|
||||
S3D_PLUGIN_ITEM( const wxString& aPluginPath );
|
||||
~S3D_PLUGIN_ITEM();
|
||||
bool Open( void );
|
||||
void Close( void );
|
||||
S3D_PLUGIN* GetPlugin( void );
|
||||
const wxString GetPluginName( void );
|
||||
};
|
||||
|
||||
|
||||
S3D_PLUGIN_ITEM::S3D_PLUGIN_ITEM( const wxString& aPluginPath )
|
||||
{
|
||||
m_pluginName = aPluginPath;
|
||||
m_dlHandle = NULL;
|
||||
m_plugin = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
S3D_PLUGIN_ITEM::~S3D_PLUGIN_ITEM()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool S3D_PLUGIN_ITEM::Open( void )
|
||||
{
|
||||
if( NULL != m_dlHandle )
|
||||
return true;
|
||||
|
||||
if( m_pluginName.IsEmpty() )
|
||||
return false;
|
||||
|
||||
m_plugin = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
// NOTE: MSWin uses UTF-16 encoding
|
||||
#if defined( UNICODE ) || defined( _UNICODE )
|
||||
m_dlHandle = LoadLibrary( m_pluginName.wc_str() );
|
||||
#else
|
||||
m_dlHandle = LoadLibrary( m_pluginName.ToUTF8() );
|
||||
#endif
|
||||
#else
|
||||
m_dlHandle = dlopen( m_pluginName.ToUTF8(), RTLD_LAZY | RTLD_LOCAL );
|
||||
#endif
|
||||
|
||||
if( NULL == m_dlHandle )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * could not open file: '" << m_pluginName.ToUTF8() << "'\n";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef S3D_PLUGIN* (*pPLUGIN)( void );
|
||||
pPLUGIN Get3DPlugin = (pPLUGIN) GetProcAddress( m_dlHandle, "Get3DPlugin" );
|
||||
#else
|
||||
S3D_PLUGIN* (*Get3DPlugin)( void );
|
||||
*(void **) (&Get3DPlugin) = dlsym( m_dlHandle, "Get3DPlugin" );
|
||||
#endif
|
||||
|
||||
if( NULL == Get3DPlugin )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
|
||||
#ifdef _WIN32
|
||||
std::cerr << " * [INFO] could not find symbol\n";
|
||||
#else
|
||||
char* err = dlerror();
|
||||
std::cerr << " * [INFO] could not find symbol: '" << err << "'\n";
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// set the 3D Model Plugin object
|
||||
m_plugin = (*Get3DPlugin)();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeLibrary( m_dlHandle );
|
||||
#else
|
||||
dlclose( m_dlHandle );
|
||||
#endif
|
||||
|
||||
m_dlHandle = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
void S3D_PLUGIN_ITEM::Close( void )
|
||||
{
|
||||
m_plugin = NULL;
|
||||
|
||||
if( m_dlHandle )
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeLibrary( m_dlHandle );
|
||||
#else
|
||||
dlclose( m_dlHandle );
|
||||
#endif
|
||||
|
||||
m_dlHandle = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_PLUGIN* S3D_PLUGIN_ITEM::GetPlugin( void )
|
||||
{
|
||||
if( NULL == m_plugin && !Open() )
|
||||
return NULL;
|
||||
|
||||
return m_plugin;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_PLUGIN_ITEM::GetPluginName( void )
|
||||
{
|
||||
return m_pluginName;
|
||||
}
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
// create the initial file filter list entry
|
||||
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||
|
||||
// discover and load plugins
|
||||
loadPlugins();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !m_ExtMap.empty() )
|
||||
{
|
||||
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::const_iterator sM = m_ExtMap.begin();
|
||||
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::const_iterator eM = m_ExtMap.end();
|
||||
std::cout << "* Extension [plugin name]:\n";
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
std::cout << " + '" << sM->first.ToUTF8() << "' [";
|
||||
std::cout << sM->second->GetPluginName().ToUTF8() << "]\n";
|
||||
++sM;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "* No plugins available\n";
|
||||
}
|
||||
|
||||
|
||||
if( !m_FileFilters.empty() )
|
||||
{
|
||||
/// list of file filters
|
||||
std::list< wxString >::const_iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::const_iterator eFF = m_FileFilters.end();
|
||||
std::cout << "* File filters:\n";
|
||||
int i = 0;
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
std::cout << " + '" << *sFF << "'\n";
|
||||
++sFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "* No file filters available\n";
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
std::list< S3D_PLUGIN_ITEM* >::iterator sP = m_Plugins.begin();
|
||||
std::list< S3D_PLUGIN_ITEM* >::iterator eP = m_Plugins.end();
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
delete *sP;
|
||||
++sP;
|
||||
}
|
||||
|
||||
m_Plugins.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
{
|
||||
std::list< std::string > pathlist;
|
||||
std::list< wxString > searchpaths;
|
||||
std::list< wxString > pluginlist;
|
||||
wxFileName fn;
|
||||
|
||||
#ifdef DEBUG
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT("..") );
|
||||
fn.AppendDir( wxT("plugins") );
|
||||
fn.AppendDir( wxT("3d") );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
#endif
|
||||
fn.Assign( wxStandardPaths::Get().GetPluginsDir() );
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( std::string( fn.GetPathWithSep().ToUTF8() ), searchpaths );
|
||||
|
||||
checkPluginPath( wxT( "/usr/lib/kicad/plugins/3d" ), searchpaths );
|
||||
checkPluginPath( wxT( "/usr/local/lib/kicad/plugins/3d" ), searchpaths );
|
||||
checkPluginPath( wxT( "/opt/kicad/lib/kicad/plugins/3d" ), searchpaths );
|
||||
|
||||
#ifdef __APPLE__
|
||||
// XXX - we want to use GetOSX... so add support for that somehow in order to avoid hard coding
|
||||
// "/Library/Application Support/kicad/plugins/3d"
|
||||
checkPluginPath( wxT( "/Library/Application Support/kicad/plugins/3d" ), searchpaths );
|
||||
|
||||
// /Library/Application Support/kicad/plugins
|
||||
//fn.Assign( GetOSXKicadMachineDataDir() );
|
||||
//fn.AppendDir( wxT( "plugins" ) );
|
||||
//fn.AppendDir( wxT( "3d" ) );
|
||||
//checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
#endif
|
||||
|
||||
// note: GetUserDataDir() gives '.pcbnew' rather than '.kicad' since it uses the exe name;
|
||||
fn.Assign( wxStandardPaths::Get().GetUserDataDir() );
|
||||
fn.AppendDir( wxT( ".kicad" ) );
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
std::list< wxString >::iterator sPL = searchpaths.begin();
|
||||
std::list< wxString >::iterator ePL = searchpaths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
std::cout << "* [DEBUG] searching path: '" << (*sPL).ToUTF8() << "'\n";
|
||||
#endif
|
||||
listPlugins( *sPL, pluginlist );
|
||||
++sPL;
|
||||
}
|
||||
|
||||
if( pluginlist.empty() )
|
||||
return;
|
||||
|
||||
sPL = pluginlist.begin();
|
||||
ePL = pluginlist.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
S3D_PLUGIN_ITEM* pp = new S3D_PLUGIN_ITEM( *sPL );
|
||||
|
||||
if( pp )
|
||||
{
|
||||
if( pp->Open() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
std::cout << "* [DEBUG] adding plugin\n";
|
||||
#endif
|
||||
m_Plugins.push_back( pp );
|
||||
|
||||
S3D_PLUGIN* lpp = pp->GetPlugin();
|
||||
|
||||
if( lpp )
|
||||
{
|
||||
int nf = lpp->GetNFilters();
|
||||
|
||||
for( int i = 0; i < nf; ++i )
|
||||
addFilterString( lpp->GetFileFilter( i ) );
|
||||
|
||||
}
|
||||
|
||||
addExtensionMap( pp );
|
||||
|
||||
// close the loaded library
|
||||
pp->Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
std::cout << "* [DEBUG] deleting plugin\n";
|
||||
#endif
|
||||
delete pp;
|
||||
}
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
std::cout << "* [DEBUG] plugins loaded\n";
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// list potential plugins given a search paths
|
||||
// note on typical plugin names:
|
||||
// Linux: *.so, *.so.* (note: *.so.* will not be supported)
|
||||
// MSWin: *.dll
|
||||
// OSX: *.dylib, *.bundle
|
||||
|
||||
std::list< wxString > nameFilter; // filter to apply to files
|
||||
wxString lName; // stores name of enumerated files
|
||||
wxString fName; // full name of file
|
||||
|
||||
#ifdef __linux
|
||||
|
||||
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.so" ) );
|
||||
|
||||
#elif defined _WIN32
|
||||
|
||||
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.dll" ) );
|
||||
|
||||
#elif defined __APPLE__
|
||||
|
||||
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.dylib" ) );
|
||||
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.bundle" ) );
|
||||
|
||||
#else
|
||||
|
||||
// note: we need to positively identify a supported OS here
|
||||
// and add suffixes which may be used for 3D model plugins
|
||||
// on the specific OS
|
||||
#warning NOT IMPLEMENTED
|
||||
|
||||
#endif
|
||||
|
||||
wxDir wd;
|
||||
wd.Open( aPath );
|
||||
|
||||
if( !wd.IsOpened() )
|
||||
return;
|
||||
|
||||
wxString lp = wd.GetNameWithSep();
|
||||
std::list< wxString >::iterator sExt = nameFilter.begin();
|
||||
std::list< wxString >::iterator eExt = nameFilter.end();
|
||||
|
||||
while( sExt != eExt )
|
||||
{
|
||||
if( wd.GetFirst( &lName, *sExt, wxDIR_FILES ) )
|
||||
{
|
||||
fName = lp + lName;
|
||||
checkPluginName( fName, aPluginList );
|
||||
|
||||
while( wd.GetNext( &lName ) )
|
||||
{
|
||||
fName = lp + lName;
|
||||
checkPluginName( fName, aPluginList );
|
||||
}
|
||||
}
|
||||
|
||||
++sExt;
|
||||
}
|
||||
|
||||
wd.Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// check the existence of a plugin name and add it to the list
|
||||
|
||||
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
|
||||
return;
|
||||
|
||||
wxFileName path( aPath );
|
||||
path.Normalize();
|
||||
|
||||
// determine if the path is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
std::list< wxString >::iterator bl = aPluginList.begin();
|
||||
std::list< wxString >::iterator el = aPluginList.end();
|
||||
|
||||
while( bl != el )
|
||||
{
|
||||
if( 0 == (*bl).Cmp( wxpath ) )
|
||||
return;
|
||||
|
||||
++bl;
|
||||
}
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
std::list< wxString >& aSearchList )
|
||||
{
|
||||
// check the existence of a path and add it to the path search list
|
||||
if( aPath.empty() )
|
||||
return;
|
||||
|
||||
wxFileName path( wxFileName::DirName( aPath ) );
|
||||
path.Normalize();
|
||||
|
||||
if( !wxFileName::DirExists( path.GetFullPath() ) )
|
||||
return;
|
||||
|
||||
// determine if the directory is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
std::list< wxString >::iterator bl = aSearchList.begin();
|
||||
std::list< wxString >::iterator el = aSearchList.end();
|
||||
|
||||
while( bl != el )
|
||||
{
|
||||
if( 0 == (*bl).Cmp( wxpath ) )
|
||||
return;
|
||||
|
||||
++bl;
|
||||
}
|
||||
|
||||
aSearchList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||
{
|
||||
// add an entry to the file filter list
|
||||
if( aFilterString.empty() )
|
||||
return;
|
||||
|
||||
std::list< wxString >::iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::iterator eFF = m_FileFilters.end();
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
if( 0 == (*sFF).Cmp( aFilterString ) )
|
||||
return;
|
||||
|
||||
++sFF;
|
||||
}
|
||||
|
||||
m_FileFilters.push_back( aFilterString );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::addExtensionMap( S3D_PLUGIN_ITEM* aPlugin )
|
||||
{
|
||||
// add entries to the extension map
|
||||
if( NULL == aPlugin )
|
||||
return;
|
||||
|
||||
S3D_PLUGIN* pp = aPlugin->GetPlugin();
|
||||
|
||||
if( NULL == pp )
|
||||
return;
|
||||
|
||||
int nExt = pp->GetNExtensions();
|
||||
|
||||
for( int i = 0; i < nExt; ++i )
|
||||
{
|
||||
wxString ws = pp->GetModelExtension( i );
|
||||
|
||||
if( !ws.empty() )
|
||||
{
|
||||
m_ExtMap.insert( std::pair< const wxString, S3D_PLUGIN_ITEM* >( ws, aPlugin ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||
{
|
||||
return &m_FileFilters;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName )
|
||||
{
|
||||
wxFileName raw( aFileName );
|
||||
wxString ext = raw.GetExt();
|
||||
|
||||
std::pair < std::multimap< const wxString, S3D_PLUGIN_ITEM* >::iterator,
|
||||
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::iterator > items;
|
||||
|
||||
items = m_ExtMap.equal_range( ext );
|
||||
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::iterator sL = items.first;
|
||||
|
||||
while( sL != items.second )
|
||||
{
|
||||
S3D_PLUGIN* pplug = sL->second->GetPlugin();
|
||||
|
||||
if( NULL != pplug && pplug->CanRender() )
|
||||
{
|
||||
SCENEGRAPH* sp = pplug->Load( aFileName );
|
||||
|
||||
if( NULL != sp )
|
||||
return sp;
|
||||
}
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::ClosePlugins( void )
|
||||
{
|
||||
std::list< S3D_PLUGIN_ITEM* >::iterator sP = m_Plugins.begin();
|
||||
std::list< S3D_PLUGIN_ITEM* >::iterator eP = m_Plugins.end();
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
++sP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
96
3d-viewer/3d_cache/3d_plugin_manager.h
Normal file
96
3d-viewer/3d_cache/3d_plugin_manager.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 3d_plugin_manager.h
|
||||
* manages 3D model plugins
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_MANAGER_3D_H
|
||||
#define PLUGIN_MANAGER_3D_H
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <wx/string.h>
|
||||
|
||||
class wxWindow;
|
||||
class S3D_PLUGIN_ITEM;
|
||||
struct S3D_INFO;
|
||||
class SCENEGRAPH;
|
||||
|
||||
class S3D_PLUGIN_MANAGER
|
||||
{
|
||||
private:
|
||||
/// list of discovered plugins
|
||||
std::list< S3D_PLUGIN_ITEM* > m_Plugins;
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, S3D_PLUGIN_ITEM* > m_ExtMap;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
|
||||
/// load plugins
|
||||
void loadPlugins( void );
|
||||
|
||||
/// list potential plugins
|
||||
void listPlugins( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||
|
||||
/// check the existence of a plugin name and add it to the list
|
||||
void checkPluginName( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||
|
||||
/// check the existence of a path and add it to the path search list
|
||||
void checkPluginPath( const wxString& aPath, std::list< wxString >& aSearchList );
|
||||
|
||||
/// add an entry to the file filter list
|
||||
void addFilterString( const wxString& aFilterString );
|
||||
|
||||
/// add entries to the extension map
|
||||
void addExtensionMap( S3D_PLUGIN_ITEM* aPlugin );
|
||||
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters; this will contain at least
|
||||
* the default "All Files (*.*)|*.*" and the file filters supported
|
||||
* by any available plugins
|
||||
*
|
||||
* @return a pointer to the internal filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* iterates through all discovered plugins and closes them to
|
||||
* reclaim memory. The individual plugins will be automatically
|
||||
* reloaded as calls are made to load specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
};
|
||||
|
||||
#endif // PLUGIN_MANAGER_3D_H
|
3
3d-viewer/3d_cache/CMakeLists.txt
Normal file
3
3d-viewer/3d_cache/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# unset CMAKE_CXX_FLAGS because it's contaminated with too many options
|
||||
set( CMAKE_CXX_FLAGS "" )
|
||||
add_subdirectory( sg )
|
132
3d-viewer/3d_cache/README
Normal file
132
3d-viewer/3d_cache/README
Normal file
@ -0,0 +1,132 @@
|
||||
This directory will contain code used in the refactoring of
|
||||
the 3D viewer and 3D model management.
|
||||
|
||||
Notes on building the test program on Linux:
|
||||
1. Configure to build KiCad; ensue you have "-DS3D_TEST=ON" to
|
||||
enable the "test3dmm" test program.
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DKICAD_SCRIPTING=ON \
|
||||
-DKICAD_SCRIPTING_MODULES=ON \
|
||||
-DBUILD_GITHUB_PLUGIN=ON \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DKICAD_SKIP_BOOST=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DS3D_TEST=ON \
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON ..
|
||||
|
||||
2. After configuring to build KiCad, descend into the 3dv build
|
||||
directory:
|
||||
|
||||
cd 3dv
|
||||
|
||||
3. Build all files in the 3dv directory:
|
||||
|
||||
make -j8
|
||||
|
||||
4. Install to a directory within the build directory:
|
||||
|
||||
mkdir inst
|
||||
make install DESTDIR=./inst
|
||||
|
||||
5. Set LD_LIBRARY_PATH so that the 3d manager code can be found:
|
||||
|
||||
export LD_LIBRARY_PATH=${PWD}/inst/usr/lib/kicad
|
||||
|
||||
( note: the previous step may have installed the library in
|
||||
${PWD}/inst/usr/local/lib/kicad )
|
||||
There is no need to include the plugins directory in
|
||||
LD_LIBRARY_PATH since the manager should magically find
|
||||
plugins there and load them.
|
||||
|
||||
6. Run the test program:
|
||||
|
||||
./inst/usr/bin/test3dmm
|
||||
|
||||
|
||||
===========================
|
||||
For OSX and MSWin
|
||||
===========================
|
||||
The dynamic plugin has only been built and tested on Linux; until
|
||||
the dynamic plugin system can be made to work on MSWin and OSX, those
|
||||
systems will not be able to use the 3D cache framework for anything
|
||||
other than a filename resolver and model file browser. Without the
|
||||
plugins the 3D viewer will not be able to use the new framework for
|
||||
loading generic 3D model formats.
|
||||
|
||||
Dynamic plugins are managed in 3dv/3d_plugin_manager.cpp so that is the
|
||||
only source file which developers need to modify to support plugins
|
||||
on OSX and MSWin
|
||||
|
||||
1. OSX:
|
||||
+ In general some attention is required wherever the __APPLE__
|
||||
macro is found
|
||||
|
||||
+ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
In this function a list of reasonable search paths must be provided;
|
||||
these paths will be checked for the existence of a plugin
|
||||
|
||||
+ void S3D_PLUGIN_MANAGER::listPlugins( ... )
|
||||
In this function the list of suffixes to use in the plugin
|
||||
discovery should be checked to ensure that they comply with
|
||||
the expectations of OSX
|
||||
|
||||
+ bool S3D_PLUGIN_ITEM::Open( void )
|
||||
This function loads the dynamic plugins. If OSX use the gcc dlopen
|
||||
set of functions then there may be no further work to be done here.
|
||||
|
||||
2. MSWin:
|
||||
+ In general some attention is required wherever the _WIN32 macro is found
|
||||
|
||||
+ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
In this function a list of reasonable search paths must be provided;
|
||||
these paths will be checked for the existence of a plugin
|
||||
|
||||
+ bool S3D_PLUGIN_ITEM::Open( void )
|
||||
This function loads the dynamic plugins. Since the gcc dlopen family
|
||||
of functions do not exist on MSWin, some _WIN32 specific code must
|
||||
be added to handle the library loading.
|
||||
|
||||
===
|
||||
|
||||
Q. How do you know the plugin system is working?
|
||||
A. The plugin system is working if the dummy plugin is located and loaded.
|
||||
If the plugin is located and the software was built with the DEBUG flag,
|
||||
you will see a group of messages which, among other things, advertises
|
||||
the file types supported by the dummy plugin:
|
||||
|
||||
~/code/kicad/branch_3d/3dv/3d_plugin_manager.cpp:loadPlugins:404:
|
||||
* [DEBUG] searching path: '~/usr/lib/kicad/plugins'
|
||||
XXX - Initializing S3D_PLUGIN_DUMMY
|
||||
~/code/kicad/branch_3d/3dv/3d_plugin_manager.cpp:loadPlugins:426:
|
||||
* [DEBUG] adding plugin
|
||||
XXX - Destroying S3D_PLUGIN_DUMMY
|
||||
~/code/kicad/branch_3d/3dv/3d_plugin_manager.cpp:loadPlugins:461:
|
||||
* [DEBUG] plugins loaded
|
||||
* Extension [plugin name]:
|
||||
+ 'IDF' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'IGES' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'IGS' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'STEP' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'STP' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'WRL' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'X3D' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'idf' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'iges' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'igs' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'step' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'stp' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'wrl' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
+ 'x3d' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||
* File filters:
|
||||
+ 'All Files (*.*)|*.*'
|
||||
+ 'VRML 1.0/2.0 (*.wrl;*.WRL)|*.wrl;*.WRL'
|
||||
+ 'X3D (*.x3d;*.X3D)|*.x3d;*.X3D'
|
||||
+ 'IDF 2.0/3.0 (*.idf;*.IDF)|*.idf;*.IDF'
|
||||
+ 'IGESv5.3 (*.igs;*.iges;*.IGS;*.IGES)|*.igs;*.iges;*.IGS;*.IGES'
|
||||
+ 'STEP (*.stp;*.step;*.STP;*.STEP)|*.stp;*.step;*.STP;*.STEP'
|
||||
|
||||
The supported file extensions should appear in the list of file filters within the
|
||||
model selection dialog; if no plugins are loaded then the only available file
|
||||
filter will be the wildcard filter *.*
|
297
3d-viewer/3d_cache/ansidecl.h
Normal file
297
3d-viewer/3d_cache/ansidecl.h
Normal file
@ -0,0 +1,297 @@
|
||||
/* ANSI and traditional C compatability macros
|
||||
Copyright 1991, 1992, 1*993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* ANSI and traditional C compatibility macros
|
||||
|
||||
ANSI C is assumed if __STDC__ is #defined.
|
||||
|
||||
Macro ANSI C definition Traditional C definition
|
||||
----- ---- - ---------- ----------- - ----------
|
||||
ANSI_PROTOTYPES 1 not defined
|
||||
PTR `void *' `char *'
|
||||
PTRCONST `void *const' `char *'
|
||||
LONG_DOUBLE `long double' `double'
|
||||
const not defined `'
|
||||
volatile not defined `'
|
||||
signed not defined `'
|
||||
VA_START(ap, var) va_start(ap, var) va_start(ap)
|
||||
|
||||
Note that it is safe to write "void foo();" indicating a function
|
||||
with no return value, in all K+R compilers we have been able to test.
|
||||
|
||||
For declaring functions with prototypes, we also provide these:
|
||||
|
||||
PARAMS ((prototype))
|
||||
-- for functions which take a fixed number of arguments. Use this
|
||||
when declaring the function. When defining the function, write a
|
||||
K+R style argument list. For example:
|
||||
|
||||
char *strcpy PARAMS ((char *dest, char *source));
|
||||
...
|
||||
char *
|
||||
strcpy (dest, source)
|
||||
char *dest;
|
||||
char *source;
|
||||
{ ... }
|
||||
|
||||
VPARAMS ((prototype, ...))
|
||||
-- for functions which take a variable number of arguments. Use
|
||||
PARAMS to declare the function, VPARAMS to define it. For example:
|
||||
|
||||
int printf PARAMS ((const char *format, ...));
|
||||
...
|
||||
int
|
||||
printf VPARAMS ((const char *format, ...))
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
For writing functions which take variable numbers of arguments, we
|
||||
also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros. These
|
||||
hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
|
||||
thoroughly than the simple VA_START() macro mentioned above.
|
||||
|
||||
VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
|
||||
Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
|
||||
corresponding to the list of fixed arguments. Then use va_arg
|
||||
normally to get the variable arguments, or pass your va_list object
|
||||
around. You do not declare the va_list yourself; VA_OPEN does it
|
||||
for you.
|
||||
|
||||
Here is a complete example:
|
||||
|
||||
int
|
||||
printf VPARAMS ((const char *format, ...))
|
||||
{
|
||||
int result;
|
||||
|
||||
VA_OPEN (ap, format);
|
||||
VA_FIXEDARG (ap, const char *, format);
|
||||
|
||||
result = vfprintf (stdout, format, ap);
|
||||
VA_CLOSE (ap);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
You can declare variables either before or after the VA_OPEN,
|
||||
VA_FIXEDARG sequence. Also, VA_OPEN and VA_CLOSE are the beginning
|
||||
and end of a block. They must appear at the same nesting level,
|
||||
and any variables declared after VA_OPEN go out of scope at
|
||||
VA_CLOSE. Unfortunately, with a K+R compiler, that includes the
|
||||
argument list. You can have multiple instances of VA_OPEN/VA_CLOSE
|
||||
pairs in a single function in case you need to traverse the
|
||||
argument list more than once.
|
||||
|
||||
For ease of writing code which uses GCC extensions but needs to be
|
||||
portable to other compilers, we provide the GCC_VERSION macro that
|
||||
simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
|
||||
wrappers around __attribute__. Also, __extension__ will be #defined
|
||||
to nothing if it doesn't work. See below.
|
||||
|
||||
This header also defines a lot of obsolete macros:
|
||||
CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
|
||||
AND, DOTS, NOARGS. Don't use them. */
|
||||
|
||||
#ifndef _ANSIDECL_H
|
||||
#define _ANSIDECL_H 1
|
||||
|
||||
/* Every source file includes this file,
|
||||
so they will all get the switch for lint. */
|
||||
/* LINTLIBRARY */
|
||||
|
||||
/* Using MACRO(x,y) in cpp #if conditionals does not work with some
|
||||
older preprocessors. Thus we can't define something like this:
|
||||
|
||||
#define HAVE_GCC_VERSION(MAJOR, MINOR) \
|
||||
(__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
|
||||
|
||||
and then test "#if HAVE_GCC_VERSION(2,7)".
|
||||
|
||||
So instead we use the macro below and test it against specific values. */
|
||||
|
||||
/* This macro simplifies testing whether we are using gcc, and if it
|
||||
is of a particular mini*mum version. (Both major & minor numbers are
|
||||
significant.) This macro will evaluate to 0 if we are not using
|
||||
gcc at all. */
|
||||
#ifndef GCC_VERSION
|
||||
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
||||
#endif /* GCC_VERSION */
|
||||
|
||||
#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
|
||||
/* All known AIX compilers implement these things (but don't always
|
||||
define __STDC__). The RISC/OS MIPS compiler defines these things
|
||||
in SVR4 mode, but does not define __STDC__. */
|
||||
/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
|
||||
C ++ compilers, does not define __STDC__, though it acts as if this
|
||||
was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
|
||||
|
||||
#define ANSI_PROTOTYPES 1
|
||||
#define PTR void *
|
||||
#define PTRCONST void *const
|
||||
#define LONG_DOUBLE long double
|
||||
|
||||
#define PARAMS(ARGS) ARGS
|
||||
#define VPARAMS(ARGS) ARGS
|
||||
#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
|
||||
|
||||
/* variadic function helper macros */
|
||||
/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
|
||||
use without inhibiting further decls and without declaring an
|
||||
actual variable. */
|
||||
#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP, VAR); { struct Qdmy
|
||||
#define VA_CLOSE(AP) } va_end(AP); }
|
||||
#define VA_FIXEDARG(AP, T, N) struct Qdmy
|
||||
|
||||
#undef const
|
||||
#undef volatile
|
||||
#undef signed
|
||||
|
||||
/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
|
||||
it too, but it's not in C89. */
|
||||
#undef inline
|
||||
#if __STDC_VERSION__ > 199901L
|
||||
/* it's a keyword */
|
||||
#else
|
||||
# if GCC_VERSION >= 2007
|
||||
# define inline __inline__ /* __inline__ prevents -pedantic warnings */
|
||||
# else
|
||||
# define inline /* nothing */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* These are obsolete. Do not use. */
|
||||
#ifndef IN_GCC
|
||||
#define CONST const
|
||||
#define VOLATILE volatile
|
||||
#define SIGNED signed
|
||||
|
||||
#define PROTO(type, name, arglist) type name arglist
|
||||
#define EXFUN(name, proto) name proto
|
||||
#define DEFUN(name, arglist, args) name(args)
|
||||
#define DEFUN_VOID(name) name(void)
|
||||
#define AND ,
|
||||
#define DOTS , ...
|
||||
#define NOARGS void
|
||||
#endif /* ! IN_GCC */
|
||||
|
||||
#else /* Not ANSI C. */
|
||||
|
||||
#undef ANSI_PROTOTYPES
|
||||
#define PTR char *
|
||||
#define PTRCONST PTR
|
||||
#define LONG_DOUBLE double
|
||||
|
||||
#define PARAMS(args) ()
|
||||
#define VPARAMS(args) (va_alist) va_dcl
|
||||
#define VA_START(va_list, var) va_start(va_list)
|
||||
|
||||
#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP); { struct Qdmy
|
||||
#define VA_CLOSE(AP) } va_end(AP); }
|
||||
#define VA_FIXEDARG(AP, TYPE, NAME) TYPE NAME = va_arg(AP, TYPE)
|
||||
|
||||
/* some systems define these in header files for non-ansi mode */
|
||||
#undef const
|
||||
#undef volatile
|
||||
#undef signed
|
||||
#undef inline
|
||||
#define const
|
||||
#define volatile
|
||||
#define signed
|
||||
#define inline
|
||||
|
||||
#ifndef IN_GCC
|
||||
#define CONST
|
||||
#define VOLATILE
|
||||
#define SIGNED
|
||||
|
||||
#define PROTO(type, name, arglist) type name ()
|
||||
#define EXFUN(name, proto) name()
|
||||
#define DEFUN(name, arglist, args) name arglist args;
|
||||
#define DEFUN_VOID(name) name()
|
||||
#define AND ;
|
||||
#define DOTS
|
||||
#define NOARGS
|
||||
#endif /* ! IN_GCC */
|
||||
|
||||
#endif /* ANSI C. */
|
||||
|
||||
/* Define macros for some gcc attributes. This permits us to use the
|
||||
macros freely, and know that they will come into play for the
|
||||
version of gcc in which they are supported. */
|
||||
|
||||
#if (GCC_VERSION < 2007)
|
||||
# define __attribute__(x)
|
||||
#endif
|
||||
|
||||
/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
|
||||
#ifndef ATTRIBUTE_MALLOC
|
||||
# if (GCC_VERSION >= 2096)
|
||||
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
|
||||
# else
|
||||
# define ATTRIBUTE_MALLOC
|
||||
# endif /* GNUC >= 2.96 */
|
||||
#endif /* ATTRIBUTE_MALLOC */
|
||||
|
||||
/* Attributes on labels were valid as of gcc 2.93. */
|
||||
#ifndef ATTRIBUTE_UNUSED_LABEL
|
||||
# if (GCC_VERSION >= 2093)
|
||||
# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
|
||||
# else
|
||||
# define ATTRIBUTE_UNUSED_LABEL
|
||||
# endif /* GNUC >= 2.93 */
|
||||
#endif /* ATTRIBUTE_UNUSED_LABEL */
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||
#endif /* ATTRIBUTE_UNUSED */
|
||||
|
||||
#ifndef ATTRIBUTE_NORETURN
|
||||
#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||
#endif /* ATTRIBUTE_NORETURN */
|
||||
|
||||
#ifndef ATTRIBUTE_PRINTF
|
||||
#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
|
||||
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
|
||||
#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
|
||||
#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
|
||||
#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
|
||||
#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
|
||||
#endif /* ATTRIBUTE_PRINTF */
|
||||
|
||||
/* We use __extension__ in some places to suppress -pedantic warnings
|
||||
about GCC extensions. This feature didn't work properly before
|
||||
gcc 2.8. */
|
||||
#if GCC_VERSION < 2008
|
||||
#define __extension__
|
||||
#endif
|
||||
|
||||
/* Bootstrap support: Adjust certain macros defined by Autoconf,
|
||||
which are only valid for the stage1 compiler. If we detect
|
||||
a modern version of GCC, we are probably in stage2 or beyond,
|
||||
so unconditionally reset the values. Note that const, inline,
|
||||
etc. have been dealt with above. */
|
||||
#if (GCC_VERSION >= 2007)
|
||||
# ifndef HAVE_LONG_DOUBLE
|
||||
# define HAVE_LONG_DOUBLE 1
|
||||
# endif
|
||||
#endif /* GCC >= 2.7 */
|
||||
|
||||
#endif /* ansidecl.h */
|
72
3d-viewer/3d_cache/dialogs/3d_cache_dialogs.cpp
Normal file
72
3d-viewer/3d_cache/dialogs/3d_cache_dialogs.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <wx/filename.h>
|
||||
#include <3d_info.h>
|
||||
#include <3d_cache.h>
|
||||
#include <sg/ifsg_api.h>
|
||||
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include "dialog_config_3dpath.h"
|
||||
#include "dialog_select_3dmodel.h"
|
||||
|
||||
|
||||
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, S3D_INFO* aModel )
|
||||
{
|
||||
DLG_SEL_3DMODEL* dm = new DLG_SEL_3DMODEL( aParent, aCache,
|
||||
prevModelSelectDir, prevModelWildcard );
|
||||
|
||||
if( wxID_OK == dm->ShowModal() )
|
||||
{
|
||||
// retrieve the data entry for the 3D model
|
||||
dm->GetModelData( aModel );
|
||||
|
||||
// remember the previous settings
|
||||
prevModelWildcard = dm->GetFilterIndex();
|
||||
wxFileName name( dm->GetPath() );
|
||||
name.Normalize();
|
||||
prevModelSelectDir = name.GetPath();
|
||||
|
||||
delete dm;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dm;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver )
|
||||
{
|
||||
DLG_CFG_3DPATH* dp = new DLG_CFG_3DPATH( aParent, aResolver );
|
||||
|
||||
if( wxID_OK == dp->ShowModal() )
|
||||
{
|
||||
delete dp;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dp;
|
||||
return false;
|
||||
}
|
41
3d-viewer/3d_cache/dialogs/3d_cache_dialogs.h
Normal file
41
3d-viewer/3d_cache/dialogs/3d_cache_dialogs.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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
|
||||
*/
|
||||
|
||||
#ifndef CACHE_DIALOGS_3D_H
|
||||
#define CACHE_DIALOGS_3D_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
struct S3D_INFO;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, S3D_INFO* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||
};
|
||||
|
||||
#endif // CACHE_DIALOGS_3D_H
|
257
3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp
Normal file
257
3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <cstdlib>
|
||||
#include <list>
|
||||
#include <wx/filename.h>
|
||||
#include <3d_cache.h>
|
||||
|
||||
#include "dialog_config_3dpath.h"
|
||||
|
||||
enum
|
||||
{
|
||||
btnEditPath = wxID_HIGHEST + 1,
|
||||
btnAddPath,
|
||||
btnDeletePath,
|
||||
lbPathList
|
||||
};
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( DLG_CFG_3DPATH, wxDialog )
|
||||
EVT_BUTTON( wxID_OK, DLG_CFG_3DPATH::OnOK )
|
||||
EVT_BUTTON( wxID_CANCEL, DLG_CFG_3DPATH::OnExit )
|
||||
EVT_BUTTON( btnEditPath, DLG_CFG_3DPATH::EditPath )
|
||||
EVT_BUTTON( btnAddPath, DLG_CFG_3DPATH::AddPath )
|
||||
EVT_BUTTON( btnDeletePath, DLG_CFG_3DPATH::DeletePath )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver )
|
||||
: wxDialog( aParent, -1, _( "3D Model Path Configuration" ),
|
||||
wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxSYSTEM_MENU
|
||||
| wxRESIZE_BORDER | wxMINIMIZE_BOX )
|
||||
{
|
||||
resolver = aResolver;
|
||||
|
||||
Bind( wxEVT_LIST_ITEM_ACTIVATED, &DLG_CFG_3DPATH::EditPath, this, lbPathList );
|
||||
Bind( wxEVT_LIST_ITEM_SELECTED, &DLG_CFG_3DPATH::PathSelect, this, lbPathList );
|
||||
Bind( wxEVT_LIST_ITEM_DESELECTED, &DLG_CFG_3DPATH::PathSelect, this, lbPathList );
|
||||
|
||||
wxBoxSizer *vboxMain = new wxBoxSizer( wxVERTICAL );
|
||||
wxBoxSizer *vboxSide = new wxBoxSizer( wxVERTICAL );
|
||||
wxBoxSizer* hboxTop = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hboxBot = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
pathList = new wxListView( this, lbPathList, wxDefaultPosition, wxSize( 400, 200 ),
|
||||
wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL );
|
||||
|
||||
pathList->AppendColumn( wxEmptyString );
|
||||
|
||||
editButton = new wxButton( this, btnEditPath, _( "Edit" ),
|
||||
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||
|
||||
editButton->Enable( false );
|
||||
|
||||
wxButton* addButton = new wxButton( this, btnAddPath, _( "Add" ),
|
||||
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||
|
||||
deleteButton = new wxButton( this, btnDeletePath, _( "Delete" ),
|
||||
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||
|
||||
deleteButton->Enable( false );
|
||||
|
||||
wxButton* okButton = new wxButton( this, wxID_OK, _( "Ok" ),
|
||||
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||
|
||||
wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ),
|
||||
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||
|
||||
vboxSide->Add( editButton, 0, wxALL, 10 );
|
||||
vboxSide->Add( addButton, 0, wxALL, 10 );
|
||||
vboxSide->Add( deleteButton, 0, wxALL, 10 );
|
||||
|
||||
hboxTop->Add( pathList, 1, wxEXPAND | wxALL, 10 );
|
||||
hboxTop->Add( vboxSide, 0, wxEXPAND | wxALL, 10 );
|
||||
|
||||
hboxBot->Add( okButton, 0, wxALL, 10 );
|
||||
hboxBot->Add( cancelButton, 0, wxALL, 10 );
|
||||
|
||||
vboxMain->Add( hboxTop, 1, wxEXPAND | wxALL, 10 );
|
||||
vboxMain->Add( hboxBot, 0, wxEXPAND | wxALL, 10 );
|
||||
|
||||
if( resolver )
|
||||
{
|
||||
const std::list< wxString >* pl = resolver->GetPaths();
|
||||
std::list< wxString >::const_iterator sL = pl->begin();
|
||||
std::list< wxString >::const_iterator eL = pl->end();
|
||||
|
||||
// always skip the first entry which is the current project dir
|
||||
if( sL != eL )
|
||||
++sL;
|
||||
|
||||
long i = 0;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
m_paths.push_back( *sL );
|
||||
pathList->InsertItem( i, *sL );
|
||||
++i;
|
||||
++sL;
|
||||
}
|
||||
|
||||
pathList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||
}
|
||||
|
||||
SetSizerAndFit( vboxMain );
|
||||
Centre();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_CFG_3DPATH::OnExit( wxCommandEvent& event )
|
||||
{
|
||||
if( IsModal() )
|
||||
EndModal( wxID_EXIT );
|
||||
else
|
||||
Close( true );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_CFG_3DPATH::OnOK( wxCommandEvent& event )
|
||||
{
|
||||
if( resolver )
|
||||
resolver->UpdatePathList( m_paths );
|
||||
|
||||
if( IsModal() )
|
||||
EndModal( wxID_OK );
|
||||
else
|
||||
Close( true );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event )
|
||||
{
|
||||
long nItem = pathList->GetFirstSelected();
|
||||
wxString tmpname = m_paths[ nItem ];
|
||||
|
||||
wxDirDialog* dd = new wxDirDialog( this, _( "Change 3D model directory" ),
|
||||
m_paths[ nItem ] );
|
||||
|
||||
if( wxID_OK == dd->ShowModal() )
|
||||
{
|
||||
wxFileName path( wxFileName::DirName( dd->GetPath() ) );
|
||||
path.Normalize();
|
||||
wxString newname = path.GetPath();
|
||||
|
||||
if( tmpname.Cmp( newname ) )
|
||||
{
|
||||
pathList->DeleteItem( nItem );
|
||||
pathList->InsertItem( nItem, newname );
|
||||
m_paths[ nItem ] = newname;
|
||||
pathList->Focus( nItem );
|
||||
editButton->Enable( false );
|
||||
deleteButton->Enable( false );
|
||||
pathList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
delete dd;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event )
|
||||
{
|
||||
wxDirDialog* dd = new wxDirDialog( this, _( "Add a 3D model directory" ) );
|
||||
|
||||
if( wxID_OK == dd->ShowModal() )
|
||||
{
|
||||
wxFileName path( wxFileName::DirName( dd->GetPath() ) );
|
||||
path.Normalize();
|
||||
wxString newname = path.GetPath();
|
||||
|
||||
m_paths.push_back( newname );
|
||||
pathList->InsertItem( pathList->GetItemCount(), *m_paths.rbegin() );
|
||||
pathList->Focus( pathList->GetItemCount() -1 );
|
||||
editButton->Enable( false );
|
||||
deleteButton->Enable( false );
|
||||
pathList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||
}
|
||||
|
||||
delete dd;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event )
|
||||
{
|
||||
long nItem = pathList->GetFirstSelected();
|
||||
|
||||
if( -1 == nItem )
|
||||
return;
|
||||
|
||||
m_paths.erase( m_paths.begin() + nItem );
|
||||
pathList->DeleteItem( nItem );
|
||||
|
||||
if( m_paths.size() > 0 )
|
||||
{
|
||||
if( nItem > 0 )
|
||||
--nItem;
|
||||
|
||||
pathList->Select( nItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
editButton->Enable( false );
|
||||
deleteButton->Enable( false );
|
||||
pathList->Select( -1 );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_CFG_3DPATH::PathSelect( wxCommandEvent& event )
|
||||
{
|
||||
long nItem = pathList->GetFirstSelected();
|
||||
|
||||
if( -1 == nItem )
|
||||
{
|
||||
editButton->Enable( false );
|
||||
deleteButton->Enable( false );
|
||||
return;
|
||||
}
|
||||
|
||||
editButton->Enable( true );
|
||||
deleteButton->Enable( true );
|
||||
|
||||
return;
|
||||
}
|
62
3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h
Normal file
62
3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 dialog_config_3dpath.h
|
||||
* creates a dialog to edit the default search paths for 3D model files.
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_CONFIG_3DPATH_H
|
||||
#define DIALOG_CONFIG_3DPATH_H
|
||||
|
||||
#include <vector>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/listctrl.h>
|
||||
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
|
||||
class DLG_CFG_3DPATH : public wxDialog
|
||||
{
|
||||
private:
|
||||
wxListView* pathList;
|
||||
wxButton* editButton;
|
||||
wxButton* deleteButton;
|
||||
|
||||
S3D_FILENAME_RESOLVER* resolver;
|
||||
std::vector< wxString > m_paths;
|
||||
|
||||
public:
|
||||
DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||
|
||||
private:
|
||||
void OnExit( wxCommandEvent& event );
|
||||
void OnOK( wxCommandEvent& event );
|
||||
void EditPath( wxCommandEvent& event );
|
||||
void AddPath( wxCommandEvent& event );
|
||||
void DeletePath( wxCommandEvent& event );
|
||||
void PathSelect( wxCommandEvent& event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // DIALOG_CONFIG_3DPATH_H
|
119
3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.cpp
Normal file
119
3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <3d_cache.h>
|
||||
#include "dialog_select_3dmodel.h"
|
||||
#include "panel_prev_model.h"
|
||||
|
||||
static S3D_CACHE* mm = NULL;
|
||||
static wxFileDialog* fm = NULL;
|
||||
|
||||
static wxWindow* mkPreviewPanel( wxWindow* aParent )
|
||||
{
|
||||
PANEL_PREV_3D* pp = new PANEL_PREV_3D( aParent, true );
|
||||
pp->SetModelManager( mm );
|
||||
pp->SetFileSelectorDlg( fm );
|
||||
|
||||
return (wxWindow*)pp;
|
||||
}
|
||||
|
||||
wxBEGIN_EVENT_TABLE( DLG_SEL_3DMODEL, wxFileDialog )
|
||||
EVT_BUTTON( wxID_OK, DLG_SEL_3DMODEL::OnOK )
|
||||
EVT_BUTTON( wxID_CANCEL, DLG_SEL_3DMODEL::OnExit )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
DLG_SEL_3DMODEL::DLG_SEL_3DMODEL( wxWindow* aParent, S3D_CACHE* aManager,
|
||||
const wxString& aDefaultDir, int aFilterIndex )
|
||||
: wxFileDialog( aParent, _( "Select a 3D Model" ), aDefaultDir )
|
||||
{
|
||||
m_manager = aManager;
|
||||
mm = aManager;
|
||||
fm = this;
|
||||
|
||||
long ws = GetWindowStyleFlag();
|
||||
ws |= wxFD_FILE_MUST_EXIST;
|
||||
SetWindowStyleFlag( ws );
|
||||
SetExtraControlCreator( mkPreviewPanel );
|
||||
|
||||
if( NULL != m_manager )
|
||||
{
|
||||
std::list< wxString > const* fl = m_manager->GetFileFilters();
|
||||
std::list< wxString >::const_iterator sL = fl->begin();
|
||||
std::list< wxString >::const_iterator eL = fl->end();
|
||||
wxString filter;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
filter.Append( *sL );
|
||||
|
||||
++sL;
|
||||
|
||||
if( sL != eL )
|
||||
filter.Append( wxT( "|" ) );
|
||||
|
||||
}
|
||||
|
||||
if( !filter.empty() )
|
||||
SetWildcard( filter );
|
||||
|
||||
if( aFilterIndex >= 0 && aFilterIndex < (int)fl->size() )
|
||||
SetFilterIndex( aFilterIndex );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SEL_3DMODEL::OnExit( wxCommandEvent& event )
|
||||
{
|
||||
if( IsModal() )
|
||||
EndModal( wxID_EXIT );
|
||||
else
|
||||
Close( true );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SEL_3DMODEL::OnOK( wxCommandEvent& event )
|
||||
{
|
||||
if( IsModal() )
|
||||
EndModal( wxID_OK );
|
||||
else
|
||||
Close( true );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SEL_3DMODEL::GetModelData( S3D_INFO* aModel )
|
||||
{
|
||||
PANEL_PREV_3D* pp = (PANEL_PREV_3D*)GetExtraControl();
|
||||
|
||||
if( pp )
|
||||
pp->GetModelData( aModel );
|
||||
|
||||
return;
|
||||
}
|
57
3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.h
Normal file
57
3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 dialog_select_3dmodel.h
|
||||
* creates a dialog to select 3D model files
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_SELECT_3DMODEL_H
|
||||
#define DIALOG_SELECT_3DMODEL_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/filedlg.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class S3D_INFO;
|
||||
|
||||
class DLG_SEL_3DMODEL : public wxFileDialog
|
||||
{
|
||||
private:
|
||||
S3D_CACHE* m_manager;
|
||||
|
||||
public:
|
||||
DLG_SEL_3DMODEL( wxWindow* aParent, S3D_CACHE* aManager,
|
||||
const wxString& aDefaultDir, int aFilterIndex );
|
||||
|
||||
// Retrieve model data
|
||||
void GetModelData( S3D_INFO* aModel );
|
||||
|
||||
private:
|
||||
void OnExit( wxCommandEvent& event );
|
||||
void OnOK( wxCommandEvent& event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // DIALOG_SELECT_3DMODEL_H
|
634
3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
Normal file
634
3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
Normal file
@ -0,0 +1,634 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <3d_cache.h>
|
||||
#include <3d_info.h>
|
||||
#include <3d_filename_resolver.h>
|
||||
#include <3d_cache/sg/ifsg_api.h>
|
||||
|
||||
#include "panel_prev_model.h"
|
||||
#include "dialog_select_3dmodel.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
|
||||
|
||||
// ensure -360 < rotation < 360
|
||||
static void checkRotation( double& rot )
|
||||
{
|
||||
if( rot >= 360.0 )
|
||||
{
|
||||
int n = rot / 360.0;
|
||||
rot -= 360.0 * (double)n;
|
||||
}
|
||||
else if( rot <= -360.0 )
|
||||
{
|
||||
int n = -rot / 360.0;
|
||||
rot += 360.0 * (double)n;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
ID_SET_DIR = wxID_LAST + 1,
|
||||
ID_CFG_PATHS,
|
||||
ID_3D_ISO,
|
||||
ID_3D_UPDATE,
|
||||
ID_3D_LEFT,
|
||||
ID_3D_RIGHT,
|
||||
ID_3D_FRONT,
|
||||
ID_3D_BACK,
|
||||
ID_3D_TOP,
|
||||
ID_3D_BOTTOM
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE( PANEL_PREV_3D, wxPanel)
|
||||
EVT_CHOICE( ID_SET_DIR, PANEL_PREV_3D::SetRootDir )
|
||||
EVT_BUTTON( ID_CFG_PATHS, PANEL_PREV_3D::Cfg3DPaths )
|
||||
EVT_BUTTON( ID_3D_ISO, PANEL_PREV_3D::View3DISO )
|
||||
EVT_BUTTON( ID_3D_UPDATE, PANEL_PREV_3D::View3DUpdate )
|
||||
EVT_BUTTON( ID_3D_LEFT, PANEL_PREV_3D::View3DLeft )
|
||||
EVT_BUTTON( ID_3D_RIGHT, PANEL_PREV_3D::View3DRight )
|
||||
EVT_BUTTON( ID_3D_FRONT, PANEL_PREV_3D::View3DFront )
|
||||
EVT_BUTTON( ID_3D_BACK, PANEL_PREV_3D::View3DBack )
|
||||
EVT_BUTTON( ID_3D_TOP, PANEL_PREV_3D::View3DTop )
|
||||
EVT_BUTTON( ID_3D_BOTTOM, PANEL_PREV_3D::View3DBottom )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, bool hasFileSelector ) :
|
||||
wxPanel( aParent, -1 )
|
||||
{
|
||||
m_ModelManager = NULL;
|
||||
m_FileDlg = NULL;
|
||||
canvas = NULL;
|
||||
model = NULL;
|
||||
|
||||
wxBoxSizer* mainBox = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticBoxSizer* vbox = new wxStaticBoxSizer( wxVERTICAL, this, _( "3D Model Orientation" ) );
|
||||
wxBoxSizer* hboxDirChoice = NULL;
|
||||
dirChoices = NULL;
|
||||
|
||||
if( hasFileSelector )
|
||||
{
|
||||
hboxDirChoice = new wxBoxSizer( wxHORIZONTAL );
|
||||
dirChoices = new wxChoice( this, ID_SET_DIR );
|
||||
|
||||
#ifdef _WIN32
|
||||
// Note: On Win32 the native selector box will truncate text
|
||||
// if the text is too long.
|
||||
dirChoices->SetMinSize( wxSize( 450, -1 ) );
|
||||
#endif
|
||||
|
||||
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||
wxButton* cfgPaths = new wxButton( this, ID_CFG_PATHS, _( "Configure Paths" ) );
|
||||
hboxDirChoice->Add( stDirChoice, 0, wxALL | wxCENTER, 5 );
|
||||
hboxDirChoice->Add( dirChoices, 1, wxEXPAND | wxALL, 5 );
|
||||
hboxDirChoice->Add( cfgPaths, 0, wxALL, 5 );
|
||||
}
|
||||
|
||||
wxStaticBoxSizer* vbScale = new wxStaticBoxSizer( wxVERTICAL, this, _( "Scale" ) );
|
||||
wxStaticBoxSizer* vbRotate = new wxStaticBoxSizer( wxVERTICAL, this, _( "Rotation" ) );
|
||||
wxStaticBoxSizer* vbOffset = new wxStaticBoxSizer( wxVERTICAL, this, _( "Offset (inches)" ) );
|
||||
|
||||
wxStaticBox* modScale = vbScale->GetStaticBox();
|
||||
wxStaticBox* modRotate = vbRotate->GetStaticBox();
|
||||
wxStaticBox* modOffset = vbOffset->GetStaticBox();
|
||||
|
||||
wxBoxSizer* hbS1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbS2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbS3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxStaticText* txtS1 = new wxStaticText( modScale, -1, wxT( "X:" ) );
|
||||
wxStaticText* txtS2 = new wxStaticText( modScale, -1, wxT( "Y:" ) );
|
||||
wxStaticText* txtS3 = new wxStaticText( modScale, -1, wxT( "Z:" ) );
|
||||
xscale = new wxTextCtrl( modScale, -1, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
yscale = new wxTextCtrl( modScale, -1, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
zscale = new wxTextCtrl( modScale, -1, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
xscale->SetMaxLength( 9 );
|
||||
yscale->SetMaxLength( 9 );
|
||||
zscale->SetMaxLength( 9 );
|
||||
hbS1->Add( txtS1, 0, wxALL, 2 );
|
||||
hbS1->Add( xscale, 0, wxALL, 2 );
|
||||
hbS2->Add( txtS2, 0, wxALL, 2 );
|
||||
hbS2->Add( yscale, 0, wxALL, 2 );
|
||||
hbS3->Add( txtS3, 0, wxALL, 2 );
|
||||
hbS3->Add( zscale, 0, wxALL, 2 );
|
||||
vbScale->Add( hbS1, 0, wxEXPAND | wxALL, 2 );
|
||||
vbScale->Add( hbS2, 0, wxEXPAND | wxALL, 2 );
|
||||
vbScale->Add( hbS3, 0, wxEXPAND | wxALL, 2 );
|
||||
|
||||
wxBoxSizer* hbR1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbR2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbR3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxStaticText* txtR1 = new wxStaticText( modRotate, -1, wxT( "X:" ) );
|
||||
wxStaticText* txtR2 = new wxStaticText( modRotate, -1, wxT( "Y:" ) );
|
||||
wxStaticText* txtR3 = new wxStaticText( modRotate, -1, wxT( "Z:" ) );
|
||||
xrot = new wxTextCtrl( modRotate, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
yrot = new wxTextCtrl( modRotate, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
zrot = new wxTextCtrl( modRotate, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
xrot->SetMaxLength( 9 );
|
||||
yrot->SetMaxLength( 9 );
|
||||
zrot->SetMaxLength( 9 );
|
||||
hbR1->Add( txtR1, 0, wxALL, 2 );
|
||||
hbR1->Add( xrot, 0, wxALL, 2 );
|
||||
hbR2->Add( txtR2, 0, wxALL, 2 );
|
||||
hbR2->Add( yrot, 0, wxALL, 2 );
|
||||
hbR3->Add( txtR3, 0, wxALL, 2 );
|
||||
hbR3->Add( zrot, 0, wxALL, 2 );
|
||||
vbRotate->Add( hbR1, 0, wxEXPAND | wxALL, 2 );
|
||||
vbRotate->Add( hbR2, 0, wxEXPAND | wxALL, 2 );
|
||||
vbRotate->Add( hbR3, 0, wxEXPAND | wxALL, 2 );
|
||||
|
||||
wxBoxSizer* hbO1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbO2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbO3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxStaticText* txtO1 = new wxStaticText( modOffset, -1, wxT( "X:" ) );
|
||||
wxStaticText* txtO2 = new wxStaticText( modOffset, -1, wxT( "Y:" ) );
|
||||
wxStaticText* txtO3 = new wxStaticText( modOffset, -1, wxT( "Z:" ) );
|
||||
xoff = new wxTextCtrl( modOffset, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
yoff = new wxTextCtrl( modOffset, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
zoff = new wxTextCtrl( modOffset, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER );
|
||||
xoff->SetMaxLength( 9 );
|
||||
yoff->SetMaxLength( 9 );
|
||||
zoff->SetMaxLength( 9 );
|
||||
hbO1->Add( txtO1, 0, wxALL, 2 );
|
||||
hbO1->Add( xoff, 0, wxALL, 2 );
|
||||
hbO2->Add( txtO2, 0, wxALL, 2 );
|
||||
hbO2->Add( yoff, 0, wxALL, 2 );
|
||||
hbO3->Add( txtO3, 0, wxALL, 2 );
|
||||
hbO3->Add( zoff, 0, wxALL, 2 );
|
||||
vbOffset->Add( hbO1, 0, wxEXPAND | wxALL, 2 );
|
||||
vbOffset->Add( hbO2, 0, wxEXPAND | wxALL, 2 );
|
||||
vbOffset->Add( hbO3, 0, wxEXPAND | wxALL, 2 );
|
||||
|
||||
if( NULL != hboxDirChoice )
|
||||
mainBox->Add( hboxDirChoice, 0, wxEXPAND );
|
||||
|
||||
// hbox holding orientation data and preview
|
||||
wxBoxSizer* hbox = new wxBoxSizer( wxHORIZONTAL );
|
||||
// vbox holding orientation data
|
||||
wxBoxSizer* vboxOrient = new wxBoxSizer( wxVERTICAL );
|
||||
// vbox holding the preview and view buttons
|
||||
wxBoxSizer* vboxPrev = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
vboxOrient->Add( vbScale, 0, wxALL, 5 );
|
||||
vboxOrient->Add( vbRotate, 0, wxALL, 5 );
|
||||
vboxOrient->Add( vbOffset, 0, wxALL, 5 );
|
||||
vboxOrient->AddSpacer( 20 );
|
||||
|
||||
// add preview items
|
||||
preview = new wxPanel( this, -1 );
|
||||
preview->SetMinSize( wxSize( 320, 240 ) );
|
||||
preview->SetBackgroundColour( wxColor( 0, 0, 0 ));
|
||||
vboxPrev->Add( preview, 1, wxEXPAND | wxALIGN_CENTER | wxLEFT | wxRIGHT, 5 );
|
||||
// buttons:
|
||||
wxButton* vFront = new wxButton( this, ID_3D_FRONT, wxT( "F" ) );
|
||||
wxButton* vBack = new wxButton( this, ID_3D_BACK, wxT( "B" ) );
|
||||
wxButton* vLeft = new wxButton( this, ID_3D_LEFT, wxT( "L" ) );
|
||||
wxButton* vRight = new wxButton( this, ID_3D_RIGHT, wxT( "R" ) );
|
||||
wxButton* vTop = new wxButton( this, ID_3D_TOP, wxT( "T" ) );
|
||||
wxButton* vBottom = new wxButton( this, ID_3D_BOTTOM, wxT( "B" ) );
|
||||
wxButton* vISO = new wxButton( this, ID_3D_ISO, wxT( "I" ) );
|
||||
wxButton* vUpdate = new wxButton( this, ID_3D_UPDATE, wxT( "U" ) );
|
||||
wxBoxSizer* hbBT = new wxBoxSizer( wxHORIZONTAL );
|
||||
wxBoxSizer* hbBB = new wxBoxSizer( wxHORIZONTAL );
|
||||
hbBT->Add( vISO, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->Add( vLeft, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->Add( vFront, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->Add( vTop, 0, wxCENTER | wxALL, 3 );
|
||||
hbBT->AddSpacer( 17 );
|
||||
hbBB->Add( vUpdate, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->Add( vRight, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->Add( vBack, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->Add( vBottom, 0, wxCENTER | wxALL, 3 );
|
||||
hbBB->AddSpacer( 17 );
|
||||
|
||||
vboxPrev->AddSpacer( 7 );
|
||||
vboxPrev->Add( hbBT, 0 );
|
||||
vboxPrev->Add( hbBB, 0 );
|
||||
|
||||
// XXX - Suppress the buttons until the Renderer code is ready.
|
||||
// vboxPrev->Hide( preview, true );
|
||||
vboxPrev->Hide( hbBT, true );
|
||||
vboxPrev->Hide( hbBB, true );
|
||||
|
||||
hbox->Add( vboxOrient, 0, wxALL, 5 );
|
||||
hbox->Add( vboxPrev, 1, wxEXPAND );
|
||||
vbox->Add( hbox, 1, wxEXPAND );
|
||||
|
||||
mainBox->Add( vbox, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
if( hasFileSelector )
|
||||
{
|
||||
// NOTE: if/when the FIle Selector preview is implemented
|
||||
// we may need to hide the orientation boxes to ensure the
|
||||
// users have sufficient display area for the browser.
|
||||
// hbox->Hide( vboxOrient, true );
|
||||
// XXX -
|
||||
// NOTE: for now we always suppress the preview and model orientation
|
||||
// panels while in the file selector
|
||||
mainBox->Hide( vbox, true );
|
||||
}
|
||||
|
||||
SetSizerAndFit( mainBox );
|
||||
Centre();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||
{
|
||||
if( NULL != canvas )
|
||||
{
|
||||
canvas->Clear3DModel();
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
}
|
||||
|
||||
if( model )
|
||||
S3D::Destroy3DModel( &model );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetModelManager( S3D_CACHE* aModelManager )
|
||||
{
|
||||
m_ModelManager = aModelManager;
|
||||
updateDirChoiceList();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetFileSelectorDlg( wxFileDialog* aFileDlg )
|
||||
{
|
||||
m_FileDlg = aFileDlg;
|
||||
updateDirChoiceList();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateDirChoiceList( void )
|
||||
{
|
||||
if( NULL == m_FileDlg || NULL == m_ModelManager || NULL == dirChoices )
|
||||
return;
|
||||
|
||||
std::list< wxString > const* md = m_ModelManager->GetResolver()->GetPaths();
|
||||
std::list< wxString >::const_iterator sL = md->begin();
|
||||
std::list< wxString >::const_iterator eL = md->end();
|
||||
std::vector< wxString > cl;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
cl.push_back( *sL );
|
||||
++sL;
|
||||
}
|
||||
|
||||
if( !cl.empty() )
|
||||
{
|
||||
dirChoices->Clear();
|
||||
dirChoices->Append( (int)cl.size(), &cl[0] );
|
||||
dirChoices->Select( 0 );
|
||||
}
|
||||
|
||||
Layout();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetRootDir( wxCommandEvent& event )
|
||||
{
|
||||
if( !m_FileDlg )
|
||||
return;
|
||||
|
||||
m_FileDlg->SetDirectory( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::Cfg3DPaths( wxCommandEvent& event )
|
||||
{
|
||||
if( !m_FileDlg || !m_ModelManager )
|
||||
return;
|
||||
|
||||
if( S3D::Configure3DPaths( this, m_ModelManager->GetResolver() ) )
|
||||
updateDirChoiceList();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DISO( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Isometric View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DUpdate( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Update 3D View\n";
|
||||
|
||||
// update the model filename if appropriate
|
||||
if( NULL != m_FileDlg )
|
||||
{
|
||||
wxString modelName = m_FileDlg->GetCurrentlySelectedFilename();
|
||||
UpdateModelName( modelName );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DLeft( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Left View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DRight( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Right View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DFront( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Front View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DBack( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Back View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DTop( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Top View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::View3DBottom( wxCommandEvent& event )
|
||||
{
|
||||
// XXX - TO BE IMPLEMENTED
|
||||
std::cout << "Switch to Bottom View\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::GetModelData( S3D_INFO* aModel )
|
||||
{
|
||||
if( NULL == aModel )
|
||||
return;
|
||||
|
||||
SGPOINT scale;
|
||||
SGPOINT rotation;
|
||||
SGPOINT offset;
|
||||
|
||||
xscale->GetValue().ToDouble( &scale.x );
|
||||
yscale->GetValue().ToDouble( &scale.y );
|
||||
zscale->GetValue().ToDouble( &scale.z );
|
||||
|
||||
if( 0.001 > scale.x || 0.001 > scale.y || 0.001 > scale.z )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [INFO] invalid scale values; setting all to 1.0\n";
|
||||
scale.x = 1.0;
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
}
|
||||
|
||||
xrot->GetValue().ToDouble( &rotation.x );
|
||||
yrot->GetValue().ToDouble( &rotation.y );
|
||||
zrot->GetValue().ToDouble( &rotation.z );
|
||||
checkRotation( rotation.x );
|
||||
checkRotation( rotation.y );
|
||||
checkRotation( rotation.z );
|
||||
|
||||
xoff->GetValue().ToDouble( &offset.x );
|
||||
yoff->GetValue().ToDouble( &offset.y );
|
||||
zoff->GetValue().ToDouble( &offset.z );
|
||||
|
||||
aModel->scale = scale;
|
||||
aModel->offset = offset;
|
||||
aModel->rotation = rotation;
|
||||
|
||||
// return if we are not in file selection mode
|
||||
if( NULL == m_FileDlg )
|
||||
return;
|
||||
|
||||
// file selection mode: retrieve the filename and specify a
|
||||
// path relative to one of the config paths
|
||||
wxFileName fname = m_FileDlg->GetPath();
|
||||
fname.Normalize();
|
||||
aModel->filename = m_ModelManager->GetResolver()->ShortenPath( fname.GetFullPath() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetModelData( S3D_INFO const* aModel )
|
||||
{
|
||||
xscale->SetValue( wxString::FromDouble( aModel->scale.x ) );
|
||||
yscale->SetValue( wxString::FromDouble( aModel->scale.y ) );
|
||||
zscale->SetValue( wxString::FromDouble( aModel->scale.z ) );
|
||||
|
||||
xrot->SetValue( wxString::FromDouble( aModel->rotation.x ) );
|
||||
yrot->SetValue( wxString::FromDouble( aModel->rotation.y ) );
|
||||
zrot->SetValue( wxString::FromDouble( aModel->rotation.z ) );
|
||||
|
||||
xoff->SetValue( wxString::FromDouble( aModel->offset.x ) );
|
||||
yoff->SetValue( wxString::FromDouble( aModel->offset.y ) );
|
||||
zoff->SetValue( wxString::FromDouble( aModel->offset.z ) );
|
||||
|
||||
modelInfo = *aModel;
|
||||
UpdateModelName( aModel->filename );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
|
||||
{
|
||||
bool newModel = false;
|
||||
|
||||
// if the model name is a directory simply clear the current model
|
||||
if( aModelName.empty() || wxFileName::DirExists( aModelName ) )
|
||||
{
|
||||
currentModelFile.clear();
|
||||
modelInfo.filename.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString newModelFile;
|
||||
|
||||
if( m_ModelManager )
|
||||
newModelFile = m_ModelManager->GetResolver()->ResolvePath( aModelName );
|
||||
else if( wxFileName::FileExists( aModelName ) )
|
||||
newModelFile = aModelName;
|
||||
|
||||
if( newModelFile.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << "[3dv] Update Model: (no such file) " << aModelName.ToUTF8() << "\n";
|
||||
#endif
|
||||
}
|
||||
else if( newModelFile.Cmp( currentModelFile ) )
|
||||
{
|
||||
newModel = true;
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << "[3dv] Update Model: " << newModelFile.ToUTF8() << "\n";
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
{
|
||||
std::cout << "[3dv] Update Model: [model unchanged]\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
currentModelFile = newModelFile;
|
||||
modelInfo.filename = currentModelFile;
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() || newModel )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << "[3dv] Update Model: painting black\n";
|
||||
#endif
|
||||
if( NULL != canvas )
|
||||
canvas->Clear3DModel();
|
||||
|
||||
if( model )
|
||||
S3D::Destroy3DModel( &model );
|
||||
|
||||
if( currentModelFile.empty() )
|
||||
return;
|
||||
}
|
||||
|
||||
SGPOINT rot;
|
||||
SGPOINT trans;
|
||||
model = m_ModelManager->Prepare( &modelInfo, rot, trans );
|
||||
|
||||
if( NULL == model )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << "[3dv] Update Model: no model loaded\n";
|
||||
#endif
|
||||
|
||||
if( NULL != canvas )
|
||||
{
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cout << "[3dv] Update Model: loading preview\n";
|
||||
#endif
|
||||
|
||||
if( NULL == canvas )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cout << "[3dv] Update Model: creating canvas\n";
|
||||
#endif
|
||||
|
||||
canvas = new C3D_MODEL_VIEWER( preview,
|
||||
COGL_ATT_LIST::GetAttributesList( true ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
if( NULL == canvas )
|
||||
std::cout << "[3dv] Update Model: canvas creation FAILED\n";
|
||||
#endif
|
||||
|
||||
canvas->SetSize( preview->GetClientSize() );
|
||||
}
|
||||
|
||||
canvas->Set3DModel( *model );
|
||||
canvas->Refresh();
|
||||
canvas->Update();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateWindowUI( long flags )
|
||||
{
|
||||
/*
|
||||
XXX -
|
||||
NOTE: until we figure out how to ensure that a Paint Event is
|
||||
generated for the File Selector's UI, we cannot display any
|
||||
preview within the file browser.
|
||||
if( wxUPDATE_UI_RECURSE == flags && m_FileDlg && m_ModelManager )
|
||||
{
|
||||
// check for a change in the current model file
|
||||
S3D_INFO info;
|
||||
modelInfo = info;
|
||||
UpdateModelName( m_FileDlg->GetCurrentlySelectedFilename() );
|
||||
}
|
||||
*/
|
||||
|
||||
wxPanel::UpdateWindowUI( flags );
|
||||
|
||||
return;
|
||||
}
|
97
3d-viewer/3d_cache/dialogs/panel_prev_model.h
Normal file
97
3d-viewer/3d_cache/dialogs/panel_prev_model.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 panel_prev_model.h
|
||||
* defines a panel which is to be added to a wxFileDialog via SetExtraControl();
|
||||
* the panel shows a preview of the model being browsed (if preview is supported
|
||||
* by a plugin) and provides controls to set the offset/rotation/scale of the
|
||||
* model as per KiCad's current behavior. The panel may also be used in the 3D
|
||||
* configuration dialog to tune the positioning of the models without invoking
|
||||
* a file selector dialog.
|
||||
*/
|
||||
|
||||
#ifndef PANEL_PREV_MODEL_H
|
||||
#define PANEL_PREV_MODEL_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include <3d_rendering/c3dmodel.h>
|
||||
#include <3d_cache/3d_info.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class C3D_MODEL_VIEWER;
|
||||
|
||||
class PANEL_PREV_3D : public wxPanel
|
||||
{
|
||||
public:
|
||||
PANEL_PREV_3D( wxWindow* aParent, bool hasFileSelector = false );
|
||||
~PANEL_PREV_3D();
|
||||
|
||||
void SetModelManager( S3D_CACHE* aModelManager );
|
||||
void SetFileSelectorDlg( wxFileDialog* aFileDlg );
|
||||
void SetRootDir( wxCommandEvent& event );
|
||||
void Cfg3DPaths( wxCommandEvent& event );
|
||||
// 3D views
|
||||
void View3DISO( wxCommandEvent& event );
|
||||
void View3DUpdate( wxCommandEvent& event );
|
||||
void View3DLeft( wxCommandEvent& event );
|
||||
void View3DRight( wxCommandEvent& event );
|
||||
void View3DFront( wxCommandEvent& event );
|
||||
void View3DBack( wxCommandEvent& event );
|
||||
void View3DTop( wxCommandEvent& event );
|
||||
void View3DBottom( wxCommandEvent& event );
|
||||
// Set / Retrieve model data
|
||||
void SetModelData( S3D_INFO const* aModel );
|
||||
void GetModelData( S3D_INFO* aModel );
|
||||
void UpdateModelName( wxString const& aModel );
|
||||
// Update on change of FileDlg selection
|
||||
virtual void UpdateWindowUI( long flags = wxUPDATE_UI_NONE );
|
||||
|
||||
private:
|
||||
wxString currentModelFile;
|
||||
S3D_CACHE* m_ModelManager;
|
||||
wxFileDialog* m_FileDlg;
|
||||
wxChoice* dirChoices;
|
||||
wxTextCtrl* xscale;
|
||||
wxTextCtrl* yscale;
|
||||
wxTextCtrl* zscale;
|
||||
wxTextCtrl* xrot;
|
||||
wxTextCtrl* yrot;
|
||||
wxTextCtrl* zrot;
|
||||
wxTextCtrl* xoff;
|
||||
wxTextCtrl* yoff;
|
||||
wxTextCtrl* zoff;
|
||||
wxPanel* preview;
|
||||
C3D_MODEL_VIEWER* canvas;
|
||||
S3DMODEL* model;
|
||||
S3D_INFO modelInfo;
|
||||
|
||||
private:
|
||||
void updateDirChoiceList( void );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // PANEL_PREV_MODEL_H
|
409
3d-viewer/3d_cache/md5.cpp
Normal file
409
3d-viewer/3d_cache/md5.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
/* md5.c - Functions to compute MD5 message digest of files or memory blocks
|
||||
* according to the definition of MD5 in RFC 1321 from April 1992.
|
||||
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* NOTE: This source is derived from an old version taken from the GNU C
|
||||
* Library (glibc).
|
||||
*
|
||||
* 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, 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, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "md5.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <machine/endian.h>
|
||||
#elif !defined( _WIN32 )
|
||||
# include <endian.h>
|
||||
#endif
|
||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define SWAP(n) \
|
||||
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
|
||||
#else
|
||||
# define SWAP(n) (n)
|
||||
#endif
|
||||
|
||||
|
||||
/* This array contains the bytes used to pad the buffer to the next
|
||||
* 64-byte boundary. (RFC 1321, 3.1: Step 1) */
|
||||
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
* (RFC 1321, 3.3: Step 3) */
|
||||
void
|
||||
md5_init_ctx ( struct md5_ctx *ctx )
|
||||
{
|
||||
ctx->A = (md5_uint32) 0x67452301;
|
||||
ctx->B = (md5_uint32) 0xefcdab89;
|
||||
ctx->C = (md5_uint32) 0x98badcfe;
|
||||
ctx->D = (md5_uint32) 0x10325476;
|
||||
|
||||
ctx->total[0] = ctx->total[1] = 0;
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
/* Put result from CTX in first 16 bytes following RESBUF. The result
|
||||
* must be in little endian byte order.
|
||||
*
|
||||
* IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
* aligned for a 32 bits value. */
|
||||
void *
|
||||
md5_read_ctx ( const struct md5_ctx *ctx, void *resbuf )
|
||||
{
|
||||
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
|
||||
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
|
||||
((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
|
||||
((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
|
||||
|
||||
return resbuf;
|
||||
}
|
||||
|
||||
/* Process the remaining bytes in the internal buffer and the usual
|
||||
* prolog according to the standard and write the result to RESBUF.
|
||||
*
|
||||
* IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
* aligned for a 32 bits value. */
|
||||
void *
|
||||
md5_finish_ctx ( struct md5_ctx *ctx, void *resbuf )
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
md5_uint32 bytes = ctx->buflen;
|
||||
size_t pad;
|
||||
|
||||
/* Now count remaining bytes. */
|
||||
ctx->total[0] += bytes;
|
||||
if (ctx->total[0] < bytes)
|
||||
++ctx->total[1];
|
||||
|
||||
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
|
||||
memcpy (&ctx->buffer[bytes], fillbuf, pad);
|
||||
|
||||
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||
*(md5_uint32 *) (&ctx->buffer[bytes + pad]) = SWAP (ctx->total[0] << 3);
|
||||
*(md5_uint32 *) (&ctx->buffer[bytes + pad + 4]) = SWAP ((ctx->total[1] << 3) |
|
||||
(ctx->total[0] >> 29));
|
||||
|
||||
/* Process last bytes. */
|
||||
md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
|
||||
|
||||
return md5_read_ctx (ctx, resbuf);
|
||||
}
|
||||
|
||||
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||
* resulting message digest number will be written into the 16 bytes
|
||||
* beginning at RESBLOCK. */
|
||||
int
|
||||
md5_stream ( FILE *stream, void *resblock )
|
||||
{
|
||||
/* Important: BLOCKSIZE must be a multiple of 64. */
|
||||
#define BLOCKSIZE 4096
|
||||
struct md5_ctx ctx;
|
||||
char buffer[BLOCKSIZE + 72];
|
||||
size_t sum;
|
||||
|
||||
/* Initialize the computation context. */
|
||||
md5_init_ctx (&ctx);
|
||||
|
||||
/* Iterate over full file contents. */
|
||||
while (1)
|
||||
{
|
||||
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
|
||||
* computation function processes the whole buffer so that with the
|
||||
* next round of the loop another block can be read. */
|
||||
size_t n;
|
||||
sum = 0;
|
||||
|
||||
/* Read block. Take care for partial reads. */
|
||||
do
|
||||
{
|
||||
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
|
||||
|
||||
sum += n;
|
||||
}
|
||||
while (sum < BLOCKSIZE && n != 0);
|
||||
if (n == 0 && ferror (stream))
|
||||
return 1;
|
||||
|
||||
/* If end of file is reached, end the loop. */
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
/* Process buffer with BLOCKSIZE bytes. Note that
|
||||
* BLOCKSIZE % 64 == 0
|
||||
*/
|
||||
md5_process_block (buffer, BLOCKSIZE, &ctx);
|
||||
}
|
||||
|
||||
/* Add the last bytes if necessary. */
|
||||
if (sum > 0)
|
||||
md5_process_bytes (buffer, sum, &ctx);
|
||||
|
||||
/* Construct result in desired memory. */
|
||||
md5_finish_ctx (&ctx, resblock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||
* result is always in little endian byte order, so that a byte-wise
|
||||
* output yields to the wanted ASCII representation of the message
|
||||
* digest. */
|
||||
void *
|
||||
md5_buffer ( const char *buffer, size_t len, void *resblock )
|
||||
{
|
||||
struct md5_ctx ctx;
|
||||
|
||||
/* Initialize the computation context. */
|
||||
md5_init_ctx (&ctx);
|
||||
|
||||
/* Process whole buffer but last len % 64 bytes. */
|
||||
md5_process_bytes (buffer, len, &ctx);
|
||||
|
||||
/* Put result in desired memory area. */
|
||||
return md5_finish_ctx (&ctx, resblock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md5_process_bytes ( const void *buffer, size_t len, struct md5_ctx *ctx )
|
||||
{
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
* both inputs first. */
|
||||
if (ctx->buflen != 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
|
||||
if (left_over + add > 64)
|
||||
{
|
||||
md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
|
||||
(left_over + add) & 63);
|
||||
ctx->buflen = (left_over + add) & 63;
|
||||
}
|
||||
|
||||
buffer = (const void *) ((const char *) buffer + add);
|
||||
len -= add;
|
||||
}
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len > 64)
|
||||
{
|
||||
md5_process_block (buffer, len & ~63, ctx);
|
||||
buffer = (const void *) ((const char *) buffer + (len & ~63));
|
||||
len &= 63;
|
||||
}
|
||||
|
||||
/* Move remaining bytes in internal buffer. */
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy (ctx->buffer, buffer, len);
|
||||
ctx->buflen = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* These are the four functions used in the four steps of the MD5 algorithm
|
||||
* and defined in the RFC 1321. The first function is a little bit optimized
|
||||
* (as found in Colin Plumbs public domain implementation). */
|
||||
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
|
||||
#define FF(b, c, d) (d ^ (b & (c ^ d)))
|
||||
#define FG(b, c, d) FF (d, b, c)
|
||||
#define FH(b, c, d) (b ^ c ^ d)
|
||||
#define FI(b, c, d) (c ^ (b | ~d))
|
||||
|
||||
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||
* It is assumed that LEN % 64 == 0. */
|
||||
|
||||
void
|
||||
md5_process_block ( const void *buffer, size_t len, struct md5_ctx *ctx )
|
||||
{
|
||||
md5_uint32 correct_words[16];
|
||||
const md5_uint32 *words = (const md5_uint32 *) buffer;
|
||||
size_t nwords = len / sizeof (md5_uint32);
|
||||
const md5_uint32 *endp = words + nwords;
|
||||
md5_uint32 A = ctx->A;
|
||||
md5_uint32 B = ctx->B;
|
||||
md5_uint32 C = ctx->C;
|
||||
md5_uint32 D = ctx->D;
|
||||
|
||||
/* First increment the byte count. RFC 1321 specifies the possible
|
||||
* length of the file up to 2^64 bits. Here we only compute the
|
||||
* number of bytes. Do a double word increment. */
|
||||
ctx->total[0] += len;
|
||||
if (ctx->total[0] < len)
|
||||
++ctx->total[1];
|
||||
|
||||
/* Process all bytes in the buffer with 64 bytes in each round of
|
||||
* the loop. */
|
||||
while (words < endp)
|
||||
{
|
||||
md5_uint32 *cwp = correct_words;
|
||||
md5_uint32 A_save = A;
|
||||
md5_uint32 B_save = B;
|
||||
md5_uint32 C_save = C;
|
||||
md5_uint32 D_save = D;
|
||||
|
||||
/* First round: using the given function, the context and a constant
|
||||
* the next context is computed. Because the algorithms processing
|
||||
* unit is a 32-bit word and it is determined to work on words in
|
||||
* little endian byte order we perhaps have to change the byte order
|
||||
* before the computation. To reduce the work for the next steps
|
||||
* we store the swapped words in the array CORRECT_WORDS. */
|
||||
|
||||
#define OP(a, b, c, d, s, T) \
|
||||
do \
|
||||
{ \
|
||||
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
|
||||
++words; \
|
||||
CYCLIC (a, s); \
|
||||
a += b; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
* cyclic rotation. Hope the C compiler is smart enough. */
|
||||
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
|
||||
|
||||
/* Before we start, one word to the strange constants.
|
||||
* They are defined in RFC 1321 as
|
||||
*
|
||||
* T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
|
||||
*/
|
||||
|
||||
/* Round 1. */
|
||||
OP (A, B, C, D, 7, (md5_uint32) 0xd76aa478);
|
||||
OP (D, A, B, C, 12, (md5_uint32) 0xe8c7b756);
|
||||
OP (C, D, A, B, 17, (md5_uint32) 0x242070db);
|
||||
OP (B, C, D, A, 22, (md5_uint32) 0xc1bdceee);
|
||||
OP (A, B, C, D, 7, (md5_uint32) 0xf57c0faf);
|
||||
OP (D, A, B, C, 12, (md5_uint32) 0x4787c62a);
|
||||
OP (C, D, A, B, 17, (md5_uint32) 0xa8304613);
|
||||
OP (B, C, D, A, 22, (md5_uint32) 0xfd469501);
|
||||
OP (A, B, C, D, 7, (md5_uint32) 0x698098d8);
|
||||
OP (D, A, B, C, 12, (md5_uint32) 0x8b44f7af);
|
||||
OP (C, D, A, B, 17, (md5_uint32) 0xffff5bb1);
|
||||
OP (B, C, D, A, 22, (md5_uint32) 0x895cd7be);
|
||||
OP (A, B, C, D, 7, (md5_uint32) 0x6b901122);
|
||||
OP (D, A, B, C, 12, (md5_uint32) 0xfd987193);
|
||||
OP (C, D, A, B, 17, (md5_uint32) 0xa679438e);
|
||||
OP (B, C, D, A, 22, (md5_uint32) 0x49b40821);
|
||||
|
||||
/* For the second to fourth round we have the possibly swapped words
|
||||
* in CORRECT_WORDS. Redefine the macro to take an additional first
|
||||
* argument specifying the function to use. */
|
||||
#undef OP
|
||||
#define OP(a, b, c, d, k, s, T) \
|
||||
do \
|
||||
{ \
|
||||
a += FX (b, c, d) + correct_words[k] + T; \
|
||||
CYCLIC (a, s); \
|
||||
a += b; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define FX(b, c, d) FG (b, c, d)
|
||||
|
||||
/* Round 2. */
|
||||
OP (A, B, C, D, 1, 5, (md5_uint32) 0xf61e2562);
|
||||
OP (D, A, B, C, 6, 9, (md5_uint32) 0xc040b340);
|
||||
OP (C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51);
|
||||
OP (B, C, D, A, 0, 20, (md5_uint32) 0xe9b6c7aa);
|
||||
OP (A, B, C, D, 5, 5, (md5_uint32) 0xd62f105d);
|
||||
OP (D, A, B, C, 10, 9, (md5_uint32) 0x02441453);
|
||||
OP (C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681);
|
||||
OP (B, C, D, A, 4, 20, (md5_uint32) 0xe7d3fbc8);
|
||||
OP (A, B, C, D, 9, 5, (md5_uint32) 0x21e1cde6);
|
||||
OP (D, A, B, C, 14, 9, (md5_uint32) 0xc33707d6);
|
||||
OP (C, D, A, B, 3, 14, (md5_uint32) 0xf4d50d87);
|
||||
OP (B, C, D, A, 8, 20, (md5_uint32) 0x455a14ed);
|
||||
OP (A, B, C, D, 13, 5, (md5_uint32) 0xa9e3e905);
|
||||
OP (D, A, B, C, 2, 9, (md5_uint32) 0xfcefa3f8);
|
||||
OP (C, D, A, B, 7, 14, (md5_uint32) 0x676f02d9);
|
||||
OP (B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a);
|
||||
|
||||
#undef FX
|
||||
#define FX(b, c, d) FH (b, c, d)
|
||||
|
||||
/* Round 3. */
|
||||
OP (A, B, C, D, 5, 4, (md5_uint32) 0xfffa3942);
|
||||
OP (D, A, B, C, 8, 11, (md5_uint32) 0x8771f681);
|
||||
OP (C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122);
|
||||
OP (B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c);
|
||||
OP (A, B, C, D, 1, 4, (md5_uint32) 0xa4beea44);
|
||||
OP (D, A, B, C, 4, 11, (md5_uint32) 0x4bdecfa9);
|
||||
OP (C, D, A, B, 7, 16, (md5_uint32) 0xf6bb4b60);
|
||||
OP (B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70);
|
||||
OP (A, B, C, D, 13, 4, (md5_uint32) 0x289b7ec6);
|
||||
OP (D, A, B, C, 0, 11, (md5_uint32) 0xeaa127fa);
|
||||
OP (C, D, A, B, 3, 16, (md5_uint32) 0xd4ef3085);
|
||||
OP (B, C, D, A, 6, 23, (md5_uint32) 0x04881d05);
|
||||
OP (A, B, C, D, 9, 4, (md5_uint32) 0xd9d4d039);
|
||||
OP (D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5);
|
||||
OP (C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8);
|
||||
OP (B, C, D, A, 2, 23, (md5_uint32) 0xc4ac5665);
|
||||
|
||||
#undef FX
|
||||
#define FX(b, c, d) FI (b, c, d)
|
||||
|
||||
/* Round 4. */
|
||||
OP (A, B, C, D, 0, 6, (md5_uint32) 0xf4292244);
|
||||
OP (D, A, B, C, 7, 10, (md5_uint32) 0x432aff97);
|
||||
OP (C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7);
|
||||
OP (B, C, D, A, 5, 21, (md5_uint32) 0xfc93a039);
|
||||
OP (A, B, C, D, 12, 6, (md5_uint32) 0x655b59c3);
|
||||
OP (D, A, B, C, 3, 10, (md5_uint32) 0x8f0ccc92);
|
||||
OP (C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d);
|
||||
OP (B, C, D, A, 1, 21, (md5_uint32) 0x85845dd1);
|
||||
OP (A, B, C, D, 8, 6, (md5_uint32) 0x6fa87e4f);
|
||||
OP (D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0);
|
||||
OP (C, D, A, B, 6, 15, (md5_uint32) 0xa3014314);
|
||||
OP (B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1);
|
||||
OP (A, B, C, D, 4, 6, (md5_uint32) 0xf7537e82);
|
||||
OP (D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235);
|
||||
OP (C, D, A, B, 2, 15, (md5_uint32) 0x2ad7d2bb);
|
||||
OP (B, C, D, A, 9, 21, (md5_uint32) 0xeb86d391);
|
||||
|
||||
/* Add the starting values of the context. */
|
||||
A += A_save;
|
||||
B += B_save;
|
||||
C += C_save;
|
||||
D += D_save;
|
||||
}
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->A = A;
|
||||
ctx->B = B;
|
||||
ctx->C = C;
|
||||
ctx->D = D;
|
||||
}
|
146
3d-viewer/3d_cache/md5.h
Normal file
146
3d-viewer/3d_cache/md5.h
Normal file
@ -0,0 +1,146 @@
|
||||
/* md5.h - Declaration of functions and data types used for MD5 sum
|
||||
computing library functions.
|
||||
|
||||
Copyright 1995, 1996, 2000 Free Software Foundation, Inc.
|
||||
NOTE: The canonical source of this file is maintained with the GNU C
|
||||
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
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, 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, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _MD5_H
|
||||
#define _MD5_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined HAVE_LIMITS_H || _LIBC
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
/* The following contortions are an attempt to use the C preprocessor
|
||||
to determine an unsigned integral type that is 32 bits wide. An
|
||||
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
|
||||
doing that would require that the configure script compile and *run*
|
||||
the resulting executable. Locally running cross-compiled executables
|
||||
is usually not possible.
|
||||
*/
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <sys/types.h>
|
||||
typedef u_int32_t md5_uint32;
|
||||
#else
|
||||
# define INT_MAX_32_BITS 2147483647
|
||||
|
||||
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
|
||||
This should be valid for all systems GNU cares about because
|
||||
that doesn't include 16-bit systems, and only modern systems
|
||||
(that certainly have <limits.h>) have 64+-bit integral types.
|
||||
*/
|
||||
|
||||
# ifndef INT_MAX
|
||||
# define INT_MAX INT_MAX_32_BITS
|
||||
# endif
|
||||
|
||||
# if INT_MAX == INT_MAX_32_BITS
|
||||
typedef unsigned int md5_uint32;
|
||||
# else
|
||||
# if SHRT_MAX == INT_MAX_32_BITS
|
||||
typedef unsigned short md5_uint32;
|
||||
# else
|
||||
# if LONG_MAX == INT_MAX_32_BITS
|
||||
typedef unsigned long md5_uint32;
|
||||
# else
|
||||
/* The following line is intended to evoke an error.
|
||||
* Using #error is not portable enough. */
|
||||
"Cannot determine unsigned 32-bit data type."
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#undef __P
|
||||
#if defined (__STDC__) && __STDC__
|
||||
#define __P(x) x
|
||||
#else
|
||||
#define __P(x) ()
|
||||
#endif
|
||||
|
||||
/* Structure to save state of computation between the single steps. */
|
||||
struct md5_ctx
|
||||
{
|
||||
md5_uint32 A;
|
||||
md5_uint32 B;
|
||||
md5_uint32 C;
|
||||
md5_uint32 D;
|
||||
|
||||
md5_uint32 total[2];
|
||||
md5_uint32 buflen;
|
||||
char buffer[128];
|
||||
};
|
||||
|
||||
/*
|
||||
* The following three functions are build up the low level used in
|
||||
* the functions `md5_stream' and `md5_buffer'.
|
||||
*/
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(RFC 1321, 3.3: Step 3) */
|
||||
extern void md5_init_ctx __P ((struct md5_ctx *ctx));
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is necessary that LEN is a multiple of 64!!! */
|
||||
extern void md5_process_block __P ((const void *buffer, size_t len,
|
||||
struct md5_ctx *ctx));
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is NOT required that LEN is a multiple of 64. */
|
||||
extern void md5_process_bytes __P ((const void *buffer, size_t len,
|
||||
struct md5_ctx *ctx));
|
||||
|
||||
/* Process the remaining bytes in the buffer and put result from CTX
|
||||
in first 16 bytes following RESBUF. The result is always in little
|
||||
endian byte order, so that a byte-wise output yields to the wanted
|
||||
ASCII representation of the message digest.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
|
||||
|
||||
|
||||
/* Put result from CTX in first 16 bytes following RESBUF. The result is
|
||||
always in little endian byte order, so that a byte-wise output yields
|
||||
to the wanted ASCII representation of the message digest.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
|
||||
|
||||
|
||||
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||
resulting message digest number will be written into the 16 bytes
|
||||
beginning at RESBLOCK. */
|
||||
extern int md5_stream __P ((FILE *stream, void *resblock));
|
||||
|
||||
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||
result is always in little endian byte order, so that a byte-wise
|
||||
output yields to the wanted ASCII representation of the message
|
||||
digest. */
|
||||
extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
|
||||
|
||||
#endif
|
55
3d-viewer/3d_cache/sg/CMakeLists.txt
Normal file
55
3d-viewer/3d_cache/sg/CMakeLists.txt
Normal file
@ -0,0 +1,55 @@
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
# ${CMAKE_SOURCE_DIR}/include/gal/opengl
|
||||
${CMAKE_SOURCE_DIR}/3d-viewer
|
||||
)
|
||||
|
||||
|
||||
add_library( s3d_sg SHARED
|
||||
sg_base.cpp
|
||||
sg_node.cpp
|
||||
sg_helpers.cpp
|
||||
scenegraph.cpp
|
||||
sg_appearance.cpp
|
||||
sg_faceset.cpp
|
||||
sg_shape.cpp
|
||||
sg_colors.cpp
|
||||
sg_coords.cpp
|
||||
sg_normals.cpp
|
||||
sg_index.cpp
|
||||
sg_colorindex.cpp
|
||||
sg_coordindex.cpp
|
||||
ifsg_node.cpp
|
||||
ifsg_transform.cpp
|
||||
ifsg_appearance.cpp
|
||||
ifsg_index.cpp
|
||||
ifsg_colorindex.cpp
|
||||
ifsg_coordindex.cpp
|
||||
ifsg_colors.cpp
|
||||
ifsg_coords.cpp
|
||||
ifsg_faceset.cpp
|
||||
ifsg_normals.cpp
|
||||
ifsg_shape.cpp
|
||||
ifsg_api.cpp
|
||||
)
|
||||
|
||||
if( MSVC )
|
||||
# Define a flag to expose the appropriate SG_DLL macro at build time
|
||||
target_compile_definitions( s3d_sg PRIVATE -DDLL_SGIF )
|
||||
endif()
|
||||
|
||||
target_link_libraries( s3d_sg ${wxWidgets_LIBRARIES} )
|
||||
|
||||
if( APPLE )
|
||||
install( TARGETS
|
||||
s3d_sg
|
||||
DESTINATION /Applications/kicad.app/SharedSupport
|
||||
COMPONENT binary
|
||||
)
|
||||
else()
|
||||
install( TARGETS
|
||||
s3d_sg
|
||||
DESTINATION lib/kicad
|
||||
COMPONENT binary
|
||||
)
|
||||
endif()
|
149
3d-viewer/3d_cache/sg/api_sg_node.cpp
Normal file
149
3d-viewer/3d_cache/sg/api_sg_node.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 "sg_api.h"
|
||||
#include "sg_node.h"
|
||||
|
||||
S3D::API_SGNODE::API_SGNODE()
|
||||
{
|
||||
node = NULL;
|
||||
nodeType = SGTYPE_END; // signal an invalid type by default
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* S3D::API_SGNODE::GetNode( void )
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::AttachNode( SGNODE* aNode )
|
||||
{
|
||||
if( NULL == aNode )
|
||||
{
|
||||
node = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( aNode->GetNodeType() != nodeType )
|
||||
{
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
std::cerr << " * [BUG] object with node type " << aNode->GetNodeType();
|
||||
std::cerr << " is being attached to API node type " << nodeType << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
node = aNode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::GetNodeType( S3D::SGTYPES& aNodeType ) const
|
||||
{
|
||||
if( NULL == node )
|
||||
{
|
||||
aNodeType = SGTYPE_END;
|
||||
return false;
|
||||
}
|
||||
|
||||
aNodeType = node->GetNodeType();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::GetParent( SGNODE const*& aParent ) const
|
||||
{
|
||||
if( NULL == node )
|
||||
{
|
||||
aParent = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aParent = node->GetParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::SetParent( SGNODE* aParent )
|
||||
{
|
||||
if( NULL == node )
|
||||
return false;
|
||||
|
||||
return node->SetParent( aParent );
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::GetName( const char*& aName )
|
||||
{
|
||||
if( NULL == node )
|
||||
{
|
||||
aName = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aName = node->GetName();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::SetName( const char *aName )
|
||||
{
|
||||
if( NULL == node )
|
||||
return false;
|
||||
|
||||
node->SetName( aName );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType, const char*& aName ) const
|
||||
{
|
||||
if( NULL == node )
|
||||
{
|
||||
aName = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aName = node->GetNodeTypeName( aNodeType );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::API_SGNODE::FindNode( const char *aNodeName, const SGNODE *aCaller, SGNODE*& aNode )
|
||||
{
|
||||
if( NULL == node )
|
||||
{
|
||||
aNode = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
aNode = node->FindNode( aNodeName, aCaller );
|
||||
|
||||
if( NULL == aNode )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
26
3d-viewer/3d_cache/sg/api_sg_transform.cpp
Normal file
26
3d-viewer/3d_cache/sg/api_sg_transform.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 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 <3d_cache/sg/sg_api.h>
|
||||
|
||||
XXX - TO BE IMPLEMENTED
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user