From e1fb1fa6b7df0f4ac3bc897d64402be4a31f885b Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 18 May 2011 03:52:15 +0200 Subject: [PATCH 01/12] API change of AIFilePicker. Call AIFilePicker::create() instead of new AIFilePicker. Renamed deleteMe() to kill() and bs_deleted to bs_killed. Only default to auto destruct when created with create(true), otherwise kill() has to be called explicitely. --- indra/newview/floaterlocalassetbrowse.cpp | 2 +- indra/newview/llfloaterblacklist.cpp | 4 ++-- indra/newview/llfloatercustomize.cpp | 4 ++-- indra/newview/llfloaterfriends.cpp | 4 ++-- indra/newview/llfloaterregioninfo.cpp | 4 ++-- indra/newview/llfloatervfs.cpp | 2 +- indra/newview/llinventoryactions.cpp | 2 +- indra/newview/llinventorybackup.cpp | 4 ++-- indra/newview/llinventorybridge.cpp | 2 +- indra/newview/llpanelpick.cpp | 4 ++-- indra/newview/llpreviewanim.cpp | 2 +- indra/newview/llpreviewnotecard.cpp | 2 +- indra/newview/llpreviewscript.cpp | 4 ++-- indra/newview/llpreviewsound.cpp | 2 +- indra/newview/llpreviewtexture.cpp | 2 +- indra/newview/llviewermenu.cpp | 18 +++++++++--------- indra/newview/llviewermenufile.cpp | 6 +++--- indra/newview/llviewerobjectbackup.cpp | 4 ++-- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/statemachine/aifilepicker.cpp | 11 +++++++---- indra/newview/statemachine/aifilepicker.h | 6 +++++- indra/newview/statemachine/aistatemachine.cpp | 17 ++++++++--------- indra/newview/statemachine/aistatemachine.h | 12 ++++++------ 23 files changed, 63 insertions(+), 57 deletions(-) diff --git a/indra/newview/floaterlocalassetbrowse.cpp b/indra/newview/floaterlocalassetbrowse.cpp index 700fb8dca..90458e09f 100644 --- a/indra/newview/floaterlocalassetbrowse.cpp +++ b/indra/newview/floaterlocalassetbrowse.cpp @@ -459,7 +459,7 @@ LocalAssetBrowser::~LocalAssetBrowser() void LocalAssetBrowser::AddBitmap() { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_IMAGE, "", "image", true); filepicker->run(boost::bind(&LocalAssetBrowser::AddBitmap_continued, filepicker)); } diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp index ff76ec407..65c64cce7 100644 --- a/indra/newview/llfloaterblacklist.cpp +++ b/indra/newview/llfloaterblacklist.cpp @@ -241,7 +241,7 @@ void LLFloaterBlacklist::saveToDisk() //static void LLFloaterBlacklist::onClickSave(void* user_data) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("untitled.blacklist", FFSAVE_BLACKLIST); filepicker->run(boost::bind(&LLFloaterBlacklist::onClickSave_continued, filepicker)); } @@ -266,7 +266,7 @@ void LLFloaterBlacklist::onClickSave_continued(AIFilePicker* filepicker) //static void LLFloaterBlacklist::onClickLoad(void* user_data) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_BLACKLIST); filepicker->run(boost::bind(&LLFloaterBlacklist::onClickLoad_continued, filepicker)); } diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 96f300cd5..96008bbdb 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -1850,7 +1850,7 @@ void LLFloaterCustomize::setCurrentWearableType( EWearableType type ) // reX: new function void LLFloaterCustomize::onBtnImport( void* userdata ) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_XML); filepicker->run(boost::bind(&LLFloaterCustomize::onBtnImport_continued, filepicker)); } @@ -1910,7 +1910,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) // reX: new function void LLFloaterCustomize::onBtnExport( void* userdata ) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("", FFSAVE_XML); filepicker->run(boost::bind(&LLFloaterCustomize::onBtnExport_continued, filepicker)); } diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index c210caa1c..1d2e9142a 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -1082,7 +1082,7 @@ void LLPanelFriends::onClickExport(void* user_data) { std::string agn; gAgent.getName(agn); - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(agn + ".friendlist", FFSAVE_ALL); filepicker->run(boost::bind(&LLPanelFriends::onClickExport_continued, user_data, filepicker)); } @@ -1132,7 +1132,7 @@ bool LLPanelFriends::merging; void LLPanelFriends::onClickImport(void* user_data) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(); filepicker->run(boost::bind(&LLPanelFriends::onClickImport_filepicker_continued, filepicker)); } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 994fe3ad3..d91f4067b 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1325,7 +1325,7 @@ void LLPanelRegionTerrainInfo::onChangeSunHour(LLUICtrl* ctrl, void*) void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data) { LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("terrain.raw", FFSAVE_RAW); filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker)); } @@ -1350,7 +1350,7 @@ void LLPanelRegionTerrainInfo::onClickDownloadRaw_continued(AIFilePicker* filepi void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data) { LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_RAW); filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker)); } diff --git a/indra/newview/llfloatervfs.cpp b/indra/newview/llfloatervfs.cpp index 0192e76b9..d8b91b428 100644 --- a/indra/newview/llfloatervfs.cpp +++ b/indra/newview/llfloatervfs.cpp @@ -234,7 +234,7 @@ void LLFloaterVFS::setEditEnabled(bool enabled) void LLFloaterVFS::onClickAdd(void* user_data) { if(!user_data) return; - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(); filepicker->run(boost::bind(&LLFloaterVFS::onClickAdd_continued, user_data, filepicker)); } diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 8b04a1744..aa2374d24 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -570,7 +570,7 @@ class LLLoadInvCacheFloater : public inventory_listener_t { LLInventoryModel* model = mPtr->getPanel()->getModel(); if(!model) return false; - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_INVGZ, "", "invgz"); filepicker->run(boost::bind(&LLLoadInvCacheFloater::filepicker_callback, this, filepicker)); return true; diff --git a/indra/newview/llinventorybackup.cpp b/indra/newview/llinventorybackup.cpp index 416c82065..055cc2d61 100644 --- a/indra/newview/llinventorybackup.cpp +++ b/indra/newview/llinventorybackup.cpp @@ -357,7 +357,7 @@ void LLInventoryBackup::imageCallback(BOOL success, return; } - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(LLDir::getScrubbedFileName(item->getName()), getSaveFilter(item)); filepicker->run(boost::bind(&LLInventoryBackup::imageCallback_continued, src, filepicker)); } @@ -421,7 +421,7 @@ void LLInventoryBackup::assetCallback(LLVFS *vfs, // Write it back out... - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(LLDir::getScrubbedFileName(item->getName()), getSaveFilter(item)); filepicker->run(boost::bind(&LLInventoryBackup::assetCallback_continued, buffer, size, filepicker)); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index aa6dc78d5..d728d4274 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1109,7 +1109,7 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLInventoryItem* item = model->getItem(mUUID); if (item && item->getType() == LLAssetType::AT_TEXTURE) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_IMAGE, "", "image"); filepicker->run(boost::bind(&LLItemBridge::showFloaterImagePreview, item, filepicker)); } diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 9af829e9b..a33b3dd60 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -203,7 +203,7 @@ void LLPanelPick::initNewPick() //Imports a new pick from an xml - RK void LLPanelPick::importNewPick(void (*callback)(void*, bool), void* data) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_XML, "", "export"); filepicker->run(boost::bind(&LLPanelPick::importNewPick_continued, this, callback, data, filepicker)); } @@ -244,7 +244,7 @@ void LLPanelPick::importNewPick_continued(void (*callback)(void*, bool), void* d //Exports a pick to an XML - RK void LLPanelPick::exportPick() { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("", FFSAVE_XML, "", "export"); filepicker->run(boost::bind(&LLPanelPick::exportPick_continued, this, filepicker)); } diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 85349883b..845129a38 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -392,7 +392,7 @@ void LLPreviewAnim::gotAssetForSave(LLVFS *vfs, // Write it back out... - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(LLDir::getScrubbedFileName(self->getItem()->getName()) + ".animatn", FFSAVE_ANIMATN); filepicker->run(boost::bind(&LLPreviewAnim::gotAssetForSave_continued, buffer, size, filepicker)); } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 6acdc32ba..cf67ca516 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -720,7 +720,7 @@ void LLPreviewNotecard::saveAs() default_filename = LLDir::getScrubbedFileName(item->getName()) + ".notecard"; } - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(default_filename, FFSAVE_NOTECARD); filepicker->run(boost::bind(&LLPreviewNotecard::saveAs_continued, this, filepicker)); } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a58f1180e..e4abac51d 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1704,7 +1704,7 @@ void LLPreviewLSL::saveAs() default_filename = LLDir::getScrubbedFileName(item->getName()) + ".lsl"; } - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(default_filename, FFSAVE_LSL); filepicker->run(boost::bind(&LLPreviewLSL::saveAs_continued, this, filepicker)); } @@ -2655,7 +2655,7 @@ void LLLiveLSLEditor::saveAs() default_filename = LLDir::getScrubbedFileName(item->getName()); } - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(default_filename, FFSAVE_LSL); filepicker->run(boost::bind(&LLLiveLSLEditor::saveAs_continued, this, filepicker)); } diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index 890979578..a91cc25d0 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -330,7 +330,7 @@ void LLPreviewSound::gotAssetForSave(LLVFS *vfs, // Write it back out... - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(LLDir::getScrubbedFileName(self->getItem()->getName()) + ".ogg", FFSAVE_OGG); filepicker->run(boost::bind(&LLPreviewSound::gotAssetForSave_continued, buffer, size, filepicker)); } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 2e52f3d47..e23e662ec 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -381,7 +381,7 @@ void LLPreviewTexture::saveAs() return; const LLViewerInventoryItem* item = getItem() ; - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(item ? LLDir::getScrubbedFileName(item->getName()) + ".tga" : LLStringUtil::null, FFSAVE_TGA, "", "image"); filepicker->run(boost::bind(&LLPreviewTexture::saveAs_continued, this, item, filepicker)); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 50b76cc8c..afff999fa 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1241,7 +1241,7 @@ void init_debug_world_menu(LLMenuGL* menu) static void handle_export_menus_to_xml_continued(AIFilePicker* filepicker); void handle_export_menus_to_xml(void*) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("", FFSAVE_XML); filepicker->run(boost::bind(&handle_export_menus_to_xml_continued, filepicker)); } @@ -8519,7 +8519,7 @@ void handle_mesh_save_llm(void* data) return; } - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(*mesh_name, FFSAVE_ALL, default_path, "mesh_llm"); filepicker->run(boost::bind(&handle_mesh_save_llm_continued, data, filepicker)); } @@ -8595,7 +8595,7 @@ void handle_mesh_save_current_obj(void* data) std::string file_name = *mesh_name + "_current.obj"; std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, ""); - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(file_name, FFSAVE_ALL, default_path, "mesh_obj"); filepicker->run(boost::bind(&handle_mesh_save_current_obj_continued, data, filepicker)); } @@ -8644,7 +8644,7 @@ void handle_mesh_save_obj(void* data) std::string file_name = *mesh_name + ".obj"; std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, ""); - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(file_name, FFSAVE_ALL, default_path, "mesh_obj"); filepicker->run(boost::bind(&handle_mesh_save_obj_continued, data, filepicker)); } @@ -8687,7 +8687,7 @@ void handle_mesh_load_obj(void* data) return; } - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_ALL, default_path, "mesh_obj"); filepicker->run(boost::bind(&handle_mesh_load_obj_continued, data, filepicker)); } @@ -8737,7 +8737,7 @@ void handle_morph_save_obj(void* data) std::string file_name = *mesh_name + "." + morph_name + ".obj"; std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, ""); - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(file_name, FFSAVE_ALL, default_path, "mesh_obj"); filepicker->run(boost::bind(&handle_morph_save_obj_continued, data, filepicker)); } @@ -8782,7 +8782,7 @@ void handle_morph_load_obj(void* data) llinfos << "Load morph OBJ " << morph_name << " of mesh " << *mesh_name <open(FFLOAD_ALL, default_path, "mesh_obj"); filepicker->run(boost::bind(&handle_morph_load_obj_continued, data, filepicker)); } @@ -9091,7 +9091,7 @@ void handle_save_to_xml(void*) LLStringUtil::replaceChar(default_name, ':', '_'); LLStringUtil::replaceChar(default_name, '"', '_'); - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(default_name, FFSAVE_XML); filepicker->run(boost::bind(&handle_save_to_xml_continued, frontmost, filepicker)); } @@ -9108,7 +9108,7 @@ static void handle_save_to_xml_continued(LLFloater* frontmost, AIFilePicker* fil static void handle_load_from_xml_continued(AIFilePicker* filepicker); void handle_load_from_xml(void*) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_XML); filepicker->run(boost::bind(&handle_load_from_xml_continued, filepicker)); } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 0a3254ea0..d246ffe62 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -179,7 +179,7 @@ void AIFileUpload::start_filepicker(ELoadFilter filter, char const* context) } llassert(!mPicker); - mPicker = new AIFilePicker; + mPicker = AIFilePicker::create(); mPicker->open(filter, "", context); mPicker->run(boost::bind(&AIFileUpload::filepicker_callback, this, filter)); } @@ -370,7 +370,7 @@ class LLFileUploadBulk : public view_listener_t else // cancel return false; - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_ALL, "", "openfile", true); filepicker->run(boost::bind(&LLFileUploadBulk::onConfirmBulkUploadTemp_continued, enabled, filepicker)); return true; @@ -586,7 +586,7 @@ class LLFileQuit : public view_listener_t static void handle_compress_image_continued(AIFilePicker* filepicker); void handle_compress_image(void*) { - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_IMAGE, "", "openfile", true); filepicker->run(boost::bind(&handle_compress_image_continued, filepicker)); } diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index 51d0a4336..0ec25719e 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -341,7 +341,7 @@ void LLObjectBackup::exportObject() mThisGroup.clear(); // Open the file save dialog - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("", FFSAVE_XML); filepicker->run(boost::bind(&LLObjectBackup::exportObject_continued, this, filepicker)); } @@ -739,7 +739,7 @@ void LLObjectBackup::importObject(bool upload) mRetexture = upload; // Open the file open dialog - AIFilePicker* filepicker = new AIFilePicker; + AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_XML, "", "import"); filepicker->run(boost::bind(&LLObjectBackup::importObject_continued, this, filepicker)); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4b84744e4..64163b895 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4018,7 +4018,7 @@ void LLViewerWindow::saveImageNumbered(LLPointer image) // AIFilePicker will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. // pick a directory in which to save - AIFilePicker* filepicker = new AIFilePicker; // Deleted in LLViewerWindow::saveImageNumbered_continued1 + AIFilePicker* filepicker = AIFilePicker::create(); // Deleted in LLViewerWindow::saveImageNumbered_continued1 filepicker->open(proposed_name, pick_type, "", "snapshot"); filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker)); return; diff --git a/indra/newview/statemachine/aifilepicker.cpp b/indra/newview/statemachine/aifilepicker.cpp index 5e7a64da9..fdfb5a968 100644 --- a/indra/newview/statemachine/aifilepicker.cpp +++ b/indra/newview/statemachine/aifilepicker.cpp @@ -60,7 +60,7 @@ char const* AIFilePicker::state_str_impl(state_type run_state) const return "UNKNOWN STATE"; } -AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mCanceled(false) +AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mAutoKill(false), mCanceled(false) { } @@ -400,9 +400,12 @@ void AIFilePicker::finish_impl(void) mPluginManager = NULL; } mFilter.clear(); // Check that open is called before calling run (again). - // The default behavior is to delete the plugin. This can be overridden in - // the callback by calling run() again. - deleteMe(); + if (mAutoKill) + { + // The default behavior is to delete the plugin. This can be overridden in + // the callback by calling run() again. + kill(); + } } // This function is called when a new message is received from the plugin. diff --git a/indra/newview/statemachine/aifilepicker.h b/indra/newview/statemachine/aifilepicker.h index ee2013306..c86223124 100644 --- a/indra/newview/statemachine/aifilepicker.h +++ b/indra/newview/statemachine/aifilepicker.h @@ -132,7 +132,7 @@ new AIFilePicker which sets the state to AIFilePicker_canceled or AIFilePicker_done respectively, causing a call to AIStateMachine::finish(), which calls AIFilePicker::finish_impl which destroys the plugin (mPluginBase), - the plugin manager (mPluginManager) and calls AIStateMachine::deleteMe() + the plugin manager (mPluginManager) and calls AIStateMachine::kill() causing the AIFilePicker to be deleted. */ @@ -150,6 +150,9 @@ class AIFilePicker : public AIStateMachine { public: AIFilePicker(void); + // Create a dynamically created AIFilePicker object. + static AIFilePicker* create(bool auto_kill = true) { AIFilePicker* filepicker = new AIFilePicker; filepicker->mAutoKill = auto_kill; return filepicker; } + // The starting directory that the user will be in when the file picker opens // will be the same as the directory used the last time the file picker was // opened with the same context. If the file picker was never opened before @@ -184,6 +187,7 @@ private: typedef std::map context_map_type; //!< Type of mContextMap. static AIThreadSafeSimple sContextMap; //!< Map context (ie, "snapshot" or "image") to last used folder. std::string mContext; //!< Some key to indicate the context (remembers the folder per key). + bool mAutoKill; //!< True if the default behavior is to delete itself after being finished. // Input variables (cache variable between call to open and run). open_type mOpenType; //!< Set to whether opening a filepicker to select for saving one file, for loading one file, or loading multiple files. diff --git a/indra/newview/statemachine/aistatemachine.cpp b/indra/newview/statemachine/aistatemachine.cpp index d53a053c4..6d128b467 100644 --- a/indra/newview/statemachine/aistatemachine.cpp +++ b/indra/newview/statemachine/aistatemachine.cpp @@ -71,7 +71,6 @@ namespace { bool calling_mainloop; }; static AITHREADSAFE(cscm_type, continued_statemachines_and_calling_mainloop, ); - } // static @@ -177,8 +176,8 @@ void AIStateMachine::finish(void) idle(); mState = bs_finish; finish_impl(); - // Did finish_impl call deleteMe? Then that is only the default. Remember it. - bool default_delete = (mState == bs_deleted); + // Did finish_impl call kill()? Then that is only the default. Remember it. + bool default_delete = (mState == bs_killed); mState = bs_finish; if (mParent) { @@ -202,20 +201,20 @@ void AIStateMachine::finish(void) mState = bs_initialize; if (mCallback) { - mCallback->callback(!mAborted); // This can/may call deleteMe(), in which case the whole AIStateMachine will be deleted from the mainloop. + mCallback->callback(!mAborted); // This can/may call kill(), in which case the whole AIStateMachine will be deleted from the mainloop. delete mCallback; mCallback = NULL; } // Restore the request for deletion if we weren't started again from the callback. if (default_delete && mState == bs_initialize) - mState = bs_deleted; + mState = bs_killed; } -void AIStateMachine::deleteMe(void) +void AIStateMachine::kill(void) { // Should only be called from finish(). llassert(mIdle && (mState == bs_initialize || mState == bs_finish)); - mState = bs_deleted; + mState = bs_killed; } // Return stringified 'state'. @@ -229,7 +228,7 @@ char const* AIStateMachine::state_str(state_type state) AI_CASE_RETURN(bs_run); AI_CASE_RETURN(bs_abort); AI_CASE_RETURN(bs_finish); - AI_CASE_RETURN(bs_deleted); + AI_CASE_RETURN(bs_killed); } } return state_str_impl(state); @@ -326,7 +325,7 @@ void AIStateMachine::mainloop(void*) { Dout(dc::statemachine, "Erasing " << (void*)&statemachine << " from active_statemachines"); iter = active_statemachines.erase(iter); - if (statemachine.mState == bs_deleted) + if (statemachine.mState == bs_killed) { Dout(dc::statemachine, "Deleting " << (void*)&statemachine); delete &statemachine; diff --git a/indra/newview/statemachine/aistatemachine.h b/indra/newview/statemachine/aistatemachine.h index dff51c99b..4e041adff 100644 --- a/indra/newview/statemachine/aistatemachine.h +++ b/indra/newview/statemachine/aistatemachine.h @@ -169,7 +169,7 @@ class AIStateMachine { bs_run, bs_abort, bs_finish, - bs_deleted + bs_killed }; public: @@ -178,7 +178,7 @@ class AIStateMachine { //! Integral value equal to the state with the lowest value. static state_type const min_state = bs_initialize; //! Integral value one more than the state with the highest value. - static state_type const max_state = bs_deleted + 1; + static state_type const max_state = bs_killed + 1; private: base_state_type mState; //!< State of the base class. @@ -214,8 +214,8 @@ class AIStateMachine { AIStateMachine(void) : mState(bs_initialize), mIdle(true), mAborted(true), mSleep(0), mParent(NULL), mCallback(NULL) { updateSettings(); } protected: - //! The user should call 'deleteMe()', not delete a AIStateMachine (derived) directly. - virtual ~AIStateMachine() { llassert(mState == bs_deleted); } + //! The user should call 'kill()', not delete a AIStateMachine (derived) directly. + virtual ~AIStateMachine() { llassert(mState == bs_killed); } public: //! Halt the state machine until cont() is called. @@ -286,8 +286,8 @@ class AIStateMachine { //! Refine state while in the bs_run state. May only be called while in the bs_run state. void set_state(state_type run_state); - //! Change state to 'bs_deleted'. May only be called while in the bs_finish state. - void deleteMe(void); + //! Change state to 'bs_killed'. May only be called while in the bs_finish state. + void kill(void); //--------------------------------------- // Other. From 13560e292eef7108b71bda895dfeb4c36db142f4 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 22 May 2011 22:01:11 +0200 Subject: [PATCH 02/12] Added AIFetchInventoryFolder and more. Added a new statemachine AIFetchInventoryFolder, which can be used to fetch the contents of a folder by name or UUID. Also added AIEvent (and one event, AIEvent::LLInventoryModel_mIsAgentInvUsable_true, which is needed for AIFetchInventoryFolder). Fixed LLInventoryModel::sBackgroundFetchActive to correctly reflect whether or not LLInventoryModel::backgroundFetch is added to gIdleCallbacks. Avoid duplicated entries in sFetchQueue. Reset sFullFetchStarted in LLInventoryModel::stopBackgroundFetch to allow for a renewed full fetch when some single-folder fetch stops it. Added AIStateMachine::mQueued to make calling 'cont()' more robust: calling cont() / idle() / cont() on a row would otherwise add a statemachine twice to the active list, which would cause a crash when it's killed. --- indra/llcommon/aithreadsafe.h | 3 +- indra/newview/llhudeffectlookat.h | 1 + indra/newview/llinventorymodel.cpp | 43 +++- indra/newview/llinventorymodel.h | 4 + indra/newview/llviewerobject.h | 1 + indra/newview/statemachine/CMakeLists.txt | 11 +- indra/newview/statemachine/aievent.cpp | 113 ++++++++++ indra/newview/statemachine/aievent.h | 78 +++++++ .../statemachine/aifetchinventoryfolder.cpp | 193 ++++++++++++++++++ .../statemachine/aifetchinventoryfolder.h | 152 ++++++++++++++ indra/newview/statemachine/aistatemachine.cpp | 10 + indra/newview/statemachine/aistatemachine.h | 5 +- 12 files changed, 603 insertions(+), 11 deletions(-) create mode 100644 indra/newview/statemachine/aievent.cpp create mode 100644 indra/newview/statemachine/aievent.h create mode 100644 indra/newview/statemachine/aifetchinventoryfolder.cpp create mode 100644 indra/newview/statemachine/aifetchinventoryfolder.h diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index 3963281cb..52c4ac8d2 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -403,7 +403,8 @@ protected: // Locking control. LLMutex mMutex; - // For use by AIThreadSafeSimpleDC + friend struct AIRegisteredStateMachinesList; + // For use by AIThreadSafeSimpleDC and AIRegisteredStateMachinesList. AIThreadSafeSimple(void) { } AIThreadSafeSimple(AIAPRPool& parent) : mMutex(parent) { } diff --git a/indra/newview/llhudeffectlookat.h b/indra/newview/llhudeffectlookat.h index 922c718f6..97de0e8ba 100644 --- a/indra/newview/llhudeffectlookat.h +++ b/indra/newview/llhudeffectlookat.h @@ -34,6 +34,7 @@ #define LL_LLHUDEFFECTLOOKAT_H #include "llhudeffect.h" +#include "llframetimer.h" class LLViewerObject; class LLVOAvatar; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 910d94baf..1cc9393d7 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -59,6 +59,7 @@ #include "llviewercontrol.h" #include "llvoavatar.h" #include "llsdutil.h" +#include "statemachine/aievent.h" // #include "llappviewer.h" // gLostItemsRoot // @@ -349,6 +350,13 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, items = get_ptr_in_map(mParentChildItemTree, cat_id); } +// Same but just categories. +void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, + cat_array_t*& categories) const +{ + categories = get_ptr_in_map(mParentChildCategoryTree, cat_id); +} + // SJB: Added version to lock the arrays to catch potential logic bugs void LLInventoryModel::lockDirectDescendentArrays(const LLUUID& cat_id, cat_array_t*& categories, @@ -1727,7 +1735,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) { if (!sAllFoldersFetched) { - sBackgroundFetchActive = TRUE; if (cat_id.isNull()) { if (!sFullFetchStarted) @@ -1735,15 +1742,29 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) sFullFetchStarted = TRUE; sFetchQueue.push_back(gInventoryLibraryRoot); sFetchQueue.push_back(gAgent.getInventoryRootID()); - gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + if (!sBackgroundFetchActive) + { + sBackgroundFetchActive = TRUE; + gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + } } } else { // specific folder requests go to front of queue - if (sFetchQueue.empty() || sFetchQueue.front() != cat_id) + // Remove it from the queue first, to avoid getting it twice. + if (!sFetchQueue.empty() && sFetchQueue.front() != cat_id) { - sFetchQueue.push_front(cat_id); + std::deque::iterator old_entry = std::find(sFetchQueue.begin(), sFetchQueue.end(), cat_id); + if (old_entry != sFetchQueue.end()) + { + sFetchQueue.erase(old_entry); + } + } + sFetchQueue.push_front(cat_id); + if (!sBackgroundFetchActive) + { + sBackgroundFetchActive = TRUE; gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); } } @@ -1753,9 +1774,12 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) //static void LLInventoryModel::findLostItems() { - sBackgroundFetchActive = TRUE; sFetchQueue.push_back(LLUUID::null); - gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + if (!sBackgroundFetchActive) + { + sBackgroundFetchActive = TRUE; + gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + } } //static @@ -1767,7 +1791,11 @@ void LLInventoryModel::stopBackgroundFetch() gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL); sBulkFetchCount=0; sMinTimeBetweenFetches=0.0f; -// sFullFetchStarted=FALSE; + if (!sAllFoldersFetched) + { + // We didn't finish this, so set it to FALSE in order to be able to start it again. + sFullFetchStarted=FALSE; + } } } @@ -2941,6 +2969,7 @@ void LLInventoryModel::buildParentChildMap() // root of the agent's inv found. // The inv tree is built. mIsAgentInvUsable = true; + AIEvent::trigger(AIEvent::LLInventoryModel_mIsAgentInvUsable_true); } } llinfos << " finished buildParentChildMap " << llendl; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 6fdb59d1a..a6dc0f31a 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "llpermissionsflags.h" #include "llstring.h" +#include "llhttpclient.h" #include #include @@ -199,6 +200,9 @@ public: void getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t*& categories, item_array_t*& items) const; + // Same but only get categories. + void getDirectDescendentsOf(const LLUUID& cat_id, + cat_array_t*& categories) const; // Starting with the object specified, add its descendents to the // array provided, but do not add the inventory object specified diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 4833b96d8..2a08b5f50 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -73,6 +73,7 @@ class LLViewerPartSourceScript; class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; +class LLPartSysData; typedef enum e_object_update_type { diff --git a/indra/newview/statemachine/CMakeLists.txt b/indra/newview/statemachine/CMakeLists.txt index b11f1c3e1..a95431b0f 100644 --- a/indra/newview/statemachine/CMakeLists.txt +++ b/indra/newview/statemachine/CMakeLists.txt @@ -13,7 +13,9 @@ include(LLWindow) include(LLUI) include(LLRender) include(LLImage) - +include(LLCharacter) +include(LLInventory) +include(LLPrimitive) include_directories( ${CMAKE_SOURCE_DIR}/newview @@ -27,11 +29,16 @@ include_directories( ${LLUI_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} + ${LLCHARACTER_INCLUDE_DIRS} + ${LLINVENTORY_INCLUDE_DIRS} + ${LLPRIMITIVE_INCLUDE_DIRS} ) set(statemachine_SOURCE_FILES aistatemachine.cpp aifilepicker.cpp + aifetchinventoryfolder.cpp + aievent.cpp ) set(statemachine_HEADER_FILES @@ -39,6 +46,8 @@ set(statemachine_HEADER_FILES aistatemachine.h aifilepicker.h aidirpicker.h + aifetchinventoryfolder.h + aievent.h ) set_source_files_properties(${statemachine_HEADER_FILES} diff --git a/indra/newview/statemachine/aievent.cpp b/indra/newview/statemachine/aievent.cpp new file mode 100644 index 000000000..0e7e9fa6e --- /dev/null +++ b/indra/newview/statemachine/aievent.cpp @@ -0,0 +1,113 @@ +/** + * @file aievent.cpp + * @brief Implementation of AIEvent. + * + * Copyright (c) 2011, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 19/05/2011 + * Initial version, written by Aleric Inglewood @ SL + */ + +#include "linden_common.h" +#include "aievent.h" +#include "aistatemachine.h" +#include + +// Additional information stored per registered statemachine in AIRegisteredStateMachines std::map. +struct AIRSData { + bool mOneShot; + AIRSData(void) { } + AIRSData(bool one_shot) : mOneShot(one_shot) { } +}; + +// A list of all statemachines registered for a particular event, and and API to work on it. +struct AIRegisteredStateMachines { + typedef std::map rsm_type; + rsm_type mRegisteredStateMachines; + void Register(AIStateMachine* statemachine, bool one_shot) { mRegisteredStateMachines[statemachine] = one_shot; } + void Unregister(AIStateMachine* statemachine) { mRegisteredStateMachines.erase(statemachine); } + void trigger(void); +}; + +// Inline this, because it's only called from one place. +inline void AIRegisteredStateMachines::trigger(void) +{ + rsm_type::iterator sm = mRegisteredStateMachines.begin(); + while(sm != mRegisteredStateMachines.end()) + { + sm->first->cont(); // This is safe, cont() does never access mRegisteredStateMachines. + if (sm->second.mOneShot) + mRegisteredStateMachines.erase(sm++); + else + ++sm; + } +} + +// A list (array) with all AIRegisteredStateMachines maps, one for each event type. +struct AIRegisteredStateMachinesList { + AIThreadSafeSimple mRegisteredStateMachinesList[AIEvent::number_of_events]; + AIRegisteredStateMachinesList(void); + AIThreadSafeSimple& operator[](AIEvent::AIEvents event) { return mRegisteredStateMachinesList[event]; } +}; + +AIRegisteredStateMachinesList::AIRegisteredStateMachinesList(void) +{ + for (int event = 0; event < AIEvent::number_of_events; ++event) + { + new (&mRegisteredStateMachinesList[event]) AIRegisteredStateMachines; + } +} + +// Instantiate the list with all AIRegisteredStateMachines maps. +static AIRegisteredStateMachinesList registered_statemachines_list; + +//----------------------------------------------------------------------------- +// External API starts here. +// Each function obtains access to the thread-safe AIRegisteredStateMachines that belongs +// to the given event (locking it's mutex) and then calls the corresponding method. + +// Register a statemachine for notification of event. +// static +void AIEvent::Register(AIEvents event, AIStateMachine* statemachine, bool one_shot) +{ + statemachine->idle(); + AIAccess registered_statemachines_w(registered_statemachines_list[event]); + registered_statemachines_w->Register(statemachine, one_shot); +} + +// Unregister a statemachine for notification of event. +// static +void AIEvent::Unregister(AIEvents event, AIStateMachine* statemachine) +{ + AIAccess registered_statemachines_w(registered_statemachines_list[event]); + registered_statemachines_w->Unregister(statemachine); +} + +// Trigger event. +// static +void AIEvent::trigger(AIEvents event) +{ + AIAccess registered_statemachines_w(registered_statemachines_list[event]); + registered_statemachines_w->trigger(); +} + diff --git a/indra/newview/statemachine/aievent.h b/indra/newview/statemachine/aievent.h new file mode 100644 index 000000000..a90a04aaf --- /dev/null +++ b/indra/newview/statemachine/aievent.h @@ -0,0 +1,78 @@ +/** + * @file aievent.h + * @brief Collect viewer events for statemachines. + * + * Copyright (c) 2011, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 19/05/2011 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AIEVENT_H +#define AIEVENT_H + +class AIStateMachine; + +class AIEvent { + public: + enum AIEvents { + LLInventoryModel_mIsAgentInvUsable_true, // LLInventoryModel::mIsAgentInvUsable was set to true. + number_of_events + }; + + /** + * Register a statemachine for the given event. + * + * If the event happens then statemachine->cont() is called. + * + * @param event the event that we want to be notified of. + * @param statemachine the statemachine. + * @param one_shot if true then AIEvent::Unregister is called automatically when the event occured once. + */ + static void Register(AIEvents event, AIStateMachine* statemachine, bool one_shot = true); + + /** + * Unregister a previously registered event. + * + * This may be called for already unregistered events. + * This should be called from the destructor of a statemachine for any event it registers, + * as well as when it doesn't need the event anymore (in the case on non- one shot events). + * + * @param event the event we want to no longer be notified off. + * @param statemachine the statemachine. + */ + static void Unregister(AIEvents event, AIStateMachine* statemachine); + + /** + * Trigger the event. + * + * This is called by the viewer code when the event happens and + * causes statemachine->cont() to be called for every registered + * statemachine. + * + * @param event the event that just happened. + */ + static void trigger(AIEvents event); +}; + +#endif diff --git a/indra/newview/statemachine/aifetchinventoryfolder.cpp b/indra/newview/statemachine/aifetchinventoryfolder.cpp new file mode 100644 index 000000000..3a3865a6e --- /dev/null +++ b/indra/newview/statemachine/aifetchinventoryfolder.cpp @@ -0,0 +1,193 @@ +/** + * @file aifetchinventoryfolder.cpp + * @brief Implementation of AIFetchInventoryFolder + * + * Copyright (c) 2011, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 19/05/2011 + * Initial version, written by Aleric Inglewood @ SL + */ + +#include "linden_common.h" +#include "aifetchinventoryfolder.h" +#include "aievent.h" +#include "llagent.h" + +enum fetchinventoryfolder_state_type { + AIFetchInventoryFolder_checkFolderExists = AIStateMachine::max_state, + AIFetchInventoryFolder_fetchDescendents, + AIFetchInventoryFolder_folderCompleted +}; + +class AIInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver { + public: + AIInventoryFetchDescendentsObserver(AIStateMachine* statemachine, LLUUID const& folder); + ~AIInventoryFetchDescendentsObserver() { gInventory.removeObserver(this); } + + protected: + /*virtual*/ void done() + { + mStateMachine->set_state(AIFetchInventoryFolder_folderCompleted); + delete this; + } + + private: + AIStateMachine* mStateMachine; +}; + +AIInventoryFetchDescendentsObserver::AIInventoryFetchDescendentsObserver(AIStateMachine* statemachine, LLUUID const& folder) : mStateMachine(statemachine) +{ + mStateMachine->idle(); + folder_ref_t folders(1, folder); + fetchDescendents(folders); + gInventory.addObserver(this); + if (isEverythingComplete()) + done(); +} + +void AIFetchInventoryFolder::fetch(std::string const& foldername, bool create, bool fetch_contents) +{ + fetch(gAgent.getInventoryRootID(), foldername, create, fetch_contents); +} + +char const* AIFetchInventoryFolder::state_str_impl(state_type run_state) const +{ + switch(run_state) + { + AI_CASE_RETURN(AIFetchInventoryFolder_checkFolderExists); + AI_CASE_RETURN(AIFetchInventoryFolder_fetchDescendents); + AI_CASE_RETURN(AIFetchInventoryFolder_folderCompleted); + } + return "UNKNOWN STATE"; +} + +void AIFetchInventoryFolder::initialize_impl(void) +{ + mExists = false; + mCreated = false; + mNeedNotifyObservers = false; + set_state(AIFetchInventoryFolder_checkFolderExists); + if (!gInventory.isInventoryUsable()) + AIEvent::Register(AIEvent::LLInventoryModel_mIsAgentInvUsable_true, this); +} + +void AIFetchInventoryFolder::multiplex_impl(void) +{ + switch (mRunState) + { + case AIFetchInventoryFolder_checkFolderExists: + { + // If LLInventoryModel_mIsAgentInvUsable_true then this should be and stay true forever. + llassert(gInventory.isInventoryUsable()); + if (mParentFolder.isNull()) + mParentFolder = gAgent.getInventoryRootID(); + if (mFolderUUID.isNull() || !gInventory.getCategory(mFolderUUID)) // Is the UUID unknown, or doesn't exist? + { + // Set this to null here in case we abort. + mFolderUUID.setNull(); + if (mFolderName.empty()) + { + // We can only find a folder by name, or create it, if we know it's name. + llwarns << "Unknown folder ID " << mFolderUUID << llendl; + abort(); + break; + } + // Check if the parent exists. + if (mParentFolder != gAgent.getInventoryRootID() && !gInventory.getCategory(mParentFolder)) + { + llwarns << "Unknown parent folder ID " << mParentFolder << llendl; + abort(); + break; + } + // Look up UUID by name. + LLInventoryModel::cat_array_t* categories; + gInventory.getDirectDescendentsOf(mParentFolder, categories); + for (S32 i = 0; i < categories->getLength(); ++i) + { + LLPointer const& category(categories->get(i)); + if (category->getName() == mFolderName) + { + mFolderUUID = category->getUUID(); + break; + } + } + if (mFolderUUID.isNull()) // Does the folder exist? + { + if (!mCreate) + { + // We're done. + finish(); + break; + } + // Create the folder. + mFolderUUID = gInventory.createNewCategory(mParentFolder, LLAssetType::AT_NONE, mFolderName); + llassert_always(!mFolderUUID.isNull()); + Dout(dc::statemachine, "Created folder \"" << mFolderName << "\"."); + mNeedNotifyObservers = true; + } + mCreated = true; + } + // mFolderUUID is now valid. + mExists = true; + if (!mFetchContents || // No request to fetch contents. + LLInventoryModel::isEverythingFetched()) // No need to fetch contents. + { + // We're done. + finish(); + break; + } + set_state(AIFetchInventoryFolder_fetchDescendents); + /*Fall-through*/ + } + case AIFetchInventoryFolder_fetchDescendents: + { + // This sets the state to AIFetchInventoryFolder_folderCompleted once the folder is complete. + new AIInventoryFetchDescendentsObserver(this, mFolderUUID); + break; + } + case AIFetchInventoryFolder_folderCompleted: + { + // Does it still exist? + if (!gInventory.getCategory(mFolderUUID)) + { + // Assume the folder was deleted in the meantime. + abort(); + break; + } + llassert(gInventory.isCategoryComplete(mFolderUUID)); + // The folder is complete! + finish(); + break; + } + } +} + +void AIFetchInventoryFolder::abort_impl(void) +{ +} + +void AIFetchInventoryFolder::finish_impl(void) +{ + if (mNeedNotifyObservers) + gInventory.notifyObservers(); +} diff --git a/indra/newview/statemachine/aifetchinventoryfolder.h b/indra/newview/statemachine/aifetchinventoryfolder.h new file mode 100644 index 000000000..c83c3ef1b --- /dev/null +++ b/indra/newview/statemachine/aifetchinventoryfolder.h @@ -0,0 +1,152 @@ +/** + * @file aifetchinventoryfolder.h + * @brief Fetch an inventory folder + * + * Copyright (c) 2011, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 19/05/2011 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AIFETCHINVENTORYFOLDER_H +#define AIFETCHINVENTORYFOLDER_H + +#include "aistatemachine.h" +#include "lluuid.h" +#include + +// An inventory folder fetch state machine. +// +// Before calling run(), call fetch() to pass needed parameters. +// +// When the state machine finishes, call aborted() to check +// whether or not the statemachine succeeded in fetching +// the folder or not. +// +// Objects of this type can be reused multiple times, see +// also the documentation of AIStateMachine. +class AIFetchInventoryFolder : public AIStateMachine { + private: + std::string mFolderName; //!< Input variable. + bool mCreate; //!< Input variable: create mFolderName if it doesn't exist. + bool mFetchContents; //!< Input variable: fetch contents before finishing. + LLUUID mParentFolder; //!< Input variable: the UUID of the parent folder. + LLUUID mFolderUUID; //!< Input and/or output variable. + bool mExists; //!< Output variable: true if the folder exists. + bool mCreated; //!< Output variable: true if mFolderName didn't exist and was created by this object. + + bool mNeedNotifyObservers; + + public: + AIFetchInventoryFolder(void) : mCreate(false), mFetchContents(false), mExists(false), mCreated(false) + { Dout(dc::statemachine, "Calling AIFetchInventoryFolder constructor [" << (void*)this << "]"); } + + /** + * @brief Fetch an inventory folder by name, optionally creating it. + * + * Upon successful finish (aborted() returns false), exists() will return true + * if the folder exists; created() will return true if it was created; + * UUID() will return the UUID of the folder. It will then also be possible + * to scan over all folders (Category) of this folder. If fetch_contents + * is set, you will also be able to scan over the contents of the folder + * upon successful finish. + * + * @param parentUUID The UUID of the parent. Passing gAgent.getInventoryRootID(), or a null ID, will assume a root folder. + * @param foldername The name of the folder. + * @param create if set, create the folder if it doesn't exists yet. + * @param fetch_contents if set, fetch the contents before finishing. + */ + void fetch(LLUUID const& parentUUID, std::string const& foldername, bool create = false, bool fetch_contents = true) + { + mParentFolder = parentUUID; + mFetchContents = fetch_contents; + if (mFolderName != foldername) + { + mFolderName = foldername; + mFolderUUID.setNull(); + } + } + + /** + * @brief Fetch an inventory folder by name, optionally creating it. + * + * Upon successful finish (aborted() returns false), exists() will return + * true if the folder exists; created() will return true if it was created; + * UUID() will return the UUID of the folder. It will then also be possible + * to scan over all folders (Category) of this folder. If fetch_contents + * is set, you will also be able to scan over the contents of the folder + * upon successful finish. + * + * @param foldername The name of the folder. + * @param create if set, create the folder if it doesn't exists yet. + * @param fetch_contents if set, fetch the contents before finishing. + */ + void fetch(std::string const& foldername, bool create = false, bool fetch_contents = true); + + /** + * @brief Fetch an inventory folder by UUID. + * + * Upon successful finish (aborted() returns false), exists() will return true + * if the folder exists; it will then be possible to scan over all folders (Category) + * of this folder. If fetch_contents is set, you will also be able to scan over + * the contents of the folder upon successful finish. + * + * @param folderUUID The UUID of the folder. + * @param fetch_contents if set, fetch the contents before finishing. + */ + void fetch(LLUUID const& folderUUID, bool fetch_contents = true) + { + mFetchContents = fetch_contents; + if (mFolderUUID != folderUUID) + { + mFolderName.clear(); + mFolderUUID = folderUUID; + } + } + + std::string const& name(void) const { return mFolderName; } + bool exists(void) const { return mExists; } + bool created(void) const { return mCreated; } + LLUUID const& UUID(void) const { llassert(mExists || mFolderUUID.isNull()); return mFolderUUID; } + + protected: + // Call finish() (or abort()), not delete. + /*virtual*/ ~AIFetchInventoryFolder() { Dout(dc::statemachine, "Calling ~AIFetchInventoryFolder() [" << (void*)this << "]"); } + + // Handle initializing the object. + /*virtual*/ void initialize_impl(void); + + // Handle mRunState. + /*virtual*/ void multiplex_impl(void); + + // Handle aborting from current bs_run state. + /*virtual*/ void abort_impl(void); + + // Handle cleaning up from initialization (or post abort) state. + /*virtual*/ void finish_impl(void); + + // Implemenation of state_str for run states. + /*virtual*/ char const* state_str_impl(state_type run_state) const; +}; + +#endif diff --git a/indra/newview/statemachine/aistatemachine.cpp b/indra/newview/statemachine/aistatemachine.cpp index 6d128b467..b950fc236 100644 --- a/indra/newview/statemachine/aistatemachine.cpp +++ b/indra/newview/statemachine/aistatemachine.cpp @@ -132,6 +132,8 @@ void AIStateMachine::cont(void) DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]"); llassert(mIdle); mIdle = false; + if (mQueued) + return; AIWriteAccess cscm_w(continued_statemachines_and_calling_mainloop); cscm_w->continued_statemachines.push_back(this); if (!cscm_w->calling_mainloop) @@ -140,6 +142,7 @@ void AIStateMachine::cont(void) cscm_w->calling_mainloop = true; gIdleCallbacks.addFunction(&AIStateMachine::mainloop); } + mQueued = true; } void AIStateMachine::set_state(state_type state) @@ -214,6 +217,12 @@ void AIStateMachine::kill(void) { // Should only be called from finish(). llassert(mIdle && (mState == bs_initialize || mState == bs_finish)); + if (mState == bs_initialize) + { + // Bump the statemachine onto the active statemachine list, or else it won't be deleted. + cont(); + idle(); + } mState = bs_killed; } @@ -288,6 +297,7 @@ void AIStateMachine::mainloop(void*) nonempty = true; active_statemachines.push_back(QueueElement(*iter)); Dout(dc::statemachine, "Adding " << (void*)*iter << " to active_statemachines"); + (*iter)->mQueued = false; } if (nonempty) AIWriteAccess(cscm_r)->continued_statemachines.clear(); diff --git a/indra/newview/statemachine/aistatemachine.h b/indra/newview/statemachine/aistatemachine.h index 4e041adff..cc0b63ce1 100644 --- a/indra/newview/statemachine/aistatemachine.h +++ b/indra/newview/statemachine/aistatemachine.h @@ -184,6 +184,7 @@ class AIStateMachine { base_state_type mState; //!< State of the base class. bool mIdle; //!< True if this state machine is not running. bool mAborted; //!< True after calling abort() and before calling run(). + bool mQueued; //!< True when the statemachine is queued to be added back to the active list. S64 mSleep; //!< Non-zero while the state machine is sleeping. // Callback facilities. @@ -211,11 +212,11 @@ class AIStateMachine { public: //! Create a non-running state machine. - AIStateMachine(void) : mState(bs_initialize), mIdle(true), mAborted(true), mSleep(0), mParent(NULL), mCallback(NULL) { updateSettings(); } + AIStateMachine(void) : mState(bs_initialize), mIdle(true), mAborted(true), mQueued(false), mSleep(0), mParent(NULL), mCallback(NULL) { updateSettings(); } protected: //! The user should call 'kill()', not delete a AIStateMachine (derived) directly. - virtual ~AIStateMachine() { llassert(mState == bs_killed); } + virtual ~AIStateMachine() { llassert(mState == bs_killed && !mQueued); } public: //! Halt the state machine until cont() is called. From b82c94383bab5cba8661e64ee684f41493dd7624 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Tue, 24 May 2011 18:56:53 +0200 Subject: [PATCH 03/12] Make V2Renderer branch compile. --- indra/llmath/llcamera.cpp | 2 +- indra/llmath/llcamera.h | 2 +- indra/llmath/llplane.h | 2 +- indra/newview/pipeline.cpp | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index da71cae9d..263803930 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -92,7 +92,7 @@ F32 LLCamera::getMaxView() const // ---------------- LLCamera::setFoo() member functions ---------------- -void LLCamera::setUserClipPlane(LLPlane& plane) +void LLCamera::setUserClipPlane(LLPlane const& plane) { mPlaneCount = 7; mAgentPlanes[6] = plane; diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 38555b1e7..56afca025 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -143,7 +143,7 @@ public: virtual ~LLCamera(); - void setUserClipPlane(LLPlane& plane); + void setUserClipPlane(LLPlane const& plane); void disableUserClipPlane(); virtual void setView(F32 vertical_fov_rads); void setViewHeightInPixels(S32 height); diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index ebfe77a9c..8803d0774 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -78,7 +78,7 @@ public: inline void getVector3(LLVector3& vec) const { vec.set(mV[0], mV[1], mV[2]); } // Retrieve the mask indicating which of the x, y, or z axis are greater or equal to zero. - inline U8 calcPlaneMask() + inline U8 calcPlaneMask() const { U8 mask = 0; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 827afec95..808807494 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8612,7 +8612,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) //hack to disable projector shadows - static bool clear = true; static const LLCachedControl gen_shadow("RenderShadowDetail",0); if (gen_shadow > 1) From e3742734f01f509e40b3294fac79bbf40fc6b925 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 25 May 2011 19:55:42 +0200 Subject: [PATCH 04/12] Beacons (floater) fixup After a user spend three days trying to find out why certain textures looked red (as if they had alpha and you pressed control-alt-T, but not all of them were like that); and nothing helped, not relogging, not clearing cache, not even reinstalling the viewer... I decided to take this bug serious. Note that, according to Shyotl, there have been more users every now and then that reported this problem. The problem (after doing a research for 1 hour) turned out to be that she had beacons on, highlighting prims with scripts. The immediate bug is, of course, that this was persistent over a relog. Upon further investigation, this bug exists because a Debug Setting had a double meaning: it meant both "beacon floater is visible", which you want to be persistent, and it was later renamed and given the meaning "Keep beacons when closing the floater". Digging deeper it turned out that there was a REAL mess with regard to the beacons: A non-finished floater with immature comments (called "dingdong floater") was half-created and replaced the original floater which, according to the comment was "so fucked over and over" (== commented out in several places), but then everything was commented out and replaced with a menu (because they couldn't get it to work?). The floater simply didn't exist anymore! That reduced the meaning of the Debug Setting to "Show beacons", although you now could only set it in the menu by clicking on "Beacons Always On" where 'Always' refers to also on when the floater isn't there. I nuked the immature dingdong code, brought back the original floater as it was in snowglobe (and still is in Imprudence), fixed it up a bit with a nicer layout (indentation and spacing) and disabling (graying out) when needed, and added a new checkbox that will allow people to still keep/see the beacons after closing the floater. In the end this requires THREE Debug Setting variables: ShowBeaconsFloater : TRUE when the floater is visible, FALSE when not. This is persistent, so the floater is still there if you relog with the floater open. BeaconsKeepVisible : TRUE when the new checkbox is checked. Also persistent. BeaconsVisible : TRUE when the beacons are rendered, FALSE otherwise. This is NOT persistent: we don't want unsuspecting users to try and get rid of the weird 'red prims' by relogging and failing at that. --- indra/newview/CMakeLists.txt | 2 - indra/newview/app_settings/settings.xml | 37 +- indra/newview/llfloaterbeacons.cpp | 103 +- indra/newview/llfloaterbeacons.h | 1 - indra/newview/llfloaterdickdongs.cpp | 93 -- indra/newview/llfloaterdickdongs.h | 57 - indra/newview/llstartup.cpp | 2 +- indra/newview/llviewermenu.cpp | 1110 +---------------- indra/newview/llviewerwindow.cpp | 4 +- indra/newview/pipeline.cpp | 4 +- .../default/xui/en-us/floater_beacons.xml | 17 +- .../default/xui/en-us/floater_dickdongs.xml | 19 - .../skins/default/xui/en-us/menu_viewer.xml | 99 +- 13 files changed, 114 insertions(+), 1434 deletions(-) delete mode 100644 indra/newview/llfloaterdickdongs.cpp delete mode 100644 indra/newview/llfloaterdickdongs.h delete mode 100644 indra/newview/skins/default/xui/en-us/floater_dickdongs.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8004297fe..902137a1d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -184,7 +184,6 @@ set(viewer_SOURCE_FILES llfloatercolorpicker.cpp llfloatercustomize.cpp llfloaterdaycycle.cpp - llfloaterdickdongs.cpp llfloaterdirectory.cpp llfloatereditui.cpp llfloaterenvsettings.cpp @@ -661,7 +660,6 @@ set(viewer_HEADER_FILES llfloatercolorpicker.h llfloatercustomize.h llfloaterdaycycle.h - llfloaterdickdongs.h llfloaterdirectory.h llfloatereditui.h llfloaterenvsettings.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 944b1fef0..370fce9d5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1894,10 +1894,10 @@ 0 - BeaconAlwaysOn + ShowBeaconsFloater Comment - Beacons / highlighting always on + Show beacons floater Persist 1 Type @@ -1905,6 +1905,28 @@ Value 0 + BeaconsKeepVisible + + Comment + Don't turn off BeaconsVisible when beacons floater is closed + Persist + 1 + Type + Boolean + Value + 0 + + BeaconsVisible + + Comment + Show beacons / highlighting + Persist + 0 + Type + Boolean + Value + 0 + BrowserHomePage Comment @@ -14043,6 +14065,17 @@ Value 0 + keepbeacons + + Comment + Keep beacons when closing floater + Persist + 1 + Type + Boolean + Value + 0 + LogTextureDownloadsToViewerLog Comment diff --git a/indra/newview/llfloaterbeacons.cpp b/indra/newview/llfloaterbeacons.cpp index 9ed19ed15..b8d457fa9 100644 --- a/indra/newview/llfloaterbeacons.cpp +++ b/indra/newview/llfloaterbeacons.cpp @@ -36,6 +36,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" #include "llcheckboxctrl.h" +#include "llsliderctrl.h" #include "pipeline.h" // [RLVa:KB] @@ -44,7 +45,7 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_dickdongs.xml"); + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml"); // Initialize pipeline states from saved settings. // OK to do at floater constructor time because beacons do not display unless the floater is open @@ -58,10 +59,13 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) LLPipeline::setRenderParticleBeacons( gSavedSettings.getBOOL("particlesbeacon")); LLPipeline::setRenderHighlights( gSavedSettings.getBOOL("renderhighlights")); LLPipeline::setRenderBeacons( gSavedSettings.getBOOL("renderbeacons")); + getChild("beacon_width_label")->setEnabled(gSavedSettings.getBOOL("renderbeacons")); + getChild("beacon_width")->setEnabled(gSavedSettings.getBOOL("renderbeacons")); } BOOL LLFloaterBeacons::postBuild() { + childSetCommitCallback("always_on", onClickUICheck, this); childSetCommitCallback("touch_only", onClickUICheck, this); childSetCommitCallback("scripted", onClickUICheck, this); childSetCommitCallback("physical", onClickUICheck, this); @@ -73,7 +77,6 @@ BOOL LLFloaterBeacons::postBuild() } // Needed to make the floater visibility toggle the beacons. -// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. void LLFloaterBeacons::open() { // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) @@ -84,14 +87,19 @@ void LLFloaterBeacons::open() // [/RLVa:KB] LLFloater::open(); - gSavedSettings.setBOOL( "BeaconAlwaysOn", TRUE); + gSavedSettings.setBOOL("ShowBeaconsFloater", TRUE); + gSavedSettings.setBOOL("BeaconsVisible", TRUE); } void LLFloaterBeacons::close(bool app_quitting) { LLFloater::close(app_quitting); if(!app_quitting) { - gSavedSettings.setBOOL( "BeaconAlwaysOn", FALSE); + gSavedSettings.setBOOL("ShowBeaconsFloater", FALSE); + if (!gSavedSettings.getBOOL("BeaconsKeepVisible")) + { + gSavedSettings.setBOOL("BeaconsVisible", FALSE); + } } } @@ -103,59 +111,58 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; std::string name = check->getName(); LLFloaterBeacons* view = (LLFloaterBeacons*)data; - if( name == "touch_only") + + if (name == "always_on") gSavedSettings.setBOOL("BeaconsKeepVisible", check->get()); + else if (name == "touch_only") LLPipeline::setRenderScriptedTouchBeacons(check->get()); + else if (name == "scripted") LLPipeline::setRenderScriptedBeacons(check->get()); + else if (name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get()); + else if (name == "sounds") LLPipeline::setRenderSoundBeacons(check->get()); + else if (name == "particles") LLPipeline::setRenderParticleBeacons(check->get()); + else if (name == "highlights") LLPipeline::setRenderHighlights(check->get()); + else if (name == "beacons") + { + bool enabled = check->get(); + LLPipeline::setRenderBeacons(enabled); + view->getChild("beacon_width_label")->setEnabled(enabled); + view->getChild("beacon_width")->setEnabled(enabled); + } + + if (check->get()) { - LLPipeline::toggleRenderScriptedTouchBeacons(NULL); // Don't allow both to be ON at the same time. Toggle the other one off if both now on. - if ( - LLPipeline::getRenderScriptedTouchBeacons(NULL) && + if (LLPipeline::getRenderScriptedTouchBeacons(NULL) && LLPipeline::getRenderScriptedBeacons(NULL) ) { - LLPipeline::setRenderScriptedBeacons(FALSE); - view->getChild("scripted")->setControlValue(LLSD(FALSE)); - view->getChild("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline + if (name == "touch_only") + { + LLPipeline::setRenderScriptedBeacons(FALSE); + view->getChild("scripted")->setControlValue(LLSD(FALSE)); + } + else + { + LLPipeline::setRenderScriptedTouchBeacons(FALSE); + view->getChild("touch_only")->setControlValue(LLSD(FALSE)); + } } } - else if(name == "scripted") + else { - LLPipeline::toggleRenderScriptedBeacons(NULL); - // Don't allow both to be ON at the same time. Toggle the other one off if both now on. - if ( - LLPipeline::getRenderScriptedTouchBeacons(NULL) && - LLPipeline::getRenderScriptedBeacons(NULL) ) - { - LLPipeline::setRenderScriptedTouchBeacons(FALSE); - view->getChild("touch_only")->setControlValue(LLSD(FALSE)); - view->getChild("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline - } - } - else if(name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get()); - else if(name == "sounds") LLPipeline::setRenderSoundBeacons(check->get()); - else if(name == "particles") LLPipeline::setRenderParticleBeacons(check->get()); - else if(name == "highlights") - { - LLPipeline::toggleRenderHighlights(NULL); // Don't allow both to be OFF at the same time. Toggle the other one on if both now off. - if ( - !LLPipeline::getRenderBeacons(NULL) && - !LLPipeline::getRenderHighlights(NULL) ) + if (!LLPipeline::getRenderBeacons(NULL) && + !LLPipeline::getRenderHighlights(NULL)) { - LLPipeline::setRenderBeacons(TRUE); - view->getChild("beacons")->setControlValue(LLSD(TRUE)); - view->getChild("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline - } - } - else if(name == "beacons") - { - LLPipeline::toggleRenderBeacons(NULL); - // Don't allow both to be OFF at the same time. Toggle the other one on if both now off. - if ( - !LLPipeline::getRenderBeacons(NULL) && - !LLPipeline::getRenderHighlights(NULL) ) - { - LLPipeline::setRenderHighlights(TRUE); - view->getChild("highlights")->setControlValue(LLSD(TRUE)); - view->getChild("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline + if (name == "highlights") + { + LLPipeline::setRenderBeacons(TRUE); + view->getChild("beacons")->setControlValue(LLSD(TRUE)); + view->getChild("beacon_width_label")->setEnabled(TRUE); + view->getChild("beacon_width")->setEnabled(TRUE); + } + else + { + LLPipeline::setRenderHighlights(TRUE); + view->getChild("highlights")->setControlValue(LLSD(TRUE)); + } } } } diff --git a/indra/newview/llfloaterbeacons.h b/indra/newview/llfloaterbeacons.h index c12bdd726..c7a7b8803 100644 --- a/indra/newview/llfloaterbeacons.h +++ b/indra/newview/llfloaterbeacons.h @@ -44,7 +44,6 @@ public: /*virtual*/ BOOL postBuild(); // Needed to make the floater visibility toggle the beacons. - // Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. /*virtual*/ void open(); /*virtual*/ void close(bool app_quitting); diff --git a/indra/newview/llfloaterdickdongs.cpp b/indra/newview/llfloaterdickdongs.cpp deleted file mode 100644 index f9dbc64e1..000000000 --- a/indra/newview/llfloaterdickdongs.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file LLFloaterDickDongs.cpp - * @brief Front-end to LLPipeline controls for highlighting various kinds of objects. - * @author Coco - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llfloaterdickdongs.h" -#include "llcommon.h" -#include "llmd5.h" -#include "llagent.h" -#include "lluuid.h" -#include "llviewercontrol.h" -#include "lluictrlfactory.h" -#include "llcheckboxctrl.h" - -//this is really the only thing that needs to be here atm -LLFloaterDickDongs::LLFloaterDickDongs(const LLSD& seed) -{ - //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_dickdongs.xml"); -} - -//Not needed yet -/* -BOOL LLFloaterDickDongs::postBuild() -{ - childSetCommitCallback("touch_only", onClickUICheck, this); - childSetCommitCallback("scripted", onClickUICheck, this); - childSetCommitCallback("physical", onClickUICheck, this); - childSetCommitCallback("sounds", onClickUICheck, this); - childSetCommitCallback("particles", onClickUICheck, this); - childSetCommitCallback("highlights", onClickUICheck, this); - childSetCommitCallback("beacons", onClickUICheck, this); - return TRUE; -} -*/ - - -void LLFloaterDickDongs::open() -{ - LLUUID user = gAgent.getID(); - char hex_salty_uuid[MD5HEX_STR_SIZE]; - LLMD5 salted_uuid_hash((const U8*)user.asString().c_str(), 1); - salted_uuid_hash.hex_digest(hex_salty_uuid); - int i = (int)strtol((std::string(hex_salty_uuid).substr(0, 7) + "\n").c_str(),(char **)NULL,16); - llinfos << "Bridge Channel: " << (S32)i << llendl; - LLFloater::open(); - -} -void LLFloaterDickDongs::close(bool app_quitting) -{ - LLFloater::close(app_quitting); -} - -//Also not needed yet -/* -// Callback attached to each check box control to both affect their main purpose -// and to implement the couple screwy interdependency rules that some have. -//static -void LLFloaterDickDongs::onClickUICheck(LLUICtrl *ctrl, void* data) -{ - LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - std::string name = check->getName(); - LLFloaterDickDongs* view = (LLFloaterDickDongs*)data; -} -*/ diff --git a/indra/newview/llfloaterdickdongs.h b/indra/newview/llfloaterdickdongs.h deleted file mode 100644 index fe4d7697d..000000000 --- a/indra/newview/llfloaterdickdongs.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file llfloaterbeacons.h - * @brief Front-end to LLPipeline controls for highlighting various kinds of objects. - * @author Coco - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERDICKDONGS_H -#define LL_LLFLOATERDICKDONGS_H - -#include "llfloater.h" - -class LLFloaterDickDongs : public LLFloater, public LLFloaterSingleton -{ - friend class LLUISingleton >; - -public: - // /*virtual*/ BOOL postBuild(); - - // Needed to make the floater visibility toggle the beacons. - // Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. - /*virtual*/ void open(); - /*virtual*/ void close(bool app_quitting); - -private: - LLFloaterDickDongs(const LLSD& seed); - - //static void onClickUICheck(LLUICtrl *ctrl, void* data); -}; - -#endif diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 07c8de068..de5234ae4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2035,7 +2035,7 @@ bool idle_startup() LLFloaterActiveSpeakers::showInstance(); } - if (gSavedSettings.getBOOL("BeaconAlwaysOn")) + if (gSavedSettings.getBOOL("ShowBeaconsFloater")) { LLFloaterBeacons::showInstance(); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index afff999fa..6d49ad55d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -111,7 +111,6 @@ #include "llfloaterchat.h" #include "llfloatercustomize.h" #include "llfloaterdaycycle.h" -//#include "llfloaterdickdongs.h" No need for the custom floater right now, I think. -HgB #include "llfloaterdirectory.h" #include "llfloatereditui.h" #include "llfloaterchatterbox.h" @@ -6628,10 +6627,10 @@ class LLShowFloater : public view_listener_t { LLFloaterActiveSpeakers::toggleInstance(LLSD()); } - /*else if (floater_name == "beacons") + else if (floater_name == "beacons") { - LLFloaterBeacons::toggleInstance(LLSD()); NO - }*/ + LLFloaterBeacons::toggleInstance(LLSD()); + } else if (floater_name == "perm prefs") { LLFloaterPerms::toggleInstance(LLSD()); @@ -6695,14 +6694,10 @@ class LLFloaterVisible : public view_listener_t { new_value = LLFloaterActiveSpeakers::instanceVisible(LLSD()); } - /*else if (floater_name == "beacons") + else if (floater_name == "beacons") { - new_value = LLFloaterBeacons::instanceVisible(LLSD()); Oh man fuck this floater so much. + new_value = LLFloaterBeacons::instanceVisible(LLSD()); } - else if (floater_name == "dickdongs") - { - new_value = LLFloaterDickDongs::instanceVisible(LLSD()); Not needed any more. - }*/ else if (floater_name == "inventory") { LLInventoryView* iv = LLInventoryView::getActiveInventory(); @@ -9588,1104 +9583,12 @@ class LLWorldDayCycle : public view_listener_t } }; - - static void addMenu(view_listener_t *menu, const std::string& name) { sMenus.push_back(menu); menu->registerListener(gMenuHolder, name); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//Chalice - Old beacon style -class LLViewBeaconWidth : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string width = userdata.asString(); - if(width == "1") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 1); - } - else if(width == "4") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 4); - } - else if(width == "16") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 16); - } - else if(width == "32") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 32); - } - - return true; - } -}; - -//PURPLESL - Old beacon style -class LLViewToggleBeacon : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string beacon = userdata.asString(); - if (beacon == "scriptsbeacon") - { - LLPipeline::toggleRenderScriptedBeacons(NULL); - gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); - // toggle the other one off if it's on - if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) - { - LLPipeline::toggleRenderScriptedTouchBeacons(NULL); - gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); - } - } - else if (beacon == "physicalbeacon") - { - LLPipeline::toggleRenderPhysicalBeacons(NULL); - gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) ); - } - else if (beacon == "soundsbeacon") - { - LLPipeline::toggleRenderSoundBeacons(NULL); - gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) ); - } - else if (beacon == "particlesbeacon") - { - LLPipeline::toggleRenderParticleBeacons(NULL); - gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) ); - } - else if (beacon == "scripttouchbeacon") - { - LLPipeline::toggleRenderScriptedTouchBeacons(NULL); - gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); - // toggle the other one off if it's on - if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) - { - LLPipeline::toggleRenderScriptedBeacons(NULL); - gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); - } - } - else if (beacon == "renderbeacons") - { - LLPipeline::toggleRenderBeacons(NULL); - gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); - // toggle the other one on if it's not - if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) - { - LLPipeline::toggleRenderHighlights(NULL); - gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); - } - } - else if (beacon == "renderhighlights") - { - LLPipeline::toggleRenderHighlights(NULL); - gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); - // toggle the other one on if it's not - if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) - { - LLPipeline::toggleRenderBeacons(NULL); - gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); - } - } - - return true; - } -}; -//PURPLESL - Old beacon style -class LLViewCheckBeaconEnabled : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string beacon = userdata["data"].asString(); - bool new_value = false; - if (beacon == "scriptsbeacon") - { - new_value = gSavedSettings.getBOOL( "scriptsbeacon"); - LLPipeline::setRenderScriptedBeacons(new_value); - } - else if (beacon == "physicalbeacon") - { - new_value = gSavedSettings.getBOOL( "physicalbeacon"); - LLPipeline::setRenderPhysicalBeacons(new_value); - } - else if (beacon == "soundsbeacon") - { - new_value = gSavedSettings.getBOOL( "soundsbeacon"); - LLPipeline::setRenderSoundBeacons(new_value); - } - else if (beacon == "particlesbeacon") - { - new_value = gSavedSettings.getBOOL( "particlesbeacon"); - LLPipeline::setRenderParticleBeacons(new_value); - } - else if (beacon == "scripttouchbeacon") - { - new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); - LLPipeline::setRenderScriptedTouchBeacons(new_value); - } - else if (beacon == "renderbeacons") - { - new_value = gSavedSettings.getBOOL( "renderbeacons"); - LLPipeline::setRenderBeacons(new_value); - } - else if (beacon == "renderhighlights") - { - new_value = gSavedSettings.getBOOL( "renderhighlights"); - LLPipeline::setRenderHighlights(new_value); - } - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. @@ -10757,8 +9660,6 @@ void initialize_menus() addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter"); addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); - addMenu(new LLViewToggleBeacon(), "View.ToggleBeacon"); - addMenu(new LLViewBeaconWidth(), "View.BeaconWidth"); addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); addMenu(new LLZoomer(1.2f), "View.ZoomOut"); @@ -10776,7 +9677,6 @@ void initialize_menus() addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam"); addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); - addMenu(new LLViewCheckBeaconEnabled(), "View.CheckBeaconEnabled"); addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 64163b895..cf6f4bde6 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -522,8 +522,8 @@ public: ypos += y_inc; } // only display these messages if we are actually rendering beacons at this moment - static const LLCachedControl beacon_always_on("BeaconAlwaysOn",false); - if (LLPipeline::getRenderBeacons(NULL) && beacon_always_on) + static const LLCachedControl beacons_visible("BeaconsVisible",false); + if (LLPipeline::getRenderBeacons(NULL) && beacons_visible) { if (LLPipeline::getRenderParticleBeacons(NULL)) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ac8e8e2db..12c810849 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2509,8 +2509,8 @@ void LLPipeline::postSort(LLCamera& camera) } llpushcallstacks ; // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus - static const LLCachedControl beacon_always_on("BeaconAlwaysOn",false); - if (beacon_always_on && !sShadowRender) + static const LLCachedControl beacons_visible("BeaconsVisible", false); + if (beacons_visible && !sShadowRender) { if (sRenderScriptedTouchBeacons) { diff --git a/indra/newview/skins/default/xui/en-us/floater_beacons.xml b/indra/newview/skins/default/xui/en-us/floater_beacons.xml index 361d04601..ff9ed0b0a 100644 --- a/indra/newview/skins/default/xui/en-us/floater_beacons.xml +++ b/indra/newview/skins/default/xui/en-us/floater_beacons.xml @@ -1,24 +1,25 @@ - - + rect_control="FloaterBeaconsRect" control_name="ShowBeaconsFloater"> + + + - + Beacon Width: diff --git a/indra/newview/skins/default/xui/en-us/floater_dickdongs.xml b/indra/newview/skins/default/xui/en-us/floater_dickdongs.xml deleted file mode 100644 index a1afa5798..000000000 --- a/indra/newview/skins/default/xui/en-us/floater_dickdongs.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - AMOUNT OF AWESOME: - - - - diff --git a/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/indra/newview/skins/default/xui/en-us/menu_viewer.xml index aa3f5b756..afba100cc 100644 --- a/indra/newview/skins/default/xui/en-us/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en-us/menu_viewer.xml @@ -408,100 +408,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + From e41fd0d978935230863e9eed8bd74c49301aeec2 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 25 May 2011 20:14:56 +0200 Subject: [PATCH 05/12] Add comments regarding the colors and meanings of sound beacons. --- indra/newview/pipeline.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 55e224678..facce5332 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2818,7 +2818,7 @@ void LLPipeline::postSort(LLCamera& camera) LLAudioChannel* channel = sourcep->getChannel(); bool const is_playing = channel && channel->isPlaying(); S32 width = 2; - LLColor4 color = LLColor4(0.f, 0.f, 1.f, 0.5f); + LLColor4 color = LLColor4(0.f, 0.f, 1.f, 0.5f); // Blue: Not playing and not muted. if (is_playing) { static const LLCachedControl debug_beacon_line_width("DebugBeaconLineWidth",1); @@ -2826,21 +2826,21 @@ void LLPipeline::postSort(LLCamera& camera) F32 gain = sourcep->getGain() * channel->getSecondaryGain(); if (gain == 0.f) { - color = LLColor4(1.f, 0.f, 0.f, 0.5f); + color = LLColor4(1.f, 0.f, 0.f, 0.5f); // Red: Playing with gain == 0. This sucks up CPU, these should be muted. } else if (gain == 1.f) { - color = LLColor4(0.f, 1.f, 0.f, 0.5f); + color = LLColor4(0.f, 1.f, 0.f, 0.5f); // Green: Playing with gain == 1. width = debug_beacon_line_width; } else { - color = LLColor4(1.f, 1.f, 0.f, 0.5f); + color = LLColor4(1.f, 1.f, 0.f, 0.5f); // Yellow: Playing with 0 < gain < 1. width = 1 + gain * (debug_beacon_line_width - 1); } } else if (sourcep->isMuted()) - color = LLColor4(0.f, 1.f, 1.f, 0.5f); + color = LLColor4(0.f, 1.f, 1.f, 0.5f); // Cyan: Muted sound source. gObjectList.addDebugBeacon(pos, "", color, LLColor4(1.f, 1.f, 1.f, 0.5f), width); } // From 613c6755e9ada079d345ad27fa9ecb2638a33ee5 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 3 Jun 2011 22:51:46 +0200 Subject: [PATCH 06/12] Fix sound explorer. Looping sounds were always showing as 'Looping', even after they stopped. Detection of stopped sounds is much better now. Instead of only logging a sound as stopped when the audio source is destroyed, we now detect whether or not it is associated with an audio channel or not (the normal way to stop a sound is to set the channel to NULL). This is still a bit fuzzy, since an audio channel doesn't necessarily have to be playing, but states where an audio source is associated with a non-playing audio channel are only short temporary states that don't affect the usefulness of the sound explorer. --- indra/llaudio/llaudioengine.cpp | 59 ++++++++++++++---------- indra/llaudio/llaudioengine.h | 21 +++++++-- indra/newview/llfloaterexploresounds.cpp | 29 ++++-------- 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index b61d934dd..fa5444cf5 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1336,16 +1336,17 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 LLAudioSource::~LLAudioSource() { + // + // Record destruction of LLAudioSource object. + if(mType != LLAudioEngine::AUDIO_TYPE_UI) + logSoundStop(mLogID, true); + // if (mChannelp) { // Stop playback of this sound mChannelp->setSource(NULL); - mChannelp = NULL; + setChannel(NULL); } - // - if(mType != LLAudioEngine::AUDIO_TYPE_UI) // && mSourceID.notNull()) - logSoundStop(mLogID); - // } @@ -1356,10 +1357,17 @@ void LLAudioSource::setChannel(LLAudioChannel *channelp) return; } + // + if (!channelp) + { + if(mType != LLAudioEngine::AUDIO_TYPE_UI) + logSoundStop(mLogID, false); + } + // + mChannelp = channelp; } - void LLAudioSource::update() { if (!getCurrentBuffer()) @@ -1434,10 +1442,6 @@ bool LLAudioSource::setupChannel() bool LLAudioSource::play(const LLUUID &audio_uuid) { - // - if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull()) - logSoundPlay(mLogID, this, mPositionGlobal, mType, audio_uuid, mOwnerID, mSourceID, mIsTrigger, mLoop); // is mID okay for source id? - // // Special abuse of play(); don't play a sound, but kill it. if (audio_uuid.isNull()) { @@ -1453,6 +1457,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) return false; } + // + if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull()) + logSoundPlay(this, audio_uuid); + // + // Reset our age timeout if someone attempts to play the source. mAgeTimer.reset(); @@ -1846,36 +1855,38 @@ bool LLAudioData::load() std::map gSoundHistory; // static -void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped) +void logSoundPlay(LLAudioSource* audio_source, LLUUID const& assetid) { LLSoundHistoryItem item; - item.mID = id; + item.mID = audio_source->getLogID(); item.mAudioSource = audio_source; - item.mPosition = position; - item.mType = type; + item.mPosition = audio_source->getPositionGlobal(); + item.mType = audio_source->getType(); item.mAssetID = assetid; - item.mOwnerID = ownerid; - item.mSourceID = sourceid; + item.mOwnerID = audio_source->getOwnerID(); + item.mSourceID = audio_source->getSourceID(); item.mPlaying = true; item.mTimeStarted = LLTimer::getElapsedSeconds(); item.mTimeStopped = F64_MAX; - item.mIsTrigger = is_trigger; - item.mIsLooped = is_looped; + item.mIsTrigger = audio_source->getIsTrigger(); + item.mIsLooped = audio_source->isLoop(); item.mReviewed = false; item.mReviewedCollision = false; - gSoundHistory[id] = item; + gSoundHistory[item.mID] = item; } //static -void logSoundStop(LLUUID id) +void logSoundStop(LLUUID const& id, bool destructed) { - if(gSoundHistory.find(id) != gSoundHistory.end()) + std::map::iterator iter = gSoundHistory.find(id); + if(iter != gSoundHistory.end() && iter->second.mAudioSource) { - gSoundHistory[id].mPlaying = false; - gSoundHistory[id].mTimeStopped = LLTimer::getElapsedSeconds(); - gSoundHistory[id].mAudioSource = NULL; // just in case + iter->second.mPlaying = false; + iter->second.mTimeStopped = LLTimer::getElapsedSeconds(); + if (destructed) + iter->second.mAudioSource = NULL; pruneSoundLog(); } } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 5a5d161a9..c41458553 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -306,7 +306,11 @@ public: void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; } void setType(S32 type) { mType = type; } - S32 getType() { return mType; } + S32 getType(void) const { return mType; } + + LLUUID const& getOwnerID(void) const { return mOwnerID; } + LLUUID const& getSourceID(void) const { return mSourceID; } + bool getIsTrigger(void) const { return mIsTrigger; } void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } LLVector3d getPositionGlobal() const { return mPositionGlobal; } @@ -504,12 +508,23 @@ struct LLSoundHistoryItem LLSoundHistoryItem() : mType(0), mPlaying(false), mIsTrigger(false), mIsLooped(false), mReviewed(false), mReviewedCollision(false), mTimeStarted(0), mTimeStopped(0), mAudioSource(0) {} + + bool isPlaying(void) const + { + return mPlaying && mAudioSource && mAudioSource->getChannel() + // It's only REALLY playing if the following also returns true, + // but it's too hard detect when that part is starting/stopping, + // so in the sound explorer we call "playing" (or "looping") + // those audio source that have a channel assigned and call + // it a day. + /*&& mAudioSource->getChannel()->isPlaying()*/ ; + } }; extern std::map gSoundHistory; -extern void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped); -extern void logSoundStop(LLUUID id); +extern void logSoundPlay(LLAudioSource* audio_source, LLUUID const& assetid); +extern void logSoundStop(LLUUID const& id, bool destructed); extern void pruneSoundLog(); extern int gSoundHistoryPruneCounter; diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index 56c57b4bd..7fdcfda10 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -110,9 +110,9 @@ class LLSoundHistoryItemCompare public: bool operator() (LLSoundHistoryItem first, LLSoundHistoryItem second) { - if(first.mPlaying) + if(first.isPlaying()) { - if(second.mPlaying) + if(second.isPlaying()) { return (first.mTimeStarted > second.mTimeStarted); } @@ -121,7 +121,7 @@ public: return true; } } - else if(second.mPlaying) + else if(second.isPlaying()) { return false; } @@ -205,17 +205,12 @@ BOOL LLFloaterExploreSounds::tick() LLSD& playing_column = element["columns"][0]; playing_column["column"] = "playing"; - if (item.mIsLooped) + if(item.isPlaying()) { - playing_column["value"] = " Looping"; - } - else if(item.mPlaying) - { - playing_column["value"] = " Playing"; + playing_column["value"] = item.mIsLooped ? " Looping" : " Playing"; } else { - S32 time = (LLTimer::getElapsedSeconds() - item.mTimeStopped); S32 hours = time / 3600; S32 mins = time / 60; @@ -358,23 +353,15 @@ void LLFloaterExploreSounds::handle_stop(void* user_data) { LLSoundHistoryItem item = floater->getItem((*selection_iter)->getValue()); if(item.mID.isNull()) continue; - if(item.mPlaying) + if(item.isPlaying()) { - if(item.mAudioSource) - { - S32 type = item.mType; - item.mAudioSource->setType(LLAudioEngine::AUDIO_TYPE_UI); - if(item.mAudioSource) - item.mAudioSource->play(LLUUID::null); - if(item.mAudioSource) - item.mAudioSource->setType(type); - } + item.mAudioSource->play(LLUUID::null); } } } + void LLFloaterExploreSounds::blacklistSound(void* user_data) { - LLFloaterBlacklist::show(); LLFloaterExploreSounds* floater = (LLFloaterExploreSounds*)user_data; LLScrollListCtrl* list = floater->getChild("sound_list"); From 76db4553511449864e688ae32ab00a3926abaa21 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 3 Jun 2011 23:02:38 +0200 Subject: [PATCH 07/12] Compile error fix. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit indra/newview/llselectmgr.h:517:7: error: extra qualification ‘LLSelectMgr::’ on member ‘selectionSetMediaTypeAndURL’ --- indra/newview/llselectmgr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 1472cc8b7..be482b725 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -514,7 +514,7 @@ public: void selectionSetTexGen( U8 texgen ); void selectionSetShiny( U8 shiny ); void selectionSetFullbright( U8 fullbright ); - void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url); + void selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url); void selectionSetClickAction(U8 action); void selectionSetIncludeInSearch(bool include_in_search); void selectionSetGlow(const F32 glow); From 55f1d00c3b931235b343df474df416a101361855 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 3 Jun 2011 23:10:53 +0200 Subject: [PATCH 08/12] Compiler error fix. How can this every have compiled? Please don't push commits without first at least compiling it :/ Using '#else if' instead of '#elif'?! indra/newview/llappviewer.cpp:797:7: error: extra tokens at end of #else directive --- indra/newview/llappviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 95d419d6e..e3f95f5ca 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -794,7 +794,7 @@ bool LLAppViewer::init() OSMB_OK); return 0; } -#else if (_M_IX86_FP == 1 || defined(__SSE__)) +#elif (_M_IX86_FP == 1 || defined(__SSE__)) // Without SSE support we will crash almost immediately, warn here. if (!gSysCPU.hasSSE()) { From 50ce0c4183ca4dadd62d958accb8a1d8a65234d3 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 3 Jun 2011 23:22:10 +0200 Subject: [PATCH 09/12] Compiler error fix. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit indra/newview/llspatialpartition.cpp:1079:53: error: operation on ‘((LLSpatialGroup*)this)->LLSpatialGroup::mObjectBounds[0]’ may be undefined --- indra/newview/llspatialpartition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index ca70e52e6..1c789e1ca 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1075,7 +1075,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = + mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] = mObjectExtents[0] = mObjectExtents[1] = mViewAngle; sg_assert(mOctreeNode->getListenerCount() == 0); From 08f27244819a0516f59d1069f86029a7a2d29be9 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 5 Jun 2011 15:24:32 +0200 Subject: [PATCH 10/12] Compile error for Debug. Remove last instance of mCtrlReflections. --- indra/newview/llpaneldisplay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp index 4a684a61a..c7aeabcce 100644 --- a/indra/newview/llpaneldisplay.cpp +++ b/indra/newview/llpaneldisplay.cpp @@ -650,7 +650,6 @@ void LLPanelDisplay::setHiddenGraphicsState(bool isHidden) llassert(mPostProcessText != NULL); llassert(mCtrlBumpShiny != NULL); - llassert(mCtrlReflections != NULL); llassert(mCtrlWindLight != NULL); llassert(mCtrlAvatarVP != NULL); llassert(mCtrlShaderEnable != NULL); From b31dd134f60a89638ec7cc130dba8259817254e3 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 5 Jun 2011 15:53:05 +0200 Subject: [PATCH 11/12] Never call gDirUtilp->getExpandedFilename when getLindenUserDir() is empty. --- indra/newview/llviewertexturelist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index f7562ecec..78d983025 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -265,8 +265,8 @@ void LLViewerTextureList::shutdown() if (++count >= max_count) break; } - - if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty()) + + if (count > 0 && !gDirUtilp->getLindenUserDir(true).empty()) { std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name()); llofstream file; From 5d87098bd037cd42913d6cc3d940bb9f7d16a643 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Mon, 6 Jun 2011 21:38:58 +0200 Subject: [PATCH 12/12] Port Viewer 2 indra/llvfs This introduces some API changes, like the new LLDirIterator, that causes changes elsewhere. It also include Log Linden's cache changes that aren't in viewer-development yet that increase the maximum cache size to ~10 GB. --- indra/cmake/LLVFS.cmake | 7 +- indra/llvfs/CMakeLists.txt | 8 + indra/llvfs/lldir.cpp | 126 ++++++----- indra/llvfs/lldir.h | 41 ++-- indra/llvfs/lldir_linux.cpp | 178 +++------------ indra/llvfs/lldir_linux.h | 13 +- indra/llvfs/lldir_mac.cpp | 172 +++----------- indra/llvfs/lldir_mac.h | 12 +- indra/llvfs/lldir_solaris.cpp | 134 +---------- indra/llvfs/lldir_solaris.h | 13 +- indra/llvfs/lldir_win32.cpp | 193 ++++------------ indra/llvfs/lldir_win32.h | 11 +- indra/llvfs/lldiriterator.cpp | 210 ++++++++++++++++++ indra/llvfs/lldiriterator.h | 87 ++++++++ indra/llvfs/lllfsthread.cpp | 1 - indra/llvfs/lllfsthread.h | 2 +- indra/llvfs/llpidlock.cpp | 14 +- indra/llvfs/llpidlock.h | 10 +- indra/llvfs/llvfile.cpp | 5 +- indra/llvfs/llvfs.cpp | 170 +++++++------- indra/llvfs/llvfs.h | 19 +- indra/newview/app_settings/settings.xml | 11 + indra/newview/ascentdaycyclemanager.cpp | 7 +- indra/newview/lgghunspell_wrapper.cpp | 48 ++-- indra/newview/llappviewer.cpp | 151 +++++++++---- indra/newview/llappviewerlinux.cpp | 5 +- indra/newview/llappviewermacosx.cpp | 4 +- indra/newview/llpanelnetwork.cpp | 10 +- indra/newview/llpanelskins.cpp | 7 +- indra/newview/lltexturecache.cpp | 6 +- indra/newview/llwaterparammanager.cpp | 7 +- indra/newview/llwlparammanager.cpp | 7 +- .../xui/en-us/panel_preferences_network.xml | 4 +- 33 files changed, 837 insertions(+), 856 deletions(-) create mode 100644 indra/llvfs/lldiriterator.cpp create mode 100644 indra/llvfs/lldiriterator.h diff --git a/indra/cmake/LLVFS.cmake b/indra/cmake/LLVFS.cmake index 0fe87cdea..0ff227c12 100644 --- a/indra/cmake/LLVFS.cmake +++ b/indra/cmake/LLVFS.cmake @@ -1,7 +1,12 @@ # -*- cmake -*- +include(Boost) + set(LLVFS_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llvfs ) -set(LLVFS_LIBRARIES llvfs) +set(LLVFS_LIBRARIES + llvfs + ${BOOST_REGEX_LIBRARY} + ) diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index d6a0bbc08..e5889805b 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -4,6 +4,7 @@ project(llvfs) include(00-Common) include(LLCommon) +include(UnixInstall) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -11,6 +12,7 @@ include_directories( set(llvfs_SOURCE_FILES lldir.cpp + lldiriterator.cpp lllfsthread.cpp llpidlock.cpp llvfile.cpp @@ -22,6 +24,7 @@ set(llvfs_HEADER_FILES CMakeLists.txt lldir.h + lldiriterator.h lllfsthread.h llpidlock.h llvfile.h @@ -59,6 +62,11 @@ list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES}) add_library (llvfs ${llvfs_SOURCE_FILES}) add_dependencies(llvfs prepare) +target_link_libraries(llvfs + ${BOOST_FILESYSTEM_LIBRARY} + ${BOOST_SYSTEM_LIBRARY} + ) + if (DARWIN) include(CMakeFindFrameworks) find_library(CARBON_LIBRARY Carbon) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 28fcd7751..63023a28e 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -41,9 +41,12 @@ #endif #include "lldir.h" + #include "llerror.h" +#include "lltimer.h" // ms_sleep() #include "lluuid.h" -#include "lltimer.h" + +#include "lldiriterator.h" #if LL_WINDOWS #include "lldir_win32.h" @@ -88,27 +91,38 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) std::string filename; std::string fullpath; S32 result; - while (getNextFileInDir(dirname, mask, filename, FALSE)) + + LLDirIterator iter(dirname, mask); + while (iter.next(filename)) { - if ((filename == ".") || (filename == "..")) + fullpath = dirname; + fullpath += getDirDelimiter(); + fullpath += filename; + + if(LLFile::isdir(fullpath)) { // skipping directory traversal filenames count++; continue; } - fullpath = dirname; - fullpath += getDirDelimiter(); - fullpath += filename; S32 retry_count = 0; while (retry_count < 5) { if (0 != LLFile::remove(fullpath)) { + retry_count++; result = errno; llwarns << "Problem removing " << fullpath << " - errorcode: " << result << " attempt " << retry_count << llendl; - ms_sleep(1000); + + if(retry_count >= 5) + { + llwarns << "Failed to remove " << fullpath << llendl ; + return count ; + } + + ms_sleep(100); } else { @@ -117,8 +131,7 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) llwarns << "Successfully removed " << fullpath << llendl; } break; - } - retry_count++; + } } count++; } @@ -126,23 +139,31 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) } const std::string LLDir::findFile(const std::string &filename, - const std::string searchPath1, - const std::string searchPath2, - const std::string searchPath3) const + const std::string& searchPath1, + const std::string& searchPath2, + const std::string& searchPath3) const { std::vector search_paths; search_paths.push_back(searchPath1); search_paths.push_back(searchPath2); search_paths.push_back(searchPath3); + return findFile(filename, search_paths); +} - std::vector::iterator search_path_iter; +const std::string LLDir::findFile(const std::string& filename, const std::vector search_paths) const +{ + std::vector::const_iterator search_path_iter; for (search_path_iter = search_paths.begin(); search_path_iter != search_paths.end(); ++search_path_iter) { if (!search_path_iter->empty()) { - std::string filename_and_path = (*search_path_iter) + getDirDelimiter() + filename; + std::string filename_and_path = (*search_path_iter); + if (!filename.empty()) + { + filename_and_path += getDirDelimiter() + filename; + } if (fileExists(filename_and_path)) { return filename_and_path; @@ -289,11 +310,7 @@ const std::string& LLDir::getDefaultSkinDir() const const std::string LLDir::getSkinBaseDir() const { - std::string dir = getAppRODataDir(); - dir += mDirDelimiter; - dir += "skins"; - - return dir; + return mSkinBaseDir; } const std::string &LLDir::getLLPluginDir() const @@ -325,25 +342,19 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd prefix += mDirDelimiter; prefix += "app_settings"; break; - + case LL_PATH_CHARACTER: prefix = getAppRODataDir(); prefix += mDirDelimiter; prefix += "character"; break; - case LL_PATH_MOTIONS: - prefix = getAppRODataDir(); - prefix += mDirDelimiter; - prefix += "motions"; - break; - case LL_PATH_HELP: prefix = "help"; break; case LL_PATH_CACHE: - prefix = getCacheDir(); + prefix = getCacheDir(); break; case LL_PATH_USER_SETTINGS: @@ -378,28 +389,34 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd prefix = getSkinDir(); break; - case LL_PATH_SKINS: - prefix = getAppRODataDir(); - prefix += mDirDelimiter; - prefix += "skins"; + case LL_PATH_DEFAULT_SKIN: + prefix = getDefaultSkinDir(); break; - //case LL_PATH_HTML: - // prefix = getSkinDir(); - // prefix += mDirDelimiter; - // prefix += "html"; - // break; + case LL_PATH_USER_SKIN: + prefix = getUserSkinDir(); + break; - case LL_PATH_MOZILLA_PROFILE: - prefix = getOSUserAppDir(); + case LL_PATH_SKINS: + prefix = getSkinBaseDir(); + break; + + case LL_PATH_LOCAL_ASSETS: + prefix = getAppRODataDir(); prefix += mDirDelimiter; - prefix += "browser_profile"; + prefix += "local_assets"; break; case LL_PATH_EXECUTABLE: prefix = getExecutableDir(); break; + case LL_PATH_FONTS: + prefix = getAppRODataDir(); + prefix += mDirDelimiter; + prefix += "fonts"; + break; + default: llassert(0); } @@ -415,6 +432,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd filename = subdir1 + mDirDelimiter + filename; } + if (prefix.empty()) + { + llwarns << "prefix is empty, possible bad filename" << llendl; + } + std::string expanded_filename; if (!filename.empty()) { @@ -440,7 +462,6 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd } //llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl; - return expanded_filename; } @@ -496,11 +517,14 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::st std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1) + ((subdir2.empty() ? "" : mDirDelimiter) + subdir2); - std::string found_file = findFile(filename, - getUserSkinDir() + subdirs, // first look in user skin override - getSkinDir() + subdirs, // then in current skin - getDefaultSkinDir() + subdirs); // and last in default skin + std::vector search_paths; + + search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override + search_paths.push_back(getSkinDir() + subdirs); // then in current skin + search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin + search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory + std::string found_file = findFile(filename, search_paths); return found_file; } @@ -625,9 +649,7 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string void LLDir::setSkinFolder(const std::string &skin_folder) { - mSkinDir = getAppRODataDir(); - mSkinDir += mDirDelimiter; - mSkinDir += "skins"; + mSkinDir = getSkinBaseDir(); mSkinDir += mDirDelimiter; mSkinDir += skin_folder; @@ -641,9 +663,7 @@ void LLDir::setSkinFolder(const std::string &skin_folder) // base skin which is used as fallback for all skinned files // e.g. c:\program files\secondlife\skins\default - mDefaultSkinDir = getAppRODataDir(); - mDefaultSkinDir += mDirDelimiter; - mDefaultSkinDir += "skins"; + mDefaultSkinDir = getSkinBaseDir(); mDefaultSkinDir += mDirDelimiter; mDefaultSkinDir += "default"; } @@ -688,12 +708,8 @@ void LLDir::dumpCurrentDirectories() LL_DEBUGS2("AppInit","Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL; LL_DEBUGS2("AppInit","Directories") << " TempDir: " << getTempDir() << LL_ENDL; LL_DEBUGS2("AppInit","Directories") << " CAFile: " << getCAFile() << LL_ENDL; + LL_DEBUGS2("AppInit","Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL; LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL; - -#if LL_LIBXUL_ENABLED - LL_DEBUGS2("AppInit","Directories") << " HTML Path: " << getExpandedFilename( LL_PATH_HTML, "" ) << llendl; - LL_DEBUGS2("AppInit","Directories") << " Mozilla Profile Path: " << getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) << llendl; -#endif } diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index a90b8ab24..250369b78 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -38,26 +38,27 @@ #define MAX_PATH MAXPATHLEN #endif -// these numbers *may* get serialized, so we need to be explicit +// these numbers *may* get serialized (really??), so we need to be explicit typedef enum ELLPath { LL_PATH_NONE = 0, LL_PATH_USER_SETTINGS = 1, LL_PATH_APP_SETTINGS = 2, - LL_PATH_PER_SL_ACCOUNT = 3, + LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet LL_PATH_CACHE = 4, LL_PATH_CHARACTER = 5, - LL_PATH_MOTIONS = 6, - LL_PATH_HELP = 7, - LL_PATH_LOGS = 8, - LL_PATH_TEMP = 9, - LL_PATH_SKINS = 10, - LL_PATH_TOP_SKIN = 11, - LL_PATH_CHAT_LOGS = 12, - LL_PATH_PER_ACCOUNT_CHAT_LOGS = 13, - LL_PATH_MOZILLA_PROFILE = 14, -// LL_PATH_HTML = 15, + LL_PATH_HELP = 6, + LL_PATH_LOGS = 7, + LL_PATH_TEMP = 8, + LL_PATH_SKINS = 9, + LL_PATH_TOP_SKIN = 10, + LL_PATH_CHAT_LOGS = 11, + LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12, + LL_PATH_USER_SKIN = 14, + LL_PATH_LOCAL_ASSETS = 15, LL_PATH_EXECUTABLE = 16, + LL_PATH_DEFAULT_SKIN = 17, + LL_PATH_FONTS = 18, LL_PATH_LAST } ELLPath; @@ -68,18 +69,23 @@ class LLDir LLDir(); virtual ~LLDir(); - virtual void initAppDirs(const std::string &app_name) = 0; - public: + // app_name - Usually SecondLife, used for creating settings directories + // in OS-specific location, such as C:\Documents and Settings + // app_read_only_data_dir - Usually the source code directory, used + // for test applications to read newview data files. + virtual void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir = "") = 0; + virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); // pure virtual functions virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0; - virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 0; + virtual std::string getCurPath() = 0; virtual BOOL fileExists(const std::string &filename) const = 0; - const std::string findFile(const std::string &filename, const std::string searchPath1 = "", const std::string searchPath2 = "", const std::string searchPath3 = "") const; + const std::string findFile(const std::string& filename, const std::vector filenames) const; + const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so') @@ -158,6 +164,7 @@ protected: std::string mDefaultCacheDir; // default cache diretory std::string mOSCacheDir; // operating system cache dir std::string mDirDelimiter; + std::string mSkinBaseDir; // Base for skins paths. std::string mSkinDir; // Location for current skin info. std::string mDefaultSkinDir; // Location for default skin info. std::string mUserSkinDir; // Location for user-modified skin info. diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index ce6b1885f..a4df354c5 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -94,7 +94,25 @@ LLDir_Linux::LLDir_Linux() mExecutablePathAndName = ""; mExecutableDir = tmp_str; mWorkingDir = tmp_str; +#ifdef APP_RO_DATA_DIR + mAppRODataDir = APP_RO_DATA_DIR; +#else mAppRODataDir = tmp_str; +#endif + std::string::size_type build_dir_pos = mExecutableDir.rfind("/indra/viewer-linux-"); + if (build_dir_pos != std::string::npos) + { + // ...we're in a dev checkout + mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "/indra/newview/skins"; + llinfos << "Running in dev checkout with mSkinBaseDir " + << mSkinBaseDir << llendl; + } + else + { + // ...normal installation running + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } + mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; mLindenUserDir = ""; @@ -126,31 +144,6 @@ LLDir_Linux::LLDir_Linux() mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; -#ifdef APP_RO_DATA_DIR - const char* appRODataDir = APP_RO_DATA_DIR; - if(appRODataDir[0] == '/') - { - // We have a full path to the data directory. - mAppRODataDir = appRODataDir; - } - else if(appRODataDir[0] != '\0') - { - // We have a relative path to the data directory. Search - // for it in each potential install prefix containing the - // executable. - for(std::string prefix = getDirName(mExecutableDir); - !prefix.empty(); prefix = getDirName(prefix)) - { - std::string dir = prefix + "/" + appRODataDir; - if(fileExists(dir + "/app_settings")) - { - mAppRODataDir = dir; - break; - } - } - } -#endif - // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. mTempDir = "/tmp"; } @@ -162,8 +155,15 @@ LLDir_Linux::~LLDir_Linux() // Implementation -void LLDir_Linux::initAppDirs(const std::string &app_name) +void LLDir_Linux::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) { + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } mAppName = app_name; std::string upper_app_name(app_name); @@ -226,24 +226,6 @@ void LLDir_Linux::initAppDirs(const std::string &app_name) } } - res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"")); - if (res == -1) - { - if (errno != EEXIST) - { - llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; - } - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries")); - if (res == -1) - { - if (errno != EEXIST) - { - llwarns << "Couldn't create LL_PATH_USER_SETTINGS/dictionaries dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; - } - } - mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); } @@ -266,114 +248,6 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string & return (file_count); } -// get the next file in the directory -// automatically wrap if we've hit the end -BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) -{ - glob_t g; - BOOL result = FALSE; - fname = ""; - - if(!(dirname == mCurrentDir)) - { - // different dir specified, close old search - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mCurrentDir = dirname; - } - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - if((int)g.gl_pathc != mCurrentDirCount) - { - // Number of matches has changed since the last search, meaning a file has been added or deleted. - // Reset the index. - mCurrentDirIndex = -1; - mCurrentDirCount = g.gl_pathc; - } - - mCurrentDirIndex++; - - if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap) - { - mCurrentDirIndex = 0; - } - - if(mCurrentDirIndex < (int)g.gl_pathc) - { -// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[mCurrentDirIndex]; - - char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); - - if(s == NULL) - s = g.gl_pathv[mCurrentDirIndex]; - else if(s[0] == '/') - s++; - - fname = s; - - result = TRUE; - } - } - - globfree(&g); - } - - return(result); -} - - -// get a random file in the directory -// automatically wrap if we've hit the end -void LLDir_Linux::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - S32 num_files; - S32 which_file; - DIR *dirp; - dirent *entryp = NULL; - - fname = ""; - - num_files = countFilesInDir(dirname,mask); - if (!num_files) - { - return; - } - - which_file = ll_rand(num_files); - -// llinfos << "Random select file #" << which_file << llendl; - - // which_file now indicates the (zero-based) index to which file to play - - if (!((dirp = opendir(dirname.c_str())))) - { - while (which_file--) - { - if (!((entryp = readdir(dirp)))) - { - return; - } - } - - if ((!which_file) && entryp) - { - fname = entryp->d_name; - } - - closedir(dirp); - } -} - std::string LLDir_Linux::getCurPath() { char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h index 8e94fb1c9..46bf91c69 100644 --- a/indra/llvfs/lldir_linux.h +++ b/indra/llvfs/lldir_linux.h @@ -30,6 +30,10 @@ * $/LicenseInfo$ */ +#if !LL_LINUX +#error This header must not be included when compiling for any target other than Linux. Consider including lldir.h instead. +#endif // !LL_LINUX + #ifndef LL_LLDIR_LINUX_H #define LL_LLDIR_LINUX_H @@ -44,12 +48,11 @@ public: LLDir_Linux(); virtual ~LLDir_Linux(); - virtual void initAppDirs(const std::string &app_name); -public: + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); + virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap); - virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); @@ -59,7 +62,7 @@ private: DIR *mDirp; int mCurrentDirIndex; int mCurrentDirCount; - std::string mCurrentDir; + std::string mCurrentDir; }; #endif // LL_LLDIR_LINUX_H diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 98eb8fd5e..c15bc7ee0 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -68,7 +68,8 @@ static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString, { if (stringRef) { - long bufferSize = CFStringGetLength(stringRef) + 1; + long stringSize = CFStringGetLength(stringRef) + 1; + long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8); char* buffer = new char[bufferSize]; memset(buffer, 0, bufferSize); if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8)) @@ -142,9 +143,34 @@ LLDir_Mac::LLDir_Mac() CFURLRefToLLString(executableParentURLRef, mExecutableDir, true); // mAppRODataDir - CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef); + + + // *NOTE: When running in a dev tree, use the copy of + // skins in indra/newview/ rather than in the application bundle. This + // mirrors Windows dev environment behavior and allows direct checkin + // of edited skins/xui files. JC + + // MBW -- This keeps the mac application from finding other things. + // If this is really for skins, it should JUST apply to skins. + + CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef); CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true); + U32 build_dir_pos = mExecutableDir.rfind("/indra/build-darwin-"); + if (build_dir_pos != std::string::npos) + { + // ...we're in a dev checkout + mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + + "/indra/newview/skins"; + llinfos << "Running in dev checkout with mSkinBaseDir " + << mSkinBaseDir << llendl; + } + else + { + // ...normal installation running + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } + // mOSUserDir error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); if (error == noErr) @@ -205,8 +231,15 @@ LLDir_Mac::~LLDir_Mac() // Implementation -void LLDir_Mac::initAppDirs(const std::string &app_name) +void LLDir_Mac::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) { + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); //dumpCurrentDirectories(); @@ -231,139 +264,6 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma return (file_count); } -// get the next file in the directory -// automatically wrap if we've hit the end -BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) -{ - glob_t g; - BOOL result = FALSE; - fname = ""; - - if(!(dirname == mCurrentDir)) - { - // different dir specified, close old search - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mCurrentDir = dirname; - } - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - if(g.gl_pathc != mCurrentDirCount) - { - // Number of matches has changed since the last search, meaning a file has been added or deleted. - // Reset the index. - mCurrentDirIndex = -1; - mCurrentDirCount = g.gl_pathc; - } - - mCurrentDirIndex++; - - if((mCurrentDirIndex >= g.gl_pathc) && wrap) - { - mCurrentDirIndex = 0; - } - - if(mCurrentDirIndex < g.gl_pathc) - { -// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[mCurrentDirIndex]; - - char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); - - if(s == NULL) - s = g.gl_pathv[mCurrentDirIndex]; - else if(s[0] == '/') - s++; - - fname = s; - - result = TRUE; - } - } - - globfree(&g); - } - - return(result); -} - -// get a random file in the directory -void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - S32 which_file; - glob_t g; - fname = ""; - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - - which_file = ll_rand(g.gl_pathc); - -// llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl; - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[which_file]; - - char *s = strrchr(g.gl_pathv[which_file], '/'); - - if(s == NULL) - s = g.gl_pathv[which_file]; - else if(s[0] == '/') - s++; - - fname = s; - } - - globfree(&g); - } -} - -S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask) -{ - glob_t g; - S32 result = 0; - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - int i; - - for(i = 0; i < g.gl_pathc; i++) - { -// llinfos << "deleteFilesInDir: deleting number " << i << ", path is " << g.gl_pathv[i] << llendl; - - if(unlink(g.gl_pathv[i]) != 0) - { - result = errno; - - llwarns << "Problem removing " << g.gl_pathv[i] << " - errorcode: " - << result << llendl; - } - } - - globfree(&g); - } - - return(result); -} - std::string LLDir_Mac::getCurPath() { char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h index 8be5d03b2..d99f9e39e 100644 --- a/indra/llvfs/lldir_mac.h +++ b/indra/llvfs/lldir_mac.h @@ -30,6 +30,10 @@ * $/LicenseInfo$ */ +#if !LL_DARWIN +#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. +#endif // !LL_DARWIN + #ifndef LL_LLDIR_MAC_H #define LL_LLDIR_MAC_H @@ -43,13 +47,11 @@ public: LLDir_Mac(); virtual ~LLDir_Mac(); - virtual void initAppDirs(const std::string &app_name); -public: - virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask); + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); + virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap); - virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname); virtual BOOL fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index 2ebd6e471..22df6a9a3 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -174,8 +174,14 @@ LLDir_Solaris::~LLDir_Solaris() // Implementation -void LLDir_Solaris::initAppDirs(const std::string &app_name) +void LLDir_Solaris::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) { + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + } mAppName = app_name; std::string upper_app_name(app_name); @@ -238,24 +244,6 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name) } } - res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"")); - if (res == -1) - { - if (errno != EEXIST) - { - llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; - } - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries")); - if (res == -1) - { - if (errno != EEXIST) - { - llwarns << "Couldn't create LL_PATH_USER_SETTINGS/dictionaries dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; - } - } - mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); } @@ -278,114 +266,6 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string return (file_count); } -// get the next file in the directory -// automatically wrap if we've hit the end -BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) -{ - glob_t g; - BOOL result = FALSE; - fname = ""; - - if(!(dirname == mCurrentDir)) - { - // different dir specified, close old search - mCurrentDirIndex = -1; - mCurrentDirCount = -1; - mCurrentDir = dirname; - } - - std::string tmp_str; - tmp_str = dirname; - tmp_str += mask; - - if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) - { - if(g.gl_pathc > 0) - { - if((int)g.gl_pathc != mCurrentDirCount) - { - // Number of matches has changed since the last search, meaning a file has been added or deleted. - // Reset the index. - mCurrentDirIndex = -1; - mCurrentDirCount = g.gl_pathc; - } - - mCurrentDirIndex++; - - if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap) - { - mCurrentDirIndex = 0; - } - - if(mCurrentDirIndex < (int)g.gl_pathc) - { -// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - - // The API wants just the filename, not the full path. - //fname = g.gl_pathv[mCurrentDirIndex]; - - char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); - - if(s == NULL) - s = g.gl_pathv[mCurrentDirIndex]; - else if(s[0] == '/') - s++; - - fname = s; - - result = TRUE; - } - } - - globfree(&g); - } - - return(result); -} - - -// get a random file in the directory -// automatically wrap if we've hit the end -void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - S32 num_files; - S32 which_file; - DIR *dirp; - dirent *entryp = NULL; - - fname = ""; - - num_files = countFilesInDir(dirname,mask); - if (!num_files) - { - return; - } - - which_file = ll_rand(num_files); - -// llinfos << "Random select file #" << which_file << llendl; - - // which_file now indicates the (zero-based) index to which file to play - - if (!((dirp = opendir(dirname.c_str())))) - { - while (which_file--) - { - if (!((entryp = readdir(dirp)))) - { - return; - } - } - - if ((!which_file) && entryp) - { - fname = entryp->d_name; - } - - closedir(dirp); - } -} - std::string LLDir_Solaris::getCurPath() { char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h index 139754ba2..88da8500d 100644 --- a/indra/llvfs/lldir_solaris.h +++ b/indra/llvfs/lldir_solaris.h @@ -30,6 +30,10 @@ * $/LicenseInfo$ */ +#if !LL_SOLARIS +#error This header must not be included when compiling for any target other than Solaris. Consider including lldir.h instead. +#endif // !LL_SOLARIS + #ifndef LL_LLDIR_SOLARIS_H #define LL_LLDIR_SOLARIS_H @@ -44,19 +48,18 @@ public: LLDir_Solaris(); virtual ~LLDir_Solaris(); - virtual void initAppDirs(const std::string &app_name); -public: + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); + virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap); - virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; private: DIR *mDirp; int mCurrentDirIndex; int mCurrentDirCount; - std::string mCurrentDir; + std::string mCurrentDir; }; #endif // LL_LLDIR_SOLARIS_H diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index c41c591c5..009add14b 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -87,10 +87,11 @@ LLDir_Win32::LLDir_Win32() // fprintf(stderr, "mTempDir = <%s>",mTempDir); -#if 1 - // Don't use the real app path for now, as we'll have to add parsing to detect if - // we're in a developer tree, which has a different structure from the installed product. + // Set working directory, for LLDir::getWorkingDir() + GetCurrentDirectory(MAX_PATH, w_str); + mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); + // Set the executable directory S32 size = GetModuleFileName(NULL, w_str, MAX_PATH); if (size) { @@ -106,30 +107,39 @@ LLDir_Win32::LLDir_Win32() { mExecutableFilename = mExecutablePathAndName; } - GetCurrentDirectory(MAX_PATH, w_str); - mWorkingDir = utf16str_to_utf8str(llutf16string(w_str)); } else { - LL_WARNS("AppInit") << "Couldn't get APP path, assuming current directory!\n" << LL_ENDL; - GetCurrentDirectory(MAX_PATH, w_str); - mExecutableDir = utf16str_to_utf8str(llutf16string(w_str)); + fprintf(stderr, "Couldn't get APP path, assuming current directory!\n"); + mExecutableDir = mWorkingDir; // Assume it's the current directory } -#else - GetCurrentDirectory(MAX_PATH, w_str); - mExecutableDir = utf16str_to_utf8str(llutf16string(w_str)); -#endif - - // When running in a dev tree, app_settings is under indra/newview/ - // but in production it is under Program Files/SecondLife/ - // Attempt to detect which one we're using. JC - if (mExecutableDir.find("indra") != std::string::npos) - mAppRODataDir = getCurPath(); - else - mAppRODataDir = mExecutableDir; + // mAppRODataDir = "."; + + // Determine the location of the App-Read-Only-Data + // Try the working directory then the exe's dir. + mAppRODataDir = mWorkingDir; + + +// if (mExecutableDir.find("indra") == std::string::npos) + + // *NOTE:Mani - It is a mistake to put viewer specific code in + // the LLDir implementation. The references to 'skins' and + // 'llplugin' need to go somewhere else. + // alas... this also gets called during static initialization + // time due to the construction of gDirUtil in lldir.cpp. + if(! LLFile::isdir(mAppRODataDir + mDirDelimiter + "skins")) + { + // What? No skins in the working dir? + // Try the executable's directory. + mAppRODataDir = mExecutableDir; + } + + llinfos << "mAppRODataDir = " << mAppRODataDir << llendl; + + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; // Build the default cache directory mDefaultCacheDir = buildSLOSCacheDir(); @@ -153,8 +163,15 @@ LLDir_Win32::~LLDir_Win32() // Implementation -void LLDir_Win32::initAppDirs(const std::string &app_name) +void LLDir_Win32::initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir) { + // Allow override so test apps can read newview directory + if (!app_read_only_data_dir.empty()) + { + mAppRODataDir = app_read_only_data_dir; + mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + } mAppName = app_name; mOSUserAppDir = mOSUserDir; mOSUserAppDir += "\\"; @@ -199,24 +216,6 @@ void LLDir_Win32::initAppDirs(const std::string &app_name) } } - res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"")); - if (res == -1) - { - if (errno != EEXIST) - { - llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; - } - } - - res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries")); - if (res == -1) - { - if (errno != EEXIST) - { - llwarns << "Couldn't create LL_PATH_USER_SETTINGS/dictionaries dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl; - } - } - mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem"); } @@ -247,122 +246,6 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string & return (file_count); } - -// get the next file in the directory -// automatically wrap if we've hit the end -BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) -{ - llutf16string dirnamew = utf8str_to_utf16str(dirname); - return getNextFileInDir(dirnamew, mask, fname, wrap); - -} - -BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap) -{ - WIN32_FIND_DATAW FileData; - - fname = ""; - llutf16string pathname = dirname; - pathname += utf8str_to_utf16str(mask); - - if (pathname != mCurrentDir) - { - // different dir specified, close old search - if (mCurrentDir[0]) - { - FindClose(mDirSearch_h); - } - mCurrentDir = pathname; - - // and open new one - // Check error opening Directory structure - if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) == INVALID_HANDLE_VALUE) - { -// llinfos << "Unable to locate first file" << llendl; - return(FALSE); - } - } - else // get next file in list - { - // Find next entry - if (!FindNextFile(mDirSearch_h, &FileData)) - { - if (GetLastError() == ERROR_NO_MORE_FILES) - { - // No more files, so reset to beginning of directory - FindClose(mDirSearch_h); - mCurrentDir[0] = NULL; - - if (wrap) - { - return(getNextFileInDir(pathname,"",fname,TRUE)); - } - else - { - fname[0] = 0; - return(FALSE); - } - } - else - { - // Error -// llinfos << "Unable to locate next file" << llendl; - return(FALSE); - } - } - } - - // convert from TCHAR to char - fname = utf16str_to_utf8str(FileData.cFileName); - - // fname now first name in list - return(TRUE); -} - - -// get a random file in the directory -// automatically wrap if we've hit the end -void LLDir_Win32::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ - S32 num_files; - S32 which_file; - HANDLE random_search_h; - - fname = ""; - - llutf16string pathname = utf8str_to_utf16str(dirname); - pathname += utf8str_to_utf16str(mask); - - WIN32_FIND_DATA FileData; - fname[0] = NULL; - - num_files = countFilesInDir(dirname,mask); - if (!num_files) - { - return; - } - - which_file = ll_rand(num_files); - -// llinfos << "Random select mp3 #" << which_file << llendl; - - // which_file now indicates the (zero-based) index to which file to play - - if ((random_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE) - { - while (which_file--) - { - if (!FindNextFile(random_search_h, &FileData)) - { - return; - } - } - FindClose(random_search_h); - - fname = utf16str_to_utf8str(llutf16string(FileData.cFileName)); - } -} - std::string LLDir_Win32::getCurPath() { WCHAR w_str[MAX_PATH]; diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h index 9ef4d300b..4421b87f0 100644 --- a/indra/llvfs/lldir_win32.h +++ b/indra/llvfs/lldir_win32.h @@ -30,6 +30,10 @@ * $/LicenseInfo$ */ +#if !LL_WINDOWS +#error This header must not be included when compiling for any target other than Windows. Consider including lldir.h instead. +#endif // !LL_WINDOWS + #ifndef LL_LLDIR_WIN32_H #define LL_LLDIR_WIN32_H @@ -41,20 +45,17 @@ public: LLDir_Win32(); virtual ~LLDir_Win32(); - /*virtual*/ void initAppDirs(const std::string &app_name); + /*virtual*/ void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir); /*virtual*/ std::string getCurPath(); /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap); - /*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); private: - BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap); - void* mDirSearch_h; llutf16string mCurrentDir; }; diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp new file mode 100644 index 000000000..9434efd40 --- /dev/null +++ b/indra/llvfs/lldiriterator.cpp @@ -0,0 +1,210 @@ +/** + * @file lldiriterator.cpp + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "lldiriterator.h" +#include +#include + +namespace fs = boost::filesystem; + +static std::string glob_to_regex(const std::string& glob); + +class LLDirIterator::Impl +{ +public: + Impl(const std::string &dirname, const std::string &mask); + ~Impl(); + + bool next(std::string &fname); + +private: + boost::regex mFilterExp; + fs::directory_iterator mIter; + bool mIsValid; +}; + +LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) + : mIsValid(false) +{ + fs::path dir_path(dirname); + + // Check if path exists. + if (!fs::exists(dir_path)) + { + llwarns << "Invalid path: \"" << dir_path.string() << "\"" << llendl; + return; + } + + // Initialize the directory iterator for the given path. + try + { + mIter = fs::directory_iterator(dir_path); + } +#if BOOST_FILESYSTEM_VERSION == 2 + catch (fs::basic_filesystem_error& e) +#else + catch (fs::filesystem_error& e) +#endif + { + llerrs << e.what() << llendl; + return; + } + + // Convert the glob mask to a regular expression + std::string exp = glob_to_regex(mask); + + // Initialize boost::regex with the expression converted from + // the glob mask. + // An exception is thrown if the expression is not valid. + try + { + mFilterExp.assign(exp); + } + catch (boost::regex_error& e) + { + llerrs << "\"" << exp << "\" is not a valid regular expression: " + << e.what() << llendl; + return; + } + + mIsValid = true; +} + +LLDirIterator::Impl::~Impl() +{ +} + +bool LLDirIterator::Impl::next(std::string &fname) +{ + fname = ""; + + if (!mIsValid) + { + llwarns << "The iterator is not correctly initialized." << llendl; + return false; + } + + fs::directory_iterator end_itr; // default construction yields past-the-end + bool found = false; + while (mIter != end_itr && !found) + { + boost::smatch match; +#if BOOST_FILESYSTEM_VERSION == 2 + std::string name = mIter->path().filename(); +#else + std::string name = mIter->path().filename().string(); +#endif + if (found = boost::regex_match(name, match, mFilterExp)) + { + fname = name; + } + + ++mIter; + } + + return found; +} + +std::string glob_to_regex(const std::string& glob) +{ + std::string regex; + regex.reserve(glob.size()<<1); + S32 braces = 0; + bool escaped = false; + bool square_brace_open = false; + + for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) + { + char c = *i; + + switch (c) + { + case '.': + regex+="\\."; + break; + case '*': + if (glob.begin() == i) + { + regex+="[^.].*"; + } + else + { + regex+= escaped ? "*" : ".*"; + } + break; + case '?': + regex+= escaped ? '?' : '.'; + break; + case '{': + braces++; + regex+='('; + break; + case '}': + if (!braces) + { + llerrs << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << llendl; + } + + regex+=')'; + braces--; + break; + case ',': + regex+= braces ? '|' : c; + break; + case '!': + regex+= square_brace_open ? '^' : c; + break; + default: + regex+=c; + break; + } + + escaped = ('\\' == c); + square_brace_open = ('[' == c); + } + + if (braces) + { + llerrs << "glob_to_regex: Unterminated brace expression: " << glob << llendl; + } + + return regex; +} + +LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask) +{ + mImpl = new Impl(dirname, mask); +} + +LLDirIterator::~LLDirIterator() +{ + delete mImpl; +} + +bool LLDirIterator::next(std::string &fname) +{ + return mImpl->next(fname); +} diff --git a/indra/llvfs/lldiriterator.h b/indra/llvfs/lldiriterator.h new file mode 100644 index 000000000..0b48be41b --- /dev/null +++ b/indra/llvfs/lldiriterator.h @@ -0,0 +1,87 @@ +/** + * @file lldiriterator.h + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDIRITERATOR_H +#define LL_LLDIRITERATOR_H + +#include "linden_common.h" + +/** + * Class LLDirIterator + * + * Iterates through directory entries matching the search pattern. + */ +class LLDirIterator +{ +public: + /** + * Constructs LLDirIterator object to search for glob pattern + * matches in a directory. + * + * @param dirname - name of a directory to search in. + * @param mask - search pattern, a glob expression + * + * Wildcards supported in glob expressions: + * -------------------------------------------------------------- + * | Wildcard | Matches | + * -------------------------------------------------------------- + * | * |zero or more characters | + * | ? |exactly one character | + * | [abcde] |exactly one character listed | + * | [a-e] |exactly one character in the given range | + * | [!abcde] |any character that is not listed | + * | [!a-e] |any character that is not in the given range | + * | {abc,xyz} |exactly one entire word in the options given | + * -------------------------------------------------------------- + */ + LLDirIterator(const std::string &dirname, const std::string &mask); + + ~LLDirIterator(); + + /** + * Searches for the next directory entry matching the glob mask + * specified upon iterator construction. + * Returns true if a match is found, sets fname + * parameter to the name of the matched directory entry and + * increments the iterator position. + * + * Typical usage: + * + * LLDirIterator iter(directory, pattern); + * if ( iter.next(scanResult) ) + * + * + * @param fname - name of the matched directory entry. + * @return true if a match is found, false otherwise. + */ + bool next(std::string &fname); + +protected: + class Impl; + Impl* mImpl; +}; + +#endif //LL_LLDIRITERATOR_H diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index 69c7eb6d6..ba4ccba0e 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -227,7 +227,6 @@ bool LLLFSThread::Request::processRequest() } mBytesRead = outfile.write(mBuffer, mBytes ); complete = true; - // llinfos << "LLLFSThread::WRITE:" << mFileName << " Bytes: " << mBytesRead << "/" << mBytes << " Offset:" << mOffset << llendl; } else diff --git a/indra/llvfs/lllfsthread.h b/indra/llvfs/lllfsthread.h index 5a11cb33d..9b2b542d2 100644 --- a/indra/llvfs/lllfsthread.h +++ b/indra/llvfs/lllfsthread.h @@ -39,7 +39,7 @@ #include #include "llapr.h" - +#include "llmemory.h" // LLPointer #include "llqueuedthread.h" //============================================================================ diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp index 93f1af52b..28cee2940 100644 --- a/indra/llvfs/llpidlock.cpp +++ b/indra/llvfs/llpidlock.cpp @@ -39,9 +39,17 @@ #include "llsdserialize.h" #include "llnametable.h" #include "llframetimer.h" -#include "llapp.h" #if LL_WINDOWS //For windows platform. + +#include + +namespace { + inline DWORD getpid() { + return GetCurrentProcessId(); + } +} + bool isProcessAlive(U32 pid) { return (bool) GetProcessVersion((DWORD)pid); @@ -63,11 +71,11 @@ class LLPidLockFile mAutosave(false), mSaving(false), mWaiting(false), - mPID(LLApp::getPid()), + mPID(getpid()), mNameTable(NULL), mClean(true) { - mLockName = gDirUtilp->getTempDir() + "/savelock"; + mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock"; } bool requestLock(LLNameTable *name_table, bool autosave, bool force_immediate=FALSE, F32 timeout=300.0); diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h index efcfd9150..496e99cf5 100644 --- a/indra/llvfs/llpidlock.h +++ b/indra/llvfs/llpidlock.h @@ -37,15 +37,9 @@ class LLSD; class LLFrameTimer; -#if LL_WINDOWS //For windows platform. - -#include - -#else //Everyone Else - +#if !LL_WINDOWS //For non-windows platforms. #include - -#endif //Everyone else. +#endif namespace LLPidLock { diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index 630975a05..4336cf542 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -38,7 +38,6 @@ #include "llthread.h" #include "llstat.h" #include "llvfs.h" -#include "llfasttimer.h" const S32 LLVFile::READ = 0x00000001; const S32 LLVFile::WRITE = 0x00000002; @@ -319,7 +318,7 @@ BOOL LLVFile::setMaxSize(S32 size) if (!mVFS->checkAvailable(size)) { - LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT); + //LLFastTimer t(FTM_VFILE_WAIT); S32 count = 0; while (sVFSThread->getPending() > 1000) { @@ -427,7 +426,7 @@ bool LLVFile::isLocked(EVFSLock lock) void LLVFile::waitForLock(EVFSLock lock) { - LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT); + //LLFastTimer t(FTM_VFILE_WAIT); // spin until the lock clears while (isLocked(lock)) { diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 1f4c991b2..4767ffcfb 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -32,6 +32,8 @@ #include "linden_common.h" +#include "llvfs.h" + #include #include #include @@ -45,7 +47,6 @@ #include #endif -#include "llvfs.h" #include "llstl.h" #include "lltimer.h" @@ -217,7 +218,9 @@ const S32 LLVFSFileBlock::SERIAL_SIZE = 34; LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash) -: mRemoveAfterCrash(remove_after_crash) +: mRemoveAfterCrash(remove_after_crash), + mDataFP(NULL), + mIndexFP(NULL) { mDataMutex = new LLMutex; @@ -233,17 +236,21 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename const char *file_mode = mReadOnly ? "rb" : "r+b"; - if (! (mDataFP = openAndLock(mDataFilename, file_mode, mReadOnly))) + LL_INFOS("VFS") << "Attempting to open VFS index file " << mIndexFilename << LL_ENDL; + LL_INFOS("VFS") << "Attempting to open VFS data file " << mDataFilename << LL_ENDL; + + mDataFP = openAndLock(mDataFilename, file_mode, mReadOnly); + if (!mDataFP) { - if (mReadOnly) { LL_WARNS("VFS") << "Can't find " << mDataFilename << " to open read-only VFS" << LL_ENDL; mValid = VFSVALID_BAD_CANNOT_OPEN_READONLY; return; } - - if((mDataFP = openAndLock(mDataFilename, "w+b", FALSE))) + + mDataFP = openAndLock(mDataFilename, "w+b", FALSE); + if (mDataFP) { // Since we're creating this data file, assume any index file is bogus // remove the index, since this vfs is now blank @@ -251,41 +258,12 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename } else { - LL_WARNS("VFS") << "Can't open VFS data file " << mDataFilename << " attempting to use alternate" << LL_ENDL; - - std::string temp_index; - std::string temp_data; - - for (U32 count = 0; count < 256; count++) - { - temp_index = mIndexFilename + llformat(".%u",count); - temp_data = mDataFilename + llformat(".%u", count); - - // try just opening, then creating, each alternate - if ((mDataFP = openAndLock(temp_data, "r+b", FALSE))) - { - break; - } - - if ((mDataFP = openAndLock(temp_data, "w+b", FALSE))) - { - // we're creating the datafile, so nuke the indexfile - LLFile::remove(temp_index); - break; - } - } - - if (! mDataFP) - { - LL_WARNS("VFS") << "Couldn't open vfs data file after trying many alternates" << LL_ENDL; - mValid = VFSVALID_BAD_CANNOT_CREATE; - return; - } - - mIndexFilename = temp_index; - mDataFilename = temp_data; + LL_WARNS("VFS") << "Couldn't open vfs data file " + << mDataFilename << LL_ENDL; + mValid = VFSVALID_BAD_CANNOT_CREATE; + return; } - + if (presize) { presizeDataFile(presize); @@ -334,21 +312,20 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename llstat fbuf; if (! LLFile::stat(mIndexFilename, &fbuf) && fbuf.st_size >= LLVFSFileBlock::SERIAL_SIZE && - (mIndexFP = openAndLock(mIndexFilename, file_mode, mReadOnly)) + (mIndexFP = openAndLock(mIndexFilename, file_mode, mReadOnly)) // Yes, this is an assignment and not '==' ) { - U8 *buffer = new U8[fbuf.st_size]; - size_t nread = fread(buffer, 1, fbuf.st_size, mIndexFP); - - U8 *tmp_ptr = buffer; - + std::vector buffer(fbuf.st_size); + size_t buf_offset = 0; + size_t nread = fread(&buffer[0], 1, fbuf.st_size, mIndexFP); + std::vector files_by_loc; - while (tmp_ptr < buffer + nread) + while (buf_offset < nread) { LLVFSFileBlock *block = new LLVFSFileBlock(); - block->deserialize(tmp_ptr, (S32)(tmp_ptr - buffer)); + block->deserialize(&buffer[buf_offset], (S32)buf_offset); // Do sanity check on this block. // Note that this skips zero size blocks, which helps VFS @@ -372,7 +349,6 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename LL_WARNS("VFS") << "Length: " << block->mLength << "\tLocation: " << block->mLocation << "\tSize: " << block->mSize << LL_ENDL; LL_WARNS("VFS") << "File has bad data - VFS removed" << LL_ENDL; - delete[] buffer; delete block; unlockAndClose( mIndexFP ); @@ -395,15 +371,13 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename else { // this is a null or bad entry, skip it - S32 index_loc = (S32)(tmp_ptr - buffer); - mIndexHoles.push_back(index_loc); + mIndexHoles.push_back(buf_offset); delete block; } - tmp_ptr += LLVFSFileBlock::SERIAL_SIZE; + buf_offset += LLVFSFileBlock::SERIAL_SIZE; } - delete[] buffer; std::sort( files_by_loc.begin(), @@ -526,7 +500,7 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename addFreeBlock(new LLVFSBlock(0, data_size)); } } - else + else // Pre-existing index file wasn't opened { if (mReadOnly) { @@ -566,9 +540,8 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename } } - // Success! - LL_INFOS("VFS") << "Using index file " << mIndexFilename << LL_ENDL; - LL_INFOS("VFS") << "Using data file " << mDataFilename << LL_ENDL; + LL_INFOS("VFS") << "Using VFS index file " << mIndexFilename << LL_ENDL; + LL_INFOS("VFS") << "Using VFS data file " << mDataFilename << LL_ENDL; mValid = VFSVALID_OK; } @@ -607,6 +580,47 @@ LLVFS::~LLVFS() delete mDataMutex; } + +// Use this function normally to create LLVFS files. +// Will append digits to the end of the filename with multiple re-trys +// static +LLVFS * LLVFS::createLLVFS(const std::string& index_filename, + const std::string& data_filename, + const BOOL read_only, + const U32 presize, + const BOOL remove_after_crash) +{ + LLVFS * new_vfs = new LLVFS(index_filename, data_filename, read_only, presize, remove_after_crash); + + if( !new_vfs->isValid() ) + { // First name failed, retry with new names + std::string retry_vfs_index_name; + std::string retry_vfs_data_name; + S32 count = 0; + while (!new_vfs->isValid() && + count < 256) + { // Append '.' to end of filenames + retry_vfs_index_name = index_filename + llformat(".%u",count); + retry_vfs_data_name = data_filename + llformat(".%u", count); + + delete new_vfs; // Delete bad VFS and try again + new_vfs = new LLVFS(retry_vfs_index_name, retry_vfs_data_name, read_only, presize, remove_after_crash); + + count++; + } + } + + if( !new_vfs->isValid() ) + { + delete new_vfs; // Delete bad VFS + new_vfs = NULL; // Total failure + } + + return new_vfs; +} + + + void LLVFS::presizeDataFile(const U32 size) { if (!mDataFP) @@ -845,20 +859,18 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type if (block->mSize > 0) { // move the file into the new block - U8 *buffer = new U8[block->mSize]; + std::vector buffer(block->mSize); fseek(mDataFP, block->mLocation, SEEK_SET); - if (fread(buffer, block->mSize, 1, mDataFP) == 1) + if (fread(&buffer[0], block->mSize, 1, mDataFP) == 1) { fseek(mDataFP, new_data_location, SEEK_SET); - if (fwrite(buffer, block->mSize, 1, mDataFP) != 1) + if (fwrite(&buffer[0], block->mSize, 1, mDataFP) != 1) { llwarns << "Short write" << llendl; } } else { llwarns << "Short read" << llendl; } - - delete[] buffer; } } @@ -1682,32 +1694,33 @@ void LLVFS::audit() fflush(mIndexFP); fseek(mIndexFP, 0, SEEK_END); - long index_size = ftell(mIndexFP); + size_t index_size = ftell(mIndexFP); fseek(mIndexFP, 0, SEEK_SET); BOOL vfs_corrupt = FALSE; - U8 *buffer = new U8[index_size]; + // since we take the address of element 0, we need to have at least one element. + std::vector buffer(llmax(index_size,1U)); - if (fread(buffer, 1, index_size, mIndexFP) != index_size) + if (fread(&buffer[0], 1, index_size, mIndexFP) != index_size) { llwarns << "Index truncated" << llendl; vfs_corrupt = TRUE; } - U8 *tmp_ptr = buffer; + size_t buf_offset = 0; std::map found_files; U32 cur_time = (U32)time(NULL); std::vector audit_blocks; - while (!vfs_corrupt && tmp_ptr < buffer + index_size) + while (!vfs_corrupt && buf_offset < index_size) { LLVFSFileBlock *block = new LLVFSFileBlock(); audit_blocks.push_back(block); - block->deserialize(tmp_ptr, (S32)(tmp_ptr - buffer)); - tmp_ptr += block->SERIAL_SIZE; + block->deserialize(&buffer[buf_offset], (S32)buf_offset); + buf_offset += block->SERIAL_SIZE; // do sanity check on this block if (block->mLength >= 0 && @@ -1766,8 +1779,6 @@ void LLVFS::audit() } } - delete[] buffer; - if (!vfs_corrupt) { for (fileblock_map::iterator it = mFileBlocks.begin(); it != mFileBlocks.end(); ++it) @@ -2013,6 +2024,11 @@ std::string get_extension(LLAssetType::EType type) case LLAssetType::AT_ANIMATION: extension = ".lla"; break; +#if 0 // Don't have this defined yet. + case LLAssetType::AT_MESH: + extension = ".slm"; + break; +#endif default: // Just use the asset server filename extension in most cases extension += "."; @@ -2072,21 +2088,21 @@ void LLVFS::dumpFiles() { LLUUID id = file_spec.mFileID; LLAssetType::EType type = file_spec.mFileType; - U8* buffer = new U8[size]; + std::vector buffer(size); unlockData(); - getData(id, type, buffer, 0, size); + getData(id, type, &buffer[0], 0, size); lockData(); std::string extension = get_extension(type); std::string filename = id.asString() + extension; llinfos << " Writing " << filename << llendl; - LLAPRFile outfile ; - outfile.open(filename, LL_APR_WB, LLAPRFile::global); - outfile.write(buffer, size); + LLAPRFile outfile; + outfile.open(filename, LL_APR_WB, LLAPRFile::local); + outfile.write(&buffer[0], size); outfile.close(); - delete[] buffer; + files_extracted++; } } diff --git a/indra/llvfs/llvfs.h b/indra/llvfs/llvfs.h index db3713f7d..da57d0468 100644 --- a/indra/llvfs/llvfs.h +++ b/indra/llvfs/llvfs.h @@ -118,11 +118,25 @@ public: class LLVFS { -public: +private: + // Use createLLVFS() to open a VFS file // Pass 0 to not presize - LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash); + LLVFS(const std::string& index_filename, + const std::string& data_filename, + const BOOL read_only, + const U32 presize, + const BOOL remove_after_crash); +public: ~LLVFS(); + // Use this function normally to create LLVFS files + // Pass 0 to not presize + static LLVFS * createLLVFS(const std::string& index_filename, + const std::string& data_filename, + const BOOL read_only, + const U32 presize, + const BOOL remove_after_crash); + BOOL isValid() const { return (VFSVALID_OK == mValid); } EVFSValid getValidState() const { return mValid; } @@ -184,6 +198,7 @@ protected: void lockData() { mDataMutex->lock(); } void unlockData() { mDataMutex->unlock(); } +protected: LLMutex* mDataMutex; // diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d0f5ac23e..9c01fb349 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4623,6 +4623,17 @@ Value 4 + DumpVFSCaches + + Comment + Dump VFS caches on startup. + Persist + 1 + Type + Boolean + Value + 0 + DynamicCameraStrength Comment diff --git a/indra/newview/ascentdaycyclemanager.cpp b/indra/newview/ascentdaycyclemanager.cpp index 43f243f08..4462435cf 100644 --- a/indra/newview/ascentdaycyclemanager.cpp +++ b/indra/newview/ascentdaycyclemanager.cpp @@ -18,6 +18,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "llcheckboxctrl.h" @@ -58,10 +59,11 @@ void AscentDayCycleManager::loadPresets(const std::string& file_name) LL_INFOS2("AppInit", "Shaders") << "Loading Default Day Cycle preset from " << path_name << LL_ENDL; bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false); + found = app_settings_iter.next(name); if(found) { @@ -84,10 +86,11 @@ void AscentDayCycleManager::loadPresets(const std::string& file_name) LL_INFOS2("AppInit", "Shaders") << "Loading User Daycycle preset from " << path_name2 << LL_ENDL; found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); diff --git a/indra/newview/lgghunspell_wrapper.cpp b/indra/newview/lgghunspell_wrapper.cpp index b8748ff2c..6eb1297f9 100644 --- a/indra/newview/lgghunspell_wrapper.cpp +++ b/indra/newview/lgghunspell_wrapper.cpp @@ -21,6 +21,7 @@ #include "llweb.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "lldiriterator.h" #include "llfile.h" #include "llhttpclient.h" #include "lggdicdownload.h" @@ -768,28 +769,18 @@ std::vector lggHunSpell_Wrapper::getDicts() { std::vector names; std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "dictionaries", "")); - bool found = true; - while (found) + std::string name; + LLDirIterator app_iter(path_name, "*.aff"); + while (app_iter.next(name)) { - std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.aff", name, false); - if (found) - { - names.push_back(dictName2FullName(name)); - } + names.push_back(dictName2FullName(name)); } path_name = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries", ""); - found = true; - while (found) + LLDirIterator user_iter(path_name, "*.aff"); + while (user_iter.next(name)) { - std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.aff", name, false); - if (found) - { - names.push_back(dictName2FullName(name)); - } + names.push_back(dictName2FullName(name)); } - return names; } @@ -797,26 +788,17 @@ std::vector lggHunSpell_Wrapper::getExtraDicts() { std::vector names; std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "dictionaries", "")); - bool found = true; - while (found) + std::string name; + LLDirIterator app_iter(path_name, "*.dic"); + while (app_iter.next(name)) { - std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.dic", name, false); - if (found) - { - names.push_back(dictName2FullName(name)); - } + names.push_back(dictName2FullName(name)); } path_name = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "dictionaries", ""); - found = true; - while (found) + LLDirIterator user_iter(path_name, "*.dic"); + while (user_iter.next(name)) { - std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.dic", name, false); - if (found) - { - names.push_back(dictName2FullName(name)); - } + names.push_back(dictName2FullName(name)); } return names; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e3f95f5ca..74b18209b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -178,6 +178,7 @@ #include "llviewerthrottle.h" #include "llparcel.h" +#include "lldiriterator.h" #include "llavatarnamecache.h" #include "llinventoryview.h" @@ -2952,8 +2953,10 @@ void LLAppViewer::migrateCacheDirectory() // Migrate inventory cache to avoid pain to inventory database after mass update S32 file_count = 0; std::string file_name; - std::string mask = delimiter + "*.*"; - while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name, false)) + std::string mask = "*.*"; + + LLDirIterator iter(old_cache_dir, mask); + while (iter.next(file_name)) { if (file_name == "." || file_name == "..") continue; std::string source_path = old_cache_dir + delimiter + file_name; @@ -2987,6 +2990,44 @@ void LLAppViewer::migrateCacheDirectory() #endif // LL_WINDOWS || LL_DARWIN } +void dumpVFSCaches() +{ + llinfos << "======= Static VFS ========" << llendl; + gStaticVFS->listFiles(); +#if LL_WINDOWS + llinfos << "======= Dumping static VFS to StaticVFSDump ========" << llendl; + WCHAR w_str[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, w_str); + S32 res = LLFile::mkdir("StaticVFSDump"); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create dir StaticVFSDump" << llendl; + } + } + SetCurrentDirectory(utf8str_to_utf16str("StaticVFSDump").c_str()); + gStaticVFS->dumpFiles(); + SetCurrentDirectory(w_str); +#endif + llinfos << "========= Dynamic VFS ====" << llendl; + gVFS->listFiles(); +#if LL_WINDOWS + llinfos << "========= Dumping dynamic VFS to VFSDump ====" << llendl; + res = LLFile::mkdir("VFSDump"); + if (res == -1) + { + if (errno != EEXIST) + { + llwarns << "Couldn't create dir VFSDump" << llendl; + } + } + SetCurrentDirectory(utf8str_to_utf16str("VFSDump").c_str()); + gVFS->dumpFiles(); + SetCurrentDirectory(w_str); +#endif +} + //static U32 LLAppViewer::getTextureCacheVersion() { @@ -3017,11 +3058,12 @@ bool LLAppViewer::initCache() if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) { - gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); - mPurgeCache = true; + gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); + mPurgeCache = true; // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad - texture_cache_mismatch = true; - } + // Bullshit, mPurgeCache already causes the same and doing it twice just leads to loads of warnings. --Aleric + //texture_cache_mismatch = true; + } // We have moved the location of the cache directory over time. migrateCacheDirectory(); @@ -3047,38 +3089,53 @@ bool LLAppViewer::initCache() { LLSplashScreen::update("Clearing cache..."); purgeCache(); + // + texture_cache_mismatch = false; + // } LLSplashScreen::update("Initializing Texture Cache..."); // Init the texture cache // Allocate 80% of the cache size for textures - const S32 MB = 1024*1024; + const S32 MB = 1024 * 1024; + const S64 MIN_CACHE_SIZE = 64 * MB; + const S64 MAX_CACHE_SIZE = 9984ll * MB; + const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB + S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB; - const S64 MAX_CACHE_SIZE = 1024*MB; - cache_size = llmin(cache_size, MAX_CACHE_SIZE); - S64 texture_cache_size = ((cache_size * 8)/10); + cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); + + S64 texture_cache_size = ((cache_size * 8) / 10); + S64 vfs_size = cache_size - texture_cache_size; + + if (vfs_size > MAX_VFS_SIZE) + { + // Give the texture cache more space, since the VFS can't be bigger than 1GB. + // This happens when the user's CacheSize setting is greater than 5GB. + vfs_size = MAX_VFS_SIZE; + texture_cache_size = cache_size - MAX_VFS_SIZE; + } + S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); texture_cache_size -= extra; LLSplashScreen::update("Initializing VFS..."); // Init the VFS - S64 vfs_size = cache_size - texture_cache_size; - const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB - vfs_size = llmin(vfs_size, MAX_VFS_SIZE); + vfs_size = llmin(vfs_size + extra, MAX_VFS_SIZE); vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned U32 vfs_size_u32 = (U32)vfs_size; U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB; bool resize_vfs = (vfs_size_u32 != old_vfs_size); if (resize_vfs) { - gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB); + gSavedSettings.setU32("VFSOldSize", vfs_size_u32 / MB); } - LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << LL_ENDL; + LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size / (1024*1024) << " MB" << LL_ENDL; // This has to happen BEFORE starting the vfs - //time_t ltime; + // time_t ltime; srand(time(NULL)); // Flawfinder: ignore U32 old_salt = gSavedSettings.getU32("VFSSalt"); U32 new_salt; @@ -3099,10 +3156,10 @@ bool LLAppViewer::initCache() do { new_salt = rand(); - } while( new_salt == old_salt ); + } while(new_salt == old_salt); } - old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",old_salt); + old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u",old_salt); // make sure this file exists llstat s; @@ -3111,15 +3168,15 @@ bool LLAppViewer::initCache() { // doesn't exist, look for a data file std::string mask; - mask = gDirUtilp->getDirDelimiter(); - mask += VFS_DATA_FILE_BASE; + mask = VFS_DATA_FILE_BASE; mask += "*"; std::string dir; - dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""); + dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); std::string found_file; - if (gDirUtilp->getNextFileInDir(dir, mask, found_file, false)) + LLDirIterator iter(dir, mask); + if (iter.next(found_file)) { old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; @@ -3132,7 +3189,7 @@ bool LLAppViewer::initCache() } } - old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE) + llformat("%u",old_salt); + old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",old_salt); stat_result = LLFile::stat(old_vfs_index_file, &s); if (stat_result) @@ -3145,27 +3202,25 @@ bool LLAppViewer::initCache() // Just in case, nuke any other old cache files in the directory. std::string dir; - dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""); + dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); std::string mask; - mask = gDirUtilp->getDirDelimiter(); - mask += VFS_DATA_FILE_BASE; + mask = VFS_DATA_FILE_BASE; mask += "*"; gDirUtilp->deleteFilesInDir(dir, mask); - mask = gDirUtilp->getDirDelimiter(); - mask += VFS_INDEX_FILE_BASE; + mask = VFS_INDEX_FILE_BASE; mask += "*"; gDirUtilp->deleteFilesInDir(dir, mask); } - new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",new_salt); - new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",new_salt); + new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u", new_salt); + new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u", new_salt); - static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2"); - static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2"); + static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_data.db2"); + static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_index.db2"); if (resize_vfs) { @@ -3187,36 +3242,44 @@ bool LLAppViewer::initCache() gSavedSettings.setU32("VFSSalt", new_salt); // Don't remove VFS after viewer crashes. If user has corrupt data, they can reinstall. JC - gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false); - if( VFSVALID_BAD_CORRUPT == gVFS->getValidState() ) + gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false); + if (!gVFS) { - // Try again with fresh files - // (The constructor deletes corrupt files when it finds them.) - LL_WARNS("AppCache") << "VFS corrupt, deleted. Making new VFS." << LL_ENDL; - delete gVFS; - gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false); + return false; } - gStaticVFS = new LLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false); + gStaticVFS = LLVFS::createLLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false); + if (!gStaticVFS) + { + return false; + } BOOL success = gVFS->isValid() && gStaticVFS->isValid(); - if( !success ) + if (!success) { return false; } else { LLVFile::initClass(); + +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (gSavedSettings.getBOOL("DumpVFSCaches")) + { + dumpVFSCaches(); + } +#endif + return true; } } void LLAppViewer::purgeCache() { - LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl; + LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); - std::string mask = gDirUtilp->getDirDelimiter() + "*.*"; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask); + std::string mask = "*.*"; + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask); } const std::string& LLAppViewer::getSecondLifeTitle() const diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 4e4bbcb43..154e38de3 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -36,6 +36,7 @@ #include "llcommandlineparser.h" +#include "lldiriterator.h" #include "llmemtype.h" #include "llurldispatcher.h" // SLURL from other app instance #include "llviewernetwork.h" @@ -741,8 +742,8 @@ std::string LLAppViewerLinux::generateSerialNumber() // trawl /dev/disk/by-uuid looking for a good-looking UUID to grab std::string this_name; - BOOL wrap = FALSE; - while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name, wrap)) + LLDirIterator iter(uuiddir, "*"); + while (iter.next(this_name)) { if (this_name.length() > best.length() || (this_name.length() == best.length() && diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index b7bb39a74..67e5b8d78 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -41,6 +41,7 @@ #include "llmemtype.h" +#include "lldiriterator.h" #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llmd5.h" @@ -406,7 +407,8 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) std::string pathname = std::string(path) + std::string("/CrashReporter/"); std::string mask = "Second Life*"; std::string file_name; - while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false)) + LLDirIterator iter(pathname, mask); + while(iter.next(file_name)) { LLFile::remove(pathname + file_name); } diff --git a/indra/newview/llpanelnetwork.cpp b/indra/newview/llpanelnetwork.cpp index 6bc34989a..003af8116 100644 --- a/indra/newview/llpanelnetwork.cpp +++ b/indra/newview/llpanelnetwork.cpp @@ -186,12 +186,14 @@ void LLPanelNetwork::onClickSetCache_continued(void* user_data, AIDirPicker* dir void LLPanelNetwork::onClickResetCache(void* user_data) { LLPanelNetwork* self = (LLPanelNetwork*)user_data; - if (!gSavedSettings.getString("CacheLocation").empty()) + if (gDirUtilp->getCacheDir(false) == gDirUtilp->getCacheDir(true)) { - gSavedSettings.setString("NewCacheLocation", ""); - LLNotifications::instance().add("CacheWillBeMoved"); + // The cache location was already the default. + return; } - std::string cache_location = gDirUtilp->getCacheDir(true); + gSavedSettings.setString("NewCacheLocation", ""); + LLNotifications::instance().add("CacheWillBeMoved"); + std::string cache_location = gDirUtilp->getCacheDir(false); self->childSetText("cache_location", cache_location); } diff --git a/indra/newview/llpanelskins.cpp b/indra/newview/llpanelskins.cpp index 324efa20d..7be656031 100644 --- a/indra/newview/llpanelskins.cpp +++ b/indra/newview/llpanelskins.cpp @@ -38,6 +38,7 @@ #include "llradiogroup.h" #include "llbutton.h" #include "lluictrlfactory.h" +#include "lldiriterator.h" // project includes #include "llviewercontrol.h" @@ -79,8 +80,6 @@ void LLPanelSkins::refresh() if(comboBox != NULL) { - std::string name; - gDirUtilp->getNextFileInDir(gDirUtilp->getChatLogsDir(),"*",name,false);//stupid hack to clear last file search comboBox->removeall(); datas.clear(); //comboBox->add("===OFF==="); @@ -88,9 +87,11 @@ void LLPanelSkins::refresh() llinfos << "Reading skin listing from " << path_name << llendl; bool found = true; std::string currentSkinName(""); + LLDirIterator iter(path_name, "*.xml"); while(found) { - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false); + std::string name; + found = iter.next(name); //llinfos << "path name " << path_name << " and name " << name << " and found " << found << llendl; if(found) { diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index c37add97a..e10880ecc 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -951,7 +951,7 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache max_size -= sCacheMaxTexturesSize; LL_INFOS("TextureCache") << "Headers: " << sCacheMaxEntries - << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << LL_ENDL; + << " Textures size: " << sCacheMaxTexturesSize / (1024 * 1024) << " MB" << LL_ENDL; setDirNames(location); @@ -1513,12 +1513,12 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) { const char* subdirs = "0123456789abcdef"; std::string delem = gDirUtilp->getDirDelimiter(); - std::string mask = delem + "*"; + std::string mask = "*"; for (S32 i=0; i<16; i++) { std::string dirname = mTexturesDirName + delem + subdirs[i]; llinfos << "Deleting files in directory: " << dirname << llendl; - gDirUtilp->deleteFilesInDir(dirname,mask); + gDirUtilp->deleteFilesInDir(dirname, mask); if (purge_directories) { LLFile::rmdir(dirname); diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 682079249..77ca7e54b 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -39,6 +39,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "llcheckboxctrl.h" @@ -93,10 +94,11 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) LL_INFOS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL; bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false); + found = app_settings_iter.next(name); if(found) { @@ -119,10 +121,11 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name) LL_INFOS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL; found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index bb41f9aac..d3fc32835 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -37,6 +37,7 @@ #include "pipeline.h" #include "llsky.h" +#include "lldiriterator.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "llcheckboxctrl.h" @@ -111,10 +112,11 @@ void LLWLParamManager::loadPresets(const std::string& file_name) LL_INFOS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL; bool found = true; + LLDirIterator app_settings_iter(path_name, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false); + found = app_settings_iter.next(name); if(found) { @@ -137,10 +139,11 @@ void LLWLParamManager::loadPresets(const std::string& file_name) LL_INFOS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL; found = true; + LLDirIterator user_settings_iter(path_name2, "*.xml"); while(found) { std::string name; - found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false); + found = user_settings_iter.next(name); if(found) { name=name.erase(name.length()-4); diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_network.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_network.xml index 51f24730d..c1040da37 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_network.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_network.xml @@ -25,11 +25,11 @@ follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" height="10" left="12" mouse_opaque="false" name="cache_size_label_l" v_pad="0" width="200"> - Disk Cache Size: + Disk Cache Size (MB):