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 );
 	}
