Index: /trunk/nv/base/common.hh
===================================================================
--- /trunk/nv/base/common.hh	(revision 504)
+++ /trunk/nv/base/common.hh	(revision 505)
@@ -224,4 +224,7 @@
 	typedef unsigned long long uint64;
 
+	typedef signed   long long sintmax;
+	typedef unsigned long long uintmax;
+
 	typedef unsigned char      uchar8;
 	typedef unsigned short     uchar16;
Index: /trunk/nv/core/io_event.hh
===================================================================
--- /trunk/nv/core/io_event.hh	(revision 504)
+++ /trunk/nv/core/io_event.hh	(revision 505)
@@ -46,4 +46,7 @@
 	struct key_event
 	{
+		/// Associated window ID
+		uint32 window_id;
+
 		/// Input event ASCII code
 		uchar8 ascii;
@@ -70,4 +73,7 @@
 	struct mouse_button_event
 	{
+		/// Associated window ID
+		uint32 window_id;
+
 		/// X position where mouse was clicked.
 		uint16 x;
@@ -84,4 +90,6 @@
 	struct mouse_wheel_event
 	{
+		/// Associated window ID
+		uint32 window_id;
 		/// amount scrolled horizontally positive to the right
 		sint32 x;
@@ -92,4 +100,6 @@
 	struct mouse_move_event
 	{
+		/// Associated window ID
+		uint32 window_id;
 		/// X Position the mouse moved to.
 		uint16 x;
Index: /trunk/nv/core/resource.hh
===================================================================
--- /trunk/nv/core/resource.hh	(revision 504)
+++ /trunk/nv/core/resource.hh	(revision 505)
@@ -44,5 +44,5 @@
 		//virtual void release( resource_id id ) = 0;
 		virtual bool exists( resource_id id ) = 0;
-		virtual bool load_resource( const string_view& id ) = 0;
+		virtual bool load_resource( const string_view& ) { return false; };
 
 		template< typename T >
Index: /trunk/nv/engine/animation.hh
===================================================================
--- /trunk/nv/engine/animation.hh	(revision 504)
+++ /trunk/nv/engine/animation.hh	(revision 505)
@@ -378,4 +378,12 @@
 	};
 
+	class animator_bind_manager : public nv::manual_resource_manager< nv::animator_bind_data >
+	{
+	public:
+		animator_bind_manager() {}
+		using nv::manual_resource_manager< nv::animator_bind_data >::add;
+		using nv::manual_resource_manager< nv::animator_bind_data >::exists;
+	protected:
+	};
 
 }
Index: /trunk/nv/engine/image_manager.hh
===================================================================
--- /trunk/nv/engine/image_manager.hh	(revision 504)
+++ /trunk/nv/engine/image_manager.hh	(revision 505)
@@ -24,12 +24,10 @@
 	NV_RTTI_DECLARE_NAME( image_data, "image_data" )
 
-	class image_manager : public manual_resource_manager< image_data >
+	class image_manager : public file_resource_manager< image_data >
 	{
 	public:
 		image_manager() {}
-		void add_base_path( const string_view& path );
 	protected:
 		virtual bool load_resource( const string_view& id );
-		vector< string128 > m_paths;
 	};
 
Index: /trunk/nv/engine/material_manager.hh
===================================================================
--- /trunk/nv/engine/material_manager.hh	(revision 504)
+++ /trunk/nv/engine/material_manager.hh	(revision 505)
@@ -48,15 +48,14 @@
 	};
 
-	class gpu_material_manager : public manual_resource_manager< gpu_material >
+	class gpu_material_manager : public dependant_resource_manager< gpu_material, material_manager >
 	{
 	public:
 		gpu_material_manager( context* context, material_manager* matmgr, image_manager* imgmgr );
 	protected:
-		virtual bool load_resource( const string_view& id );
+		resource< gpu_material > create_resource( resource< material > m );
 		virtual void release( gpu_material* m );
 	private:
 		texture           m_default;
 		context*          m_context;
-		material_manager* m_material_manager;
 		image_manager*    m_image_manager;
 	};
Index: /trunk/nv/engine/mesh_manager.hh
===================================================================
--- /trunk/nv/engine/mesh_manager.hh	(revision 504)
+++ /trunk/nv/engine/mesh_manager.hh	(revision 505)
@@ -37,22 +37,47 @@
 	};
 
+	struct mesh_data
+	{
+		vector< data_node_info >               infos;
+		vector< resource< data_channel_set > > meshes;
+		hash_store< shash64, uint32 >          names;
+		hash_store< shash64, uint32 >          node_names;
+		data_node_list*                        node_data;
+	};
+
 	NV_RTTI_DECLARE_NAME( data_channel_set, "data_channel_set" )
 	NV_RTTI_DECLARE_NAME( gpu_mesh, "gpu_mesh" )
+	NV_RTTI_DECLARE_NAME( mesh_data, "mesh_data" )
 
 	using mesh_manager = manual_resource_manager< data_channel_set >;
 
-	class gpu_mesh_manager : public nv::manual_resource_manager< gpu_mesh >
+	class gpu_mesh_manager : public dependant_resource_manager< gpu_mesh, mesh_manager >
 	{
 	public:
 		gpu_mesh_manager( context* context, mesh_manager* mesh_manager )
-			: m_context( context )
-			, m_mesh_manager( mesh_manager ) {}
-		virtual bool load_resource( const string_view& id );
-		resource< gpu_mesh > load_resource( resource< data_channel_set > mesh );
+			: dependant_resource_manager( mesh_manager )
+			, m_context( context ) {}
 	protected:
+		resource< gpu_mesh > create_resource( resource< data_channel_set > mesh );
 		virtual void release( gpu_mesh* m );
 	private:
 		context*      m_context;
-		mesh_manager* m_mesh_manager;
+	};
+
+	class mesh_data_manager : public file_resource_manager< mesh_data >
+	{
+	public:
+		mesh_data_manager( mesh_manager* meshes )
+			: m_mesh_manager( meshes ) , m_strings( new string_table ) {}
+		string_view resolve( shash64 h ) { return ( *m_strings )[h]; }
+		resource< data_channel_set > get_path( const string_view& path,
+			resource< mesh_data > default = resource< mesh_data >(),
+			data_node_info* info = nullptr );
+		~mesh_data_manager() { delete m_strings; }
+	protected:
+		virtual bool load_resource( const string_view& id );
+
+		mesh_manager*           m_mesh_manager;
+		string_table*           m_strings;
 	};
 
Index: /trunk/nv/engine/program_manager.hh
===================================================================
--- /trunk/nv/engine/program_manager.hh	(revision 504)
+++ /trunk/nv/engine/program_manager.hh	(revision 505)
@@ -20,5 +20,5 @@
 {
 
-	class program_manager : public lua_resource_manager< program, false >
+	class program_manager : public file_resource_manager< program, false, lua_resource_manager_base >
 	{
 	public:
@@ -30,4 +30,5 @@
 		string_buffer load_source( lua::table_guard& table, const string_view& append );
 		virtual void release( program p );
+		virtual nv::const_string file_to_string( const string_view& path );
 	private:
 		context* m_context;
Index: /trunk/nv/engine/resource_system.hh
===================================================================
--- /trunk/nv/engine/resource_system.hh	(revision 504)
+++ /trunk/nv/engine/resource_system.hh	(revision 505)
@@ -16,8 +16,10 @@
 #include <nv/common.hh>
 #include <nv/interface/context.hh>
+#include <nv/stl/file_system.hh>
 #include <nv/core/resource.hh>
 #include <nv/lua/lua_state.hh>
 #include <nv/stl/hash_store.hh>
 #include <nv/stl/vector.hh>
+#include <nv/stl/string.hh>
 
 namespace nv
@@ -151,14 +153,66 @@
 
 
-	template < typename T, bool Heap = true >
-	class manual_resource_manager : public custom_resource_manager< T, Heap >
+	template < typename T, bool Heap = true, typename Base = resource_handler >
+	class manual_resource_manager : public custom_resource_manager< T, Heap, Base >
 	{
 	public:
 		manual_resource_manager() {}
-		using custom_resource_manager< T, Heap >::add;
-	protected:
-		virtual bool load_resource( const nv::string_view& ) { return false; }
-
-	};
+		using custom_resource_manager< T, Heap, Base >::add;
+	};
+
+	template < typename T, typename SourceManager, bool Heap = true >
+	class dependant_resource_manager : public manual_resource_manager< T, Heap >
+	{
+	public:
+		typedef SourceManager source_manager_type;
+		typedef typename SourceManager::resource_type source_type;
+	public:
+		explicit dependant_resource_manager( source_manager_type* source ) : m_source( source ) {}
+		virtual resource< T > load_resource( source_type u )
+		{
+			resource< T > result = get( u.id().value() );
+			if ( result ) return result;
+			return create_resource( u );
+		}
+	protected:
+		virtual resource< T > create_resource( source_type u ) = 0;
+		virtual bool load_resource( const string_view& id )
+		{
+			source_type u = m_source->get( id );
+			return u && create_resource( u );
+		}
+	protected:
+		source_manager_type* m_source;
+	};
+
+	template < typename T, bool Heap = true, typename Base = resource_handler >
+	class file_resource_manager : public manual_resource_manager< T, Heap, Base >
+	{
+	public:
+		explicit file_resource_manager() {}
+		void add_base_path( const string_view& path )
+		{
+			m_paths.emplace_back( path );
+		}
+	protected:
+		stream* open_stream( file_system& fs, const string_view& filename )
+		{
+			if ( fs.exists( filename ) ) return fs.open( filename );
+			if ( m_paths.size() > 0 )
+			{
+				for ( const auto& path : m_paths )
+				{
+					string128 fpath( path );
+					fpath.append( filename );
+					if ( fs.exists( fpath ) )
+						return fs.open( fpath );
+				}
+			}
+			return nullptr;
+		}
+
+		vector< string128 > m_paths;
+	};
+
 }
 
Index: /trunk/nv/gl/gl_window.hh
===================================================================
--- /trunk/nv/gl/gl_window.hh	(revision 504)
+++ /trunk/nv/gl/gl_window.hh	(revision 505)
@@ -39,4 +39,6 @@
 
 		virtual void swap_buffers();
+		virtual void make_current();
+		virtual uint32 window_id();
 		virtual ~gl_window();
 	private:
@@ -47,4 +49,5 @@
 		void*       m_handle;
 		void*       m_hwnd;
+		void*       m_dc;
 		gl_context* m_context;
 
Index: /trunk/nv/interface/context.hh
===================================================================
--- /trunk/nv/interface/context.hh	(revision 504)
+++ /trunk/nv/interface/context.hh	(revision 505)
@@ -151,5 +151,4 @@
 			m_device = a_device; 
 		}
-
 		virtual vertex_array create_vertex_array( const vertex_array_desc& desc ) = 0;
 		virtual framebuffer create_framebuffer( uint32 temp_samples = 1 ) = 0;
Index: /trunk/nv/interface/window.hh
===================================================================
--- /trunk/nv/interface/window.hh	(revision 504)
+++ /trunk/nv/interface/window.hh	(revision 505)
@@ -36,5 +36,7 @@
 		virtual bool poll_event( io_event& event ) = 0;
 		virtual void swap_buffers() = 0;
+		virtual void make_current() = 0;
 		virtual device* get_device() = 0;
+		virtual uint32 window_id() = 0;
 		virtual ~window() {}
 	};
Index: /trunk/nv/lua/lua_state.hh
===================================================================
--- /trunk/nv/lua/lua_state.hh	(revision 504)
+++ /trunk/nv/lua/lua_state.hh	(revision 505)
@@ -364,11 +364,12 @@
 			virtual ~table_guard();
 			size_t get_size();
+			
 			bool has_field( string_view element );
+			
 			shash64 get_string_hash_64( string_view element, uint64 defval = 0 );
-			// remove this one
-			shash64 get_string( string_view element, string_table& table, uint64 defval = 0 );
 			shash64 get_string( string_view element, string_table* table, uint64 defval = 0 );
 			const_string get_string( string_view element, string_view defval = string_view() );
 			string128 get_string128( string_view element, string_view defval = string_view() );
+			
 			char get_char( string_view element, char defval = ' ' );
 			int get_integer( string_view element, int defval = 0 );
@@ -377,8 +378,26 @@
 			float get_float( string_view element, float defval = 0.0 );
 			bool get_boolean( string_view element, bool defval = false );
+
+			shash64 get_string_hash_64( int i, uint64 defval = 0 );
+			shash64 get_string( int i, string_table* table, uint64 defval = 0 );
+			const_string get_string( int i, string_view defval = string_view() );
+			string128 get_string128( int i, string_view defval = string_view() );
+
+			char get_char( int i, char defval = ' ' );
+			int get_integer( int i, int defval = 0 );
+			unsigned get_unsigned( int i, unsigned defval = 0 );
+			double get_double( int i, double defval = 0.0 );
+			float get_float( int i, float defval = 0.0 );
+			bool get_boolean( int i, bool defval = false );
+
 			bool is_table( string_view element );
 			bool is_number( string_view element );
 			bool is_boolean( string_view element );
 			bool is_string( string_view element );
+			bool is_table( int i );
+			bool is_number( int i );
+			bool is_boolean( int i );
+			bool is_string( int i );
+
 			template < typename T >
 			bool read( const string_view& element, T& t )
Index: /trunk/nv/sdl/sdl_window.hh
===================================================================
--- /trunk/nv/sdl/sdl_window.hh	(revision 504)
+++ /trunk/nv/sdl/sdl_window.hh	(revision 505)
@@ -29,4 +29,6 @@
 			virtual void set_title( const string_view& title );
 			virtual void swap_buffers();
+			virtual void make_current();
+
 
 			virtual context* get_context()    { return m_context; }
@@ -38,5 +40,6 @@
 			virtual bool is_event_pending()            { return m_input->is_event_pending(); }
 			virtual bool poll_event( io_event& event ) { return m_input->poll_event( event ); }
-
+			void* get_handle() { return m_handle;  }
+			virtual uint32 window_id();
 			virtual ~window();
 		private:
Index: /trunk/nv/sdl/sdl_window_manager.hh
===================================================================
--- /trunk/nv/sdl/sdl_window_manager.hh	(revision 504)
+++ /trunk/nv/sdl/sdl_window_manager.hh	(revision 505)
@@ -31,4 +31,6 @@
 			virtual uint32 get_ticks();
 			virtual ~window_manager();
+		private:
+			void* primal_window;
 		};
 	}
Index: /trunk/nv/stl/math/common.hh
===================================================================
--- /trunk/nv/stl/math/common.hh	(revision 504)
+++ /trunk/nv/stl/math/common.hh	(revision 505)
@@ -109,4 +109,13 @@
 		template <> struct is_bool_vec < tvec4< bool > > : true_type {};
 
+		template < typename T > constexpr bool is_vec_v      = is_vec<T>::value;
+		template < typename T > constexpr bool is_mat_v      = is_mat<T>::value;
+		template < typename T > constexpr bool is_quat_v     = is_quat<T>::value;
+		template < typename T > constexpr bool is_fp_v       = is_fp<T>::value;
+		template < typename T > constexpr bool is_fp_vec_v   = is_fp_vec<T>::value;
+		template < typename T > constexpr bool is_fp_mat_v   = is_fp_mat<T>::value;
+		template < typename T > constexpr bool is_fp_quat_v  = is_fp_quat<T>::value;
+		template < typename T > constexpr bool is_bool_vec_v = is_bool_vec<T>::value;
+
 		namespace detail
 		{
@@ -227,4 +236,6 @@
 	typedef math::tmat4< float > mat4;
 
+	typedef math::tquat< float > quat;
+
 	template < typename T > 
 	struct make_unsigned< math::tvec2< T > >
@@ -265,3 +276,14 @@
 }
 
+NV_RTTI_DECLARE( nv::vec2 )
+NV_RTTI_DECLARE( nv::vec3 )
+NV_RTTI_DECLARE( nv::vec4 )
+NV_RTTI_DECLARE( nv::ivec2 )
+NV_RTTI_DECLARE( nv::ivec3 )
+NV_RTTI_DECLARE( nv::ivec4 )
+NV_RTTI_DECLARE( nv::mat2 )
+NV_RTTI_DECLARE( nv::mat3 )
+NV_RTTI_DECLARE( nv::mat4 )
+NV_RTTI_DECLARE( nv::quat )
+
 #endif // NV_STL_MATH_COMMON_HH
Index: /trunk/nv/stl/math/quaternion.hh
===================================================================
--- /trunk/nv/stl/math/quaternion.hh	(revision 504)
+++ /trunk/nv/stl/math/quaternion.hh	(revision 505)
@@ -112,6 +112,4 @@
 
 		};
-
-		typedef tquat< f32 > quat;
 
 		namespace detail
@@ -589,6 +587,4 @@
 	}
 
-	typedef math::quat quat;
-
 }
 
Index: /trunk/nv/stl/rtti_types.hh
===================================================================
--- /trunk/nv/stl/rtti_types.hh	(revision 504)
+++ /trunk/nv/stl/rtti_types.hh	(revision 505)
@@ -15,5 +15,4 @@
 
 #include <nv/common.hh>
-#include <nv/stl/math.hh>
 
 NV_RTTI_DECLARE( void )
@@ -30,14 +29,4 @@
 NV_RTTI_DECLARE_NAME( nv::f32, "f32" )
 NV_RTTI_DECLARE_NAME( nv::f64, "f64" )
-NV_RTTI_DECLARE( nv::vec2 )
-NV_RTTI_DECLARE( nv::vec3 )
-NV_RTTI_DECLARE( nv::vec4 )
-NV_RTTI_DECLARE( nv::ivec2 )
-NV_RTTI_DECLARE( nv::ivec3 )
-NV_RTTI_DECLARE( nv::ivec4 )
-NV_RTTI_DECLARE( nv::mat2 )
-NV_RTTI_DECLARE( nv::mat3 )
-NV_RTTI_DECLARE( nv::mat4 )
-NV_RTTI_DECLARE( nv::quat )
 
 #endif // NV_STL_RTTI_TYPES_HH
Index: /trunk/nv/stl/string/short_string.hh
===================================================================
--- /trunk/nv/stl/string/short_string.hh	(revision 504)
+++ /trunk/nv/stl/string/short_string.hh	(revision 505)
@@ -220,6 +220,10 @@
 	using string256 = short_string< 255 >;
 
-
 }
 
+NV_RTTI_DECLARE( nv::string32 )
+NV_RTTI_DECLARE( nv::string64 )
+NV_RTTI_DECLARE( nv::string128 )
+NV_RTTI_DECLARE( nv::string256 )
+
 #endif // NV_STL_STRING_SHORT_STRING_HH
Index: /trunk/nv/stl/type_traits/common.hh
===================================================================
--- /trunk/nv/stl/type_traits/common.hh	(revision 504)
+++ /trunk/nv/stl/type_traits/common.hh	(revision 505)
@@ -29,4 +29,7 @@
 	};
 
+	template < typename T >
+	constexpr T integral_constant_v = integral_constant<T>::value;
+
 	// TODO: Propagate
 	template< bool B >
@@ -36,4 +39,7 @@
 	typedef bool_constant<false> false_type;
 
+	template < typename T >
+	constexpr T bool_constant_v = bool_constant<T>::value;
+
 	template< bool Test, typename T = void>
 	struct enable_if {};
@@ -68,4 +74,7 @@
 	template < typename T >
 	struct is_same < T, T > : true_type{};
+
+	template < typename T1, typename T2 >
+	constexpr bool is_same_v = is_same<T1, T2>::value;
 
 	// TODO: these seem to simple compared to MSVC/GCC - so we'll leave them in
@@ -73,12 +82,16 @@
 	template < typename T >	struct is_const : false_type {};
 	template < typename T > struct is_const < T const > : true_type{};
+	template < typename T >	constexpr bool is_const_v = is_const<T>::value;
 	template < typename T > struct is_volatile : false_type {};
 	template < typename T > struct is_volatile < T volatile > : true_type{};
+	template < typename T >	constexpr bool is_volatile_v = is_volatile<T>::value;
 	// TODO END
 
 	template < typename T >	struct is_lvalue_reference : false_type {};
 	template < typename T >	struct is_lvalue_reference < T& > : true_type{};
+	template < typename T > constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value;
 	template < typename T >	struct is_rvalue_reference : false_type {};
 	template < typename T >	struct is_rvalue_reference < T&& > : true_type{};
+	template < typename T > constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value;
 
 	template < typename T >
@@ -87,4 +100,5 @@
 		is_rvalue_reference<T>::value 
 	> {};
+	template < typename T > constexpr bool is_reference_v = is_reference<T>::value;
 
 	// add const volatile and reference mutators
Index: /trunk/nv/stl/type_traits/primary.hh
===================================================================
--- /trunk/nv/stl/type_traits/primary.hh	(revision 504)
+++ /trunk/nv/stl/type_traits/primary.hh	(revision 505)
@@ -45,8 +45,14 @@
 	}
 
-	template< typename T > struct is_void           : is_same < void,      remove_cv_t<T> > {};
-	template< typename T > struct is_nullptr        : is_same < nullptr_t, remove_cv_t<T> > {};
-	template< typename T > struct is_integral       : detail::is_integral_impl < remove_cv_t<T> > {};
-	template< typename T > struct is_floating_point : detail::is_floating_point_impl < remove_cv_t<T> > {};
+	template < typename T > struct is_void           : is_same < void,      remove_cv_t<T> > {};
+	template < typename T > struct is_nullptr        : is_same < nullptr_t, remove_cv_t<T> > {};
+	template < typename T > struct is_integral       : detail::is_integral_impl < remove_cv_t<T> > {};
+	template < typename T > struct is_floating_point : detail::is_floating_point_impl < remove_cv_t<T> > {};
+
+	template < typename T > constexpr bool is_void_v           = is_void<T>::value;
+	template < typename T > constexpr bool is_nullptr_v        = is_nullptr<T>::value;
+	template < typename T > constexpr bool is_integral_v       = is_integral<T>::value;
+	template < typename T > constexpr bool is_floating_point_v = is_floating_point<T>::value;
+
 
 	template < typename T >           struct is_array          : false_type {};
@@ -57,4 +63,9 @@
 	template < typename T >           struct is_union : bool_constant < __is_union( T ) > {};
 	template < typename T >           struct is_class : bool_constant < __is_class( T ) > {};
+
+	template < typename T > constexpr bool is_array_v = is_array<T>::value;
+	template < typename T > constexpr bool is_enum_v  = is_enum<T>::value;
+	template < typename T > constexpr bool is_union_v = is_union<T>::value;
+	template < typename T > constexpr bool is_class_v = is_class<T>::value;
 
 	// is_function_pointer / is_member_function pointer - extension
@@ -115,4 +126,9 @@
 	template< typename T > struct is_function < T&& > : false_type{};
 
+	template < typename T > constexpr bool is_function_pointer_v        = is_function_pointer<T>::value;
+	template < typename T > constexpr bool is_member_function_pointer_v = is_member_function_pointer<T>::value;
+	template < typename T > constexpr bool is_member_pointer_v          = is_member_pointer<T>::value;
+	template < typename T > constexpr bool is_function_v                = is_function<T>::value;
+
 }
 
Index: /trunk/nv/stl/type_traits/properties.hh
===================================================================
--- /trunk/nv/stl/type_traits/properties.hh	(revision 504)
+++ /trunk/nv/stl/type_traits/properties.hh	(revision 505)
@@ -53,4 +53,10 @@
 	struct is_compound : bool_constant < !is_fundamental< T >::value > {};
 
+	template < typename T > constexpr bool is_fundamental_v = is_fundamental<T>::value;
+	template < typename T > constexpr bool is_arithmetic_v  = is_arithmetic<T>::value;
+	template < typename T > constexpr bool is_scalar_v      = is_scalar<T>::value;
+	template < typename T > constexpr bool is_object_v      = is_object<T>::value;
+	template < typename T > constexpr bool is_compound_v    = is_compound<T>::value;
+
 	// TODO : confirm conformance
 #if NV_COMPILER == NV_MSVC
@@ -68,4 +74,12 @@
 	template < typename T > struct is_abstract        : bool_constant < __is_abstract( T ) > {};
 
+	template < typename T > constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
+	template < typename T > constexpr bool is_trivial_v            = is_trivial<T>::value;
+	template < typename T > constexpr bool is_pod_v                = is_pod<T>::value;
+	template < typename T > constexpr bool is_literal_type_v       = is_literal_type<T>::value;
+	template < typename T > constexpr bool is_empty_v              = is_empty<T>::value;
+	template < typename T > constexpr bool is_polymorphic_v        = is_polymorphic<T>::value;
+	template < typename T > constexpr bool is_abstract_v           = is_abstract<T>::value;
+	
 	template < typename T > struct is_signed : false_type {};
 	template <> struct is_signed<char>       : bool_constant< ( char( 0 ) > char( -1 ) ) > {};
@@ -93,4 +107,7 @@
 	template <> struct is_unsigned<unsigned long long>       : true_type{};
 	template <> struct is_unsigned<const unsigned long long> : true_type{};
+
+	template < typename T > constexpr bool is_signed_v   = is_signed<T>::value;
+	template < typename T > constexpr bool is_unsigned_v = is_unsigned<T>::value;
 
 #if NV_COMPILER == NV_MSVC
@@ -207,4 +224,7 @@
 	struct is_assignable : detail::is_assignable_impl< To, From >::type { };
 
+	template < typename To, typename From > constexpr bool is_assignable_v = is_assignable<To, From>::value;
+
+
 	namespace detail
 	{
@@ -230,4 +250,10 @@
 	struct is_move_assignable : detail::is_move_assignable_impl < T > {};
 
+	template < typename T > 
+	constexpr bool is_copy_assignable_v = is_copy_assignable<T>::value;
+
+	template < typename T >
+	constexpr bool is_move_assignable_v = is_move_assignable<T>::value;
+
 // TODO : implement if needed
 // 	template < typename T > 
@@ -249,7 +275,10 @@
 
 	template < typename T >	struct has_virtual_destructor  : bool_constant < __has_virtual_destructor( T ) > {};
+	template < typename T >	constexpr bool has_virtual_destructor_v = has_virtual_destructor<T>::value;
 
 	template< typename T >
 	struct alignment_of	: integral_constant < size_t, alignof( typename remove_reference< T >::type ) > {};
+
+	template < typename T >	constexpr size_t alignment_of_v = alignment_of<T>::value;
 
 	template < typename T >
@@ -259,4 +288,6 @@
 	template < typename T, size_t N >
 	struct rank<T[N]> : integral_constant < size_t, rank<T>::value + 1 > {};
+
+	template < typename T >	constexpr size_t rank_v = rank<T>::value;
 
 	template < typename T, unsigned N = 0>
@@ -271,6 +302,11 @@
 	struct extent< T[I], N > : integral_constant < size_t, extent<T, N - 1>::value > {};
 
+	template < typename T >	constexpr size_t extent_v = extent<T>::value;
+
 	template < typename Base, typename Derived > 
 	struct is_base_of : bool_constant < __is_base_of( Base, Derived ) > {};
+
+	template < typename Base, typename Derived >
+	constexpr bool is_base_of_v = is_base_of<Base,Derived>::value;
 
 #if NV_COMPILER == NV_MSVC 
@@ -281,4 +317,7 @@
 	struct is_convertible : detail::is_convertible_impl< From, To >::type {};
 #endif
+
+	template < typename From, typename To >
+	constexpr bool is_convertible_v = is_convertible<From, To>::value;
 
 	namespace detail
@@ -298,5 +337,4 @@
 	struct is_template_base_of : bool_constant< detail::is_template_base_of_impl< T, Template >::value > {};
 
-
 // TODO: non-standard, remove?
 	template < typename T >	struct has_trivial_constructor : bool_constant < __has_trivial_constructor( T ) || __is_pod( T ) > {};
@@ -305,4 +343,9 @@
 	template < typename T >	struct has_trivial_destructor  : bool_constant < __has_trivial_destructor( T ) || __is_pod( T ) > {};
 
+	template < typename T > constexpr bool has_trivial_constructor_v = has_trivial_constructor<T>::value;
+	template < typename T > constexpr bool has_trivial_copy_v        = has_trivial_copy<T>::value;
+	template < typename T > constexpr bool has_trivial_assign_v      = has_trivial_assign<T>::value;
+	template < typename T > constexpr bool has_trivial_destructor_v  = has_trivial_destructor<T>::value;
+
 }
 
Index: /trunk/nv/stl/utility/common.hh
===================================================================
--- /trunk/nv/stl/utility/common.hh	(revision 504)
+++ /trunk/nv/stl/utility/common.hh	(revision 505)
@@ -51,4 +51,18 @@
 	}
 
+	template < typename T, typename U = T >
+	inline T exchange( T& t, U&& u )
+	{
+		T v = nv::move( t );
+		t = nv::forward<U>( u );
+		return v;
+	}
+
+	template < typename T > 
+	constexpr add_const_t<T>& as_const( T& t )
+	{
+		return t;
+	}
+
 }
 
Index: /trunk/nv/wx/wx_canvas.hh
===================================================================
--- /trunk/nv/wx/wx_canvas.hh	(revision 504)
+++ /trunk/nv/wx/wx_canvas.hh	(revision 505)
@@ -50,9 +50,12 @@
 	{
 	public:
-		explicit wx_gl_canvas( wxWindow *parent );
+		explicit wx_gl_canvas( wxWindow *parent, input* in );
+		explicit wx_gl_canvas( wxWindow *parent, wx_gl_canvas *sibling, input* in );
 		virtual void on_update() = 0;
 		virtual void stop();
 		virtual void start();
 		virtual void on_idle( wxIdleEvent& evt );
+		virtual void make_current();
+		uint32 window_id() { return m_window->window_id(); }
 		~wx_gl_canvas();
 	protected:
@@ -64,4 +67,5 @@
 		nv::window*         m_window;
 		bool                m_render;
+		bool                m_main;
 		wxDECLARE_EVENT_TABLE();
 	};
Index: /trunk/src/core/io_event.cc
===================================================================
--- /trunk/src/core/io_event.cc	(revision 504)
+++ /trunk/src/core/io_event.cc	(revision 505)
@@ -71,29 +71,33 @@
 
 	db->create_type<key_event>()
-		.field( "ascii",   &key_event::ascii )
-		.field( "code",    &key_event::code )
-		.field( "shift",   &key_event::shift )
-		.field( "control", &key_event::control )
-		.field( "alt",     &key_event::alt )
-		.field( "pressed", &key_event::pressed );
+		.field( "window_id",&key_event::window_id )
+		.field( "ascii",    &key_event::ascii )
+		.field( "code",     &key_event::code )
+		.field( "shift",    &key_event::shift )
+		.field( "control",  &key_event::control )
+		.field( "alt",      &key_event::alt )
+		.field( "pressed",  &key_event::pressed );
 
 	db->create_type<mouse_button_event>()
-		.field( "x",       &mouse_button_event::x )
-		.field( "y",       &mouse_button_event::y )
-		.field( "button",  &mouse_button_event::button )
-		.field( "pressed", &mouse_button_event::pressed )
-		.field( "code",    &mouse_button_event::code );
+		.field( "window_id",&mouse_button_event::window_id )
+		.field( "x",        &mouse_button_event::x )
+		.field( "y",        &mouse_button_event::y )
+		.field( "button",   &mouse_button_event::button )
+		.field( "pressed",  &mouse_button_event::pressed )
+		.field( "code",     &mouse_button_event::code );
 
 	db->create_type<mouse_move_event>()
-		.field( "x",       &mouse_move_event::x )
-		.field( "y",       &mouse_move_event::y )
-		.field( "rx",      &mouse_move_event::rx )
-		.field( "ry",      &mouse_move_event::ry )
-		.field( "pressed", &mouse_move_event::pressed )
-		.field( "code",    &mouse_move_event::code );
+		.field( "window_id",&mouse_move_event::window_id )
+		.field( "x",        &mouse_move_event::x )
+		.field( "y",        &mouse_move_event::y )
+		.field( "rx",       &mouse_move_event::rx )
+		.field( "ry",       &mouse_move_event::ry )
+		.field( "pressed",  &mouse_move_event::pressed )
+		.field( "code",     &mouse_move_event::code );
 
 	db->create_type<mouse_wheel_event>()
-		.field( "x",       &mouse_wheel_event::x )
-		.field( "y",       &mouse_wheel_event::y );
+		.field( "window_id",&mouse_wheel_event::window_id )
+		.field( "x",        &mouse_wheel_event::x )
+		.field( "y",        &mouse_wheel_event::y );
 
 	db->create_type<pad_button_event>()
Index: /trunk/src/core/types.cc
===================================================================
--- /trunk/src/core/types.cc	(revision 504)
+++ /trunk/src/core/types.cc	(revision 505)
@@ -3,4 +3,5 @@
 #include "nv/interface/clear_state.hh"
 #include "nv/interface/render_state.hh"
+#include "nv/stl/string.hh"
 
 using namespace nv;
@@ -26,4 +27,9 @@
 	db->create_type<ivec3>();
 	db->create_type<ivec4>();
+	db->create_type<quat>();
+	db->create_type<string32>();
+	db->create_type<string64>();
+	db->create_type<string128>();
+	db->create_type<string256>();
 
 	db->create_type<color_mask>()
Index: /trunk/src/engine/image_manager.cc
===================================================================
--- /trunk/src/engine/image_manager.cc	(revision 504)
+++ /trunk/src/engine/image_manager.cc	(revision 505)
@@ -12,38 +12,19 @@
 using namespace nv;
 
-void nv::image_manager::add_base_path( const string_view& path )
+bool image_manager::load_resource( const string_view& filename )
 {
-	m_paths.emplace_back( path );
+	c_file_system fs;
+	if ( stream* file = open_stream( fs, filename ) )
+	{
+		png_loader loader;
+		image_data* result = loader.load( *file );
+		delete file;
+		if ( result )
+		{
+			add( filename, result );
+			return true;
+		}
+	}
+	return false;
 }
 
-bool image_manager::load_resource( const string_view& filename )
-{
-	png_loader loader;
-	c_file_system fs;
-	image_data* result = nullptr;
-	if ( fs.exists( filename ) )
-	{
-		stream* file = fs.open( filename );
-		result = loader.load( *file );
-		delete file;
-	}
-	else if ( m_paths.size() > 0 )
-	{
-		for ( const auto& path : m_paths )
-		{
-			string128 fpath = path;
-			fpath.append( filename );
-			if ( fs.exists( fpath ) )
-			{
-				stream* file = fs.open( fpath );
-				result = loader.load( *file );
-				delete file;
-				break;
-			}
-		}
-	}
-	if ( result ) 
-		add( filename, result );
-	return result != nullptr;
-}
-
Index: /trunk/src/engine/material_manager.cc
===================================================================
--- /trunk/src/engine/material_manager.cc	(revision 504)
+++ /trunk/src/engine/material_manager.cc	(revision 505)
@@ -14,6 +14,5 @@
 
 nv::gpu_material_manager::gpu_material_manager( context* context, material_manager* matmgr, image_manager* imgmgr )
-	: m_context( context )
-	, m_material_manager( matmgr )
+	: dependant_resource_manager( matmgr ), m_context( context )
 	, m_image_manager( imgmgr )
 {
@@ -23,7 +22,8 @@
 }
 
-bool gpu_material_manager::load_resource( const string_view& id )
+nv::resource< nv::gpu_material > nv::gpu_material_manager::create_resource( resource< material > m )
 {
-	if ( auto mat = m_material_manager->get( id ).lock() )
+	resource_id id = m.id();
+	if ( auto mat = m.lock() )
 	{
 		gpu_material* result = new gpu_material;
@@ -39,12 +39,11 @@
 
 		// HACK
- 		for ( uint32 i = 0; i < 8; ++i )
- 			if ( result->textures[i].is_nil() )
- 				result->textures[i] = m_default;
-			
-		add( id, result );
-		return true;
+		for ( uint32 i = 0; i < 8; ++i )
+			if ( result->textures[i].is_nil() )
+				result->textures[i] = m_default;
+
+		return add( id, result );
 	}
-	return false;
+	return resource< nv::gpu_material >();
 }
 
Index: /trunk/src/engine/mesh_manager.cc
===================================================================
--- /trunk/src/engine/mesh_manager.cc	(revision 504)
+++ /trunk/src/engine/mesh_manager.cc	(revision 505)
@@ -6,11 +6,11 @@
 
 #include "nv/engine/mesh_manager.hh"
+#include "nv/formats/nmd_loader.hh"
+#include "nv/io/c_file_system.hh"
 
 using namespace nv;
 
-resource< gpu_mesh > gpu_mesh_manager::load_resource( resource< data_channel_set > mesh )
+resource< gpu_mesh > gpu_mesh_manager::create_resource( resource< data_channel_set > mesh )
 {
-	resource< gpu_mesh > result = get( mesh.id().value() );
-	if ( result ) return result;
 	if ( auto lmesh = mesh.lock() )
 	{
@@ -24,20 +24,106 @@
 }
 
-bool nv::gpu_mesh_manager::load_resource( const string_view& id )
-{
-	if ( auto lmesh = m_mesh_manager->get( id ).lock() )
-	{
-		gpu_mesh* gm = new gpu_mesh;
-		gm->va = m_context->create_vertex_array( &*lmesh, STATIC_DRAW );
-		gm->count = lmesh->get_channel_size( slot::INDEX );
-		gm->shader = lmesh->get_channel( slot::BONEINDEX ) != nullptr ? BONE : NORMAL;
-		add( id, gm );
-		return true;
-	}
-	return false;
-}
-
 void gpu_mesh_manager::release( gpu_mesh* m )
 {
 	m_context->release( m->va );
 }
+
+nv::resource< nv::data_channel_set > nv::mesh_data_manager::get_path( const string_view& path, resource< mesh_data > default /*= resource< mesh_data >()*/, data_node_info* info /*= nullptr */ )
+{
+	nv::resource< nv::mesh_data > mr = default;
+
+	nv::string_view sub_mesh_name;
+	nv::string128 base_mesh_name( path );
+	nv::size_t sub_mesh_pos = path.find( ":" );
+	nv::size_t dot_pos = path.find( "." );
+	if ( sub_mesh_pos != nv::string_view::npos )
+	{
+		sub_mesh_name = path.substr( sub_mesh_pos + 1 );
+		base_mesh_name.assign( path.substr( 0, sub_mesh_pos ) );
+		NV_LOG_INFO( "Requested submesh - [", sub_mesh_name, "] in [", base_mesh_name, "]" );
+	}
+
+	if ( dot_pos != nv::string_view::npos )
+	{
+		mr = get( base_mesh_name );
+	}
+	else
+	{
+		sub_mesh_name = base_mesh_name;
+	}
+
+	if ( !mr )
+	{
+		NV_LOG_ERROR( "MESH FILE NOT FOUND - ", path );
+		NV_ASSERT( false, "MESH FILE NOT FOUND!" );
+		return nv::resource< nv::data_channel_set >();
+	}
+
+	if ( auto mdata = mr.lock() )
+	{
+		sint32 index = -1;
+		if ( sub_mesh_name.empty() )
+		{
+			index = 0;
+		}
+		else if ( sub_mesh_name[0] >= '0' && sub_mesh_name[0] <= '9' )
+		{
+			index = nv::buffer_to_uint32( sub_mesh_name.data(), nullptr );
+		}
+		else
+		{
+			auto itr = mdata->names.find( sub_mesh_name );
+			if ( itr != mdata->names.end() )
+				index = itr->second;
+		}
+		if ( index >= 0 )
+		{
+			if ( info )
+				*info = mdata->infos[index];
+			return mdata->meshes[index];
+		}
+
+		NV_LOG_ERROR( "Resource path fail! - ", path );
+		NV_ASSERT( false, "Resource path fail!" );
+	}
+	else
+	{
+		NV_LOG_ERROR( "Resource lock fail! - ", path );
+		NV_ASSERT( false, "Resource lock fail!" );
+	}
+	return nv::resource< nv::data_channel_set >();
+}
+
+bool nv::mesh_data_manager::load_resource( const string_view& id )
+{
+	nmd_loader* loader = nullptr;
+	c_file_system fs;
+	stream* mesh_file = open_stream( fs, id );
+	if ( !mesh_file ) return false;
+
+	loader = new nmd_loader( m_strings );
+	loader->load( *mesh_file );
+	delete mesh_file;
+
+	mesh_data* result = new mesh_data;
+	result->node_data = loader->release_data_node_list();
+	if ( result->node_data )
+	{
+		data_node_list* nd = result->node_data;
+		for ( uint32 i = 0; i < nd->size(); ++i )
+			result->node_names[(*nd)[i].name] = i;
+	}
+	for ( uint32 i = 0; i < loader->get_mesh_count(); ++i )
+	{
+		data_node_info info;
+		data_channel_set* data = loader->release_mesh_data( i, info );
+		result->infos.push_back( info );
+		result->names[ info.name ] = i;
+		auto mesh = m_mesh_manager->add( shash64( id.get_hash() + i ), data );
+		result->meshes.push_back( mesh );
+	}
+	delete loader;
+	if ( result )
+		add( id, result );
+	return result != nullptr;
+}
Index: /trunk/src/engine/program_manager.cc
===================================================================
--- /trunk/src/engine/program_manager.cc	(revision 504)
+++ /trunk/src/engine/program_manager.cc	(revision 505)
@@ -45,4 +45,16 @@
 }
 
+nv::const_string nv::program_manager::file_to_string( const string_view& path )
+{
+	c_file_system fs;
+	stream* fstream = open_stream( fs, path );
+	if ( !fstream ) return const_string();
+	uint32 size = fstream->size();
+	const_string result( nullptr, size );
+	fstream->read( const_cast<char*>( result.data() ), size, 1 );
+	delete fstream;
+	return result;
+}
+
 nv::string_buffer nv::program_manager::load_source( lua::table_guard& table, const string_view& append )
 {
@@ -51,5 +63,5 @@
 	if ( table.is_string( "files" ) )
 	{
-		out.append( fs.slurp( table.get_string( "files" ) ) );
+		out.append( file_to_string( table.get_string( "files" ) ) );
 	}
 	else if ( table.is_table( "files" ) )
@@ -61,5 +73,5 @@
 			const_string include( inctable.get<const_string,uint32>(i) );
 			if ( i == count ) out.append( "#line 1\n" );
-			out.append( fs.slurp( include ) );
+			out.append( file_to_string( include ) );
 		}
 	}
@@ -67,5 +79,5 @@
 	if ( table.is_string( "file" ) )
 	{
-		const_string data = fs.slurp( table.get_string( "file" ) );
+		const_string data = file_to_string( table.get_string( "file" ) );
 		out.append( "#line 1\n" + data );
 	}
Index: /trunk/src/gfx/image.cc
===================================================================
--- /trunk/src/gfx/image.cc	(revision 504)
+++ /trunk/src/gfx/image.cc	(revision 505)
@@ -98,4 +98,5 @@
 	const uint8* data = idata->get_data();
 	size_t depth      = idata->get_depth();
+	size_t cdepth     = m_depth > depth ? depth : m_depth;
 	uint32 dstride    = rsizex * depth;
 
@@ -106,5 +107,5 @@
 		{
 			uint32 xy = pos + x * m_depth;
-			for( size_t e = 0; e < depth; ++e )
+			for( size_t e = 0; e < cdepth; ++e )
 			{
 				m_data[ xy + e ] = data[ y*dstride + x * depth + e ];
Index: /trunk/src/gl/gl_context.cc
===================================================================
--- /trunk/src/gl/gl_context.cc	(revision 504)
+++ /trunk/src/gl/gl_context.cc	(revision 505)
@@ -848,5 +848,4 @@
 }
 
-
 nv::gl_context::~gl_context()
 {
Index: /trunk/src/gl/gl_device.cc
===================================================================
--- /trunk/src/gl/gl_device.cc	(revision 504)
+++ /trunk/src/gl/gl_device.cc	(revision 505)
@@ -145,5 +145,4 @@
 {
 	unsigned glid = 0;
-	unsigned glenum = buffer_type_to_enum( type );
 	glGenBuffers( 1, &glid );
 
Index: /trunk/src/gl/gl_window.cc
===================================================================
--- /trunk/src/gl/gl_window.cc	(revision 504)
+++ /trunk/src/gl/gl_window.cc	(revision 505)
@@ -9,4 +9,5 @@
 #include "nv/core/logging.hh"
 #include "nv/lib/gl.hh"
+#include "nv/lib/sdl.hh"
 
 using namespace nv;
@@ -31,5 +32,4 @@
 	delete m_context;
 	m_context = nullptr;
-	delete m_input;
 }
 
@@ -41,4 +41,5 @@
 
 	m_handle = handle;
+	m_dc     = dc;
 
 	// TODO: error checking
@@ -110,2 +111,15 @@
 }
 
+void nv::gl_window::make_current()
+{
+#if NV_PLATFORM == NV_WINDOWS
+	HDC hdc = reinterpret_cast<HDC>( m_hwnd );
+	dynwglMakeCurrent( hdc, reinterpret_cast<HGLRC>( m_context->get_native_handle() ) );
+#endif
+}
+
+nv::uint32 nv::gl_window::window_id()
+{
+	return SDL_GetWindowID( static_cast<SDL_Window*>( m_handle ) );
+}
+
Index: /trunk/src/lua/lua_state.cc
===================================================================
--- /trunk/src/lua/lua_state.cc	(revision 504)
+++ /trunk/src/lua/lua_state.cc	(revision 505)
@@ -201,5 +201,5 @@
 }
 
-shash64 nv::lua::table_guard::get_string( string_view element, string_table& table, uint64 defval /*= 0 */ )
+nv::shash64 nv::lua::table_guard::get_string( string_view element, string_table* table, uint64 defval /*= 0 */ )
 {
 	lua_getfield( m_state, -1, element.data() );
@@ -210,13 +210,68 @@
 	{
 		str = lua_tolstring( m_state, -1, &l );
-		result = table.insert( string_view( str, l ) );
-	}
-	lua_pop( m_state, 1 );
-	return result;
-}
-
-nv::shash64 nv::lua::table_guard::get_string( string_view element, string_table* table, uint64 defval /*= 0 */ )
-{
-	lua_getfield( m_state, -1, element.data() );
+		string_view sv( str, l );
+		result = table ? table->insert( sv ) : shash64( sv );
+	}
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+shash64 nv::lua::table_guard::get_string_hash_64( int i, uint64 defval /*= 0 */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	size_t l = 0;
+	const char* str = nullptr;
+	uint64 result = defval;
+	if ( lua_type( m_state, -1 ) == LUA_TSTRING )
+	{
+		str = lua_tolstring( m_state, -1, &l );
+		result = hash_string< uint64 >( str, l );
+		//NV_LOG_DEBUG( str );
+	}
+	lua_pop( m_state, 1 );
+	return shash64( result );
+}
+
+nv::string128 nv::lua::table_guard::get_string128( int i, string_view defval /*= string_view() */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	size_t l = 0;
+	const char* str = nullptr;
+	if ( lua_type( m_state, -1 ) == LUA_TSTRING )
+	{
+		str = lua_tolstring( m_state, -1, &l );
+	}
+	else
+	{
+		l = defval.size();
+		str = defval.data();
+	}
+	string128 result( str, l );
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+const_string nv::lua::table_guard::get_string( int i, string_view defval /*= string_view() */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	size_t l = 0;
+	const char* str = nullptr;
+	if ( lua_type( m_state, -1 ) == LUA_TSTRING )
+	{
+		str = lua_tolstring( m_state, -1, &l );
+	}
+	else
+	{
+		l = defval.size();
+		str = defval.data();
+	}
+	const_string result( str, l );
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+shash64 nv::lua::table_guard::get_string( int i, string_table* table, uint64 defval /*= 0 */ )
+{
+	lua_rawgeti( m_state, -1, i );
 	size_t l = 0;
 	const char* str = nullptr;
@@ -302,4 +357,52 @@
 }
 
+char nv::lua::table_guard::get_char( int i, char defval /*= ' ' */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	char result = ( lua_type( m_state, -1 ) == LUA_TSTRING && nlua_rawlen( m_state, -1 ) > 0 ) ? lua_tostring( m_state, -1 )[0] : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+int nv::lua::table_guard::get_integer( int i, int defval /*= 0 */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	lua_Integer result = lua_type( m_state, -1 ) == LUA_TNUMBER ? lua_tointeger( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
+	return static_cast<int>( result );
+}
+
+unsigned nv::lua::table_guard::get_unsigned( int i, unsigned defval /*= 0 */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	unsigned result = lua_type( m_state, -1 ) == LUA_TNUMBER ? nlua_tounsigned( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+double nv::lua::table_guard::get_double( int i, double defval /*= 0.0 */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	double result = lua_type( m_state, -1 ) == LUA_TNUMBER ? lua_tonumber( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+float nv::lua::table_guard::get_float( int i, float defval /*= 0.0 */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	float result = lua_type( m_state, -1 ) == LUA_TNUMBER ? static_cast<float>( lua_tonumber( m_state, -1 ) ) : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+bool nv::lua::table_guard::get_boolean( int i, bool defval /*= false */ )
+{
+	lua_rawgeti( m_state, -1, i );
+	bool result = lua_type( m_state, -1 ) == LUA_TBOOLEAN ? lua_toboolean( m_state, -1 ) != 0 : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
 float nv::lua::table_guard::get_float( string_view element, float defval /*= 0.0 */ )
 {
@@ -326,4 +429,36 @@
 }
 
+bool nv::lua::table_guard::is_table( int i )
+{
+	lua_rawgeti( m_state, -1, i );
+	bool result = lua_type( m_state, -1 ) == LUA_TTABLE;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+bool nv::lua::table_guard::is_number( int i )
+{
+	lua_rawgeti( m_state, -1, i );
+	bool result = lua_type( m_state, -1 ) == LUA_TNUMBER;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+bool nv::lua::table_guard::is_boolean( int i )
+{
+	lua_rawgeti( m_state, -1, i );
+	bool result = lua_type( m_state, -1 ) == LUA_TBOOLEAN;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+bool nv::lua::table_guard::is_string( int i )
+{
+	lua_rawgeti( m_state, -1, i );
+	bool result = lua_type( m_state, -1 ) == LUA_TSTRING;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
 bool nv::lua::table_guard::is_number( string_view element )
 {
@@ -349,5 +484,4 @@
 	return result;
 }
-
 
 bool nv::lua::table_guard::read( const string_view& element, const type_entry* entry, void* object )
Index: /trunk/src/sdl/sdl_input.cc
===================================================================
--- /trunk/src/sdl/sdl_input.cc	(revision 504)
+++ /trunk/src/sdl/sdl_input.cc	(revision 505)
@@ -20,8 +20,9 @@
 static bool sdl_key_event_to_io_event( const SDL_KeyboardEvent& ke, io_event& kevent )
 {
-	kevent.type        = EV_KEY;
-	kevent.key.pressed = ( ke.state != SDL_RELEASED );
-	kevent.key.ascii   = 0;
-	kevent.key.code    = KEY_NONE;
+	kevent.type          = EV_KEY;
+	kevent.key.window_id = ke.windowID;
+	kevent.key.pressed   = ( ke.state != SDL_RELEASED );
+	kevent.key.ascii     = 0;
+	kevent.key.code      = KEY_NONE;
 
 	uint32 ucode = static_cast<uint32>( ke.keysym.sym );
@@ -107,9 +108,10 @@
 static bool sdl_mouse_button_to_io_event( const SDL_MouseButtonEvent& mb, io_event& mevent )
 {
-	mevent.type            = EV_MOUSE_BUTTON;
-	mevent.mbutton.button  = MOUSE_NONE;
-	mevent.mbutton.pressed = (mb.state != SDL_RELEASED);
-	mevent.mbutton.x       = static_cast< uint16 >( mb.x );
-	mevent.mbutton.y       = static_cast< uint16 >( mb.y );
+	mevent.type              = EV_MOUSE_BUTTON;
+	mevent.mbutton.window_id = mb.windowID;
+	mevent.mbutton.button    = MOUSE_NONE;
+	mevent.mbutton.pressed   = (mb.state != SDL_RELEASED);
+	mevent.mbutton.x         = static_cast< uint16 >( mb.x );
+	mevent.mbutton.y         = static_cast< uint16 >( mb.y );
 
 	switch ( mb.button )
@@ -126,7 +128,8 @@
 static bool sdl_mouse_wheel_to_io_event( const SDL_MouseWheelEvent& mm, io_event& mevent )
 {
-	mevent.type          = EV_MOUSE_WHEEL;
-	mevent.mwheel.x      = static_cast< sint32 >( mm.x );
-	mevent.mwheel.y      = static_cast< sint32 >( mm.y );
+	mevent.type             = EV_MOUSE_WHEEL;
+	mevent.mwheel.window_id = mm.windowID;
+	mevent.mwheel.x         = static_cast< sint32 >( mm.x );
+	mevent.mwheel.y         = static_cast< sint32 >( mm.y );
 	return true;
 }
@@ -134,10 +137,11 @@
 static bool sdl_mouse_motion_to_io_event( const SDL_MouseMotionEvent& mm, io_event& mevent )
 {
-	mevent.type          = EV_MOUSE_MOVE;
-	mevent.mmove.pressed = (mm.state != SDL_RELEASED);
-	mevent.mmove.x       = static_cast< uint16 >( mm.x );
-	mevent.mmove.y       = static_cast< uint16 >( mm.y );
-	mevent.mmove.rx      = static_cast< sint16 >( mm.xrel );
-	mevent.mmove.ry      = static_cast< sint16 >( mm.yrel );
+	mevent.type            = EV_MOUSE_MOVE;
+	mevent.mmove.window_id = mm.windowID;
+	mevent.mmove.pressed   = (mm.state != SDL_RELEASED);
+	mevent.mmove.x         = static_cast< uint16 >( mm.x );
+	mevent.mmove.y         = static_cast< uint16 >( mm.y );
+	mevent.mmove.rx        = static_cast< sint16 >( mm.xrel );
+	mevent.mmove.ry        = static_cast< sint16 >( mm.yrel );
 	return true;
 }
@@ -222,4 +226,6 @@
 	case SDL_VIDEOEXPOSE     : return false;
 */
+	case SDL_WINDOWEVENT_ENTER: ioevent.type = EV_SYSTEM; ioevent.system.param1 = 1; ioevent.system.param1 = e.window.windowID; return true;
+	case SDL_WINDOWEVENT_LEAVE: ioevent.type = EV_SYSTEM; ioevent.system.param1 = 0; ioevent.system.param1 = e.window.windowID; return true;
 	case SDL_SYSWMEVENT      : ioevent.type = EV_SYSTEM; return true;
 	case SDL_QUIT            : ioevent.type = EV_QUIT;   return true;
Index: /trunk/src/sdl/sdl_window.cc
===================================================================
--- /trunk/src/sdl/sdl_window.cc	(revision 504)
+++ /trunk/src/sdl/sdl_window.cc	(revision 505)
@@ -133,2 +133,13 @@
 	SDL_GL_SetSwapInterval( enabled ? 1 : 0 );
 }
+
+void nv::sdl::window::make_current()
+{
+	SDL_GLContext native = static_cast<SDL_GLContext>( m_context->get_native_handle() );
+	SDL_GL_MakeCurrent( static_cast<SDL_Window*>( m_handle ), native );
+}
+
+nv::uint32 nv::sdl::window::window_id()
+{
+	return SDL_GetWindowID( static_cast<SDL_Window*>( m_handle ) );
+}
Index: /trunk/src/sdl/sdl_window_manager.cc
===================================================================
--- /trunk/src/sdl/sdl_window_manager.cc	(revision 504)
+++ /trunk/src/sdl/sdl_window_manager.cc	(revision 505)
@@ -17,4 +17,5 @@
 sdl::window_manager::window_manager()
 {
+	primal_window = nullptr;
 	nv::load_sdl_library();
 
@@ -29,5 +30,7 @@
 {
 	if ( ! SDL_WasInit( SDL_INIT_VIDEO ) ) SDL_InitSubSystem( SDL_INIT_VIDEO );
-	return new sdl::window( dev, width, height, fullscreen );
+	sdl::window* result = new sdl::window( dev, width, height, fullscreen );
+	primal_window = result->get_handle();
+	return result;
 }
 
@@ -35,5 +38,12 @@
 {
 	if ( ! SDL_WasInit( SDL_INIT_VIDEO ) ) SDL_InitSubSystem( SDL_INIT_VIDEO );
-	return SDL_CreateWindowFrom( sys_w_handle );
+	if ( primal_window )
+	{
+		char buffer[128];
+		sprintf( buffer, "%p", primal_window );
+		NV_ASSERT( SDL_SetHint( "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT", buffer ) == SDL_TRUE );
+	}
+	primal_window = SDL_CreateWindowFrom( sys_w_handle );
+	return primal_window;
 }
 
Index: /trunk/src/wx/wx_canvas.cc
===================================================================
--- /trunk/src/wx/wx_canvas.cc	(revision 504)
+++ /trunk/src/wx/wx_canvas.cc	(revision 505)
@@ -13,5 +13,5 @@
 wxEND_EVENT_TABLE()
 
-nv::wx_gl_canvas::wx_gl_canvas( wxWindow *parent )
+nv::wx_gl_canvas::wx_gl_canvas( wxWindow *parent, input* in )
 	: wxWindow( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
 	wxFULL_REPAINT_ON_RESIZE )
@@ -19,13 +19,32 @@
 	nv::load_gl_no_context();
 	wxClientDC dc( this );
+	m_render  = true;
+	m_wm      = new nv::sdl::window_manager;
+	m_device  = new nv::gl_device();
+	if ( !in ) in = new nv::sdl::input;
+	m_window = new nv::gl_window( m_device, m_wm, in, GetHWND(), dc.GetHDC() );
+	m_context = m_window->get_context();
+	m_main    = true;
+}
+
+nv::wx_gl_canvas::wx_gl_canvas( wxWindow *parent, wx_gl_canvas *sibling, input* in )
+	: wxWindow( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
+		wxFULL_REPAINT_ON_RESIZE )
+{
+	wxClientDC dc( this );
 	m_render = true;
-	m_wm = new nv::sdl::window_manager;
+	m_wm = sibling->m_wm;
 	m_device = new nv::gl_device();
-	m_window = new nv::gl_window( m_device, m_wm, new nv::sdl::input(), GetHWND(), dc.GetHDC() );
+	if ( !in ) in = new nv::sdl::input;
+	m_window = new nv::gl_window( m_device, m_wm, in, GetHWND(), dc.GetHDC() );
 	m_context = m_window->get_context();
+	make_current();
+	m_main = false;
+
 }
 
 nv::wx_gl_canvas::~wx_gl_canvas()
 {
+	make_current();
 	delete m_window;
 	delete m_device;
@@ -34,4 +53,5 @@
 void nv::wx_gl_canvas::on_paint( wxPaintEvent& )
 {
+	make_current();
 	const wxSize client_size = GetClientSize();
 	m_context->set_viewport( nv::ivec4( nv::ivec2(), client_size.x, client_size.y ) );
@@ -53,10 +73,16 @@
 void nv::wx_gl_canvas::on_idle( wxIdleEvent& evt )
 {
-	nv::sleep( 10 );
+	nv::sleep( 1 );
 	if ( m_render )
 	{
+		make_current();
 		on_update();
 		evt.RequestMore(); // render continuously, not only once on idle
 	}
+}
+
+void nv::wx_gl_canvas::make_current()
+{
+	m_window->make_current();
 }
 
