diff --git a/doc/contributions.txt b/doc/contributions.txt index e6442310cf..d5d964e31c 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -220,6 +220,7 @@ Ansariel Hiller MAINT-7899 STORM-2151 MAINT-8085 + STORM-2122 Aralara Rajal Arare Chantilly CHUIBUG-191 diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 9cf9b7267f..b539a69ad6 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -258,7 +258,7 @@ int LLFile::remove(const std::string& filename, int supress_error) return warnif("remove", filename, rc, supress_error); } -int LLFile::rename(const std::string& filename, const std::string& newname) +int LLFile::rename(const std::string& filename, const std::string& newname, int supress_error) { #if LL_WINDOWS std::string utf8filename = filename; @@ -269,7 +269,7 @@ int LLFile::rename(const std::string& filename, const std::string& newname) #else int rc = ::rename(filename.c_str(),newname.c_str()); #endif - return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc); + return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error); } bool LLFile::copy(const std::string from, const std::string to) diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index ba935b8714..398938b729 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -74,7 +74,7 @@ public: static int rmdir(const std::string& filename); static int remove(const std::string& filename, int supress_error = 0); - static int rename(const std::string& filename,const std::string& newname); + static int rename(const std::string& filename,const std::string& newname, int supress_error = 0); static bool copy(const std::string from, const std::string to); static int stat(const std::string& filename,llstat* file_status); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index fee9df352e..8e8ab79f8a 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -439,6 +439,7 @@ LLUrlEntrySLURL::LLUrlEntrySLURL() // see http://slurl.com/about.php for details on the SLURL format mPattern = boost::regex("https?://(maps.secondlife.com|slurl.com)/secondlife/[^ /]+(/\\d+){0,3}(/?(\\?title|\\?img|\\?msg)=\\S*)?/?", boost::regex::perl|boost::regex::icase); + mIcon = "Hand"; mMenuName = "menu_url_slurl.xml"; mTooltip = LLTrans::getString("TooltipSLURL"); } diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 49205e3181..ebf6517e52 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -190,6 +190,7 @@ class LLUrlEntrySLURL : public LLUrlEntryBase { public: LLUrlEntrySLURL(); + /*virtual*/ bool isTrusted() const { return true; } /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); /*virtual*/ std::string getLocation(const std::string &url) const; }; diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp index f5579158f2..68f273fb35 100644 --- a/indra/llui/llviewereventrecorder.cpp +++ b/indra/llui/llviewereventrecorder.cpp @@ -35,21 +35,21 @@ LLViewerEventRecorder::LLViewerEventRecorder() { // Remove any previous event log file // Name this properly and silence the warnings //std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old"); - //LLFile::remove(old_log_ui_events_to_llsd_file); + //LLFile::remove(old_log_ui_events_to_llsd_file, ENOENT); // //mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd"); - //LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file); + //LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file, ENOENT); std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, llformat("%s_Events_log.old", APP_NAME.c_str())); if (LLFile::isfile(old_log_ui_events_to_llsd_file)) { - LLFile::remove(old_log_ui_events_to_llsd_file); + LLFile::remove(old_log_ui_events_to_llsd_file, ENOENT); } mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, llformat("%s_Events_log.llsd", APP_NAME.c_str())); if (LLFile::isfile(mLogFilename)) { - LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file); + LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file, ENOENT); } // } diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index c725635830..06040ba307 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -654,6 +654,28 @@ Value + SnapshotBaseDir + + Comment + Path to last snapshot save location + Persist + 1 + Type + String + Value + + + SnapshotBaseName + + Comment + Pattern for naming snapshots + Persist + 1 + Type + String + Value + Snapshot + DebugLookAt diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index ceb90084cc..663651ae0c 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -55,6 +55,7 @@ #include "llstylemap.h" #include "llslurl.h" #include "lllayoutstack.h" +#include "llnotifications.h" #include "llnotificationsutil.h" #include "lltoastnotifypanel.h" #include "lltooltip.h" @@ -1381,44 +1382,52 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // notify processing if (chat.mNotifId.notNull()) { - bool create_toast = true; - for (LLToastNotifyPanel::instance_iter ti(LLToastNotifyPanel::beginInstances()) - , tend(LLToastNotifyPanel::endInstances()); ti != tend; ++ti) - { - LLToastNotifyPanel& panel = *ti; - LLIMToastNotifyPanel * imtoastp = dynamic_cast(&panel); - const std::string& notification_name = panel.getNotificationName(); - if (notification_name == "OfferFriendship" && panel.isControlPanelEnabled() && imtoastp) - { - create_toast = false; - break; - } - } - - if (create_toast) - { LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); if (notification != NULL) { - LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( - notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor); + bool create_toast = true; + if (notification->getName() == "OfferFriendship") + { + // We don't want multiple friendship offers to appear, this code checks if there are previous offers + // by iterating though all panels. + // Note: it might be better to simply add a "pending offer" flag somewhere + for (LLToastNotifyPanel::instance_iter ti(LLToastNotifyPanel::beginInstances()) + , tend(LLToastNotifyPanel::endInstances()); ti != tend; ++ti) + { + LLToastNotifyPanel& panel = *ti; + LLIMToastNotifyPanel * imtoastp = dynamic_cast(&panel); + const std::string& notification_name = panel.getNotificationName(); + if (notification_name == "OfferFriendship" + && panel.isControlPanelEnabled() + && imtoastp) + { + create_toast = false; + break; + } + } + } - //Prepare the rect for the view - LLRect target_rect = mEditor->getDocumentView()->getRect(); - // squeeze down the widget by subtracting padding off left and right - target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); - target_rect.mRight -= mRightWidgetPad; - notify_box->reshape(target_rect.getWidth(), notify_box->getRect().getHeight()); - notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom); + if (create_toast) + { + LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( + notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor); - LLInlineViewSegment::Params params; - params.view = notify_box; - params.left_pad = mLeftWidgetPad; - params.right_pad = mRightWidgetPad; - mEditor->appendWidget(params, "\n", false); + //Prepare the rect for the view + LLRect target_rect = mEditor->getDocumentView()->getRect(); + // squeeze down the widget by subtracting padding off left and right + target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); + target_rect.mRight -= mRightWidgetPad; + notify_box->reshape(target_rect.getWidth(), notify_box->getRect().getHeight()); + notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom); + + LLInlineViewSegment::Params params; + params.view = notify_box; + params.left_pad = mLeftWidgetPad; + params.right_pad = mRightWidgetPad; + mEditor->appendWidget(params, "\n", false); + } } } - } // usual messages showing else diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index e6fe29f115..db766ad770 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2159,11 +2159,11 @@ void LLFloaterPreference::refreshEnabledState() // now turn off any features that are unavailable disableUnavailableSettings(); - getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess()); - // Cannot have floater active until caps have been received //getChild("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true); getChild("fs_default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true); + + getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess()); } void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() @@ -2310,8 +2310,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() // now turn off any features that are unavailable disableUnavailableSettings(); - - getChildView("block_list")->setEnabled(LLLoginInstance::getInstance()->authSuccess()); } @@ -4117,6 +4115,7 @@ BOOL LLPanelPreferenceGraphics::postBuild() //LLFloaterReg::hideInstance("prefs_graphics_advanced"); // + // Advanced graphics preferences // Don't do this on Mac as their braindead GL versioning // sets this when 8x and 16x are indeed available // @@ -4128,6 +4127,7 @@ BOOL LLPanelPreferenceGraphics::postBuild() combo->remove("16x"); } #endif + // resetDirtyChilds(); setPresetText(); @@ -4320,6 +4320,23 @@ LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) mCommitCallbackRegistrar.add("Proxy.Change", boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); } +BOOL LLFloaterPreferenceGraphicsAdvanced::postBuild() +{ + // Don't do this on Mac as their braindead GL versioning + // sets this when 8x and 16x are indeed available + // +#if !LL_DARWIN + if (gGLManager.mIsIntel || gGLManager.mGLVersion < 3.f) + { //remove FSAA settings above "4x" + LLComboBox* combo = getChild("fsaa"); + combo->remove("8x"); + combo->remove("16x"); + } +#endif + + return TRUE; +} + void LLFloaterPreferenceGraphicsAdvanced::onOpen(const LLSD& key) { refresh(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 6060f49326..0453925823 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -382,6 +382,7 @@ class LLFloaterPreferenceGraphicsAdvanced : public LLFloater public: LLFloaterPreferenceGraphicsAdvanced(const LLSD& key); ~LLFloaterPreferenceGraphicsAdvanced(); + /*virtual*/ BOOL postBuild(); void onOpen(const LLSD& key); void onClickCloseBtn(bool app_quitting); void disableUnavailableSettings(); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 5d6b792baf..bc8626a744 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -111,6 +111,7 @@ BOOL LLFloaterWebContent::postBuild() // these buttons are always enabled mBtnReload->setEnabled( true ); + mBtnReload->setVisible( false ); getChildView("popexternal")->setEnabled( true ); // cache image for secure browsing diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index f32d597b24..b73c2e1afe 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -918,6 +918,7 @@ void LLMeshRepoThread::run() LLMeshRepository::sLODProcessing--; mMutex->unlock(); + // Todo: this and other cases shouldn't retry indefinitely, at the very least do as with mDecompositionRequests if (!fetchMeshLOD(req.mMeshParams, req.mLOD)) // failed, resubmit { mMutex->lock(); @@ -1289,16 +1290,16 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) //check VFS for mesh skin info LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) - { - LLMeshRepository::sCacheBytesRead += size; - ++LLMeshRepository::sCacheReads; - file.seek(offset); + { U8* buffer = new(std::nothrow) U8[size]; if (!buffer) { - LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info" << LL_ENDL; + LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL; return false; } + LLMeshRepository::sCacheBytesRead += size; + ++LLMeshRepository::sCacheReads; + file.seek(offset); file.read(buffer, size); //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) @@ -1393,16 +1394,16 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { + U8* buffer = new(std::nothrow) U8[size]; + if (!buffer) + { + LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL; + return false; + } LLMeshRepository::sCacheBytesRead += size; ++LLMeshRepository::sCacheReads; file.seek(offset); - U8* buffer = new(std::nothrow) U8[size]; - if (!buffer) - { - LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition" << LL_ENDL; - return false; - } file.read(buffer, size); //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) @@ -1503,7 +1504,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) U8* buffer = new(std::nothrow) U8[size]; if (!buffer) { - LL_WARNS(LOG_MESH) << "Failed to allocate memory for physics shape" << LL_ENDL; + LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for physics shape, size: " << size << LL_ENDL; return false; } file.read(buffer, size); @@ -1695,15 +1696,17 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); if (file.getSize() >= offset+size) { - LLMeshRepository::sCacheBytesRead += size; - ++LLMeshRepository::sCacheReads; - file.seek(offset); U8* buffer = new(std::nothrow) U8[size]; if (!buffer) { - LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh LOD" << LL_ENDL; + LL_WARNS_ONCE(LOG_MESH) << "Can't allocate memory for mesh LOD, size: " << size << LL_ENDL; + // todo: for now it will result in indefinite constant retries, should result in timeout + // or in retry-count and disabling mesh. (but usually viewer is beyond saving at this point) return false; } + LLMeshRepository::sCacheBytesRead += size; + ++LLMeshRepository::sCacheReads; + file.seek(offset); file.read(buffer, size); //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index c31a7c6713..93b3b540b7 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -786,9 +786,9 @@ void LLPanelStandStopFlying::updatePosition() // left_tb_width = toolbar_left->getRect().getWidth(); // } // -// if (!mStateManagementButtons.get()) +// if (!mStateManagementButtons.get()) // Obsolete?!! // { -// LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container"); +// LLPanel* panel_ssf_container = gToolBarView->getChild("state_management_buttons_container"); // if (panel_ssf_container) // { // mStateManagementButtons = panel_ssf_container->getHandle(); diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp index 019122539e..66ad5c0b7b 100644 --- a/indra/newview/llnotificationlistitem.cpp +++ b/indra/newview/llnotificationlistitem.cpp @@ -300,9 +300,7 @@ BOOL LLGroupInviteNotificationListItem::postBuild() //invitation with any non-default group role, doesn't have newline characters at the end unlike simple invitations std::string invitation_desc = mNoticeTextExp->getValue().asString(); - boost::regex pattern = boost::regex("\n\n$", boost::regex::perl|boost::regex::icase); - boost::match_results matches; - if(!boost::regex_search(invitation_desc, matches, pattern)) + if (invitation_desc.substr(invitation_desc.size() - 2) != "\n\n") { invitation_desc += "\n\n"; mNoticeTextExp->setValue(invitation_desc); diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 0957782404..a9c403e927 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -590,6 +590,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) mNoticesList->setNeedsSort(save_sort); mNoticesList->updateSort(); + mNoticesList->selectFirstItem(); } void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data) diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index ca09ac4e04..781802d035 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -273,9 +273,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLTextBox* forgot_password_text = getChild("forgot_password_text"); forgot_password_text->setClickedCallback(onClickForgotPassword, NULL); - LLTextBox* need_help_text = getChild("login_help"); - need_help_text->setClickedCallback(onClickHelp, NULL); - // get the web browser control LLMediaCtrl* web_browser = getChild("login_html"); web_browser->addObserver(this); @@ -926,16 +923,6 @@ void LLPanelLogin::onClickForgotPassword(void*) } } -//static -void LLPanelLogin::onClickHelp(void*) -{ - if (sInstance) - { - LLViewerHelp* vhelp = LLViewerHelp::getInstance(); - vhelp->showTopic(vhelp->preLoginTopic()); - } -} - // static void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data) { diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 458d2cf090..97fc6f22de 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -101,7 +101,6 @@ private: static void onClickNewAccount(void*); static void onClickVersion(void*); static void onClickForgotPassword(void*); - static void onClickHelp(void*); static void onPassKey(LLLineEditor* caller, void* user_data); static void updateServerCombo(); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index ba5b96bc80..45fc1c63be 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -628,22 +628,6 @@ void LLPanelObject::getState( ) S32 roots_selected = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); BOOL editable = root_objectp->permModify(); - // Select Single Message - // We don't have those in FS (2013-04-28) - //getChildView("select_single")->setVisible( FALSE); - //getChildView("edit_object")->setVisible( FALSE); - //if (!editable || single_volume || selected_count <= 1) - //{ - // getChildView("edit_object")->setVisible( TRUE); - // getChildView("edit_object")->setEnabled(TRUE); - //} - //else - //{ - // getChildView("select_single")->setVisible( TRUE); - // getChildView("select_single")->setEnabled(TRUE); - //} - // - BOOL is_flexible = volobjp && volobjp->isFlexible(); BOOL is_permanent = root_objectp->flagObjectPermanent(); BOOL is_permanent_enforced = root_objectp->isPermanentEnforced(); @@ -2559,12 +2543,6 @@ void LLPanelObject::clearCtrls() mLabelTaper ->setEnabled( FALSE ); mLabelRadiusOffset->setEnabled( FALSE ); mLabelRevolutions->setEnabled( FALSE ); - - // We don't have those in Firestorm (2013-04-28) - //getChildView("select_single")->setVisible( FALSE); - //getChildView("edit_object")->setVisible( TRUE); - //getChildView("edit_object")->setEnabled(FALSE); - // getChildView("scale_hole")->setEnabled(FALSE); getChildView("scale_taper")->setEnabled(FALSE); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index fcc1cb4b28..976b5bf74b 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1097,9 +1097,13 @@ void LLTaskSoundBridge::performAction(LLInventoryModel* model, std::string actio void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { LLInventoryItem* item = findItem(); - if(!item) return; std::vector items; std::vector disabled_items; + if (!item) + { + hide_context_entries(menu, items, disabled_items); + return; + } if(item->getPermissions().getOwner() != gAgent.getID() && item->getSaleInfo().isForSale()) @@ -1492,9 +1496,13 @@ void LLTaskMeshBridge::performAction(LLInventoryModel* model, std::string action void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { LLInventoryItem* item = findItem(); - if(!item) return; std::vector items; std::vector disabled_items; + if(!item) + { + hide_context_entries(menu, items, disabled_items); + return; + } if(item->getPermissions().getOwner() != gAgent.getID() && item->getSaleInfo().isForSale()) diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9de0c3e098..7e0996dfd8 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -637,7 +637,6 @@ BOOL LLPanelPeople::postBuild() getChild("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); getChild("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); getChild("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); - //getChild("fbc_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); // Doesn't exist anymore // Don't bother with "want more?" advertisement //if(gMaxAgentGroups <= BASE_MAX_AGENT_GROUPS) diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 5ee5f559b0..f17e4d7fd4 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -282,9 +282,6 @@ void LLPanelVolume::getState( ) if (is_light && editable && single_volume) { - // We don't have that one in Firestorm (2013-04-28) - //getChildView("label color")->setEnabled(true); - // //mLabelColor ->setEnabled( TRUE ); LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); if(LightColorSwatch) @@ -327,9 +324,6 @@ void LLPanelVolume::getState( ) getChild("Light Radius", true)->clear(); getChild("Light Falloff", true)->clear(); - // We don't have that one in Firestorm (2013-04-28) - //getChildView("label color")->setEnabled(false); - // LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); if(LightColorSwatch) { @@ -571,11 +565,7 @@ void LLPanelVolume::clearCtrls() getChildView("select_single")->setVisible(true); getChildView("edit_object")->setEnabled(false); getChildView("edit_object")->setVisible(false); - getChildView("Light Checkbox Ctrl")->setEnabled(false); - // We don't have that one in Firestorm (2013-04-28) - //getChildView("label color")->setEnabled(false); - //getChildView("label color")->setEnabled(false); - // + getChildView("Light Checkbox Ctrl")->setEnabled(false);; LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); if(LightColorSwatch) { diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp index e9e740cc35..52983e14b7 100644 --- a/indra/newview/llpanelvolumepulldown.cpp +++ b/indra/newview/llpanelvolumepulldown.cpp @@ -35,6 +35,7 @@ // Linden libs #include "llbutton.h" +#include "llcheckboxctrl.h" #include "lltabcontainer.h" #include "llfloaterreg.h" #include "llfloaterpreference.h" @@ -56,7 +57,9 @@ LLPanelVolumePulldown::LLPanelVolumePulldown() mHoverTimer.stop(); /*// Handled centrally now - mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); + mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); + mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this)); + mCommitCallbackRegistrar.add("Vol.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelVolumePulldown::updateMediaAutoPlayCheckbox, this, _1)); mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2)); // Missing callback function mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::setSounds, this)); @@ -67,12 +70,6 @@ LLPanelVolumePulldown::LLPanelVolumePulldown() BOOL LLPanelVolumePulldown::postBuild() { - // set the initial volume-slider's position to reflect reality - // Was renamed to "System Volume" - //LLSliderCtrl* volslider = getChild( "mastervolume" ); - LLSliderCtrl* volslider = getChild( "System Volume" ); - volslider->setValue(gSavedSettings.getF32("AudioLevelMaster")); - // FIRE-9856: Mute sound effects disable plays sound from collisions and plays sound from gestures checkbox not disable after restart/relog bool mute_sound_effects = gSavedSettings.getBOOL("MuteSounds"); bool mute_all_sounds = gSavedSettings.getBOOL("MuteAudio"); @@ -150,6 +147,28 @@ void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data) if (control) control->set(LLSD(FALSE)); } + +void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) +{ + std::string name = ctrl->getName(); + + // Disable "Allow Media to auto play" only when both + // "Streaming Music" and "Media" are unchecked. STORM-513. + if ((name == "enable_music") || (name == "enable_media")) + { + bool music_enabled = getChild("enable_music")->get(); + bool media_enabled = getChild("enable_media")->get(); + + getChild("media_auto_play_btn")->setEnabled(music_enabled || media_enabled); + } +} + +void LLPanelVolumePulldown::onClickSetSounds() +{ + // Disable Enable gesture sounds checkbox if the master sound is disabled + // or if sound effects are disabled. + getChild("gesture_audio_play_btn")->setEnabled(!gSavedSettings.getBOOL("MuteSounds")); +} */ //virtual diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h index 224d33f850..b8293d20ce 100644 --- a/indra/newview/llpanelvolumepulldown.h +++ b/indra/newview/llpanelvolumepulldown.h @@ -48,6 +48,10 @@ class LLPanelVolumePulldown : public LLPanel private: /*// Handled centrally now void setControlFalse(const LLSD& user_data); + void onClickSetSounds(); + // Disables "Allow Media to auto play" check box only when both + // "Streaming Music" and "Media" are unchecked. Otherwise enables it. + void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl); void onAdvancedButtonClick(const LLSD& user_data); // Missing callback function void setSounds(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 2a09fe100a..a6478957e4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1172,7 +1172,6 @@ bool idle_startup() // Moved this to initBase() in llviewerwindow.cpp to get the edit menu set up // before any text widget uses it // initialize_spellcheck_menu(); - // initialize_edit_menu(); // init_menus(); } diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 2943dd459f..3175151342 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -178,7 +178,6 @@ LLStatusBar::LLStatusBar(const LLRect& rect) mSGBandwidth(NULL), mSGPacketLoss(NULL), mBandwidthButton(NULL), // FIRE-6287: Clicking on traffic indicator toggles Lag Meter window - mBtnStats(NULL), mBtnVolume(NULL), mBoxBalance(NULL), mBalance(0), @@ -299,9 +298,6 @@ BOOL LLStatusBar::postBuild() mBoxBalance = getChild("balance"); mBoxBalance->setClickedCallback( &LLStatusBar::onClickBalance, this ); - - // Not used in Firestorm - //mBtnStats = getChildView("stat_btn"); mIconPresets = getChild( "presets_icon" ); // FIRE-19697: Add setting to disable graphics preset menu popup on mouse over @@ -418,7 +414,6 @@ BOOL LLStatusBar::postBuild() mPanelNearByMedia->setVisible(FALSE); // Script debug - //mScriptOut = getChildView("scriptout"); mScriptOut = getChild("scriptout"); mScriptOut->setMouseDownCallback(boost::bind(&LLFloaterScriptDebug::show, LLUUID::null)); mNearbyIcons = LLHUDIcon::scriptIconsNearby(); @@ -506,7 +501,6 @@ BOOL LLStatusBar::postBuild() updateVolumeControlsVisibility(LLSD(FALSE)); } // - return TRUE; } diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index a8f389dc63..cedd76301a 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -328,7 +328,6 @@ private: LLStatGraph *mSGBandwidth; LLStatGraph *mSGPacketLoss; - LLView *mBtnStats; LLButton *mIconPresets; LLButton *mBtnVolume; LLTextBox *mBoxBalance; @@ -336,7 +335,6 @@ private: LLButton *mMediaToggle; LLButton *mBandwidthButton; // FIRE-6287: Clicking on traffic indicator toggles Lag Meter window // Script debug - //LLView *mScriptOut; LLIconCtrl *mScriptOut; // Script debug LLFrameTimer mClockUpdateTimer; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 6247049bcc..f5f0a8e7a9 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -10123,6 +10123,23 @@ void handle_web_browser_test(const LLSD& param) LLWeb::loadURLInternal(url); } +bool callback_clear_cache_immediately(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) // YES + { + //clear cache + LLAppViewer::instance()->purgeCacheImmediate(); + } + + return false; +} + +void handle_cache_clear_immediately() +{ + LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately); +} + void handle_web_content_test(const LLSD& param) { std::string url = param.asString(); @@ -11471,6 +11488,8 @@ void initialize_menus() //Develop (Texture Fetch Debug Console) view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger"); + //Develop (clear cache immediately) + commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); // Admin >Object view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 4617451913..bda1b3714e 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -146,6 +146,7 @@ std::map LLViewerObject::sObjectDataMap; // JC 3/18/2003 const F32 PHYSICS_TIMESTEP = 1.f / 45.f; +const U32 MAX_INV_FILE_READ_FAILS = 25; static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object"); @@ -3172,6 +3173,7 @@ BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) llifstream ifs(filename_and_local_path.c_str()); if(ifs.good()) { + U32 fail_count = 0; char buffer[MAX_STRING]; /* Flawfinder: ignore */ // *NOTE: This buffer size is hard coded into scanf() below. char keyword[MAX_STRING]; /* Flawfinder: ignore */ @@ -3186,8 +3188,14 @@ BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) while(ifs.good()) { ifs.getline(buffer, MAX_STRING); - sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */ - if(0 == strcmp("inv_item", keyword)) + if (sscanf(buffer, " %254s", keyword) == EOF) /* Flawfinder: ignore */ + { + // Blank file? + LL_WARNS() << "Issue reading from file '" + << filename << "'" << LL_ENDL; + break; + } + else if(0 == strcmp("inv_item", keyword)) { LLPointer inv = new LLViewerInventoryItem; inv->importLegacyStream(ifs); @@ -3200,9 +3208,17 @@ BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) inv->rename("Contents"); mInventory->push_front(inv); } + else if (fail_count >= MAX_INV_FILE_READ_FAILS) + { + LL_WARNS() << "Encountered too many unknowns while reading from file: '" + << filename << "'" << LL_ENDL; + break; + } else { - LL_WARNS() << "Unknown token in inventory file '" + // Is there really a point to continue processing? We already failing to display full inventory + fail_count++; + LL_WARNS_ONCE() << "Unknown token while reading from inventory file. Token: '" << keyword << "'" << LL_ENDL; } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index aae7d604b7..60348e3b67 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1984,10 +1984,7 @@ void LLViewerRegion::updateNetStats() mLastPacketsLost = mPacketsLost; mPacketsIn = cdp->getPacketsIn(); - // FIRE-17071: UDP network data measuring is wrong - //mBitsIn = 8 * cdp->getBytesIn(); mBitsIn = cdp->getBytesIn(); - // mPacketsOut = cdp->getPacketsOut(); mPacketsLost = cdp->getPacketsLost(); mPingDelay = cdp->getPingDelay(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b0c664ffb6..2a43d92655 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -288,10 +288,8 @@ static const F32 MIN_UI_SCALE = 0.75f; static const F32 MAX_UI_SCALE = 7.0f; static const F32 MIN_DISPLAY_SCALE = 0.75f; -std::string LLViewerWindow::sSnapshotBaseName; -std::string LLViewerWindow::sSnapshotDir; - -std::string LLViewerWindow::sMovieBaseName; +static LLCachedControl sSnapshotBaseName(LLCachedControl(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot")); +static LLCachedControl sSnapshotDir(LLCachedControl(gSavedPerAccountSettings, "SnapshotBaseDir", "")); LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity"); @@ -1776,11 +1774,6 @@ LLViewerWindow::LLViewerWindow(const Params& p) LL_INFOS() << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << LL_ENDL; } - // Default to application directory. - LLViewerWindow::sSnapshotBaseName = "Snapshot"; - LLViewerWindow::sMovieBaseName = "SLmovie"; - resetSnapshotLoc(); - BOOL useLegacyCursors = gSavedSettings.getBOOL("FSUseLegacyCursors");// Legacy cursor setting from main program @@ -2000,6 +1993,11 @@ void LLViewerWindow::showSystemUIScaleFactorChanged() LLNotificationsUtil::add("SystemUIScaleFactorChanged", LLSD(), LLSD(), onSystemUIScaleFactorChanged); } +std::string LLViewerWindow::getLastSnapshotDir() +{ + return sSnapshotDir; +} + //static bool LLViewerWindow::onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response) { @@ -2075,8 +2073,12 @@ void LLViewerWindow::initBase() // Create global views - // Move console further down in the view hierarchy to not float - // in front of floaters! + // Login screen and main_view.xml need edit menus for preferences and browser + LL_DEBUGS("AppInit") << "initializing edit menu" << LL_ENDL; + initialize_edit_menu(); + initialize_spellcheck_menu(); // Set up edit menu here to get the spellcheck callbacks assigned before anyone uses them + + // Move console further down in the view hierarchy to not float in front of floaters! // Console llassert( !gConsole ); LLConsole::Params cp; @@ -2093,11 +2095,6 @@ void LLViewerWindow::initBase() getRootView()->addChild(gConsole); // - // Set up edit menu here to get the spellcheck callbacks assigned before anyone uses them - initialize_edit_menu(); - initialize_spellcheck_menu(); - // - // Centralize a some of these volume panel callbacks initialize_volume_controls_callbacks(); // @@ -5587,10 +5584,10 @@ void LLViewerWindow::saveImageCallback(const std::string& filename, LLImageForma { if (!filename.empty()) { - LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filename, true); - LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filename); + gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filename, true)); + gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filename)); - do_save_image(image, LLViewerWindow::sSnapshotDir, LLViewerWindow::sSnapshotBaseName, extension, callback); + do_save_image(image, sSnapshotDir, sSnapshotBaseName, extension, callback); return; } @@ -5659,20 +5656,21 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke // // Copy the directory + file name // std::string filepath = picker.getFirstFile(); - // LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true); - // LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath); + // gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); + // gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); //} - //if(LLViewerWindow::sSnapshotDir.empty()) + //std::string snapshot_dir = sSnapshotDir; + //if(snapshot_dir.empty()) //{ // return FALSE; //} // Check if there is enough free space to save snapshot //#ifdef LL_WINDOWS -// boost::filesystem::space_info b_space = boost::filesystem::space(utf8str_to_utf16str(sSnapshotDir)); +// boost::filesystem::space_info b_space = boost::filesystem::space(utf8str_to_utf16str(snapshot_dir)); //#else -// boost::filesystem::space_info b_space = boost::filesystem::space(sSnapshotDir); +// boost::filesystem::space_info b_space = boost::filesystem::space(snapshot_dir); //#endif // if (b_space.free < image->getDataSize()) // { @@ -5708,7 +5706,7 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke //return image->save(filepath); // Get a base file location if needed. - if (force_picker || !isSnapshotLocSet() || !LLFile::isdir(sSnapshotDir)) + if (force_picker || !isSnapshotLocSet() || !LLFile::isdir(sSnapshotDir())) { std::string proposed_name( sSnapshotBaseName ); @@ -5716,19 +5714,19 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke return; } - do_save_image(image, LLViewerWindow::sSnapshotDir, LLViewerWindow::sSnapshotBaseName, extension, callback); + do_save_image(image, sSnapshotDir, sSnapshotBaseName, extension, callback); // } void LLViewerWindow::resetSnapshotLoc() { - sSnapshotDir.clear(); + gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); } // static void LLViewerWindow::movieSize(S32 new_width, S32 new_height) { - // FS:TS FIRE-6182: Set Window Size sets random size each time + // FIRE-6182: Set Window Size sets random size each time // Don't use LLCoordWindow, since the chosen resolution winds up // with position dependent numbers added each time. Instead, we use // LLCoordScreen, which avoids this. Fix from Niran's Viewer. @@ -5746,7 +5744,7 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) new_size.mX = new_width + nChromeW; new_size.mY = new_height + nChromeH; gViewerWindow->getWindow()->setSize(new_size); - // FS:TS FIRE-6182 end + // } @@ -5792,6 +5790,17 @@ void LLViewerWindow::playSnapshotAnimAndSound() send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f); } +BOOL LLViewerWindow::isSnapshotLocSet() const +{ + std::string snapshot_dir = sSnapshotDir; + return !snapshot_dir.empty(); +} + +void LLViewerWindow::resetSnapshotLoc() const +{ + gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); +} + BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type) { return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 94c0c9ce27..5f973e832b 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -351,8 +351,8 @@ public: BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type); - BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } - void resetSnapshotLoc() const { sSnapshotDir.clear(); } + BOOL isSnapshotLocSet() const; + void resetSnapshotLoc() const; // Threaded filepickers BOOL saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory); void saveImageNumbered(LLImageFormatted *image, bool force_picker = false, boost::function callback = NULL); @@ -427,7 +427,7 @@ public: bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; } static void showSystemUIScaleFactorChanged(); - static std::string getLastSnapshotDir() { return sSnapshotDir; } + static std::string getLastSnapshotDir(); private: bool shouldShowToolTipFor(LLMouseHandler *mh); @@ -513,11 +513,6 @@ private: boost::scoped_ptr mWindowListener; boost::scoped_ptr mViewerWindowListener; - static std::string sSnapshotBaseName; - static std::string sSnapshotDir; - - static std::string sMovieBaseName; - // Object temporarily hovered over while dragging LLPointer mDragHoveredObject; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index af737df80c..eec8d66ec0 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5947,6 +5947,11 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) if (use_new_walk_run) result = ANIM_AGENT_RUN_NEW; } + // keeps in sync with setSex() related code (viewer controls sit's sex) + else if (id == ANIM_AGENT_SIT_FEMALE) + { + result = ANIM_AGENT_SIT; + } } @@ -6793,7 +6798,26 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) //----------------------------------------------------------------------------- void LLVOAvatar::updateVisualParams() { - setSex( (getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE ); + ESex avatar_sex = (getVisualParamWeight("male") > 0.5f) ? SEX_MALE : SEX_FEMALE; + if (getSex() != avatar_sex) + { + if (mIsSitting && findMotion(avatar_sex == SEX_MALE ? ANIM_AGENT_SIT_FEMALE : ANIM_AGENT_SIT) != NULL) + { + // In some cases of gender change server changes sit motion with motion message, + // but in case of some avatars (legacy?) there is no update from server side, + // likely because server doesn't know about difference between motions + // (female and male sit ids are same server side, so it is likely unaware that it + // need to send update) + // Make sure motion is up to date + stopMotion(ANIM_AGENT_SIT); + setSex(avatar_sex); + startMotion(ANIM_AGENT_SIT); + } + else + { + setSex(avatar_sex); + } + } LLCharacter::updateVisualParams();