Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 422)
+++ trunk/src/formats/assimp_loader.cc	(revision 423)
@@ -200,5 +200,5 @@
 		mat4    offset = assimp_mat4_cast( bone->mOffsetMatrix );
 //		bones[m].name = bone->mName.data;
-		bones[m].name_hash = hash_string< uint64 >( bone->mName.data );
+		bones[m].name = hash_string< uint64 >( bone->mName.data );
 		bones[m].data = nullptr;
 		bones[m].parent_id = -1;
@@ -302,5 +302,5 @@
 
 				mesh_node_data& bone = bones[b];
-				auto iname = names.find( bone.name_hash );
+				auto iname = names.find( bone.name );
 				if ( iname == names.end() )
 				{
@@ -308,5 +308,5 @@
 					uint16 index = uint16( final_bones.size() );
 					final_bones.push_back( bone );
-					names[ bone.name_hash] = index;
+					names[ bone.name] = index;
 					translate[b] = index;
 				}
@@ -336,5 +336,6 @@
 	mesh_node_data* bones = new mesh_node_data[ final_bones.size() ];
 	raw_copy( final_bones.begin(), final_bones.end(), bones );
-	return new mesh_nodes_data( "bones", final_bones.size(), bones );
+	int name_;
+	return new mesh_nodes_data( /*"bones"*/0, final_bones.size(), bones );
 }
 
@@ -357,5 +358,6 @@
 	load_node( index, data, root, 0, -1 );
 
-	return new mesh_nodes_data( anim->mName.data, count, data, frame_rate, duration, flat );
+	int name;
+	return new mesh_nodes_data( /*anim->mName.data*/0, count, data, frame_rate, duration, flat );
 }
 
@@ -389,5 +391,5 @@
 
 //	a_data.name      = name;
-	a_data.name_hash = hash_string< uint64 >( name.c_str() );
+	a_data.name = hash_string< uint64 >( name.c_str() );
 	a_data.parent_id = parent_id;
 	// This value is ignored by the create_transformed_keys, but needed by create_direct_keys!
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 422)
+++ trunk/src/formats/md3_loader.cc	(revision 423)
@@ -426,10 +426,11 @@
 
 		nodes[i].transform = mat4();
-		nodes[i].name_hash = hash_string< uint64 >( name.data() );
+		nodes[i].name = hash_string< uint64 >( name.data() );
 		nodes[i].parent_id = -1;
 		nodes[i].data      = data_channel_set_creator::create( 1 );
 		load_tags( data_channel_set_creator( nodes[i].data ).add_channel<md3_key>( uint32( md3->header.num_frames ) ).channel(), name );
 	}
-	return new mesh_nodes_data( "tags", node_count, nodes );
+	int name_;
+	return new mesh_nodes_data( 0,/*"tags"*/ node_count, nodes );
 }
 
Index: trunk/src/formats/md5_loader.cc
===================================================================
--- trunk/src/formats/md5_loader.cc	(revision 422)
+++ trunk/src/formats/md5_loader.cc	(revision 423)
@@ -112,5 +112,6 @@
 			assert( m_nodes == nullptr );
 			nodes = new mesh_node_data[ num_joints ];
-			m_nodes = new mesh_nodes_data( "md5_bones", num_joints, nodes );
+			int name_; //"md5_bones"
+			m_nodes = new mesh_nodes_data( 0, num_joints, nodes );
 			discard( sstream, "{" );
 			for ( size_t i = 0; i < m_nodes->get_count(); ++i )
@@ -128,5 +129,5 @@
 				remove_quotes( name );
 //				nodes[i].name = name;
-				nodes[i].name_hash = hash_string< uint64 >( name.c_str() );
+				nodes[i].name = hash_string< uint64 >( name.c_str() );
 //				nodes[i].target_id       = -1;
 				nodes[i].parent_id       = -1;
@@ -242,5 +243,6 @@
 			assert( nodes == nullptr );
 			nodes = new mesh_node_data[ num_joints ];
-			m_nodes = new mesh_nodes_data( "md5_animation", num_joints, nodes, static_cast< nv::uint16 >( frame_rate ), static_cast< float >( num_frames ), true );
+			int name_;
+			m_nodes = new mesh_nodes_data( 0/*"md5_animation"*/, num_joints, nodes, static_cast< nv::uint16 >( frame_rate ), static_cast< float >( num_frames ), true );
 			joint_infos.resize( num_joints );
 
@@ -252,5 +254,5 @@
 				remove_quotes( name );
 //				nodes[i].name = name;
-				nodes[i].name_hash = hash_string< uint64 >( name.c_str() );
+				nodes[i].name = hash_string< uint64 >( name.c_str() );
 				nodes[i].transform = mat4();
 				nodes[i].data = data_channel_set_creator::create( 1 );
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 422)
+++ trunk/src/formats/nmd_loader.cc	(revision 423)
@@ -28,5 +28,5 @@
 		case nmd_type::MESH           : load_mesh( source, element_header ); break;
 		case nmd_type::ANIMATION      : load_animation( source, element_header ); break;
-//		case nmd_type::STRING_TABLE   : load_strings( source ); break;
+		case nmd_type::STRINGS        : load_strings( source ); break;
 		default: NV_ASSERT( false, "UNKNOWN NMD ELEMENT!" ); break;
 		}
@@ -68,5 +68,5 @@
 {
 	for ( auto mesh : m_meshes ) if ( mesh ) delete mesh;
-//	if ( m_strings )   delete m_strings;
+	if ( m_strings )   delete m_strings;
 	if ( m_node_data ) delete m_node_data;
 	m_meshes.clear();
@@ -76,5 +76,5 @@
 	m_node_data  = nullptr;
 	m_node_array = nullptr;
-//	m_strings    = nullptr;
+	m_strings    = nullptr;
 }
 
@@ -90,8 +90,9 @@
 }
 
-bool nv::nmd_loader::load_strings( stream& /*source*/ )
-{
-//	NV_ASSERT( m_strings == nullptr, "MULTIPLE STRING ENTRIES!" );
-//	m_strings = new string_table( &source );
+bool nv::nmd_loader::load_strings( stream& source )
+{
+	NV_ASSERT( m_strings == nullptr, "MULTIPLE STRING ENTRIES!" );
+	// TODO: load strings optionally
+	m_strings = new string_table( source );
 	return true;
 }
@@ -112,5 +113,5 @@
 		load_node( source, &m_node_array[i], element_header );
 	}
-	m_node_data = new mesh_nodes_data( "animation", e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
+	m_node_data = new mesh_nodes_data( e.name, e.children, m_node_array, animation_header.frame_rate, animation_header.duration, animation_header.flat );
 	return true;
 }
@@ -118,5 +119,5 @@
 bool nv::nmd_loader::load_node( stream& source, mesh_node_data* data, const nmd_element_header& e )
 {
-	data->name_hash = e.name_hash;
+	data->name = e.name;
 	data->parent_id = e.parent_id;
 	data->transform = e.transform;
@@ -190,26 +191,4 @@
 }
 
-static void nmd_dump_mesh( const data_channel_set* mesh, stream& stream_out )
-{
-	uint32 size = 0;
-	for ( auto& chan : *mesh )
-	{
-		size += sizeof( nmd_channel_header );
-		size += chan.raw_size();
-	}
-
-	nmd_element_header eheader;
-	eheader.type       = nmd_type::MESH;
-//	eheader.name       = 0;
-	eheader.children   = static_cast< uint16 >( mesh->size() );
-	eheader.size       = size;
-	eheader.name_hash  = 0;
-	eheader.transform  = mat4();
-	eheader.parent_id  = -1;
-	eheader.attributes = 0;
-	stream_out.write( &eheader, sizeof( eheader ), 1 );
-	nmd_dump_channel_set( mesh, stream_out );
-}
-
 static void nmd_dump_node( const mesh_node_data* node, stream& stream_out )
 {
@@ -227,5 +206,5 @@
 	eheader.children   = static_cast<uint16>( chan_count );
 	eheader.size       = chan_size;
-	eheader.name_hash  = node->name_hash;
+	eheader.name       = node->name;
 	eheader.parent_id  = node->parent_id;
 	eheader.transform  = node->transform;
@@ -235,10 +214,46 @@
 }
 
-static void nmd_dump_nodes_data( const mesh_nodes_data* nodes, stream& stream_out, string_table_creator* /*strings*/ )
+void nv::nmd_dump_header( stream& stream_out, uint32 elements, uint64 name )
+{
+	nmd_header header;
+	header.id = four_cc<'n', 'm', 'f', '1'>::value;
+	header.elements = elements; // +1 string array
+	header.name = name;
+	header.version = 1;
+	header.attributes = 0;
+	stream_out.write( &header, sizeof( header ), 1 );
+}
+
+void nv::nmd_dump_mesh( stream& stream_out, const data_channel_set& mesh )
+{
+	uint32 size = 0;
+	for ( auto& chan : mesh )
+	{
+		size += sizeof( nmd_channel_header );
+		size += chan.raw_size();
+	}
+
+	nmd_element_header eheader;
+	eheader.type       = nmd_type::MESH;
+	eheader.children   = static_cast<uint16>( mesh.size() );
+	eheader.size       = size;
+	int uncomment;
+// 	eheader.name       = mesh.get_name();
+// 	eheader.transform  = mesh.get_transform();
+// 	eheader.parent_id  = mesh.get_parent_id();
+ 	eheader.name       = 0;
+ 	eheader.transform  = mat4();
+ 	eheader.parent_id  = -1;
+	eheader.attributes = 0;
+	stream_out.write( &eheader, sizeof( eheader ), 1 );
+	nmd_dump_channel_set( &mesh, stream_out );
+}
+
+void nv::nmd_dump_nodes( stream& stream_out, const mesh_nodes_data& nodes )
 {
 	uint32 total = sizeof( nmd_animation_header );
-	for ( uint32 i = 0; i < nodes->get_count(); ++i )
-	{
-		const mesh_node_data* node = nodes->get_node(i);
+	for ( uint32 i = 0; i < nodes.get_count(); ++i )
+	{
+		const mesh_node_data* node = nodes.get_node( i );
 		total += sizeof( nmd_element_header );
 		if ( node->data )
@@ -246,16 +261,15 @@
 			{
 				total += sizeof( nmd_channel_header );
-				total += node->data->get_channel(c)->raw_size();
+				total += node->data->get_channel( c )->raw_size();
 			}
 	}
 
 	nmd_element_header header;
-//	header.name       = 0;
-	header.type       = nmd_type::ANIMATION;
-	header.children   = static_cast< uint16 >( nodes->get_count() );
-	header.size       = total;
-	header.name_hash  = 0;
-	header.transform  = mat4();
-	header.parent_id  = -1;
+	header.type = nmd_type::ANIMATION;
+	header.children = static_cast<uint16>( nodes.get_count() );
+	header.size = total;
+	header.name = nodes.get_name();
+	header.transform = mat4();
+	header.parent_id = -1;
 	header.attributes = 0;
 
@@ -263,48 +277,48 @@
 
 	nmd_animation_header aheader;
-	aheader.frame_rate  = nodes->get_frame_rate();
-	aheader.duration    = nodes->get_duration();
-	aheader.flat        = nodes->is_flat();
+	aheader.frame_rate = nodes.get_frame_rate();
+	aheader.duration = nodes.get_duration();
+	aheader.flat = nodes.is_flat();
 	stream_out.write( &aheader, sizeof( aheader ), 1 );
 
-	for ( uint32 i = 0; i < nodes->get_count(); ++i )
-	{
-		nmd_dump_node( nodes->get_node( i ), stream_out );
-	}
-}
-
-void nv::nmd_dump( const mesh_data_pack* model, stream& stream_out )
-{
-	string_table_creator strings;
-	{
-		nmd_header header;
-		header.id       = four_cc<'n','m','f','1'>::value;
-		header.elements = 0; // +1 string array
-		header.elements += model->get_count();
-		if ( model->get_nodes() && model->get_nodes()->get_count() > 0 ) 
-			header.elements += 1;//  +1 bone array
-		header.version  = 1;
-		header.attributes = 0;
-		stream_out.write( &header, sizeof( header ), 1 );
-	}
+	for ( uint32 i = 0; i < nodes.get_count(); ++i )
+	{
+		nmd_dump_node( nodes.get_node( i ), stream_out );
+	}
+}
+
+void nv::nmd_dump_strings( stream& stream_out, const string_table& strings )
+{
+	nmd_element_header sheader;
+	sheader.type       = nv::nmd_type::STRINGS;
+	sheader.children   = 0;
+	sheader.size       = strings.dump_size();
+	sheader.name       = 0;
+	sheader.parent_id  = -1;
+    sheader.attributes = 0;
+	stream_out.write( &sheader, sizeof( sheader ), 1 );
+	strings.dump( stream_out );
+}
+
+void nv::nmd_dump( stream& stream_out, const mesh_data_pack* model, const string_table* strings, uint64 name )
+{
+	uint32 elements = ( strings ? 1 : 0 ) // +1 string array
+		+ model->get_count() // meshes
+		+ ( model->get_node_count() > 0 ? 1 : 0 ); // nodes
+	nmd_dump_header( stream_out, elements, name );
 
 	for ( uint32 i = 0; i < model->get_count(); ++i )
 	{
-		const data_channel_set* mesh = model->get_mesh(i);
-		nmd_dump_mesh( mesh, stream_out );
-	}
-
-	if ( model->get_nodes() && model->get_nodes()->get_count() > 0 )
-	{
-		nmd_dump_nodes_data( model->get_nodes(), stream_out, &strings );
-	}
-
-// 	nmd_element_header sheader;
-// 	sheader.type     = nv::nmd_type::STRING_TABLE;
-// 	sheader.name     = 0;
-// 	sheader.size     = strings.dump_size();
-// 	sheader.children = 0;
-//  sheader.attributes = 0;
-// 	stream_out.write( &sheader, sizeof( sheader ), 1 );
-// 	strings.dump( &stream_out );
-}
+		nmd_dump_mesh( stream_out, *model->get_mesh( i ) );
+	}
+
+	if ( model->get_node_count() > 0 )
+	{
+		nmd_dump_nodes( stream_out, *model->get_nodes() );
+	}
+
+	if ( strings )
+	{
+		nmd_dump_strings( stream_out, *strings );
+	}
+}
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 422)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 423)
@@ -178,5 +178,5 @@
 	{
 		const mesh_node_data* bone = bones->get_node(bi);
-		bone_names[ bone->name_hash ] = bi;
+		bone_names[ bone->name ] = bi;
 		m_offsets[bi] = bone->transform;
 	}
@@ -187,5 +187,5 @@
 		sint16 bone_id = -1;
 
-		auto bi = bone_names.find( node->name_hash );
+		auto bi = bone_names.find( node->name );
 		if ( bi != bone_names.end() )
 		{
