bool ESceneAIMapTool::GenerateMap(bool bFromSelectedOnly)
{
	std::sort(m_ignored_materials.begin(),m_ignored_materials.end());
	bool bRes = false;
	if (!GetSnapList()->empty()){
	    if (!RealUpdateSnapList()) return false;
	    if (m_Nodes.empty()){
			ELog.DlgMsg(mtError,"Append at least one node.");
            return false;
        }

        if (!m_Flags.is(flSlowCalculate)){
            // evict resources
            ExecCommand				(COMMAND_EVICT_OBJECTS);
            ExecCommand				(COMMAND_EVICT_TEXTURES);
        
            // prepare collision model
            u32 avg_face_cnt 		= 0;
            u32 avg_vert_cnt 		= 0;
            u32 mesh_cnt		 	= 0;
            Fbox snap_bb;			
            {
                snap_bb.invalidate	();
                for (ObjectIt o_it=m_SnapObjects.begin(); o_it!=m_SnapObjects.end(); o_it++){
                    CSceneObject* 	S = dynamic_cast<CSceneObject*>(*o_it); VERIFY(S);
                    avg_face_cnt	+= S->GetFaceCount();
                    avg_vert_cnt	+= S->GetVertexCount();
                    mesh_cnt	   	+= S->Meshes()->size();
                    Fbox 			bb;
                    S->GetBox		(bb);
                    snap_bb.merge	(bb);
                }
            }

            SPBItem* pb = UI->ProgressStart(mesh_cnt,"Prepare collision model...");

            CDB::Collector* CL		= ETOOLS::create_collector();
            Fvector verts[3];
            for (ObjectIt o_it=m_SnapObjects.begin(); o_it!=m_SnapObjects.end(); o_it++)
            {
                CSceneObject* 		S = dynamic_cast<CSceneObject*>(*o_it); VERIFY(S);
                CEditableObject*    E = S->GetReference(); VERIFY(E);
                EditMeshVec& 		_meshes = E->Meshes();
                for (EditMeshIt m_it=_meshes.begin(); m_it!=_meshes.end(); m_it++)
                {
                    pb->Inc(AnsiString().sprintf("%s [%s]",S->Name,(*m_it)->Name().c_str()).c_str());
                    const SurfFaces&	_sfaces = (*m_it)->GetSurfFaces();
                    for (SurfFaces::const_iterator sp_it=_sfaces.begin(); sp_it!=_sfaces.end(); sp_it++)
                    {
                        CSurface* surf		= sp_it->first;
                        // test passable
    //.			        SGameMtl* mtl 		= GMLib.GetMaterialByID(surf->_GameMtl());
    //.					if (mtl->Flags.is(SGameMtl::flPassable))continue;

                        Shader_xrLC* c_sh	= Device.ShaderXRLC.Get(surf->_ShaderXRLCName());
                        if (!c_sh->flags.bCollision) 			continue;
                        // collect tris
                        const IntVec& face_lst 	= sp_it->second;
                        for (IntVec::const_iterator it=face_lst.begin(); it!=face_lst.end(); it++)
                        {
                            E->GetFaceWorld	(S->_Transform(),*m_it,*it,verts);

                            ETOOLS::collector_add_face_d(CL,verts[0],verts[1],verts[2], surf->_GameMtl() /* *it */);
                            if (surf->m_Flags.is(CSurface::sf2Sided))
                                ETOOLS::collector_add_face_d(CL,verts[2],verts[1],verts[0], surf->_GameMtl() /* *it */);
                        }
                    }
                }
            }

            UI->ProgressEnd(pb);

            UI->SetStatus		("Building collision model...");
            // create CFModel
            m_CFModel 			= ETOOLS::create_model_cl(CL);
            ETOOLS::destroy_collector(CL);
    	}

        // building
        Scene->lock			();
CTimer tm;
tm.Start();
        BuildNodes			(bFromSelectedOnly);
tm.GetElapsed_sec();
        Scene->unlock		();
//.        Log("-test time: ",	g_tm.GetElapsed_sec());
		Log("-building time: ",tm.GetElapsed_sec());
//.        Msg("-Rate: %3.2f Count: %d",(g_tm.GetElapsed_sec()/tm.GetElapsed_sec())*100.f,g_tm.count);

        // unload CFModel
		ETOOLS::destroy_model(m_CFModel);

        Scene->UndoSave		();
        bRes = true;

        UI->SetStatus		("");
    }else{
    	ELog.DlgMsg(mtError,"Fill snap list before generating slots!");
    }
    return bRes;
}