//------------------------------------------------------------------------------ bool CPSLibrary::Save2() { FS.dir_delete("$game_particles$","",TRUE); string_path fn; SPBItem* pb = UI->ProgressStart(m_PEDs.size()+m_PGDs.size(),"Saving particles..."); for (PS::PEDIt it=m_PEDs.begin(); it!=m_PEDs.end(); ++it) { pb->Inc (); PS::CPEDef* pe = (*it); FS.update_path (fn, "$game_particles$", pe->m_Name.c_str()); strcat (fn,".pe"); CInifile ini(fn,FALSE,FALSE,FALSE); pe->Save2 (ini); ini.save_as (fn); } for (PS::PGDIt g_it=m_PGDs.begin(); g_it!=m_PGDs.end(); ++g_it) { pb->Inc (); PS::CPGDef* pg = (*g_it); FS.update_path (fn, "$game_particles$", pg->m_Name.c_str()); strcat (fn,".pg"); CInifile ini(fn,FALSE,FALSE,FALSE); pg->Save2 (ini); ini.save_as (fn); } UI->ProgressEnd (pb); return true; }
bool EDetailManager::UpdateObjects(bool bUpdateTex, bool bUpdateSelectedOnly) { m_Base.ReloadImage(); if (!m_Base.Valid()){ ELog.DlgMsg(mtError,"Invalid base texture!"); return false; } if (objects.empty()){ ELog.DlgMsg(mtError,"Object list empty!"); return false; } // update objects SPBItem* pb = UI->ProgressStart(dtH.size_x*dtH.size_z,"Updating objects..."); for (u32 z=0; z<dtH.size_z; z++) for (u32 x=0; x<dtH.size_x; x++){ if (!bUpdateSelectedOnly||(bUpdateSelectedOnly&&m_Selected[z*dtH.size_x+x])) UpdateSlotObjects(x,z); pb->Inc(); } UI->ProgressEnd(pb); InvalidateCache (); return true; }
void TfraBottomBar::RedrawBar() { SPBItem* pbi = UI->ProgressLast(); if (pbi){ AnsiString txt; float p,m; pbi->GetInfo(txt,p,m); // status line if (paStatus->Caption!=txt){ paStatus->Caption = txt; paStatus->Repaint (); } // progress int val = fis_zero(m)?0:(int)((p/m)*100); if (val!=cgProgress->Progress){ cgProgress->Progress = val; cgProgress->Repaint (); } if (false==cgProgress->Visible) cgProgress->Visible = true; }else{ if (cgProgress->Visible){ // status line paStatus->Caption = ""; paStatus->Repaint (); // progress cgProgress->Visible = false; cgProgress->Progress = 0; } } }
void TfrmImageLib::InitItemsList() { if (!form->bImportMode) ImageLib.GetTexturesRaw(texture_map); ListItemsVec items; /* xr_string ltx_nm; FS.update_path (ltx_nm,_game_textures_,"textures.ltx"); CInifile* ltx_ini = xr_new<CInifile> (ltx_nm.c_str(),FALSE,TRUE,FALSE); */ SPBItem* pb = UI->ProgressStart (texture_map.size(),"Fill list..."); // fill FS_FileSetIt it = texture_map.begin(); FS_FileSetIt _E = texture_map.end(); for (; it!=_E; it++) { pb->Inc (); ListItem* I = LHelper().CreateItem(items,it->name.c_str(),0); //. I->tag = ltx_ini->line_exist("types",it->name.c_str())?ltx_ini->r_u32("types",it->name.c_str()):-1; I->tag = Device.Resources->m_textures_description.GetTextureType(it->name.c_str()); Msg("%s-%d",it->name.c_str(),I->tag); } UI->ProgressEnd (pb); m_ItemList->AssignItems (items,false,true); //. xr_delete (ltx_ini); }
void CSoundManager::CleanupSounds() { FS_FileSet M_BASE; FS_FileSet M_THUM; FS_FileSet M_GAME; FS_FileSet M_GAME_DEL; FS_FileSet M_THM_DEL; FS.file_list (M_BASE,_sounds_, FS_ListFiles|FS_ClampExt,"*.wav"); FS.file_list (M_THUM,_sounds_, FS_ListFiles|FS_ClampExt,"*.thm"); FS.file_list (M_GAME,_game_sounds_, FS_ListFiles|FS_ClampExt,"*.ogg"); FS_FileSetIt it; FS_FileSetIt _E; // check source exist it = M_GAME.begin(); _E = M_GAME.end(); for (; it!=_E; it++){ xr_string base_name = EFS.ChangeFileExt(it->name,""); xr_strlwr(base_name); FS_FileSetIt bs = M_BASE.find(base_name); if (bs==M_BASE.end()) M_GAME_DEL.insert (*it); } it = M_THUM.begin(); _E = M_THUM.end(); for (; it!=_E; it++){ xr_string base_name = EFS.ChangeFileExt(it->name,""); xr_strlwr(base_name); FS_FileSetIt bs = M_BASE.find(base_name); if (bs==M_BASE.end()) M_THM_DEL.insert (*it); } SPBItem* pb = UI->ProgressStart(M_GAME_DEL.size()+M_THM_DEL.size(),"Cleanup sounds..."); // mark game del sounds it = M_GAME_DEL.begin(); _E = M_GAME_DEL.end(); for (; it!=_E; it++){ xr_string base_name = EFS.ChangeFileExt(it->name,""); xr_strlwr(base_name); string_path fn; FS.update_path (fn,_game_sounds_,EFS.ChangeFileExt(base_name,".ogg").c_str()); EFS.MarkFile (fn,true); pb->Inc (); } // mark thm sounds it = M_THM_DEL.begin(); _E = M_THM_DEL.end(); for (; it!=_E; it++){ xr_string base_name = EFS.ChangeFileExt(it->name,""); xr_strlwr(base_name); string_path fn; FS.update_path (fn,_sounds_,EFS.ChangeFileExt(base_name,".thm").c_str()); EFS.MarkFile (fn,true); pb->Inc (); } UI->ProgressEnd (pb); }
void CEditableObject::OptimizeSMotions() { #ifdef _EDITOR SPBItem* pb = UI->ProgressStart(m_SMotions.size(),"Motions optimizing..."); #endif for (SMotionIt s_it=m_SMotions.begin(); s_it!=m_SMotions.end(); s_it++){ (*s_it)->Optimize (); #ifdef _EDITOR pb->Inc (); #endif } #ifdef _EDITOR UI->ProgressEnd (pb); #endif }
bool EDetailManager::UpdateSlots() { // clear previous slots xr_free (dtSlots); dtSlots = xr_alloc<DetailSlot>(dtH.size_x*dtH.size_z); SPBItem* pb = UI->ProgressStart(dtH.size_x*dtH.size_z,"Updating bounding boxes..."); for (u32 z=0; z<dtH.size_z; z++){ for (u32 x=0; x<dtH.size_x; x++){ DetailSlot* slot = dtSlots+z*dtH.size_x+x; UpdateSlotBBox (x,z,*slot); pb->Inc(); } } UI->ProgressEnd(pb); m_Selected.resize (dtH.size_x*dtH.size_z); return true; }
void __fastcall TfrmImageLib::ebRebuildAssociationClick(TObject *) { if (ELog.DlgMsg(mtConfirmation,TMsgDlgButtons()<<mbYes<<mbNo,"Are you sure to export association?")==mrNo) return; if (!modif_map.empty()){ int res = ELog.DlgMsg(mtConfirmation,TMsgDlgButtons()<<mbYes<<mbNo<<mbCancel,"Save modified properties?"); switch (res){ case mrYes: UpdateLib(); break; case mrNo: break; case mrCancel: return; } } string_path nm; FS.update_path (nm,_game_textures_,"textures.ltx"); CInifile* ini = xr_new<CInifile>(nm, FALSE, FALSE, TRUE); LockForm (); FS_FileSetIt it = texture_map.begin(); FS_FileSetIt _E = texture_map.end(); SPBItem* pb = UI->ProgressStart(texture_map.size(),"Export association"); bool bRes=true; for (;it!=_E; it++){ ETextureThumbnail* m_Thm = xr_new<ETextureThumbnail>(it->name.c_str()); pb->Inc (it->name.c_str()); AnsiString base_name= ChangeFileExt(it->name.c_str(),""); ImageLib.WriteAssociation (ini,base_name.c_str(),m_Thm->_Format()); xr_delete (m_Thm); if (UI->NeedAbort()){ bRes=false; break; } } UI->ProgressEnd(pb); UnlockForm(); if (!bRes) ini->bSaveAtEnd = false; xr_delete(ini); }
void ESceneAIMapTool::RemoveSelection() { switch (LTools->GetSubTarget()){ case estAIMapNode:{ if (m_Nodes.size()==(u32)SelectionCount(true)){ Clear (true); }else{ SPBItem* pb = UI->ProgressStart(3,"Removing nodes..."); // remove link to sel nodes pb->Inc("erasing nodes"); // remove sel nodes AINodeIt result = std::remove_if(m_Nodes.begin(), m_Nodes.end(), delete_sel_node_pred()); m_Nodes.erase (result,m_Nodes.end()); pb->Inc("updating hash"); hash_Clear (); hash_FillFromNodes (); pb->Inc("end"); UI->ProgressEnd(pb); } }break; } UpdateHLSelected (); UI->RedrawScene (); }
void ESceneAIMapTool::BuildNodes(bool bFromSelectedOnly) { // begin m_Nodes.reserve (1024*1024); // Initialize hash // hash_Initialize (); R_ASSERT(!m_Nodes.empty()); // Estimate nodes Fvector Pos,LevelSize; m_AIBBox.getsize (LevelSize); float estimated_nodes = (LevelSize.x/m_Params.fPatchSize)*(LevelSize.z/m_Params.fPatchSize); SPBItem* pb = UI->ProgressStart(1, "Building nodes..."); // General cycle for (int k=0; k<(int)m_Nodes.size(); k++){ SAINode* N = m_Nodes[k]; if (bFromSelectedOnly && !N->flags.is(SAINode::flSelected)) continue; // left if (0==N->n1){ Pos.set (N->Pos); Pos.x -= m_Params.fPatchSize; N->n1 = BuildNode(N->Pos,Pos,false); } // fwd if (0==N->n2){ Pos.set (N->Pos); Pos.z += m_Params.fPatchSize; N->n2 = BuildNode(N->Pos,Pos,false); } // right if (0==N->n3){ Pos.set (N->Pos); Pos.x += m_Params.fPatchSize; N->n3 = BuildNode(N->Pos,Pos,false); } // back if (0==N->n4){ Pos.set (N->Pos); Pos.z -= m_Params.fPatchSize; N->n4 = BuildNode(N->Pos,Pos,false); } if (bFromSelectedOnly){ // select neighbour nodes if (N->n1) N->n1->flags.set(SAINode::flSelected,TRUE); if (N->n2) N->n2->flags.set(SAINode::flSelected,TRUE); if (N->n3) N->n3->flags.set(SAINode::flSelected,TRUE); if (N->n4) N->n4->flags.set(SAINode::flSelected,TRUE); } if (k%512==0) { float p1 = float(k)/float(m_Nodes.size()); float p2 = float(m_Nodes.size())/estimated_nodes; float p = 0.1f*p1+0.9f*p2; clamp (p,0.f,1.f); pb->Update(p); // check need abort && redraw if (k%32768==0) UI->RedrawScene(true); if (UI->NeedAbort()) break; } } UI->ProgressEnd(pb); }
//------------------------------------------------------------------------------ // возвращает список не синхронизированных (модифицированных) текстур // source_list - содержит список текстур с расширениями // sync_list - реально сохраненные файлы (после использования освободить) //------------------------------------------------------------------------------ void CSoundManager::SynchronizeSounds(bool sync_thm, bool sync_game, bool bForceGame, FS_FileSet* source_list, AStringVec* sync_list, FS_FileSet* modif_map) { FS_FileSet M_BASE; FS_FileSet M_THUM; FS_FileSet M_GAME; if (source_list) M_BASE = *source_list; else FS.file_list(M_BASE,_sounds_,FS_ListFiles|FS_ClampExt,"*.wav"); if (M_BASE.empty()) return; if (sync_thm) FS.file_list(M_THUM,_sounds_,FS_ListFiles|FS_ClampExt,"*.thm"); if (sync_game) FS.file_list(M_GAME,_game_sounds_,FS_ListFiles|FS_ClampExt,"*.ogg"); bool bProgress = M_BASE.size()>1; int m_age = time(NULL); SPBItem* pb = 0; if (bProgress) pb = UI->ProgressStart(M_BASE.size(),"Synchronize sounds..."); FS_FileSetIt it=M_BASE.begin(); FS_FileSetIt _E = M_BASE.end(); for (; it!=_E; it++){ BOOL bUpdated = FALSE; xr_string base_name = EFS.ChangeFileExt(it->name,""); xr_strlwr(base_name); string_path fn; FS.update_path (fn,_sounds_,EFS.ChangeFileExt(base_name,".wav").c_str()); if (!FS.exist(fn)) continue; FS_FileSetIt th = M_THUM.find(base_name); bool bThm = ((th==M_THUM.end()) || ((th!=M_THUM.end())&&(th->time_write!=it->time_write))); FS_FileSetIt gm = M_GAME.find(base_name); bool bGame = bThm || ((gm==M_GAME.end()) || ((gm!=M_GAME.end())&&(gm->time_write!=it->time_write))); ESoundThumbnail* THM = 0; // backup base sound // check thumbnail if (sync_thm&&bThm){ THM = xr_new<ESoundThumbnail>(it->name.c_str()); THM->Save (m_age); bUpdated = TRUE; } // check game sounds if (bForceGame||(sync_game&&bGame)){ if (!THM) THM = xr_new<ESoundThumbnail>(it->name.c_str()); R_ASSERT(THM); string_path src_name; strconcat (sizeof(src_name),src_name, base_name.c_str(), ".wav"); FS.update_path (src_name,_sounds_,src_name); string_path game_name; strconcat (sizeof(game_name),game_name, base_name.c_str(), ".ogg"); FS.update_path (game_name,_game_sounds_,game_name); MakeGameSound (THM,src_name,game_name); if (sync_list) sync_list->push_back(base_name.c_str()); if (modif_map) modif_map->insert(*it); bUpdated = TRUE; } if (THM) xr_delete(THM); if (UI->NeedAbort()) break; if (bProgress) pb->Inc (bUpdated?xr_string(base_name+" - UPDATED.").c_str():"",bUpdated); if (bUpdated){ string_path wav_fn,thm_fn,ogg_fn; FS.update_path (wav_fn,_sounds_, EFS.ChangeFileExt(base_name,".wav").c_str()); FS.update_path (thm_fn,_sounds_, EFS.ChangeFileExt(base_name,".thm").c_str()); FS.update_path (ogg_fn,_game_sounds_, EFS.ChangeFileExt(base_name,".ogg").c_str()); FS.set_file_age (wav_fn,m_age); FS.set_file_age (thm_fn,m_age); FS.set_file_age (ogg_fn,m_age); } } if (bProgress) UI->ProgressEnd(pb); }
bool ESceneObjectTool::ExportBreakableObjects(SExportStreams* F) { bool bResult = true; CGeomPartExtractor* extractor=0; Fbox bb; if (!GetBox(bb)) return false; extractor = xr_new<CGeomPartExtractor>(); extractor->Initialize(bb,EPS_L,2); UI->SetStatus ("Export breakable objects..."); // collect verts&&faces { SPBItem* pb = UI->ProgressStart(m_Objects.size(),"Prepare geometry..."); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++){ pb->Inc(); CSceneObject* obj = dynamic_cast<CSceneObject*>(*it); VERIFY(obj); if (obj->IsStatic()){ CEditableObject *O = obj->GetReference(); const Fmatrix& T = obj->_Transform(); for(EditMeshIt M=O->FirstMesh();M!=O->LastMesh();M++) if (!build_mesh (T,*M,extractor,SGameMtl::flBreakable,FALSE)){bResult=false;break;} } } UI->ProgressEnd(pb); } if (!extractor->Process()) bResult = false; // export parts if (bResult){ SBPartVec& parts = extractor->GetParts(); SPBItem* pb = UI->ProgressStart(parts.size(),"Export Parts..."); for (SBPartVecIt p_it=parts.begin(); p_it!=parts.end(); p_it++){ pb->Inc(); SBPart* P = *p_it; if (P->Valid()){ // export visual AnsiString sn = AnsiString().sprintf("meshes\\brkbl#%d.ogf",(p_it-parts.begin())); xr_string fn = Scene->LevelPath()+sn.c_str(); IWriter* W = FS.w_open(fn.c_str()); R_ASSERT(W); if (!P->Export(*W,1)){ ELog.DlgMsg (mtError,"Invalid breakable object."); bResult = false; break; } FS.w_close (W); // export spawn object { AnsiString entity_ref = "breakable_object"; ISE_Abstract* m_Data = create_entity(entity_ref.c_str()); VERIFY(m_Data); CSE_Visual* m_Visual = m_Data->visual(); VERIFY(m_Visual); // set params m_Data->set_name (entity_ref.c_str()); m_Data->set_name_replace (sn.c_str()); m_Data->position().set (P->m_RefOffset); m_Data->angle().set (P->m_RefRotate); m_Visual->set_visual (sn.c_str(),false); if (s_draw_dbg){ Fmatrix MX; MX.setXYZi (P->m_RefRotate); MX.translate_over (P->m_RefOffset); Fvector DR = {0,0,1}; MX.transform_dir (DR); Tools->m_DebugDraw.AppendLine(P->m_RefOffset,Fvector().mad(P->m_RefOffset,MX.k,1.f),0xFF0000FF,false,false); } NET_Packet Packet; m_Data->Spawn_Write (Packet,TRUE); F->spawn.stream.open_chunk (F->spawn.chunk++); F->spawn.stream.w (Packet.B.data,Packet.B.count); F->spawn.stream.close_chunk (); destroy_entity (m_Data); } }else{ ELog.Msg(mtError,"Can't export invalid part #%d",p_it-parts.begin()); } } UI->ProgressEnd(pb); } // clean up xr_delete(extractor); return bResult; }
bool ESceneObjectTool::ExportClimableObjects(SExportStreams* F) { bool bResult = true; CGeomPartExtractor* extractor = 0; Fbox bb; if (!GetBox(bb)) return false; extractor = xr_new<CGeomPartExtractor>(); extractor->Initialize (bb,EPS_L,int_max); UI->SetStatus ("Export climable objects..."); // collect verts&&faces { SPBItem* pb = UI->ProgressStart(m_Objects.size(), "Prepare geometry..."); for (ObjectIt it=m_Objects.begin(); it!=m_Objects.end(); it++) { pb->Inc(); CSceneObject* obj = dynamic_cast<CSceneObject*>(*it); VERIFY (obj); if (obj->IsStatic()) { CEditableObject *O = obj->GetReference(); const Fmatrix& T = obj->_Transform(); for(EditMeshIt M =O->FirstMesh(); M!=O->LastMesh(); M++) if (!build_mesh (T, *M, extractor, SGameMtl::flClimable, TRUE)) { bResult = false; break; } } } UI->ProgressEnd(pb); } if (!extractor->Process()) bResult = false; // export parts if (bResult) { SBPartVec& parts = extractor->GetParts(); SPBItem* pb = UI->ProgressStart(parts.size(),"Export Parts..."); for (SBPartVecIt p_it=parts.begin(); p_it!=parts.end(); p_it++) { pb->Inc (); SBPart* P = *p_it; if (P->Valid()) { // export visual AnsiString sn = AnsiString().sprintf("clmbl#%d",(p_it-parts.begin())); Fvector local_normal = {0,0,0}; LPCSTR mat_name = NULL; for (SBFaceVecIt it=P->m_Faces.begin(); it!=P->m_Faces.end(); it++) { for (u32 k=0; k<3; k++) local_normal.add ((*it)->n[k]); mat_name = (*it)->surf->_GameMtlName(); } local_normal.normalize_safe (); // export spawn object { AnsiString entity_ref = "climable_object"; ISE_Abstract* m_Data = create_entity(entity_ref.c_str()); VERIFY(m_Data); ISE_Shape* m_Shape = m_Data->shape(); VERIFY(m_Shape); // CSE_Visual* m_Visual = m_Data->visual(); VERIFY(m_Visual); // set params m_Data->set_name (entity_ref.c_str()); m_Data->set_name_replace (sn.c_str()); // set shape CShapeData::shape_def shape; shape.type = CShapeData::cfBox; shape.data.box.scale ((P->m_BBox.max.x-P->m_BBox.min.x)*0.5f, (P->m_BBox.max.y-P->m_BBox.min.y)*0.5f, (P->m_BBox.max.z-P->m_BBox.min.z)*0.5f); m_Shape->assign_shapes (&shape,1); // orientate object if (!OrientToNorm(local_normal,P->m_OBB.m_rotate,P->m_OBB.m_halfsize)) { ELog.Msg(mtError,"Invalid climable object found. [%3.2f, %3.2f, %3.2f]",VPUSH(P->m_RefOffset)); } else { Fmatrix M; M.set (P->m_OBB.m_rotate.i,P->m_OBB.m_rotate.j,P->m_OBB.m_rotate.k,P->m_OBB.m_translate); M.getXYZ (P->m_RefRotate); // не i потому что в движке так m_Data->position().set (P->m_RefOffset); m_Data->angle().set (P->m_RefRotate); m_Data->set_additional_info((void*)mat_name); NET_Packet Packet; m_Data->Spawn_Write (Packet,TRUE); F->spawn.stream.open_chunk (F->spawn.chunk++); F->spawn.stream.w (Packet.B.data,Packet.B.count); F->spawn.stream.close_chunk (); if (s_draw_dbg) { Tools->m_DebugDraw.AppendOBB(P->m_OBB); M.transform_dir (local_normal); Tools->m_DebugDraw.AppendLine(P->m_RefOffset,Fvector().mad(P->m_RefOffset,local_normal,1.f)); } } destroy_entity (m_Data); } }else { ELog.Msg(mtError,"Can't export invalid part #%d",p_it-parts.begin()); } } UI->ProgressEnd (pb); } // clean up xr_delete (extractor); return bResult; }
void ESceneAIMapTool::SmoothNodes() { SPBItem* pb = UI->ProgressStart(m_Nodes.size(), "Smoothing nodes..."); AINodeVec smoothed; smoothed.reserve(m_Nodes.size()); U8Vec mark; mark.assign (m_Nodes.size(),0); int sm_nodes=0; EnumerateNodes (); for (AINodeIt it=m_Nodes.begin(); it!=m_Nodes.end(); it++){ SAINode& N = **it; Fvector P1,P2,P3,P4,P,REF; int c; if (N.flags.is(SAINode::flSelected)){ sm_nodes++; // smooth point LF { bool bCorner = false; c=1; N.PointLF(REF,m_Params.fPatchSize); P1.set(REF); if (N.nLeft()) { SAINode& L = *N.nLeft(); L.PointFR(P,m_Params.fPatchSize); merge(P1); if (L.nForward()) { bCorner = true; SAINode& C = *L.nForward(); C.PointRB(P,m_Params.fPatchSize); merge(P1); } } if (N.nForward()) { SAINode& F = *N.nForward(); F.PointBL(P,m_Params.fPatchSize); merge(P1); if ((!bCorner) && F.nLeft()) { bCorner = true; SAINode& C = *F.nLeft(); C.PointRB(P,m_Params.fPatchSize); merge(P1); } } R_ASSERT(c<=4); P1.div(float(c)); } // smooth point FR { bool bCorner = false; c=1; N.PointFR(REF,m_Params.fPatchSize); P2.set(REF); if (N.nForward()) { SAINode& F = *N.nForward(); F.PointRB(P,m_Params.fPatchSize); merge(P2); if (F.nRight()) { bCorner = true; SAINode& C = *F.nRight(); C.PointBL(P,m_Params.fPatchSize); merge(P2); } } if (N.nRight()) { SAINode& R = *N.nRight(); R.PointLF(P,m_Params.fPatchSize); merge(P2); if ((!bCorner) && R.nForward()) { bCorner = true; SAINode& C = *R.nForward(); C.PointBL(P,m_Params.fPatchSize); merge(P2); } } R_ASSERT(c<=4); P2.div(float(c)); } // smooth point RB { bool bCorner = false; c=1; N.PointRB(REF,m_Params.fPatchSize); P3.set(REF); if (N.nRight()) { SAINode& R = *N.nRight(); R.PointBL(P,m_Params.fPatchSize); merge(P3); if (R.nBack()) { bCorner = true; SAINode& C = *R.nBack(); C.PointLF(P,m_Params.fPatchSize); merge(P3); } } if (N.nBack()) { SAINode& B = *N.nBack(); B.PointFR(P,m_Params.fPatchSize); merge(P3); if ((!bCorner) && B.nRight()) { bCorner = true; SAINode& C = *B.nRight(); C.PointLF(P,m_Params.fPatchSize); merge(P3); } } R_ASSERT(c<=4); P3.div(float(c)); } // smooth point BL { bool bCorner = false; c=1; N.PointBL(REF,m_Params.fPatchSize); P4.set(REF); if (N.nBack()) { SAINode& B = *N.nBack(); B.PointLF(P,m_Params.fPatchSize); merge(P4); if (B.nLeft()) { bCorner = true; SAINode& C = *B.nLeft(); C.PointFR(P,m_Params.fPatchSize); merge(P4); } } if (N.nLeft()) { SAINode& L = *N.nLeft(); L.PointRB(P,m_Params.fPatchSize); merge(P4); if ((!bCorner) && L.nBack()) { bCorner = true; SAINode& C = *L.nBack(); C.PointFR(P,m_Params.fPatchSize); merge(P4); } } R_ASSERT(c<=4); P4.div(float(c)); } // align plane Fvector data[4]; data[0]=P1; data[1]=P2; data[2]=P3; data[3]=P4; Fvector vOffs,vNorm,D; vNorm.set(N.Plane.n); vOffs.set(N.Pos); Mgc::OrthogonalPlaneFit( 4,(Mgc::Vector3*)data, *((Mgc::Vector3*)&vOffs), *((Mgc::Vector3*)&vNorm) ); if (vNorm.y<0) vNorm.invert(); // create _new node SAINode* NEW = xr_new<SAINode>(N); NEW->n1 = (SAINode*)(N.n1?N.n1->idx:InvalidNode); NEW->n2 = (SAINode*)(N.n2?N.n2->idx:InvalidNode); NEW->n3 = (SAINode*)(N.n3?N.n3->idx:InvalidNode); NEW->n4 = (SAINode*)(N.n4?N.n4->idx:InvalidNode); NEW->Plane.build(vOffs,vNorm); D.set (0,1,0); N.Plane.intersectRayPoint(N.Pos,D,NEW->Pos); // "project" position smoothed.push_back (NEW); }else{ // create _new node SAINode* NEW = xr_new<SAINode>(N); NEW->n1 = (SAINode*)(N.n1?N.n1->idx:InvalidNode); NEW->n2 = (SAINode*)(N.n2?N.n2->idx:InvalidNode); NEW->n3 = (SAINode*)(N.n3?N.n3->idx:InvalidNode); NEW->n4 = (SAINode*)(N.n4?N.n4->idx:InvalidNode); smoothed.push_back (NEW); } int k = it-m_Nodes.begin(); if (k%128==0) { pb->Update(k); if (UI->NeedAbort()) break; } } UI->ProgressEnd(pb); Clear (true); m_Nodes = smoothed; DenumerateNodes (); hash_FillFromNodes (); UpdateHLSelected (); if (sm_nodes) Scene->UndoSave(); }
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; }
int ESceneAIMapTool::BuildNodes(const Fvector& pos, int sz, bool bIC) { // Align emitter Fvector Pos = pos; SnapXZ (Pos,m_Params.fPatchSize); Pos.y += 1; Fvector Dir; Dir.set(0,-1,0); int cnt = 0; if (m_CFModel) cnt=Scene->RayQuery(PQ,Pos,Dir,3,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,m_CFModel); else cnt=Scene->RayQuery(PQ,Pos,Dir,3,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,GetSnapList()); if (0==cnt) { ELog.Msg (mtInformation,"Can't align position."); return 0; } else { Pos.y = Pos.y - PQ.r_begin()->range; } // Build first node int oldcount = m_Nodes.size(); SAINode* start = BuildNode(Pos,Pos,bIC); if (!start) return 0; // Estimate nodes float estimated_nodes = (2*sz-1)*(2*sz-1); SPBItem* pb = 0; if (estimated_nodes>1024) pb = UI->ProgressStart(1, "Building nodes..."); float radius = sz*m_Params.fPatchSize-EPS_L; // General cycle for (int k=0; k<(int)m_Nodes.size(); k++){ SAINode* N = m_Nodes[k]; // left if (0==N->n1){ Pos.set (N->Pos); Pos.x -= m_Params.fPatchSize; if (Pos.distance_to(start->Pos)<=radius) N->n1 = BuildNode(N->Pos,Pos,bIC); } // fwd if (0==N->n2){ Pos.set (N->Pos); Pos.z += m_Params.fPatchSize; if (Pos.distance_to(start->Pos)<=radius) N->n2 = BuildNode(N->Pos,Pos,bIC); } // right if (0==N->n3){ Pos.set (N->Pos); Pos.x += m_Params.fPatchSize; if (Pos.distance_to(start->Pos)<=radius) N->n3 = BuildNode(N->Pos,Pos,bIC); } // back if (0==N->n4){ Pos.set (N->Pos); Pos.z -= m_Params.fPatchSize; if (Pos.distance_to(start->Pos)<=radius) N->n4 = BuildNode(N->Pos,Pos,bIC); } if (estimated_nodes>1024){ if (k%128==0) { float p1 = float(k)/float(m_Nodes.size()); float p2 = float(m_Nodes.size())/estimated_nodes; float p = 0.1f*p1+0.9f*p2; clamp (p,0.f,1.f); pb->Update(p); // check need abort && redraw if (UI->NeedAbort()) break; } } } if (estimated_nodes>1024) UI->ProgressEnd(pb); return oldcount-m_Nodes.size(); }
bool EDetailManager::Export(LPCSTR path) { AnsiString fn = AnsiString(path)+"build.details"; bool bRes=true; SPBItem* pb = UI->ProgressStart(5,"Making details..."); CMemoryWriter F; pb->Inc ("merge textures"); Fvector2Vec offsets; Fvector2Vec scales; boolVec rotated; RStringSet textures_set; RStringVec textures; U32Vec remap; U8Vec remap_object (objects.size(),u8(-1)); int slot_cnt = dtH.size_x*dtH.size_z; for (int slot_idx=0; slot_idx<slot_cnt; slot_idx++){ DetailSlot* it = &dtSlots[slot_idx]; for (int part=0; part<4; part++){ u8 id = it->r_id(part); if (id!=DetailSlot::ID_Empty) { textures_set.insert(((EDetail*)(objects[id]))->GetTextureName()); remap_object[id] = 1; } } } textures.assign (textures_set.begin(),textures_set.end()); U8It remap_object_it= remap_object.begin(); u32 new_idx = 0; for (DetailIt d_it=objects.begin(); d_it!=objects.end(); d_it++,remap_object_it++) if ((*remap_object_it==1)&&(textures_set.find(((EDetail*)(*d_it))->GetTextureName())!=textures_set.end())) *remap_object_it = (u8)new_idx++; AnsiString do_tex_name = ChangeFileExt(fn,"_details"); int res = ImageLib.CreateMergedTexture(textures,do_tex_name.c_str(),STextureParams::tfADXT1,256,1024,256,1024,offsets,scales,rotated,remap); if (1!=res) bRes=FALSE; pb->Inc ("export geometry"); // objects int object_idx = 0; if (bRes){ do_tex_name = ExtractFileName(do_tex_name); F.open_chunk (DETMGR_CHUNK_OBJECTS); for (DetailIt it=objects.begin(); it!=objects.end(); it++){ if (remap_object[it-objects.begin()]!=u8(-1)){ F.open_chunk (object_idx++); if (!((EDetail*)(*it))->m_pRefs){ ELog.DlgMsg(mtError, "Bad object or object not found '%s'.", ((EDetail*)(*it))->m_sRefs.c_str()); bRes=false; }else{ LPCSTR tex_name = ((EDetail*)(*it))->GetTextureName(); for (u32 t_idx=0; t_idx<textures.size(); t_idx++) if (textures[t_idx]==tex_name) break; VERIFY(t_idx<textures.size()); t_idx = remap[t_idx]; ((EDetail*)(*it))->Export (F,do_tex_name.c_str(),offsets[t_idx],scales[t_idx],rotated[t_idx]); } F.close_chunk (); if (!bRes) break; } } F.close_chunk (); } pb->Inc ("export slots"); // slots if (bRes){ xr_vector<DetailSlot> dt_slots(slot_cnt); dt_slots.assign(dtSlots,dtSlots+slot_cnt); for (slot_idx=0; slot_idx<slot_cnt; slot_idx++){ DetailSlot& it = dt_slots[slot_idx]; // zero colors need lighting it.c_dir = 0; it.c_hemi = 0; it.c_r = 0; it.c_g = 0; it.c_b = 0; for (int part=0; part<4; part++){ u8 id = it.r_id(part); if (id!=DetailSlot::ID_Empty) it.w_id(part,remap_object[id]); } } F.open_chunk (DETMGR_CHUNK_SLOTS); F.w (dt_slots.begin(),dtH.size_x*dtH.size_z*sizeof(DetailSlot)); F.close_chunk (); pb->Inc(); // write header dtH.version = DETAIL_VERSION; dtH.object_count= object_idx; F.w_chunk (DETMGR_CHUNK_HEADER,&dtH,sizeof(DetailHeader)); bRes = F.save_to(fn.c_str()); } pb->Inc(); UI->ProgressEnd(pb); return bRes; }