void smart_cover::action::add_animation(LPCSTR type, luabind::object const &table)
{	
	VERIFY						( table.type() == LUA_TTABLE );
	luabind::object::iterator I	= table.begin();
	luabind::object::iterator E	= table.end();
	Animations* animations		= xr_new<Animations>( );
	for ( ; I != E; ++I) {
		luabind::object	string	= *I;
		if (string.type() != LUA_TSTRING) {
			VERIFY				( string.type() != LUA_TNIL );
			continue;
		}

		shared_str animation	= luabind::object_cast<LPCSTR>(string);
		VERIFY2					(
			std::find(
				animations->begin(),
				animations->end(),
				animation
			) == 
			animations->end(),
			make_string(
				"duplicated_animation found: %s",
				animation.c_str()
			)
		);
		animations->push_back	( animation );
	}

	m_animations.insert			( std::make_pair( type, animations ) );
}
void print_free_functions				(lua_State *L, const luabind::object &object, LPCSTR header, const xr_string &indent)
{
	u32							count = 0;
	luabind::object::iterator	I = object.begin();
	luabind::object::iterator	E = object.end();
	for ( ; I != E; ++I) {
		if ((*I).type() != LUA_TFUNCTION)
			continue;
		(*I).pushvalue();
		luabind::detail::free_functions::function_rep* rep = 0;
		if (lua_iscfunction(L, -1))
		{
			if (lua_getupvalue(L, -1, 2) != 0)
			{
				// check the magic number that identifies luabind's functions
				if (lua_touserdata(L, -1) == (void*)0x1337)
				{
					if (lua_getupvalue(L, -2, 1) != 0)
					{
						if (!count)
							FastMsg("\n%snamespace %s {",indent.c_str(),header);
						++count;
						rep = static_cast<luabind::detail::free_functions::function_rep*>(lua_touserdata(L, -1));
						std::vector<luabind::detail::free_functions::overload_rep>::const_iterator	i = rep->overloads().begin();
						std::vector<luabind::detail::free_functions::overload_rep>::const_iterator	e = rep->overloads().end();
						for ( ; i != e; ++i) {
							xr_string	S;
							(*i).get_signature(L,S);
							FastMsg("    %sfunction %s%s;",indent.c_str(),rep->name(), process_signature(S).c_str());
						}
						lua_pop(L, 1);
					}
				}
				lua_pop(L, 1);
			}
		}
		lua_pop(L, 1);
	}
	{
		static xr_vector<xr_string> nesting_path;

		xr_string				_indent = indent;
		xr_string				last_key = "?";
		_indent.append			("    ");
		
		object.pushvalue();
		int n_table = lua_gettop(L);
		// Msg("# n_table = %d ", n_table);
		lua_pushnil		(L);		
		int save_top = lua_gettop(L);

// #pragma todo("alpet : при загруженной сохраненке здесь иногда происходит сбой invalid key to 'next', а потом креш в недрах Direct3D ")
		while (lua_next(L, n_table) != 0) {  
			last_key = "~"; 
			int key_type = lua_type(L, -2);			
			if (lua_type(L, -1) == LUA_TTABLE && key_type == LUA_TSTRING && lua_objlen(L, -2) > 0) {				
				last_key = lua_tostring(L, -2);
				LPCSTR	S = last_key.c_str();
				MsgCB("~#CONTEXT: last_key = %s", S);
				string_path script_name;
				sprintf_s(script_name, sizeof(script_name) - 1, "%s.script", S);
				if (nesting_path.size() == 0 && // скан глобального пространства имен
					(last_key == "" || last_key == "config" || last_key == "package" || last_key == "jit" || last_key == "loaded" || last_key == "md_list" ||
   					 FS.exist("$game_scripts$", script_name) )) // с дампом экспортируемых luabind вещей, возникают сбои!
				{
					Msg("! skipping namespace %s ", last_key.c_str());
					lua_pop(L, 1);
					continue;
				}
				
				if (xr_strcmp("_G", S)) {					
					luabind::object		object(L);
					object.set();
					// if (!xr_strcmp("security", S)) { S = S; } /// wtf?
					xr_string path_dump = "";
					for (u32 ns = 0; ns < nesting_path.size(); ns++)
						path_dump = path_dump + nesting_path.at(ns) + ".";

					path_dump = path_dump + S;
					Msg("#dumping namespace %s ", path_dump.c_str());
					nesting_path.push_back(S);

					u32 nest_level = nesting_path.size();
					// если слишком много вложений или начали повторяться строки
					if (nest_level < 2 &&
						!(nest_level > 1 && nesting_path.at(0) == S)
						)
					{
						print_free_functions(L, object, S, _indent);
					}
					else
					{
						// problem detected
						Msg("! WARN: to many nested levels for export = %d, or self-reference detected ", nest_level);
						FlushLog();
						dumper->flush();
					}
					nesting_path.pop_back();

				}
			}
			// #pragma todo("Dima to Dima : Remove this hack if find out why")			
			
			// */			
			// lua_pop	(L, 1);	// remove value from stack
			lua_pop(L, 1);
			if (lua_gettop(L) > save_top)
			{
				Msg("lua_gettop returned %d vs expected %d", lua_gettop(L), save_top);
				lua_settop(L, save_top);
			}
		} 		
		
	}
	if (count)
		FastMsg("%s};",indent.c_str());
}
void print_free_functions				(lua_State *L, const luabind::object &object, LPCSTR header, const xr_string &indent)
{
	u32							count = 0;
	luabind::object::iterator	I = object.begin();
	luabind::object::iterator	E = object.end();
	for ( ; I != E; ++I) {
		if ((*I).type() != LUA_TFUNCTION)
			continue;
		(*I).pushvalue();
		luabind::detail::free_functions::function_rep* rep = 0;
		if (lua_iscfunction(L, -1))
		{
			if (lua_getupvalue(L, -1, 2) != 0)
			{
				// check the magic number that identifies luabind's functions
				if (lua_touserdata(L, -1) == (void*)0x1337)
				{
					if (lua_getupvalue(L, -2, 1) != 0)
					{
						if (!count)
							Msg("\n%snamespace %s {",indent.c_str(),header);
						++count;
						rep = static_cast<luabind::detail::free_functions::function_rep*>(lua_touserdata(L, -1));
						std::vector<luabind::detail::free_functions::overload_rep>::const_iterator	i = rep->overloads().begin();
						std::vector<luabind::detail::free_functions::overload_rep>::const_iterator	e = rep->overloads().end();
						for ( ; i != e; ++i) {
							xr_string	S;
							(*i).get_signature(L,S);
							Msg("    %sfunction %s%s;",indent.c_str(),rep->name(),process_signature(S).c_str());
						}
						lua_pop(L, 1);
					}
				}
				lua_pop(L, 1);
			}
		}
		lua_pop(L, 1);
	}
	{
		xr_string				_indent = indent;
		_indent.append			("    ");
		object.pushvalue();
		lua_pushnil		(L);
		while (lua_next(L, -2) != 0) {
			if (lua_type(L, -1) == LUA_TTABLE) {
				if (xr_strcmp("_G",lua_tostring(L, -2))) {
					LPCSTR				S = lua_tostring(L, -2);
					luabind::object		object(L);
					object.set			();
					if (!xr_strcmp("security",S)) {
						S = S;
					}
					print_free_functions(L,object,S,_indent);
				}
			}
#pragma todo("Dima to Dima : Remove this hack if find out why")
			if (lua_isnumber(L,-2)) {
				lua_pop(L,1);
				lua_pop(L,1);
				break;
			}
			lua_pop	(L, 1);
		}
	}
	if (count)
		Msg("%s};",indent.c_str());
}