Index: /trunk/nv/interface/stream.hh
===================================================================
--- /trunk/nv/interface/stream.hh	(revision 278)
+++ /trunk/nv/interface/stream.hh	(revision 279)
@@ -32,5 +32,5 @@
 		virtual ~stream() {}
 		virtual size_t read( void* buffer, size_t size, size_t count ) = 0;
-		virtual size_t write( void* buffer, size_t size, size_t count ) = 0;
+		virtual size_t write( const void* buffer, size_t size, size_t count ) = 0;
 		virtual bool seek( long offset, origin orig ) = 0;
 		virtual size_t tell() = 0;
Index: /trunk/nv/io/c_stream.hh
===================================================================
--- /trunk/nv/io/c_stream.hh	(revision 278)
+++ /trunk/nv/io/c_stream.hh	(revision 279)
@@ -29,5 +29,5 @@
 		virtual ~c_stream();
 		virtual size_t read( void* buffer, size_t size, size_t count );
-		virtual size_t write( void* buffer, size_t size, size_t count );
+		virtual size_t write( const void* buffer, size_t size, size_t count );
 		virtual bool seek( long offset, origin orig );
 		virtual size_t tell();
Index: /trunk/nv/io/string_table.hh
===================================================================
--- /trunk/nv/io/string_table.hh	(revision 279)
+++ /trunk/nv/io/string_table.hh	(revision 279)
@@ -0,0 +1,125 @@
+// Copyright (C) 2014 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+/**
+ * @file string_table.hh
+ * @author Kornel Kisielewicz
+ */
+
+#ifndef NV_IO_STRING_TABLE_HH
+#define NV_IO_STRING_TABLE_HH
+
+#include <nv/common.hh>
+#include <nv/array.hh>
+#include <unordered_map>
+#include <nv/interface/stream.hh>
+
+namespace nv
+{
+
+	class string_table : noncopyable
+	{
+	public:
+		string_table( char* data, uint32 size, uint32* indices, uint32 count )
+			: m_count( count ), m_size( size ), m_data( data ), m_indices( indices )
+		{
+
+		}
+		explicit string_table( nv::stream* in )
+		{
+			load( in );
+		}
+
+		const char* get( uint16 index )
+		{
+			return index < m_count ? m_data + m_indices[index] : nullptr;
+		}
+
+		void dump( nv::stream* out )
+		{
+			out->write( &m_count,  sizeof( m_count ), 1 );
+			out->write( &m_size,   sizeof( m_size ), 1 );
+			out->write( m_indices, sizeof( uint32 ), m_count );
+			out->write( m_data,    sizeof( char ), m_size );
+		}
+
+		~string_table()
+		{
+			delete[] m_data;
+			delete[] m_indices;
+		}
+	private:
+		void load( stream* in )
+		{
+			in->read( &m_count, sizeof( m_count ), 1 );
+			in->read( &m_size, sizeof( m_size ), 1 );
+			m_indices = new uint32[ m_count ];
+			m_data    = new char[ m_count ];
+			in->read( m_indices, sizeof( uint32 ), m_count );
+			in->read( m_data,    sizeof( char ), m_size );
+		}
+
+		uint32  m_count;
+		uint32  m_size;
+		uint32* m_indices;
+		char*   m_data;
+	};
+
+	class string_table_creator
+	{
+	public:
+		string_table_creator() {}
+
+		uint32 insert( const char* s )
+		{
+			return insert( std::string(s) );
+		}
+
+		uint32 insert( const std::string& s )
+		{
+			auto i = m_map.find( s );
+			if ( i != m_map.end() )
+			{
+				return i->second;
+			}
+			const char* cs = s.c_str();
+			uint32 cs_size = s.size() + 1;
+			uint32 result = m_indexes.size();
+			uint32 index  = m_data.size();
+			m_indexes.push_back( index );
+			std::copy( cs, cs + cs_size, std::back_inserter( m_data ) );
+			m_map[ s ] = result;
+			return result;
+		}
+
+		string_table* create_table() const
+		{
+			uint32* indexes = new uint32[m_indexes.size()];
+			char*   data    = new char  [m_data.size()];
+			std::copy( m_indexes.begin(), m_indexes.end(), indexes );
+			std::copy( m_data.begin(),    m_data.end(),    data );
+			return new string_table( data, m_data.size(), indexes, m_indexes.size() );
+		}
+
+		void dump( nv::stream* out ) const
+		{
+			uint32 count = m_indexes.size();
+			uint32 size  = m_data.size();
+			out->write( &count,  sizeof( count ), 1 );
+			out->write( &size,   sizeof( size ), 1 );
+			out->write( m_indexes.data(), sizeof( uint16 ), count );
+			out->write( m_data.data(),    sizeof( char ), size );
+		}
+	private:
+		std::unordered_map< std::string, uint32 > m_map;
+		std::vector< uint32 > m_indexes;
+		std::vector< char >   m_data;
+	};
+
+
+}
+
+#endif // NV_IO_STRING_TABLE_HH
Index: /trunk/src/formats/assimp_loader.cc
===================================================================
--- /trunk/src/formats/assimp_loader.cc	(revision 278)
+++ /trunk/src/formats/assimp_loader.cc	(revision 279)
@@ -391,4 +391,8 @@
 	a_data.parent_id = parent_id;
 	a_data.bone_id = -1;
+	// This value is ignored by the create_transformed_keys, but needed by create_direct_keys!
+	// TODO: find a common solution!
+	//       This is bad because create_transformed_keys never uses node-transformations for
+	//       node's without keys
 	a_data.transform = nv::assimp_mat4_cast( node->mTransformation );
 
Index: /trunk/src/io/c_stream.cc
===================================================================
--- /trunk/src/io/c_stream.cc	(revision 278)
+++ /trunk/src/io/c_stream.cc	(revision 279)
@@ -40,5 +40,5 @@
 }
 
-size_t c_stream::write( void* buffer, size_t size, size_t count )
+size_t c_stream::write( const void* buffer, size_t size, size_t count )
 {
 	NV_ASSERT( buffer != nullptr && size != 0 && count != 0, "Bad parameter passed to write!" );
