From 8eef368d45fe9237e5e37dd5309aa4d4ec0c1b51 Mon Sep 17 00:00:00 2001
From: Amorilia <amorilia@users.sourceforge.net>
Date: Fri, 23 Mar 2007 08:44:57 +0000
Subject: [PATCH] * modularized swig interface to reduce wrapper size (only
 main niflib   header and NiNode for now)

* created a common swig interface "common.i" to be used by all modules

* smart pointers now use the __call__() method, again this reduces the
  wrapper size

* removed __str__() from the niflib API as it does not belong there,
  instead renamed asString() to __str__() in the common.i interface

* version constants now also belong to the Niflib namespace

* SWIGFLAGS are now defined through scons environment, so we only need
  to set them once

* extra settings "-fcompact" and "-fvirtual" to SWIGFLAGS to reduce
  wrapper size

* enabled niflib as a shared library under non-win32 platforms
  (still need to find a solution for win32) under scons

* removed "pyniflib.h" and instead added CreateNiNode wrapper to ninode.i

* renamed "pyniflib.i" to "pyniflib.i_old" in case I forgot to port
  something to the new modularized system; to be removed in future
---
 SConstruct                          |  21 +-
 include/nif_versions.h              |   4 +
 include/obj/NiObject.h              |   5 -
 swig/SConscript                     |   5 +-
 swig/common.i                       | 370 ++++++++++++++++++++++++++++
 swig/niflib.i                       | 133 ++++++++++
 swig/ninode.i                       |  58 +++++
 swig/pyniflib.h                     |  16 --
 swig/{pyniflib.i => pyniflib.i_old} |   0
 test/SConscript                     |   4 +-
 test/niflib_test.py                 |   9 +-
 11 files changed, 589 insertions(+), 36 deletions(-)
 create mode 100644 swig/common.i
 create mode 100644 swig/niflib.i
 create mode 100644 swig/ninode.i
 delete mode 100644 swig/pyniflib.h
 rename swig/{pyniflib.i => pyniflib.i_old} (100%)

diff --git a/SConstruct b/SConstruct
index 7f9c1079..30768285 100644
--- a/SConstruct
+++ b/SConstruct
@@ -15,7 +15,7 @@ JOBS = 1                      # default number of jobs, if detection fails
 DETECT_JOBS = True            # set this to False, if you are setting JOBS
 DEBUG = True                  # turn on debugging info?
 CFFLAGS_EXTRA_WARNING = False # extra compiler warnings
-PYWRAP = True                 # build the python wrapper?
+SWIG = True                   # build the swig python wrapper?
 TEST = True                   # build test scripts?
 
 # Setting up a basic default environment
@@ -23,6 +23,8 @@ TEST = True                   # build test scripts?
 
 env = Environment(ENV = os.environ)
 
+env.Append(SWIGFLAGS = ' -c++ -python -fcompact -fvirtual')
+
 # linux platform
 if sys.platform in ['linux2', 'linux-i386', 'cygwin']:
     # set python environment
@@ -59,7 +61,7 @@ if sys.platform in ['linux2', 'linux-i386', 'cygwin']:
                env.Append(CCFLAGS = ' -mtune=k8')
            #elif commands.getoutput('uname -i') == 'GenuineIntel':
            #    env.Append(CCFLAGS = ' -mtune=nocona')
-    # detect the number of jobs
+    # detect the number of processors, and set number of jobs accordingly
     if DETECT_JOBS:
         detected_jobs = int(commands.getoutput('cat /proc/cpuinfo | grep -c "^processor"'))
         if detected_jobs >= 2:
@@ -88,7 +90,7 @@ env.SetOption('num_jobs', JOBS)
 try:
     env['SWIG']
 except KeyError:
-    PYWRAP = False
+    SWIG = False
     print """
 Warning: SWIG not found. The python wrapper will not be built.
 Please install SWIG to build the python wrapper."""
@@ -382,17 +384,20 @@ blender/blender_niflib.cpp
 """)
 
 # build niflib shared library
-# (SCons bug: SharedLibrary should also build .lib file, but this is broken; so for now just build static one)
-niflib = env.StaticLibrary('niflib', [core_objfiles, gen_objfiles, obj_objfiles, NvTriStrip_files, TriStripper_files] , LIBPATH='.', CPPPATH = '.')
+# (SCons bug: under windows, SharedLibrary should also build .lib file, but this is broken; so for now just build static one)
+if sys.platform == 'win32':
+    niflib = env.StaticLibrary('niflib', [core_objfiles, gen_objfiles, obj_objfiles, NvTriStrip_files, TriStripper_files] , LIBPATH='.', CPPPATH = '.')
+else:
+    niflib = env.SharedLibrary('niflib', [core_objfiles, gen_objfiles, obj_objfiles, NvTriStrip_files, TriStripper_files] , LIBPATH='.', CPPPATH = '.')
 
 Export('env python_lib python_libpath python_include niflib')
 
-# build Python wrapper
-if PYWRAP:
+# build python wrapper
+if SWIG:
     niflib_swig = SConscript('swig/SConscript')
     Export('niflib_swig')
 
-# A test program:
+# build the test suite
 if TEST:
     SConscript('test/SConscript')
 
diff --git a/include/nif_versions.h b/include/nif_versions.h
index a37724b2..4aa85c23 100644
--- a/include/nif_versions.h
+++ b/include/nif_versions.h
@@ -6,6 +6,8 @@ All rights reserved.  Please see niflib.h for licence. */
 
 //NIF Version Constants
 
+namespace Niflib {
+
 const unsigned VER_3_1         = 0x03010000; /*!< NIF Version 3.3.0.13 */
 const unsigned VER_3_3_0_13    = 0x0303000D; /*!< NIF Version 3.3.0.13 */
 const unsigned VER_4_0_0_0     = 0x04000000; /*!< NIF Version 4.0.0.0 */
@@ -23,4 +25,6 @@ const unsigned VER_20_0_0_5    = 0x14000005; /*!< NIF Version 20.0.0.4 */
 const unsigned VER_UNSUPPORTED = 0xFFFFFFFF; /*!< Unsupported NIF Version */
 const unsigned VER_INVALID     = 0xFFFFFFFE; /*!< Not a NIF file */
 
+}
+
 #endif
diff --git a/include/obj/NiObject.h b/include/obj/NiObject.h
index d0cca61b..efb9a584 100644
--- a/include/obj/NiObject.h
+++ b/include/obj/NiObject.h
@@ -128,11 +128,6 @@ public:
 	 */
 	NIFLIB_API virtual list<NiObjectRef> GetRefs() const;
 	
-	// Python Operator Overloads
-	NIFLIB_API string __str__() const {
-		return asString();
-	};
-
 	NIFLIB_API virtual void RemoveCrossRef( NiObject * block_to_remove );
 
 	NIFLIB_API void IncCrossRef( NiObject * block );
diff --git a/swig/SConscript b/swig/SConscript
index b6d2575c..4d604be0 100644
--- a/swig/SConscript
+++ b/swig/SConscript
@@ -1,5 +1,6 @@
 Import('*')
 
-niflib_python = env.SharedLibrary('_niflib', 'pyniflib.i', LIBS=[niflib] + python_lib, LIBPATH = python_libpath, SWIGFLAGS = '-c++ -python', CPPPATH = ['.'] + python_include, SHLIBPREFIX='')
+niflib_python = env.SharedLibrary('_niflib', 'niflib.i', LIBS=[niflib] + python_lib, LIBPATH = python_libpath, CPPPATH = ['.'] + python_include, SHLIBPREFIX='')
+ninode_python = env.SharedLibrary('_ninode', 'ninode.i', LIBS=[niflib] + python_lib, LIBPATH = python_libpath, CPPPATH = ['.'] + python_include, SHLIBPREFIX='')
 
-Return('niflib_python')
+Return('niflib_python ninode_python')
diff --git a/swig/common.i b/swig/common.i
new file mode 100644
index 00000000..22f384aa
--- /dev/null
+++ b/swig/common.i
@@ -0,0 +1,370 @@
+// Swig module description file for a C dynamic library source file
+// This header contains all the nifty details.
+
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above
+     copyright notice, this list of conditions and the following
+     disclaimer in the documentation and/or other materials provided
+     with the distribution.
+
+   * Neither the name of the NIF File Format Library and Tools
+     project nor the names of its contributors may be used to endorse
+     or promote products derived from this software without specific
+     prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+%include "stl.i"
+%include "std_map.i"
+%include "exception.i"
+%include "std_list.i"
+%include "typemaps.i"
+
+// enable string assignment in structure member functions
+%typemap(in) std::string* ($*1_ltype tempstr) {
+  char * temps; int templ;
+   if (PyString_AsStringAndSize($input, &temps, &templ)) return NULL;
+   tempstr = $*1_ltype(temps, templ);
+   $1 = &tempstr;
+}
+%typemap(out) std::string* "$result = PyString_FromStringAndSize($1->data(), $1->length());";
+
+// we need a version of SWIG that has SWIG_CATCH_STDEXCEPT support
+#if SWIG_VERSION >= 0x010322
+%exception {
+  try {
+    $action
+  }
+  SWIG_CATCH_STDEXCEPT // catch std::exception
+  catch (...) {
+    SWIG_exception(SWIG_UnknownError, "Unknown exception");
+  }
+}
+#endif
+
+// print
+%rename(__str__) asString;
+
+// smart pointers via "()."
+%rename(__call__) Ptr;
+
+//Ignore the const versions of these functions
+%ignore Niflib::DynamicCast( const Niflib::NiObject * object );
+%ignore Niflib::StaticCast ( const Niflib::NiObject * object );
+
+//Do not use smart pointer support as it doubles the size of the library
+//and makes it take twice as long to be imported.
+%ignore Niflib::Ref::operator->;
+%ignore Niflib::Ref::operator=;
+
+// At the moment, let us ignore some common functions that are
+// not essential for NIF manipulating scripts.
+// This will reduce the size of the wrapper file.
+
+%ignore FixLinks;
+%ignore Read;
+%ignore Write;
+%ignore operator=;
+%ignore operator[];
+%ignore TypeConst;
+%ignore GetIDString;
+%ignore IsSameType;
+%ignore IsDerivedType;
+%ignore NumObjectsInMemory;
+
+// ignore things swig complains about
+// (TODO)
+
+// Import the symbols from these but do not include them in the wrapper
+%import "../include/gen/obj_defines.h"
+%import "../include/NIF_IO.h"
+%import "../include/dll_export.h"
+%import "../include/Type.h"
+
+%{
+// main header file
+#include "../include/niflib.h"
+
+// SWIG is very picky about namespaces. Using namespace Niflib throughout
+// ensures that SWIG wraps all types in the right way.
+using namespace Niflib;
+
+// auxilary header files
+#include "../include/Ref.h"
+#include "../include/Type.h"
+#include "../include/nif_math.h"
+#include "../include/gen/obj_defines.h"
+#include "../include/obj/NiObject.h"
+#include "../include/obj/AKeyedData.h"
+#include "../include/obj/AParticleModifier.h"
+#include "../include/obj/bhkRefObject.h"
+#include "../include/obj/bhkSerializable.h"
+#include "../include/obj/AbhkConstraint.h"
+#include "../include/obj/AbhkRagdollConstraint.h"
+#include "../include/obj/bhkShape.h"
+#include "../include/obj/AbhkShapeCollection.h"
+#include "../include/obj/bhkSphereRepShape.h"
+#include "../include/obj/bhkConvexShape.h"
+#include "../include/obj/bhkWorldObject.h"
+#include "../include/obj/bhkEntity.h"
+#include "../include/obj/NiCollisionObject.h"
+#include "../include/obj/NiExtraData.h"
+#include "../include/obj/NiInterpolator.h"
+#include "../include/obj/NiBlendInterpolator.h"
+#include "../include/obj/NiBSplineInterpolator.h"
+#include "../include/obj/NiObjectNET.h"
+#include "../include/obj/NiAVObject.h"
+#include "../include/obj/NiDynamicEffect.h"
+#include "../include/obj/NiLight.h"
+#include "../include/obj/NiProperty.h"
+#include "../include/obj/NiPSysModifier.h"
+#include "../include/obj/NiPSysEmitter.h"
+#include "../include/obj/NiPSysVolumeEmitter.h"
+#include "../include/obj/NiTimeController.h"
+#include "../include/obj/ABoneLODController.h"
+#include "../include/obj/NiSingleInterpolatorController.h"
+#include "../include/obj/APSysCtlr.h"
+#include "../include/obj/NiGeometry.h"
+#include "../include/obj/NiTriBasedGeom.h"
+#include "../include/obj/NiGeometryData.h"
+#include "../include/obj/NiTriBasedGeomData.h"
+#include "../include/obj/APSysData.h"
+#include "../include/obj/bhkBlendCollisionObject.h"
+#include "../include/obj/bhkBlendController.h"
+#include "../include/obj/bhkBoxShape.h"
+#include "../include/obj/bhkCapsuleShape.h"
+#include "../include/obj/bhkCollisionObject.h"
+#include "../include/obj/bhkConvexVerticesShape.h"
+#include "../include/obj/bhkHingeConstraint.h"
+#include "../include/obj/bhkLimitedHingeConstraint.h"
+#include "../include/obj/bhkListShape.h"
+#include "../include/obj/bhkMalleableConstraint.h"
+#include "../include/obj/bhkMoppBvTreeShape.h"
+#include "../include/obj/bhkMultiSphereShape.h"
+#include "../include/obj/bhkNiTriStripsShape.h"
+#include "../include/obj/bhkPackedNiTriStripsShape.h"
+#include "../include/obj/bhkPrismaticConstraint.h"
+#include "../include/obj/bhkRagdollConstraint.h"
+#include "../include/obj/bhkRigidBody.h"
+#include "../include/obj/bhkRigidBodyT.h"
+#include "../include/obj/bhkSimpleShapePhantom.h"
+#include "../include/obj/bhkSPCollisionObject.h"
+#include "../include/obj/bhkSphereShape.h"
+#include "../include/obj/bhkStiffSpringConstraint.h"
+#include "../include/obj/bhkTransformShape.h"
+#include "../include/obj/bhkConvexTransformShape.h"
+#include "../include/obj/BSBound.h"
+#include "../include/obj/BSFurnitureMarker.h"
+#include "../include/obj/BSParentVelocityModifier.h"
+#include "../include/obj/BSPSysArrayEmitter.h"
+#include "../include/obj/BSXFlags.h"
+#include "../include/obj/hkPackedNiTriStripsData.h"
+#include "../include/obj/NiAlphaController.h"
+#include "../include/obj/NiAlphaProperty.h"
+#include "../include/obj/NiAmbientLight.h"
+#include "../include/obj/NiAutoNormalParticlesData.h"
+#include "../include/obj/NiBinaryExtraData.h"
+#include "../include/obj/NiBlendBoolInterpolator.h"
+#include "../include/obj/NiBlendFloatInterpolator.h"
+#include "../include/obj/NiBlendPoint3Interpolator.h"
+#include "../include/obj/NiBlendTransformInterpolator.h"
+#include "../include/obj/NiBoneLODController.h"
+#include "../include/obj/NiBoolData.h"
+#include "../include/obj/NiBooleanExtraData.h"
+#include "../include/obj/NiBoolInterpolator.h"
+#include "../include/obj/NiBoolTimelineInterpolator.h"
+#include "../include/obj/NiBSBoneLODController.h"
+#include "../include/obj/NiBSplineBasisData.h"
+#include "../include/obj/NiBSplineCompFloatInterpolator.h"
+#include "../include/obj/NiBSplineCompPoint3Interpolator.h"
+#include "../include/obj/NiBSplineCompTransformInterpolator.h"
+#include "../include/obj/NiBSplineData.h"
+#include "../include/obj/NiCamera.h"
+#include "../include/obj/NiCollisionData.h"
+#include "../include/obj/NiColorData.h"
+#include "../include/obj/NiColorExtraData.h"
+#include "../include/obj/NiControllerManager.h"
+#include "../include/obj/NiControllerSequence.h"
+#include "../include/obj/NiDefaultAVObjectPalette.h"
+#include "../include/obj/NiDirectionalLight.h"
+#include "../include/obj/NiDitherProperty.h"
+#include "../include/obj/NiFlipController.h"
+#include "../include/obj/NiFloatData.h"
+#include "../include/obj/NiFloatExtraData.h"
+#include "../include/obj/NiFloatExtraDataController.h"
+#include "../include/obj/NiFloatInterpolator.h"
+#include "../include/obj/NiFloatsExtraData.h"
+#include "../include/obj/NiFogProperty.h"
+#include "../include/obj/NiGeomMorpherController.h"
+#include "../include/obj/NiGravity.h"
+#include "../include/obj/NiIntegerExtraData.h"
+#include "../include/obj/NiIntegersExtraData.h"
+#include "../include/obj/NiKeyframeController.h"
+#include "../include/obj/BSKeyframeController.h"
+#include "../include/obj/NiKeyframeData.h"
+#include "../include/obj/NiLightColorController.h"
+#include "../include/obj/NiLightDimmerController.h"
+#include "../include/obj/NiLookAtController.h"
+#include "../include/obj/NiLookAtInterpolator.h"
+#include "../include/obj/NiMaterialColorController.h"
+#include "../include/obj/NiMaterialProperty.h"
+#include "../include/obj/NiMeshPSysData.h"
+#include "../include/obj/NiMorphData.h"
+#include "../include/obj/NiMultiTargetTransformController.h"
+#include "../include/obj/NiNode.h"
+#include "../include/obj/AvoidNode.h"
+#include "../include/obj/FxWidget.h"
+#include "../include/obj/FxButton.h"
+#include "../include/obj/FxRadioButton.h"
+#include "../include/obj/NiBillboardNode.h"
+#include "../include/obj/NiBSAnimationNode.h"
+#include "../include/obj/NiBSParticleNode.h"
+#include "../include/obj/NiLODNode.h"
+#include "../include/obj/NiPalette.h"
+#include "../include/obj/NiParticleBomb.h"
+#include "../include/obj/NiParticleColorModifier.h"
+#include "../include/obj/NiParticleGrowFade.h"
+#include "../include/obj/NiParticleMeshModifier.h"
+#include "../include/obj/NiParticleRotation.h"
+#include "../include/obj/NiParticles.h"
+#include "../include/obj/NiAutoNormalParticles.h"
+#include "../include/obj/NiParticleMeshes.h"
+#include "../include/obj/NiParticlesData.h"
+#include "../include/obj/NiParticleMeshesData.h"
+#include "../include/obj/NiParticleSystem.h"
+#include "../include/obj/NiMeshParticleSystem.h"
+#include "../include/obj/NiParticleSystemController.h"
+#include "../include/obj/NiBSPArrayController.h"
+#include "../include/obj/NiPathController.h"
+#include "../include/obj/NiPathInterpolator.h"
+#include "../include/obj/NiPixelData.h"
+#include "../include/obj/NiPlanarCollider.h"
+#include "../include/obj/NiPoint3Interpolator.h"
+#include "../include/obj/NiPointLight.h"
+#include "../include/obj/NiPosData.h"
+#include "../include/obj/NiPSysAgeDeathModifier.h"
+#include "../include/obj/NiPSysBombModifier.h"
+#include "../include/obj/NiPSysBoundUpdateModifier.h"
+#include "../include/obj/NiPSysBoxEmitter.h"
+#include "../include/obj/NiPSysColliderManager.h"
+#include "../include/obj/NiPSysColorModifier.h"
+#include "../include/obj/NiPSysCylinderEmitter.h"
+#include "../include/obj/NiPSysData.h"
+#include "../include/obj/NiPSysDragModifier.h"
+#include "../include/obj/NiPSysEmitterCtlr.h"
+#include "../include/obj/NiPSysEmitterCtlrData.h"
+#include "../include/obj/NiPSysEmitterDeclinationCtlr.h"
+#include "../include/obj/NiPSysEmitterDeclinationVarCtlr.h"
+#include "../include/obj/NiPSysEmitterInitialRadiusCtlr.h"
+#include "../include/obj/NiPSysEmitterLifeSpanCtlr.h"
+#include "../include/obj/NiPSysEmitterSpeedCtlr.h"
+#include "../include/obj/NiPSysGravityModifier.h"
+#include "../include/obj/NiPSysGravityStrengthCtlr.h"
+#include "../include/obj/NiPSysGrowFadeModifier.h"
+#include "../include/obj/NiPSysMeshEmitter.h"
+#include "../include/obj/NiPSysMeshUpdateModifier.h"
+#include "../include/obj/NiPSysModifierActiveCtlr.h"
+#include "../include/obj/NiPSysPlanarCollider.h"
+#include "../include/obj/NiPSysPositionModifier.h"
+#include "../include/obj/NiPSysResetOnLoopCtlr.h"
+#include "../include/obj/NiPSysRotationModifier.h"
+#include "../include/obj/NiPSysSpawnModifier.h"
+#include "../include/obj/NiPSysSphereEmitter.h"
+#include "../include/obj/NiPSysUpdateCtlr.h"
+#include "../include/obj/NiLODData.h"
+#include "../include/obj/NiRangeLODData.h"
+#include "../include/obj/NiScreenLODData.h"
+#include "../include/obj/NiRotatingParticles.h"
+#include "../include/obj/NiRotatingParticlesData.h"
+#include "../include/obj/NiSequenceStreamHelper.h"
+#include "../include/obj/NiShadeProperty.h"
+#include "../include/obj/NiSkinData.h"
+#include "../include/obj/NiSkinInstance.h"
+#include "../include/obj/NiClodSkinInstance.h"
+#include "../include/obj/NiSkinPartition.h"
+#include "../include/obj/NiSourceTexture.h"
+#include "../include/obj/NiSpecularProperty.h"
+#include "../include/obj/NiSphericalCollider.h"
+#include "../include/obj/NiSpotLight.h"
+#include "../include/obj/NiStencilProperty.h"
+#include "../include/obj/NiStringExtraData.h"
+#include "../include/obj/NiStringPalette.h"
+#include "../include/obj/NiStringsExtraData.h"
+#include "../include/obj/NiTextKeyExtraData.h"
+#include "../include/obj/NiTextureEffect.h"
+#include "../include/obj/NiTextureTransformController.h"
+#include "../include/obj/NiTextureModeProperty.h"
+#include "../include/obj/NiImage.h"
+#include "../include/obj/NiTextureProperty.h"
+#include "../include/obj/NiTexturingProperty.h"
+#include "../include/obj/NiTransformController.h"
+#include "../include/obj/NiTransformData.h"
+#include "../include/obj/NiTransformInterpolator.h"
+#include "../include/obj/NiTriShape.h"
+#include "../include/obj/NiTriShapeData.h"
+#include "../include/obj/NiTriStrips.h"
+#include "../include/obj/NiTriStripsData.h"
+#include "../include/obj/NiClod.h"
+#include "../include/obj/NiClodData.h"
+#include "../include/obj/NiUVController.h"
+#include "../include/obj/NiUVData.h"
+#include "../include/obj/NiVectorExtraData.h"
+#include "../include/obj/NiVertexColorProperty.h"
+#include "../include/obj/NiVertWeightsExtraData.h"
+#include "../include/obj/NiVisController.h"
+#include "../include/obj/NiVisData.h"
+#include "../include/obj/NiWireframeProperty.h"
+#include "../include/obj/NiZBufferProperty.h"
+#include "../include/obj/RootCollisionNode.h"
+#include "../include/gen/ByteArray.h"
+#include "../include/gen/Footer.h"
+#include "../include/gen/LODRange.h"
+#include "../include/gen/MatchGroup.h"
+#include "../include/gen/MipMap.h"
+#include "../include/gen/NodeGroup.h"
+#include "../include/gen/QuaternionXYZW.h"
+#include "../include/gen/SkinShape.h"
+#include "../include/gen/SkinShapeGroup.h"
+#include "../include/gen/SkinWeight.h"
+#include "../include/gen/AVObject.h"
+#include "../include/gen/ControllerLink.h"
+#include "../include/gen/Header.h"
+#include "../include/gen/StringPalette.h"
+#include "../include/gen/TBC.h"
+#include "../include/gen/KeyGroup.h"
+#include "../include/gen/RotationKeyArray.h"
+#include "../include/gen/TexDesc.h"
+#include "../include/gen/ShaderTexDesc.h"
+#include "../include/gen/TexSource.h"
+#include "../include/gen/SkinPartition.h"
+#include "../include/gen/BoundingBox.h"
+#include "../include/gen/FurniturePosition.h"
+#include "../include/gen/hkTriangle.h"
+#include "../include/gen/Morph.h"
+#include "../include/gen/Particle.h"
+#include "../include/gen/SkinData.h"
+#include "../include/gen/Sphere.h"
+#include "../include/gen/RagDollDescriptor.h"
+#include "../include/gen/LimitedHingeDescriptor.h"
+%}
+
diff --git a/swig/niflib.i b/swig/niflib.i
new file mode 100644
index 00000000..dfe74fdb
--- /dev/null
+++ b/swig/niflib.i
@@ -0,0 +1,133 @@
+// Swig module description file for a C dynamic library source file
+// Generate with: swig -c++ -python -o py_wrap.cpp niflib.i
+
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above
+     copyright notice, this list of conditions and the following
+     disclaimer in the documentation and/or other materials provided
+     with the distribution.
+
+   * Neither the name of the NIF File Format Library and Tools
+     project nor the names of its contributors may be used to endorse
+     or promote products derived from this software without specific
+     prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+%module niflib
+
+// a few common things are defined in a seperate file
+// to avoid cluttering up the main interface file
+
+%include "common.i"
+
+// expose headers (templates first)
+
+%include "../include/Key.h"
+%include "../include/Ref.h"
+%include "../include/niflib.h"
+%include "../include/nif_versions.h"
+%include "../include/nif_math.h"
+
+// data structures
+
+%include "../include/gen/ByteArray.h"
+%include "../include/gen/Footer.h"
+%include "../include/gen/LODRange.h"
+%include "../include/gen/MatchGroup.h"
+%include "../include/gen/MipMap.h"
+%include "../include/gen/NodeGroup.h"
+%include "../include/gen/QuaternionXYZW.h"
+%include "../include/gen/SkinShape.h"
+%include "../include/gen/SkinShapeGroup.h"
+%include "../include/gen/SkinWeight.h"
+%include "../include/gen/AVObject.h"
+%include "../include/gen/ControllerLink.h"
+%include "../include/gen/Header.h"
+%include "../include/gen/StringPalette.h"
+%include "../include/gen/TBC.h"
+%include "../include/gen/KeyGroup.h"
+%include "../include/gen/RotationKeyArray.h"
+%include "../include/gen/TexDesc.h"
+%include "../include/gen/ShaderTexDesc.h"
+%include "../include/gen/TexSource.h"
+%include "../include/gen/SkinPartition.h"
+%include "../include/gen/BoundingBox.h"
+%include "../include/gen/FurniturePosition.h"
+%include "../include/gen/hkTriangle.h"
+%include "../include/gen/Morph.h"
+%include "../include/gen/Particle.h"
+%include "../include/gen/SkinData.h"
+%include "../include/gen/Sphere.h"
+%include "../include/gen/RagDollDescriptor.h"
+%include "../include/gen/LimitedHingeDescriptor.h"
+
+// essential file blocks
+
+%include "../include/obj/NiObject.h"
+%include "../include/obj/NiObjectNET.h"
+%include "../include/obj/NiAVObject.h"
+%include "../include/obj/NiNode.h"
+%include "../include/obj/NiControllerSequence.h"
+
+// essential templates
+
+%template(NiObjectRef) Niflib::Ref<Niflib::NiObject>;
+%template(NiObjectNETRef) Niflib::Ref<Niflib::NiObjectNET>;
+%template(NiAVObjectRef) Niflib::Ref<Niflib::NiAVObject>;
+%template(NiNodeRef) Niflib::Ref<Niflib::NiNode>;
+%template(vector_NiObjectRef) std::vector<Niflib::NiObjectRef>; // for ReadNifList
+/*
+%template(vector_byte) std::vector<Niflib::byte>;
+%template(vector_ushort) std::vector<unsigned short>;
+%template(vector_SkinShape) std::vector<Niflib::SkinShape>;
+%template(vector_LineString) std::vector<Niflib::LineString>;
+%template(vector_string) std::vector<std::string>;
+%template(vector_Triangle) std::vector<Niflib::Triangle>;
+%template(vector_Vector3) std::vector<Niflib::Vector3>;
+%template(vector_SkinWeight) std::vector<Niflib::SkinWeight>;
+%template(vector_uint) std::vector<unsigned int>;
+%template(vector_NodeGroup) std::vector<Niflib::NodeGroup>;
+%template(vector_Color4) std::vector<Niflib::Color4>;
+%template(vector_float) std::vector<float>;
+%template(vector_Float4) std::vector<Niflib::Float4>;
+%template(vector_Sphere) std::vector<Niflib::Sphere>;
+%template(vector_FurniturePosition) std::vector<Niflib::FurniturePosition>;
+%template(vector_hkTriangle) std::vector<Niflib::hkTriangle>;
+%template(vector_SkinShapeGroup) std::vector<Niflib::SkinShapeGroup>;
+%template(vector_short) std::vector<short>;
+%template(vector_ControllerLink) std::vector<Niflib::ControllerLink>;
+%template(vector_AVObject) std::vector<Niflib::AVObject>;
+%template(vector_Morph) std::vector<Niflib::Morph>;
+%template(vector_LODRange) std::vector<Niflib::LODRange>;
+%template(vector_Quaternion) std::vector<Niflib::Quaternion>;
+%template(vector_Particle) std::vector<Niflib::Particle>;
+%template(vector_MipMap) std::vector<Niflib::MipMap>;
+%template(vector_SkinData) std::vector<Niflib::SkinData>;
+%template(vector_SkinPartition) std::vector<Niflib::SkinPartition>;
+%template(vector_ShaderTexDesc) std::vector<Niflib::ShaderTexDesc>;
+%template(vector_MatchGroup) std::vector<Niflib::MatchGroup>;
+%template(pair_int_float) std::pair<int, float>;
+%template(map_int_float) std::map<int, float>;
+*/
+
diff --git a/swig/ninode.i b/swig/ninode.i
new file mode 100644
index 00000000..2fa40236
--- /dev/null
+++ b/swig/ninode.i
@@ -0,0 +1,58 @@
+/* Copyright (c) 2006, NIF File Format Library and Tools
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above
+     copyright notice, this list of conditions and the following
+     disclaimer in the documentation and/or other materials provided
+     with the distribution.
+
+   * Neither the name of the NIF File Format Library and Tools
+     project nor the names of its contributors may be used to endorse
+     or promote products derived from this software without specific
+     prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+%module(package="niflib") ninode
+%include "common.i"
+%import "niflib.i"
+
+/*** already defined in niflib.i
+%import "../include/obj/NiObject.h"
+%import "../include/obj/NiObjectNET.h"
+%import "../include/obj/NiAVObject.h"
+%include "../include/obj/NiNode.h"
+%template(NiNodeRef) Niflib::Ref<Niflib::NiNode>;
+***/
+
+// create a new NiNode block
+%{
+Niflib::NiNodeRef CreateNiNode() {
+  return Niflib::NiNodeRef(new Niflib::NiNode);
+}
+%}
+// now wrap it
+Niflib::NiNodeRef CreateNiNode();
+
+// template functions to cast a NiObjectRef to a NiNodeRef
+%template(DynamicCastToNiNode) Niflib::DynamicCast<Niflib::NiNode>;
+%template(StaticCastToNiNode) Niflib::StaticCast<Niflib::NiNode>;
+
diff --git a/swig/pyniflib.h b/swig/pyniflib.h
deleted file mode 100644
index 4ebb00d5..00000000
--- a/swig/pyniflib.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _PYNIFLIB_H_
-#define _PYNIFLIB_H_
-
-#include "../include/niflib.h"
-#include "../include/obj/NiObject.h"
-#include "../include/obj/NiNode.h"
-
-namespace Niflib {
-
-using namespace std;
-
-Niflib::NiNodeRef CreateNiNode() { return Niflib::NiNodeRef(new Niflib::NiNode); }
-
-};
-
-#endif
diff --git a/swig/pyniflib.i b/swig/pyniflib.i_old
similarity index 100%
rename from swig/pyniflib.i
rename to swig/pyniflib.i_old
diff --git a/test/SConscript b/test/SConscript
index d27ee0e4..ea1afe41 100644
--- a/test/SConscript
+++ b/test/SConscript
@@ -1,4 +1,6 @@
 Import('*')
 env.Program('test', 'test.cpp', LIBS=[niflib], LIBPATH=['.'])
-env.Install('.', niflib_swig)
+for lib in niflib_swig:
+    env.Install('.', lib)
 env.Install('.', '#/swig/niflib.py') # workaround for SCons bug
+env.Install('.', '#/swig/ninode.py') # workaround for SCons bug
diff --git a/test/niflib_test.py b/test/niflib_test.py
index c0262e38..5e7a4798 100644
--- a/test/niflib_test.py
+++ b/test/niflib_test.py
@@ -3,6 +3,7 @@
 import unittest
 import os
 from niflib import *
+from ninode import *
 
 class TestNiNode(unittest.TestCase):
     def setUp(self):
@@ -11,19 +12,19 @@ class TestNiNode(unittest.TestCase):
         # create nif file
         root = CreateNiNode()
         self.x = Matrix44(Vector3(2,3,4),Matrix33(0,0,1,0,1,0,-1,0,0),0.123)
-        root.SetLocalTransform(self.x)
+        root().SetLocalTransform(self.x)
         self.nifinfo = NifInfo()
         self.nifinfo.version = 0x14000005
         self.nifinfo.creator = "amorilia"
         self.nifinfo.userVersion = 11
-        WriteNifTree("test.nif", root.Ptr(), self.nifinfo)
+        WriteNifTree("test.nif", root(), self.nifinfo)
 
         # read nif file
         self.nifinfo_in = NifInfo()
         root_obj = ReadNifTree("test.nif", self.nifinfo_in)
-        root_in = DynamicCastToNiNode(root_obj.Ptr())
+        root_in = DynamicCastToNiNode(root_obj())
 
-        self.x_in = root_in.GetLocalTransform()
+        self.x_in = root_in().GetLocalTransform()
 
         # delete nif file
         os.remove("test.nif")
-- 
GitLab