diff options
71 files changed, 1095 insertions, 389 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..6d296d7a24 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +repos: + - repo: https://bitbucket.org/lindenlab/git-hooks.git + rev: v1.0.0-beta2 + hooks: + - id: opensource-license + - id: jira-issue + - id: llsd + - id: no-trigraphs + - id: copyright + - id: end-of-file + files: \.(cpp|c|h|py|glsl|cmake|txt)$ + exclude: language.txt + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.5.0 + hooks: + - id: check-xml + - id: mixed-line-ending diff --git a/autobuild.xml b/autobuild.xml index 1f1ee45549..9185b8af22 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2107,18 +2107,18 @@ <key>archive</key> <map> <key>hash</key> - <string>95cb09a712b7b61e992fe68ab7bf8c72</string> + <string>d6e7ab8483c348f223fd24028e27a52f</string> <key>hash_algorithm</key> <string>md5</string> <key>url</key> - <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/92744/837149/llca-202201010217.567162-common-567162.tar.bz2</string> + <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/93933/844890/llca-202202010217.567974-common-567974.tar.bz2</string> </map> <key>name</key> <string>common</string> </map> </map> <key>version</key> - <string>202201010217.567162</string> + <string>202202010217.567974</string> </map> <key>llphysicsextensions_source</key> <map> diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index d35f249973..e0ebbb76bd 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1402,6 +1402,15 @@ bool LLAudioSource::setupChannel() return true; } +void LLAudioSource::stop() +{ + play(LLUUID::null); + if (mCurrentDatap) + { + // always reset data if something wants us to stop + mCurrentDatap = nullptr; + } +} bool LLAudioSource::play(const LLUUID &audio_uuid) { diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 577b36d667..b5fd4c27a1 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -304,7 +304,13 @@ public: LLAudioBuffer *getCurrentBuffer(); bool setupChannel(); - bool play(const LLUUID &audio_id); // Start the audio source playing + + // Stop the audio source, reset audio id even if muted + void stop(); + + // Start the audio source playing, + // takes mute into account to preserve previous id if nessesary + bool play(const LLUUID &audio_id); bool hasPendingPreloads() const; // Has preloads that haven't been done yet diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 75fc0fec99..c2d353b0fc 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -249,14 +249,25 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl // protected_fixedsize_stack sets a guard page past the end of the new // stack so that stack underflow will result in an access violation // instead of weird, subtle, possibly undiagnosed memory stomps. - boost::fibers::fiber newCoro(boost::fibers::launch::dispatch, - std::allocator_arg, - boost::fibers::protected_fixedsize_stack(mStackSize), - [this, &name, &callable](){ toplevel(name, callable); }); - // You have two choices with a fiber instance: you can join() it or you - // can detach() it. If you try to destroy the instance before doing - // either, the program silently terminates. We don't need this handle. - newCoro.detach(); + + try + { + boost::fibers::fiber newCoro(boost::fibers::launch::dispatch, + std::allocator_arg, + boost::fibers::protected_fixedsize_stack(mStackSize), + [this, &name, &callable]() { toplevel(name, callable); }); + + // You have two choices with a fiber instance: you can join() it or you + // can detach() it. If you try to destroy the instance before doing + // either, the program silently terminates. We don't need this handle. + newCoro.detach(); + } + catch (std::bad_alloc&) + { + // Out of memory on stack allocation? + LL_ERRS("LLCoros") << "Bad memory allocation in LLCoros::launch(" << prefix << ")!" << LL_ENDL; + } + return name; } diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 995356dc52..067b5e6fbc 100644 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -101,7 +101,7 @@ void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value) } // Drill down to where we should store 'value'. - llsd::drill(dest, path) = value; + llsd::drill_ref(dest, path) = value; } } // anonymous diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index c2fe15e9b7..8e90d1e8b8 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "llsdutil.h" +#include <sstream> #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN @@ -876,7 +877,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits) namespace llsd { -LLSD& drill(LLSD& blob, const LLSD& rawPath) +LLSD& drill_ref(LLSD& blob, const LLSD& rawPath) { LL_PROFILE_ZONE_SCOPED @@ -937,9 +938,9 @@ LLSD drill(const LLSD& blob, const LLSD& path) { LL_PROFILE_ZONE_SCOPED - // non-const drill() does exactly what we want. Temporarily cast away + // drill_ref() does exactly what we want. Temporarily cast away // const-ness and use that. - return drill(const_cast<LLSD&>(blob), path); + return drill_ref(const_cast<LLSD&>(blob), path); } } // namespace llsd diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 8678ca97f2..1321615805 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -184,10 +184,10 @@ namespace llsd * - Anything else is an error. * * By implication, if path.isUndefined() or otherwise equivalent to an empty - * LLSD::Array, drill() returns 'blob' as is. + * LLSD::Array, drill[_ref]() returns 'blob' as is. */ LLSD drill(const LLSD& blob, const LLSD& path); -LLSD& drill( LLSD& blob, const LLSD& path); +LLSD& drill_ref( LLSD& blob, const LLSD& path); } diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 4f57daf9ec..f717b2cf34 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -195,18 +195,6 @@ LLOSInfo::LLOSInfo() : GetSystemInfo(&si); //if it fails get regular system info //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load) - //msdn microsoft finds 32 bit and 64 bit flavors this way.. - //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors - //of windows than this code does (in case it is needed for the future) - if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit - { - mOSStringSimple += "64-bit "; - } - else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) - { - mOSStringSimple += "32-bit "; - } - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); @@ -253,9 +241,21 @@ LLOSInfo::LLOSInfo() : // Query WMI's Win32_OperatingSystem for OS string. Slow // and likely to return 'compatibility' string. // Check presence of dlls/libs or may be their version. - mOSStringSimple = "Microsoft Windows 10/11"; + mOSStringSimple = "Microsoft Windows 10/11 "; } - } + } + + //msdn microsoft finds 32 bit and 64 bit flavors this way.. + //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors + //of windows than this code does (in case it is needed for the future) + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit + { + mOSStringSimple += "64-bit "; + } + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + { + mOSStringSimple += "32-bit "; + } mOSString = mOSStringSimple; if (mBuild > 0) diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index efa1a4076b..3727ce85af 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5764,7 +5764,16 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) resizeIndices(grid_size*grid_size*6); if (!volume->isMeshAssetLoaded()) { - mEdge.resize(grid_size*grid_size * 6); + S32 size = grid_size * grid_size * 6; + try + { + mEdge.resize(size); + } + catch (std::bad_alloc&) + { + LL_WARNS("LLVOLUME") << "Resize of mEdge to " << size << " failed" << LL_ENDL; + return false; + } } U16* out = mIndices; @@ -6577,7 +6586,15 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!volume->isMeshAssetLoaded()) { - mEdge.resize(num_indices); + try + { + mEdge.resize(num_indices); + } + catch (std::bad_alloc&) + { + LL_WARNS("LLVOLUME") << "Resize of mEdge to " << num_indices << " failed" << LL_ENDL; + return false; + } } } @@ -6805,7 +6822,15 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) LLVector4a* norm = mNormals; static LLAlignedArray<LLVector4a, 64> triangle_normals; - triangle_normals.resize(count); + try + { + triangle_normals.resize(count); + } + catch (std::bad_alloc&) + { + LL_WARNS("LLVOLUME") << "Resize of triangle_normals to " << count << " failed" << LL_ENDL; + return false; + } LLVector4a* output = triangle_normals.mArray; LLVector4a* end_output = output+count; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 1badd54fca..33037b5001 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -175,6 +175,14 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mTripleClickTimer.reset(); setText(p.default_text()); + if (p.initial_value.isProvided() + && !p.control_name.isProvided()) + { + // Initial value often is descriptive, like "Type some ID here" + // and can be longer than size limitation, ignore size + setText(p.initial_value.getValue().asString(), false); + } + // Initialize current history line iterator mCurrentHistoryLine = mLineHistory.begin(); @@ -390,6 +398,11 @@ void LLLineEditor::updateTextPadding() void LLLineEditor::setText(const LLStringExplicit &new_text) { + setText(new_text, true); +} + +void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit) +{ // If new text is identical, don't copy and don't move insertion point if (mText.getString() == new_text) { @@ -407,13 +420,13 @@ void LLLineEditor::setText(const LLStringExplicit &new_text) all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived); std::string truncated_utf8 = new_text; - if (truncated_utf8.size() > (U32)mMaxLengthBytes) + if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes) { truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes); } mText.assign(truncated_utf8); - if (mMaxLengthChars) + if (use_size_limit && mMaxLengthChars) { mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars)); } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index f84625bea7..ae4e05c065 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -320,6 +320,8 @@ private: virtual S32 getPreeditFontSize() const; virtual LLWString getPreeditString() const { return getWText(); } + void setText(const LLStringExplicit &new_text, bool use_size_limit); + void setContextMenu(LLContextMenu* new_context_menu); protected: diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index cdaf03ebde..76fd789bec 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2362,6 +2362,16 @@ void LLMenuGL::arrange( void ) (*item_iter)->setRect( rect ); } } + + + if (getTornOff()) + { + LLTearOffMenu * torn_off_menu = dynamic_cast<LLTearOffMenu*>(getParent()); + if (torn_off_menu) + { + torn_off_menu->updateSize(); + } + } } if (mKeepFixedSize) { @@ -3879,7 +3889,8 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item) /// Class LLTearOffMenu ///============================================================================ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : - LLFloater(LLSD()) + LLFloater(LLSD()), + mQuitRequested(false) { S32 floater_header_size = getHeaderHeight(); @@ -3894,7 +3905,7 @@ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : LLRect rect; menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView); // make sure this floater is big enough for menu - mTargetHeight = (F32)(rect.getHeight() + floater_header_size); + mTargetHeight = rect.getHeight() + floater_header_size; reshape(rect.getWidth(), rect.getHeight()); setRect(rect); @@ -3926,19 +3937,24 @@ LLTearOffMenu::~LLTearOffMenu() void LLTearOffMenu::draw() { mMenu->setBackgroundVisible(isBackgroundOpaque()); - mMenu->needsArrange(); if (getRect().getHeight() != mTargetHeight) { // animate towards target height - reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f)))); + reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), (F32)mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f)))); + mMenu->needsArrange(); } LLFloater::draw(); } void LLTearOffMenu::onFocusReceived() { - // if nothing is highlighted, just highlight first item + if (mQuitRequested) + { + return; + } + + // if nothing is highlighted, just highlight first item if (!mMenu->getHighlightedItem()) { mMenu->highlightNextItem(NULL); @@ -4014,6 +4030,31 @@ LLTearOffMenu* LLTearOffMenu::create(LLMenuGL* menup) return tearoffp; } +void LLTearOffMenu::updateSize() +{ + if (mMenu) + { + S32 floater_header_size = getHeaderHeight(); + const LLRect &floater_rect = getRect(); + LLRect new_rect; + mMenu->localRectToOtherView(LLRect(-1, mMenu->getRect().getHeight() + floater_header_size, mMenu->getRect().getWidth() + 3, 0), &new_rect, gFloaterView); + + if (floater_rect.getWidth() != new_rect.getWidth() + || mTargetHeight != new_rect.getHeight()) + { + // make sure this floater is big enough for menu + mTargetHeight = new_rect.getHeight(); + reshape(new_rect.getWidth(), mTargetHeight); + + // Restore menu position + LLRect menu_rect = mMenu->getRect(); + menu_rect.setOriginAndSize(1, 1, + menu_rect.getWidth(), menu_rect.getHeight()); + mMenu->setRect(menu_rect); + } + } +} + void LLTearOffMenu::closeTearOff() { removeChild(mMenu); @@ -4024,6 +4065,7 @@ void LLTearOffMenu::closeTearOff() mMenu->setVisible(FALSE); mMenu->setTornOff(FALSE); mMenu->setDropShadowed(TRUE); + mQuitRequested = true; } LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 273bd789c4..abbfd9a24a 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -873,6 +873,8 @@ public: virtual BOOL handleKeyHere(KEY key, MASK mask); virtual void translate(S32 x, S32 y); + void updateSize(); + private: LLTearOffMenu(LLMenuGL* menup); @@ -880,7 +882,8 @@ private: LLView* mOldParent; LLMenuGL* mMenu; - F32 mTargetHeight; + S32 mTargetHeight; + bool mQuitRequested; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 38495e1e0b..1547a4ba5c 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1017,6 +1017,24 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const return LLUrlEntryBase::getLocation(url); } +// +// LLUrlEntryChat Describes a Second Life chat Url, e.g., +// secondlife:///app/chat/42/This%20Is%20a%20test +// + +LLUrlEntryChat::LLUrlEntryChat() +{ + mPattern = boost::regex("secondlife:///app/chat/\\d+/\\S+", + boost::regex::perl|boost::regex::icase); + mMenuName = "menu_url_slapp.xml"; + mTooltip = LLTrans::getString("TooltipSLAPP"); +} + +std::string LLUrlEntryChat::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + return unescapeUrl(url); +} + // LLUrlEntryParcel statics. LLUUID LLUrlEntryParcel::sAgentID(LLUUID::null); LLUUID LLUrlEntryParcel::sSessionID(LLUUID::null); diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 102e0a4fd9..63a1506731 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -370,6 +370,17 @@ public: private: }; +// +// LLUrlEntryChat Describes a Second Life chat Url, e.g., +// secondlife:///app/chat/42/This%20Is%20a%20test +// +class LLUrlEntryChat : public LLUrlEntryBase +{ +public: + LLUrlEntryChat(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); +}; + /// /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index bfcd970529..c9d7013a11 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -63,6 +63,7 @@ LLUrlRegistry::LLUrlRegistry() // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since // LLUrlEntryAgent is a less specific (catchall for agent urls) registerUrl(new LLUrlEntryAgent()); + registerUrl(new LLUrlEntryChat()); registerUrl(new LLUrlEntryGroup()); registerUrl(new LLUrlEntryParcel()); registerUrl(new LLUrlEntryTeleport()); @@ -71,7 +72,6 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryObjectIM()); registerUrl(new LLUrlEntryPlace()); registerUrl(new LLUrlEntryInventory()); - registerUrl(new LLUrlEntryObjectIM()); registerUrl(new LLUrlEntryExperienceProfile()); //LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern, //so it should be registered in the end of list diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 26e624c6ec..33b4257706 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4369,7 +4369,8 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res S32 context_offset; LLWString context = find_context(wtext, preedit, preedit_length, &context_offset); preedit -= context_offset; - if (preedit_length) + preedit_length = llmin(preedit_length, (S32)context.length() - preedit); + if (preedit_length && preedit >= 0) { // IMR_DOCUMENTFEED may be called when we have an active preedit. // We should pass the context string *excluding* the preedit string. diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 24b7ab7441..964615320d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1913,9 +1913,7 @@ if (WINDOWS) add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts) endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) - add_dependencies(${VIEWER_BINARY_NAME} - SLPlugin - ) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin) # sets the 'working directory' for debugging from visual studio. # Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865) @@ -2266,7 +2264,7 @@ endif (INSTALL) # Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE) - if (BUGSPLAT_DB) + if (USE_BUGSPLAT) # BugSplat symbol-file generation if (WINDOWS) # Just pack up a tarball containing only the .pdb file for the @@ -2350,7 +2348,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE if (LINUX) # TBD endif (LINUX) - endif (BUGSPLAT_DB) + endif (USE_BUGSPLAT) # for both Bugsplat and Breakpad add_dependencies(llpackage generate_symbols) diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 7514913d13..dd2b656ce3 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -207,14 +207,6 @@ <map> <key>map-to</key> <string>NoAudio</string> - </map> - - <key>noinvlib</key> - <map> - <key>desc</key> - <string>Do not request the inventory library.</string> - <key>map-to</key> - <string>NoInventoryLibrary</string> </map> <key>noninteractive</key> diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml index 1a5157838c..55babc88bc 100644 --- a/indra/newview/app_settings/key_bindings.xml +++ b/indra/newview/app_settings/key_bindings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<keys> +<keys xml_version="1"> <first_person> <binding key="A" mask="NONE" command="slide_left"/> <binding key="D" mask="NONE" command="slide_right"/> @@ -17,22 +17,13 @@ <binding key="PGDN" mask="NONE" command="push_down"/> <binding key="HOME" mask="NONE" command="toggle_fly"/> - <binding key="PAD_LEFT" mask="NONE" command="slide_left"/> - <binding key="PAD_RIGHT" mask="NONE" command="slide_right"/> - <binding key="PAD_UP" mask="NONE" command="push_forward"/> - <binding key="PAD_DOWN" mask="NONE" command="push_backward"/> - <binding key="PAD_PGUP" mask="NONE" command="jump"/> - <binding key="PAD_PGDN" mask="NONE" command="push_down"/> - <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/> - <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/> - <binding key="PAD_ENTER" mask="NONE" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/> - <binding key="SPACE" mask="NONE" command="stop_moving"/> <binding key="ENTER" mask="NONE" command="start_chat"/> <binding key="DIVIDE" mask="NONE" command="start_gesture"/> <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> + + <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/> </first_person> <third_person> <binding key="A" mask="NONE" command="turn_left"/> @@ -60,19 +51,6 @@ <binding key="PGDN" mask="NONE" command="push_down"/> <binding key="HOME" mask="NONE" command="toggle_fly"/> - <binding key="PAD_LEFT" mask="NONE" command="turn_left"/> - <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/> - <binding key="PAD_RIGHT" mask="NONE" command="turn_right"/> - <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/> - <binding key="PAD_UP" mask="NONE" command="push_forward"/> - <binding key="PAD_DOWN" mask="NONE" command="push_backward"/> - <binding key="PAD_PGUP" mask="NONE" command="jump"/> - <binding key="PAD_PGDN" mask="NONE" command="push_down"/> - <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/> - <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/> - <binding key="PAD_ENTER" mask="NONE" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/> - <!--Camera controls in third person on Alt--> <binding key="LEFT" mask="ALT" command="spin_around_cw"/> <binding key="RIGHT" mask="ALT" command="spin_around_ccw"/> @@ -88,15 +66,6 @@ <binding key="E" mask="ALT" command="spin_over"/> <binding key="C" mask="ALT" command="spin_under"/> - <binding key="PAD_LEFT" mask="ALT" command="spin_around_cw"/> - <binding key="PAD_RIGHT" mask="ALT" command="spin_around_ccw"/> - <binding key="PAD_UP" mask="ALT" command="move_forward"/> - <binding key="PAD_DOWN" mask="ALT" command="move_backward"/> - <binding key="PAD_PGUP" mask="ALT" command="spin_over"/> - <binding key="PAD_PGDN" mask="ALT" command="spin_under"/> - <binding key="PAD_ENTER" mask="ALT" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/> - <!--mimic alt zoom behavior with keyboard only--> <binding key="W" mask="CTL_ALT" command="spin_over"/> <binding key="S" mask="CTL_ALT" command="spin_under"/> @@ -104,9 +73,6 @@ <binding key="UP" mask="CTL_ALT" command="spin_over"/> <binding key="DOWN" mask="CTL_ALT" command="spin_under"/> - <binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/> - <binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/> - <!--Therefore pan on Alt-Shift--> <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/> <binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/> @@ -118,14 +84,10 @@ <binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/> <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/> - <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/> - <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/> - <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/> - <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/> - <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/> - <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> + <binding key="" mask="NONE" mouse="LMB" command="walk_to"/> + + <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/> </third_person> <sitting> <binding key="A" mask="ALT" command="spin_around_cw"/> @@ -167,16 +129,6 @@ <binding key="PGUP" mask="NONE" command="spin_over_sitting"/> <binding key="PGDN" mask="NONE" command="spin_under_sitting"/> - <binding key="PAD_LEFT" mask="NONE" command="spin_around_cw_sitting"/> - <binding key="PAD_RIGHT" mask="NONE" command="spin_around_ccw_sitting"/> - <binding key="PAD_UP" mask="NONE" command="move_forward_sitting"/> - <binding key="PAD_DOWN" mask="NONE" command="move_backward_sitting"/> - <binding key="PAD_PGUP" mask="NONE" command="spin_over_sitting"/> - <binding key="PAD_PGDN" mask="NONE" command="spin_under_sitting"/> - <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/> - <binding key="PAD_ENTER" mask="NONE" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/> - <!--these are for passing controls when sitting on vehicles--> <binding key="A" mask="SHIFT" command="slide_left"/> <binding key="D" mask="SHIFT" command="slide_right"/> @@ -192,15 +144,6 @@ <binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/> <binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/> - <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/> - <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/> - <binding key="PAD_UP" mask="SHIFT" command="move_forward_sitting"/> - <binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/> - <binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/> - <binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/> - <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/> - <!--pan on Alt-Shift--> <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/> <binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/> @@ -212,17 +155,12 @@ <binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/> <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/> - <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/> - <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/> - <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/> - <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/> - <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/> - <binding key="ENTER" mask="NONE" command="start_chat"/> <binding key="DIVIDE" mask="NONE" command="start_gesture"/> <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> + + <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/> </sitting> <edit_avatar> <!--Avatar editing camera controls--> @@ -240,15 +178,9 @@ <binding key="PGDN" mask="NONE" command="edit_avatar_spin_under"/> <binding key="ENTER" mask="NONE" command="start_chat"/> <binding key="DIVIDE" mask="NONE" command="start_gesture"/> - <binding key="PAD_LEFT" mask="NONE" command="edit_avatar_spin_cw"/> - <binding key="PAD_RIGHT" mask="NONE" command="edit_avatar_spin_ccw"/> - <binding key="PAD_UP" mask="NONE" command="edit_avatar_move_forward"/> - <binding key="PAD_DOWN" mask="NONE" command="edit_avatar_move_backward"/> - <binding key="PAD_PGUP" mask="NONE" command="edit_avatar_spin_over"/> - <binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/> - <binding key="PAD_ENTER" mask="NONE" command="start_chat"/> - <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/> <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/> + + <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/> </edit_avatar> </keys> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 17071d4a65..a6dce3cceb 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4758,7 +4758,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> + <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> </map> <key>GuidebookURL</key> <map> @@ -5895,17 +5895,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>LoginAsGod</key> - <map> - <key>Comment</key> - <string>Attempt to login with god powers (Linden accounts only)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>LoginLocation</key> <map> <key>Comment</key> @@ -6975,6 +6964,17 @@ <key>Value</key> <integer>1000</integer> </map> + <key>FakeInitialOutfitName</key> + <map> + <key>Comment</key> + <string>Pretend that this is first time login and specified name was chosen</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>MyOutfitsAutofill</key> <map> <key>Comment</key> @@ -7077,7 +7077,7 @@ <key>NoInventoryLibrary</key> <map> <key>Comment</key> - <string>Do not request inventory library.</string> + <string>(Deprecated) Do not request inventory library.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 650cc4e193..b79af04c36 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1988,7 +1988,8 @@ void LLAgent::propagate(const F32 dt) //----------------------------------------------------------------------------- void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y) { - if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > gSavedSettings.getF32("NotMovingHintTimeout")) + static LLCachedControl<F32> hint_timeout(gSavedSettings, "NotMovingHintTimeout"); + if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > hint_timeout) { LLFirstUse::notMoving(); } @@ -2159,7 +2160,8 @@ void LLAgent::endAnimationUpdateUI() LLNavigationBar::getInstance()->setVisible(TRUE && gSavedSettings.getBOOL("ShowNavbarNavigationPanel")); gStatusBar->setVisibleForMouselook(true); - if (gSavedSettings.getBOOL("ShowMiniLocationPanel")) + static LLCachedControl<bool> show_mini_location_panel(gSavedSettings, "ShowMiniLocationPanel"); + if (show_mini_location_panel) { LLPanelTopInfoBar::getInstance()->setVisible(TRUE); } @@ -3901,10 +3903,6 @@ bool LLAgent::teleportCore(bool is_local) // yet if the teleport will succeed. Look in // process_teleport_location_reply - // close the map panel so we can see our destination. - // we don't close search floater, see EXT-5840. - LLFloaterReg::hideInstance("world_map"); - // hide land floater too - it'll be out of date LLFloaterReg::hideInstance("about_land"); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 61fc693b99..787503a6e4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5368,14 +5368,18 @@ void LLAppViewer::disconnectViewer() } // save inventory if appropriate - gInventory.cache(gInventory.getRootFolderID(), gAgent.getID()); - if (gInventory.getLibraryRootFolderID().notNull() - && gInventory.getLibraryOwnerID().notNull()) - { - gInventory.cache( - gInventory.getLibraryRootFolderID(), - gInventory.getLibraryOwnerID()); - } + if (gInventory.isInventoryUsable() + && gAgent.getID().notNull()) // Shouldn't be null at this stage + { + gInventory.cache(gInventory.getRootFolderID(), gAgent.getID()); + if (gInventory.getLibraryRootFolderID().notNull() + && gInventory.getLibraryOwnerID().notNull()) + { + gInventory.cache( + gInventory.getLibraryRootFolderID(), + gInventory.getLibraryOwnerID()); + } + } saveNameCache(); if (LLExperienceCache::instanceExists()) diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 82b6b0c77c..ab52bf15f9 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -51,8 +51,8 @@ protected: bool initHardwareTest() override; // Win32 uses DX9 to test hardware. bool initParseCommandLine(LLCommandLineParser& clp) override; - virtual bool beingDebugged(); - virtual bool restoreErrorTrap(); + bool beingDebugged() override; + bool restoreErrorTrap() override; bool sendURLToOtherInstance(const std::string& url) override; diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 140b9e6f36..fe94cd27b6 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -370,6 +370,8 @@ void LLAvatarRenderInfoAccountant::idle() && regionp->capabilitiesReceived()) { // each of these is further governed by and resets its own timer + // Note: We can have multiple regions, each launches up to two coroutines, + // it likely is expensive sendRenderInfoToRegion(regionp); getRenderInfoFromRegion(regionp); } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 9ee9900eba..bddbc79df4 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -645,7 +645,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) { if(mBuddyInfo.find(agent_id) != mBuddyInfo.end()) { - if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) + if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) + && !gAgent.isDoNotDisturb()) { LLSD args; args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString(); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index fee85d50bd..20fa6d490b 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -96,10 +96,14 @@ LLConversationViewSession::~LLConversationViewSession() { mActiveVoiceChannelConnection.disconnect(); - if(LLVoiceClient::instanceExists() && mVoiceClientObserver) - { - LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); - } + if (mVoiceClientObserver) + { + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); + } + delete mVoiceClientObserver; + } mFlashTimer->unset(); } @@ -255,7 +259,12 @@ BOOL LLConversationViewSession::postBuild() mIsInActiveVoiceChannel = true; if(LLVoiceClient::instanceExists()) { - LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); + if (mVoiceClientObserver) + { + LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); + delete mVoiceClientObserver; + } + mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver); } break; diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index 3b192ff81b..1c69b9d60b 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -453,18 +453,18 @@ void LLFloaterCamera::setMode(ECameraControlMode mode) void LLFloaterCamera::switchMode(ECameraControlMode mode) { - setMode(mode); - switch (mode) { case CAMERA_CTRL_MODE_PRESETS: case CAMERA_CTRL_MODE_PAN: sFreeCamera = false; + setMode(mode); // depends onto sFreeCamera clear_camera_tool(); break; case CAMERA_CTRL_MODE_FREE_CAMERA: sFreeCamera = true; + setMode(mode); activate_camera_tool(); break; diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index c4e0dd483f..6e326ff3cf 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -582,8 +582,7 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command) LLInventoryItem* item = gInventory.getItem(*it); if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE) { - LLWString item_name = utf8str_to_wstring(item->getName()); - LLClipboard::instance().addToClipboard(item_name, 0, item_name.size()); + LLClipboard::instance().addToClipboard(*it); } } } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 43dc304c10..34499ac170 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -384,7 +384,7 @@ void LLFloaterIMSessionTab::draw() void LLFloaterIMSessionTab::enableDisableCallBtn() { - if (LLVoiceClient::instanceExists()) + if (LLVoiceClient::instanceExists() && mVoiceButton) { mVoiceButton->setEnabled( mSessionID.notNull() diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 90bb80a08b..8d19aa36bb 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2346,7 +2346,16 @@ void LLPanelPreference::saveSettings() { view_stack.push_back(*iter); } - } + } + + if (LLStartUp::getStartupState() == STATE_STARTED) + { + LLControlVariable* control = gSavedPerAccountSettings.getControl("VoiceCallsFriendsOnly"); + if (control) + { + mSavedValues[control] = control->getValue(); + } + } } void LLPanelPreference::showMultipleViewersWarning(LLUICtrl* checkbox, const LLSD& value) diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 779542cfcc..2e1fbb09e0 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -169,15 +169,6 @@ void LLFloaterSearch::search(const SearchQuery &p) // add the search query string subs["QUERY"] = LLURI::escape(p.query); - // add the permissions token that login.cgi gave us - // We use "search_token", and fallback to "auth_token" if not present. - LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token"); - if (search_token.asString().empty()) - { - search_token = LLLoginInstance::getInstance()->getResponse("auth_token"); - } - subs["AUTH_TOKEN"] = search_token.asString(); - // add the user's preferred maturity (can be changed via prefs) std::string maturity; if (gAgent.prefersAdult()) diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 27197f0b06..2c84cd1f93 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -56,10 +56,12 @@ #include "llscrolllistctrl.h" #include "llslurl.h" #include "lltextbox.h" +#include "lltoolbarview.h" #include "lltracker.h" #include "lltrans.h" #include "llviewerinventory.h" // LLViewerInventoryItem #include "llviewermenu.h" +#include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llviewerstats.h" #include "llviewertexture.h" @@ -87,6 +89,9 @@ static const F32 MAP_ZOOM_TIME = 0.2f; // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. static const S32 MAX_VISIBLE_REGIONS = 512; + +const S32 HIDE_BEACON_PAD = 133; + // It would be more logical to have this inside the method where it is used but to compile under gcc this // struct has to be here. struct SortRegionNames @@ -326,6 +331,8 @@ LLFloaterWorldMap::~LLFloaterWorldMap() mFriendObserver = NULL; gFloaterWorldMap = NULL; + + mTeleportFinishConnection.disconnect(); } //static @@ -339,12 +346,16 @@ void LLFloaterWorldMap::onClose(bool app_quitting) { // While we're not visible, discard the overlay images we're using LLWorldMap::getInstance()->clearImageRefs(); + mTeleportFinishConnection.disconnect(); } // virtual void LLFloaterWorldMap::onOpen(const LLSD& key) { - bool center_on_target = (key.asString() == "center"); + mTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> + setTeleportFinishedCallback(boost::bind(&LLFloaterWorldMap::onTeleportFinished, this)); + + bool center_on_target = (key.asString() == "center"); mIsClosing = FALSE; @@ -1566,6 +1577,13 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) } } +void LLFloaterWorldMap::onTeleportFinished() +{ + if(isInVisibleChain()) + { + LLWorldMapView::setPan(0, 0, TRUE); + } +} void LLFloaterWorldMap::onCommitSearchResult() { @@ -1642,3 +1660,103 @@ void LLFloaterWorldMap::onFocusLost() LLWorldMapView* map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; map_panel->mPanning = FALSE; } + +LLPanelHideBeacon::LLPanelHideBeacon() : + mHideButton(NULL) +{ +} + +// static +LLPanelHideBeacon* LLPanelHideBeacon::getInstance() +{ + static LLPanelHideBeacon* panel = getPanelHideBeacon(); + return panel; +} + + +BOOL LLPanelHideBeacon::postBuild() +{ + mHideButton = getChild<LLButton>("hide_beacon_btn"); + mHideButton->setCommitCallback(boost::bind(&LLPanelHideBeacon::onHideButtonClick, this)); + + gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelHideBeacon::updatePosition, this)); + + return TRUE; +} + +//virtual +void LLPanelHideBeacon::draw() +{ + if (!LLTracker::isTracking(NULL)) + { + mHideButton->setVisible(false); + return; + } + mHideButton->setVisible(true); + updatePosition(); + LLPanel::draw(); +} + +//virtual +void LLPanelHideBeacon::setVisible(BOOL visible) +{ + if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) visible = false; + + if (visible) + { + updatePosition(); + } + + LLPanel::setVisible(visible); +} + + +//static +LLPanelHideBeacon* LLPanelHideBeacon::getPanelHideBeacon() +{ + LLPanelHideBeacon* panel = new LLPanelHideBeacon(); + panel->buildFromFile("panel_hide_beacon.xml"); + + LL_INFOS() << "Build LLPanelHideBeacon panel" << LL_ENDL; + + panel->updatePosition(); + return panel; +} + +void LLPanelHideBeacon::onHideButtonClick() +{ + LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); + if (instance) + { + instance->onClearBtn(); + } +} + +/** +* Updates position of the panel (similar to Stand & Stop Flying panel). +*/ +void LLPanelHideBeacon::updatePosition() +{ + S32 bottom_tb_center = 0; + if (LLToolBar* toolbar_bottom = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_BOTTOM)) + { + bottom_tb_center = toolbar_bottom->getRect().getCenterX(); + } + + S32 left_tb_width = 0; + if (LLToolBar* toolbar_left = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)) + { + left_tb_width = toolbar_left->getRect().getWidth(); + } + + if (gToolBarView != NULL && gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)->hasButtons()) + { + S32 x_pos = bottom_tb_center - getRect().getWidth() / 2 - left_tb_width; + setOrigin( x_pos + HIDE_BEACON_PAD, 0); + } + else + { + S32 x_pos = bottom_tb_center - getRect().getWidth() / 2; + setOrigin( x_pos + HIDE_BEACON_PAD, 0); + } +} diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 97e99297cf..14a9c26fb9 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -107,7 +107,8 @@ public: // teleport to the tracked item, if there is one void teleport(); void onChangeMaturity(); - + + void onClearBtn(); //Slapp instigated avatar tracking void avatarTrackFromSlapp( const LLUUID& id ); @@ -124,7 +125,6 @@ protected: void onComboTextEntry( ); void onSearchTextEntry( ); - void onClearBtn(); void onClickTeleportBtn(); void onShowTargetBtn(); void onShowAgentBtn(); @@ -151,7 +151,7 @@ protected: void onCoordinatesCommit(); void onCommitSearchResult(); - void cacheLandmarkPosition(); + void onTeleportFinished(); private: LLPanel* mPanel; // Panel displaying the map @@ -195,9 +195,31 @@ private: LLCtrlListInterface * mListFriendCombo; LLCtrlListInterface * mListLandmarkCombo; LLCtrlListInterface * mListSearchResults; + + boost::signals2::connection mTeleportFinishConnection; }; extern LLFloaterWorldMap* gFloaterWorldMap; + +class LLPanelHideBeacon : public LLPanel +{ +public: + static LLPanelHideBeacon* getInstance(); + + LLPanelHideBeacon(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void draw(); + +private: + static LLPanelHideBeacon* getPanelHideBeacon(); + void onHideButtonClick(); + void updatePosition(); + + LLButton* mHideButton; + +}; + #endif diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 9f2119281d..489d34edca 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -483,8 +483,13 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges mActive[base_item_id] = new_gesture; - delete old_gesture; - old_gesture = NULL; + // replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id) + // replaces ids without repalcing gesture + if (old_gesture != new_gesture) + { + delete old_gesture; + old_gesture = NULL; + } if (asset_id.notNull()) { @@ -910,7 +915,7 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS) { // we've waited too long for an animation - LL_INFOS() << "Waited too long for animations to stop, continuing gesture." + LL_INFOS("GestureMgr") << "Waited too long for animations to stop, continuing gesture." << LL_ENDL; gesture->mWaitingAnimations = FALSE; gesture->mCurrentStep++; @@ -1097,6 +1102,34 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid, self.setFetchID(item_id); self.startFetch(); } + + item_map_t::iterator it = self.mActive.find(item_id); + if (it == self.mActive.end()) + { + // Gesture is supposed to be present, active, but NULL + LL_DEBUGS("GestureMgr") << "Gesture " << item_id << " not found in active list" << LL_ENDL; + } + else + { + LLMultiGesture* old_gesture = (*it).second; + if (old_gesture && old_gesture != gesture) + { + LL_DEBUGS("GestureMgr") << "Received dupplicate " << item_id << " callback" << LL_ENDL; + // In case somebody managest to activate, deactivate and + // then activate gesture again, before asset finishes loading. + // LLLoadInfo will have a different pointer, asset storage will + // see it as a different request, resulting in two callbacks. + + // deactivateSimilarGestures() did not turn this one off + // because of matching item_id + self.stopGesture(old_gesture); + + self.mActive.erase(item_id); + delete old_gesture; + old_gesture = NULL; + } + } + self.mActive[item_id] = gesture; // Everything has been successful. Add to the active list. @@ -1131,9 +1164,23 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid, } else { - LL_WARNS() << "Unable to load gesture" << LL_ENDL; - - self.mActive.erase(item_id); + LL_WARNS("GestureMgr") << "Unable to load gesture" << LL_ENDL; + + item_map_t::iterator it = self.mActive.find(item_id); + if (it != self.mActive.end()) + { + LLMultiGesture* old_gesture = (*it).second; + if (old_gesture) + { + // Shouldn't happen, just in case + LL_WARNS("GestureMgr") << "Gesture " << item_id << " existed when it shouldn't" << LL_ENDL; + + self.stopGesture(old_gesture); + delete old_gesture; + old_gesture = NULL; + } + self.mActive.erase(item_id); + } delete gesture; gesture = NULL; @@ -1151,9 +1198,23 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid, LLDelayedGestureError::gestureFailedToLoad( item_id ); } - LL_WARNS() << "Problem loading gesture: " << status << LL_ENDL; - - LLGestureMgr::instance().mActive.erase(item_id); + LL_WARNS("GestureMgr") << "Problem loading gesture: " << status << LL_ENDL; + + item_map_t::iterator it = self.mActive.find(item_id); + if (it != self.mActive.end()) + { + LLMultiGesture* old_gesture = (*it).second; + if (old_gesture) + { + // Shouldn't happen, just in case + LL_WARNS("GestureMgr") << "Gesture " << item_id << " existed when it shouldn't" << LL_ENDL; + + self.stopGesture(old_gesture); + delete old_gesture; + old_gesture = NULL; + } + self.mActive.erase(item_id); + } } } diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 9dca509262..e7bc2a9268 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -196,7 +196,7 @@ LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL; // static void LLGroupActions::search() { - LLFloaterReg::showInstance("search", LLSD().with("category", "groups")); + LLFloaterReg::showInstance("search"); } // static diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b4fc832596..37500176ea 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -138,6 +138,8 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item) LLInventoryValidationInfo::LLInventoryValidationInfo(): mFatalErrorCount(0), mWarningCount(0), + mLoopCount(0), + mOrphanedCount(0), mInitialized(false), mFatalNoRootFolder(false), mFatalNoLibraryRootFolder(false), @@ -147,7 +149,10 @@ LLInventoryValidationInfo::LLInventoryValidationInfo(): void LLInventoryValidationInfo::toOstream(std::ostream& os) const { - os << "mFatalErrorCount " << mFatalErrorCount << " mWarningCount " << mWarningCount; + os << "mFatalErrorCount " << mFatalErrorCount + << " mWarningCount " << mWarningCount + << " mLoopCount " << mLoopCount + << " mOrphanedCount " << mOrphanedCount; } @@ -161,6 +166,8 @@ void LLInventoryValidationInfo::asLLSD(LLSD& sd) const { sd["fatal_error_count"] = mFatalErrorCount; sd["warning_count"] = mWarningCount; + sd["loop_count"] = mLoopCount; + sd["orphaned_count"] = mOrphanedCount; sd["initialized"] = mInitialized; sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size()); sd["fatal_no_root_folder"] = mFatalNoRootFolder; @@ -337,21 +344,35 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL return NULL; } -bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const +LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const { LLInventoryObject *object = getObject(object_id); - while (object && object->getParentUUID().notNull()) - { - LLInventoryObject *parent_object = getObject(object->getParentUUID()); + if (!object) + { + LL_WARNS(LOG_INV) << "Unable to trace topmost ancestor, initial object " << object_id << " does not exist" << LL_ENDL; + return ANSCESTOR_MISSING; + } + + std::set<LLUUID> object_ids{ object_id }; // loop protection + while (object->getParentUUID().notNull()) + { + LLUUID parent_id = object->getParentUUID(); + if (object_ids.find(parent_id) != object_ids.end()) + { + LL_WARNS(LOG_INV) << "Detected a loop on an object " << parent_id << " when searching for ancestor of " << object_id << LL_ENDL; + return ANSCESTOR_LOOP; + } + object_ids.insert(parent_id); + LLInventoryObject *parent_object = getObject(parent_id); if (!parent_object) { - LL_WARNS(LOG_INV) << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL; - return false; + LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL; + return ANSCESTOR_MISSING; } object = parent_object; } result = object->getUUID(); - return true; + return ANSCESTOR_OK; } // Get the object by id. Returns NULL if not found. @@ -2947,42 +2968,69 @@ bool LLInventoryModel::saveToFile(const std::string& filename, LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL; - llofstream fileXML(filename.c_str()); - if (!fileXML.is_open()) - { - LL_WARNS(LOG_INV) << "unable to save inventory to: " << filename << LL_ENDL; - return false; - } + try + { + llofstream fileXML(filename.c_str()); + if (!fileXML.is_open()) + { + LL_WARNS(LOG_INV) << "Failed to open file. Unable to save inventory to: " << filename << LL_ENDL; + return false; + } - LLSD cache_ver; - cache_ver["inv_cache_version"] = sCurrentInvCacheVersion; + LLSD cache_ver; + cache_ver["inv_cache_version"] = sCurrentInvCacheVersion; - fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl; + if (fileXML.fail()) + { + LL_WARNS(LOG_INV) << "Failed to write cache version to file. Unable to save inventory to: " << filename << LL_ENDL; + return false; + } - S32 count = categories.size(); - S32 cat_count = 0; - S32 i; - for(i = 0; i < count; ++i) - { - LLViewerInventoryCategory* cat = categories[i]; - if(cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) - { - fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl; - cat_count++; - } - } + fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl; - S32 it_count = items.size(); - for(i = 0; i < it_count; ++i) - { - fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl; - } + S32 count = categories.size(); + S32 cat_count = 0; + S32 i; + for (i = 0; i < count; ++i) + { + LLViewerInventoryCategory* cat = categories[i]; + if (cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) + { + fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl; + cat_count++; + } - fileXML.close(); + if (fileXML.fail()) + { + LL_WARNS(LOG_INV) << "Failed to write a folder to file. Unable to save inventory to: " << filename << LL_ENDL; + return false; + } + } - LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL; + S32 it_count = items.size(); + for (i = 0; i < it_count; ++i) + { + fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl; - return true; + if (fileXML.fail()) + { + LL_WARNS(LOG_INV) << "Failed to write an item to file. Unable to save inventory to: " << filename << LL_ENDL; + return false; + } + } + + fileXML.close(); + + LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL; + } + catch (...) + { + LOG_UNHANDLED_EXCEPTION(""); + LL_INFOS(LOG_INV) << "Failed to save inventory to: (" << filename << ")" << LL_ENDL; + return false; + } + + return true; } // message handling functionality @@ -3850,20 +3898,23 @@ void LLInventoryModel::dumpInventory() const LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo; - S32 fatalities = 0; + S32 fatal_errs = 0; S32 warnings = 0; + S32 loops = 0; + S32 orphaned = 0; if (getRootFolderID().isNull()) { LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL; validation_info->mFatalNoRootFolder = true; - fatalities++; + fatal_errs++; } if (getLibraryRootFolderID().isNull()) { + // Probably shouldn't be a fatality, inventory can function without a library LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL; validation_info->mFatalNoLibraryRootFolder = true; - fatalities++; + fatal_errs++; } if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size()) @@ -3895,7 +3946,23 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const } LLUUID topmost_ancestor_id; // Will leave as null uuid on failure - getObjectTopmostAncestor(cat_id, topmost_ancestor_id); + EAnscestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id); + switch (res) + { + case ANSCESTOR_MISSING: + orphaned++; + break; + case ANSCESTOR_LOOP: + loops++; + break; + case ANSCESTOR_OK: + break; + default: + LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL; + warnings++; + break; + } + if (cat_id != cat->getUUID()) { LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL; @@ -3995,8 +4062,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const // Topmost ancestor should be root or library. LLUUID topmost_ancestor_id; - bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id); - if (!found) + EAnscestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id); + if (found != ANSCESTOR_OK) { LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL; warnings++; @@ -4026,7 +4093,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName() << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL; - warnings++; + orphaned++; } else { @@ -4044,6 +4111,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName() << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL; + orphaned++; } } } @@ -4052,7 +4120,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const LLFolderType::EType folder_type = cat->getPreferredType(); bool cat_is_in_library = false; LLUUID topmost_id; - if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) && topmost_id == getLibraryRootFolderID()) + if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANSCESTOR_OK && topmost_id == getLibraryRootFolderID()) { cat_is_in_library = true; } @@ -4092,6 +4160,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (parent_id.isNull()) { LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL; + orphaned++; } else { @@ -4102,6 +4171,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL; + orphaned++; } else { @@ -4118,6 +4188,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const { LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL; + orphaned++; } } @@ -4135,15 +4206,18 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType() << " missing backlink info at target_id " << target_id << LL_ENDL; + orphaned++; } // Links should have referents. if (item->getActualType() == LLAssetType::AT_LINK && !target_item) { LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL; + orphaned++; } else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat) { LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL; + orphaned++; } if (target_item && target_item->getIsLinkType()) { @@ -4215,8 +4289,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const if (is_automatic) { LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL; - fatalities++; - validation_info->mMissingRequiredSystemFolders.insert(LLFolderType::EType(ft)); + fatal_errs++; + validation_info->mMissingRequiredSystemFolders.insert(folder_type); } else { @@ -4227,8 +4301,20 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const else if (count_under_root > 1) { LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; - validation_info->mDuplicateRequiredSystemFolders.insert(LLFolderType::EType(ft)); - fatalities++; + validation_info->mDuplicateRequiredSystemFolders.insert(folder_type); + if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS) + { + // It is a fatal problem or can lead to fatal problems for COF, + // outfits, trash and other non-automatic folders. + fatal_errs++; + } + else + { + // For automatic folders it's not a fatal issue and shouldn't + // break inventory or other functionality further + // Exception: FT_SETTINGS is not automatic, but only deserves a warning. + warnings++; + } } if (count_elsewhere > 0) { @@ -4254,11 +4340,13 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const } // FIXME need to fail login and tell user to retry, contact support if problem persists. - bool valid = (fatalities == 0); - LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatalities << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL; + bool valid = (fatal_errs == 0); + LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL; - validation_info->mFatalErrorCount = fatalities; + validation_info->mFatalErrorCount = fatal_errs; validation_info->mWarningCount = warnings; + validation_info->mLoopCount = loops; + validation_info->mOrphanedCount = orphaned; return validation_info; } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index e81652820f..eeec89bfb0 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -68,6 +68,8 @@ public: S32 mFatalErrorCount; S32 mWarningCount; + S32 mLoopCount; // Presence of folders whose ansestors loop onto themselves + S32 mOrphanedCount; // Missing or orphaned items, links and folders bool mInitialized; bool mFatalNoRootFolder; bool mFatalNoLibraryRootFolder; @@ -283,9 +285,14 @@ public: // Check if one object has a parent chain up to the category specified by UUID. BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const; - + + enum EAnscestorResult{ + ANSCESTOR_OK = 0, + ANSCESTOR_MISSING = 1, + ANSCESTOR_LOOP = 2, + }; // Follow parent chain to the top. - bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const; + EAnscestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const; //-------------------------------------------------------------------- // Find diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index c1e5e5faed..d3ba18525b 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -411,8 +411,16 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode) filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default); if (!gDirUtilp->fileExists(filename) || !loadFromSettings(load_mode, filename, &mControlsMap)) { - // mind placeholders - mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); + // Mind placeholders + // Do not use mControlsMap.insert(mDefaultsMap) since mControlsMap has + // placeholders that won't be added over(to) by insert. + // Or instead move generatePlaceholders call to be after copying + control_map_t::iterator iter = mDefaultsMap.begin(); + while (iter != mDefaultsMap.end()) + { + mControlsMap[iter->first].mKeyBind = iter->second.mKeyBind; + iter++; + } } } mLoadMode = load_mode; @@ -575,6 +583,8 @@ void LLKeyConflictHandler::saveToSettings(bool temporary) break; } + keys.xml_version.set(keybindings_xml_version, true); + if (temporary) { // write to temporary xml and use it for gViewerInput @@ -736,9 +746,9 @@ void LLKeyConflictHandler::resetToDefault(const std::string &control_name) resetToDefaultAndResolve(control_name, false); } -void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) +void LLKeyConflictHandler::resetToDefaultsAndResolve() { - if (mode == MODE_SAVED_SETTINGS) + if (mLoadMode == MODE_SAVED_SETTINGS) { control_map_t::iterator iter = mControlsMap.begin(); control_map_t::iterator end = mControlsMap.end(); @@ -751,8 +761,16 @@ void LLKeyConflictHandler::resetToDefaults(ESourceMode mode) else { mControlsMap.clear(); - generatePlaceholders(mode); + + // Set key combinations. + // Copy from mDefaultsMap before doing generatePlaceholders, otherwise + // insert() will fail to add some keys into pre-existing values from + // generatePlaceholders() mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end()); + + // Set conflict masks and mark functions (un)assignable + generatePlaceholders(mLoadMode); + } mHasUnsavedChanges = true; @@ -762,7 +780,7 @@ void LLKeyConflictHandler::resetToDefaults() { if (!empty()) { - resetToDefaults(mLoadMode); + resetToDefaultsAndResolve(); } else { @@ -772,7 +790,7 @@ void LLKeyConflictHandler::resetToDefaults() // 3. We are loading 'current' only to replace it // but it is reliable and works Todo: consider optimizing. loadFromSettings(mLoadMode); - resetToDefaults(mLoadMode); + resetToDefaultsAndResolve(); } } @@ -805,7 +823,7 @@ void LLKeyConflictHandler::resetKeyboardBindings() void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) { - // These controls are meant to cause conflicts when user tries to assign same control somewhere else + // These placeholders are meant to cause conflict resolution when user tries to assign same control somewhere else // also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks if (load_mode == MODE_FIRST_PERSON) @@ -865,24 +883,60 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode) registerTemporaryControl("spin_around_ccw_sitting"); registerTemporaryControl("spin_around_cw_sitting"); } + + + // Special case, mouse clicks passed to scripts have 'lowest' piority + // thus do not conflict, everything else has a chance before them + // also in ML they have highest priority, but only when script-grabbed, + // thus do not conflict + // (see AGENT_CONTROL_ML_LBUTTON_DOWN and CONTROL_LBUTTON_DOWN_INDEX) + LLKeyConflict *type_data = &mControlsMap[script_mouse_handler_name]; + type_data->mAssignable = true; + type_data->mConflictMask = U32_MAX - CONFLICT_LMOUSE; } -bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask) +bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_mask) { if (conlict_mask == CONFLICT_NOTHING) { // Can't conflict return true; } + + if (data.mMouse == CLICK_LEFT + && data.mMask == MASK_NONE + && data.mKey == KEY_NONE) + { + if ((conlict_mask & CONFLICT_LMOUSE) == 0) + { + // Can't conflict + return true; + } + else + { + // simplify conflict mask + conlict_mask = CONFLICT_LMOUSE; + } + } + else + { + // simplify conflict mask + conlict_mask &= ~CONFLICT_LMOUSE; + } + std::map<std::string, S32> conflict_list; control_map_t::iterator cntrl_iter = mControlsMap.begin(); control_map_t::iterator cntrl_end = mControlsMap.end(); for (; cntrl_iter != cntrl_end; ++cntrl_iter) { + const U32 cmp_mask = cntrl_iter->second.mConflictMask; + if ((cmp_mask & conlict_mask) == 0) + { + // can't conflict + continue; + } S32 index = cntrl_iter->second.mKeyBind.findKeyData(data); - if (index >= 0 - && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING - && (cntrl_iter->second.mConflictMask & conlict_mask) != 0) + if (index >= 0) { if (cntrl_iter->second.mAssignable) { diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index 2926ca3aeb..23c1adf1e4 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -66,6 +66,7 @@ public: }; const U32 CONFLICT_NOTHING = 0; + const U32 CONFLICT_LMOUSE = 0x1 << 1; // at the moment this just means that key will conflict with everything that is identical const U32 CONFLICT_ANY = U32_MAX; @@ -128,23 +129,24 @@ public: // resets current mode to defaults void resetToDefaults(); - bool empty() { return mControlsMap.empty(); } + bool empty() const { return mControlsMap.empty(); } void clear(); // reloads bindings from last valid user's xml or from default xml // to keyboard's handler static void resetKeyboardBindings(); - bool hasUnsavedChanges() { return mHasUnsavedChanges; } + bool hasUnsavedChanges() const { return mHasUnsavedChanges; } void setLoadMode(ESourceMode mode) { mLoadMode = mode; } - ESourceMode getLoadMode() { return mLoadMode; } + ESourceMode getLoadMode() const { return mLoadMode; } private: void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts); - void resetToDefaults(ESourceMode mode); + void resetToDefaultsAndResolve(); // at the moment these kind of control is not savable, but takes part in conflict resolution void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask); + // conflict mask 0 means that any conflicts will be ignored void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0); typedef std::map<std::string, LLKeyConflict> control_map_t; @@ -152,7 +154,7 @@ private: bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination); void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values // returns false in case user is trying to reuse control that can't be reassigned - bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask); + bool removeConflicts(const LLKeyData &data, U32 conlict_mask); // removes flags and removes temporary file, returns 'true' if file was removed bool clearUnsavedChanges(); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index e81d2cc082..531f0b172d 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -165,13 +165,12 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia //requested_options.append("inventory-meat"); //requested_options.append("inventory-skel-targets"); #if (!defined LL_MINIMIAL_REQUESTED_OPTIONS) - if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary")) - { - requested_options.append("inventory-lib-root"); - requested_options.append("inventory-lib-owner"); - requested_options.append("inventory-skel-lib"); + + // Not requesting library will trigger mFatalNoLibraryRootFolder + requested_options.append("inventory-lib-root"); + requested_options.append("inventory-lib-owner"); + requested_options.append("inventory-skel-lib"); // requested_options.append("inventory-meat-lib"); - } requested_options.append("initial-outfit"); requested_options.append("gestures"); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 5393d0b0b7..9142aadab9 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1146,6 +1146,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) } else { + // Media might be blocked, waiting for a file, + // send an empty response to unblock it + const std::vector<std::string> empty_response; + self->sendPickFileResponse(empty_response); + LLNotificationsUtil::add("MediaFileDownloadUnsupported"); } }; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 3822a98081..859d987fc3 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -2813,7 +2813,9 @@ void LLModelPreview::lookupLODModelFiles(S32 lod) std::string lod_filename = mLODFile[LLModel::LOD_HIGH]; std::string ext = ".dae"; - std::string::size_type i = lod_filename.rfind(ext); + std::string lod_filename_lower(lod_filename); + LLStringUtil::toLower(lod_filename_lower); + std::string::size_type i = lod_filename_lower.rfind(ext); if (i != std::string::npos) { lod_filename.replace(i, lod_filename.size() - ext.size(), getLodSuffix(next_lod) + ext); diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index cb4c07a417..852b39f442 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -61,7 +61,7 @@ #define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus" -#define CAP_SERVICE_OBJECT_LINKSETS "ObjectNavMeshProperties" +#define CAP_SERVICE_OBJECT_LINKSETS "RegionObjects" #define CAP_SERVICE_TERRAIN_LINKSETS "TerrainNavMeshProperties" #define CAP_SERVICE_CHARACTERS "CharacterProperties" diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 061ecad099..39cdb6fb04 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -1029,7 +1029,6 @@ void LLPreviewGesture::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId) // active map with the new pointer. if (LLGestureMgr::instance().isGestureActive(itemId)) { - //*TODO: This is crashing for some reason. Fix it. // Active gesture edited from menu. LLGestureMgr::instance().replaceGesture(itemId, newAssetId); gInventory.notifyObservers(); diff --git a/indra/newview/llsearchableui.cpp b/indra/newview/llsearchableui.cpp index 1119e80005..620bbdfcdf 100644 --- a/indra/newview/llsearchableui.cpp +++ b/indra/newview/llsearchableui.cpp @@ -132,8 +132,11 @@ void ll::statusbar::SearchableItem::setNotHighlighted( ) { mCtrl->setHighlighted( false ); - if( mWasHiddenBySearch ) - mMenu->setVisible( TRUE ); + if (mWasHiddenBySearch) + { + mMenu->setVisible(TRUE); + mWasHiddenBySearch = false; + } } } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index bb6ad5d8fb..9782881f0e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2248,10 +2248,6 @@ bool idle_startup() // Have the agent start watching the friends list so we can update proxies gAgent.observeFriends(); - if (gSavedSettings.getBOOL("LoginAsGod")) - { - gAgent.requestEnterGodMode(); - } // Start automatic replay if the flag is set. if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession()) @@ -2732,19 +2728,34 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, gAgentAvatarp->setSex(gender); - // try to find the outfit - if not there, create some default - // wearables. + // try to find the requested outfit or folder + + // -- check for existing outfit in My Outfits + bool do_copy = false; LLUUID cat_id = findDescendentCategoryIDByName( - gInventory.getLibraryRootFolderID(), + gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS), outfit_folder_name); + + // -- check for existing folder in Library + if (cat_id.isNull()) + { + cat_id = findDescendentCategoryIDByName( + gInventory.getLibraryRootFolderID(), + outfit_folder_name); + if (!cat_id.isNull()) + { + do_copy = true; + } + } + if (cat_id.isNull()) { + // -- final fallback: create standard wearables LL_DEBUGS() << "standard wearables" << LL_ENDL; gAgentWearables.createStandardWearables(); } else { - bool do_copy = true; bool do_append = false; LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); // Need to fetch cof contents before we can wear. @@ -3619,6 +3630,19 @@ bool process_login_success_response() } } + std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName"); + if (!fake_initial_outfit_name.empty()) + { + gAgent.setFirstLogin(TRUE); + sInitialOutfit = fake_initial_outfit_name; + if (sInitialOutfitGender.empty()) + { + sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway. + } + + LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL; + } + // set the location of the Agent Appearance service, from which we can request // avatar baked textures if they are supported by the current region std::string agent_appearance_url = response["agent_appearance_service"]; diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index ba328f27c4..6d54a3770c 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -44,6 +44,7 @@ #include "lltoolmgr.h" #include "lltoolselectrect.h" #include "lltoolplacer.h" +#include "llviewerinput.h" #include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerwindow.h" @@ -745,7 +746,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) { // if the left button is grabbed, don't put up the pie menu - if (gAgent.leftButtonGrabbed()) + if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) { gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); return FALSE; @@ -762,7 +763,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask) { // if the left button is grabbed, don't put up the pie menu - if (gAgent.leftButtonGrabbed()) + if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) { gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); return FALSE; @@ -796,7 +797,10 @@ BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask) { - gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); + if (gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); + } setCurrentTool( (LLTool*) mGun ); return TRUE; } diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index 6216899dc6..897f8c1e5f 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -51,6 +51,7 @@ #include "lltoolmgr.h" #include "lltoolpie.h" #include "llviewercamera.h" +#include "llviewerinput.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" @@ -140,7 +141,6 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask) LL_INFOS() << "LLToolGrab handleMouseDown" << LL_ENDL; } - // call the base class to propogate info to sim LLTool::handleMouseDown(x, y, mask); // leftButtonGrabbed() checks if controls are reserved by scripts, but does not take masks into account @@ -150,6 +150,19 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask) gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE); } mClickedInMouselook = gAgentCamera.cameraMouselook(); + + if (mClickedInMouselook && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) + { + // LLToolCompGun::handleMouseDown handles the event if ML controls are grabed, + // but LLToolGrabBase is often the end point for mouselook clicks if ML controls + // are not grabbed and LLToolGrabBase::handleMouseDown consumes the event, + // so send clicks from here. + // We are sending specifically CONTROL_LBUTTON_DOWN instead of _ML_ version. + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN); + + // Todo: LLToolGrabBase probably shouldn't consume the event if there is nothing + // to grab in Mouselook, it intercepts handling in scanMouse + } return TRUE; } @@ -953,9 +966,18 @@ void LLToolGrabBase::handleHoverFailed(S32 x, S32 y, MASK mask) BOOL LLToolGrabBase::handleMouseUp(S32 x, S32 y, MASK mask) { - // call the base class to propogate info to sim LLTool::handleMouseUp(x, y, mask); + if (gAgentCamera.cameraMouselook() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON)) + { + // LLToolCompGun::handleMouseUp handles the event if ML controls are grabed, + // but LLToolGrabBase is often the end point for mouselook clicks if ML controls + // are not grabbed and LToolGrabBase::handleMouseUp consumes the event, + // so send clicks from here. + // We are sending specifically CONTROL_LBUTTON_UP instead of _ML_ version. + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP); + } + if( hasMouseCapture() ) { setMouseCapture( FALSE ); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index b4736841d6..43deac60d9 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -394,8 +394,9 @@ BOOL LLToolPie::handleLeftClickPick() gFocusMgr.setKeyboardFocus(NULL); } - BOOL touchable = (object && object->flagHandleTouch()) - || (parent && parent->flagHandleTouch()); + bool touchable = object + && (object->getClickAction() != CLICK_ACTION_DISABLED) + && (object->flagHandleTouch() || (parent && parent->flagHandleTouch())); // Switch to grab tool if physical or triggerable if (object && @@ -656,6 +657,12 @@ bool LLToolPie::teleportToClickedLocation() LLViewerObject* objp = mHoverPick.getObject(); LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL; + if (objp && (objp->getAvatar() == gAgentAvatarp || objp == gAgentAvatarp)) // ex: nametag + { + // Don't teleport to self, teleporting to other avatars is fine + return false; + } + bool is_in_world = mHoverPick.mObjectID.notNull() && objp && !objp->isHUDAttachment(); bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND; bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero(); @@ -750,7 +757,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) else if (!mMouseOutsideSlop && mMouseButtonDown // disable camera steering if click on land is not used for moving - && gViewerInput.isMouseBindUsed(CLICK_LEFT)) + && gViewerInput.isMouseBindUsed(CLICK_LEFT, MASK_NONE, MODE_THIRD_PERSON)) { S32 delta_x = x - mMouseDownX; S32 delta_y = y - mMouseDownY; diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 6aa1273174..70065cb5a0 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -353,7 +353,7 @@ void LLViewerAssetStorage::checkForTimeouts() // Restore requests LLCoprocedureManager* manager = LLCoprocedureManager::getInstance(); while (mCoroWaitList.size() > 0 - && manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE) + && manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1)) { CoroWaitList &request = mCoroWaitList.front(); @@ -425,13 +425,14 @@ void LLViewerAssetStorage::queueRequestHttp( if (!duplicate) { // Coroutine buffer has fixed size (synchronization buffer, so we have no alternatives), so buffer any request above limit - if (LLCoprocedureManager::instance().count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE) + LLCoprocedureManager* manager = LLCoprocedureManager::getInstance(); + if (manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1)) { bool with_http = true; bool is_temp = false; LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp); - LLCoprocedureManager::instance().enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro", + manager->enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro", boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data)); } else diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 94ec534732..43b9cd90bd 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -816,13 +816,20 @@ bool toggle_enable_media(EKeystate s) bool walk_to(EKeystate s) { - if (KEYSTATE_DOWN != s) return true; + if (KEYSTATE_DOWN != s) + { + // teleport/walk is usually on mouseclick, mouseclick needs + // to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't, + // so return false, but if it causes issues, do some kind of + // "return !has_teleported" + return false; + } return LLToolPie::getInstance()->walkToClickedLocation(); } bool teleport_to(EKeystate s) { - if (KEYSTATE_DOWN != s) return true; + if (KEYSTATE_DOWN != s) return false; return LLToolPie::getInstance()->teleportToClickedLocation(); } @@ -850,7 +857,47 @@ bool voice_follow_key(EKeystate s) return false; } -bool agen_control_lbutton_handle(EKeystate s) +bool script_trigger_lbutton(EKeystate s) +{ + // Check for script overriding/expecting left mouse button. + // Note that this does not pass event further and depends onto mouselook. + // Checks CONTROL_ML_LBUTTON_DOWN_INDEX for mouselook, + // CONTROL_LBUTTON_DOWN_INDEX for normal camera + if (gAgent.leftButtonGrabbed()) + { + bool mouselook = gAgentCamera.cameraMouselook(); + switch (s) + { + case KEYSTATE_DOWN: + if (mouselook) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN); + } + return true; + case KEYSTATE_UP: + if (mouselook) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP); + } + return true; + default: + break; + } + } + return false; +} + +// Used by scripts, for overriding/handling left mouse button +// see mControlsTakenCount +bool agent_control_lbutton_handle(EKeystate s) { switch (s) { @@ -922,6 +969,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to); REGISTER_KEYBOARD_ACTION("walk_to", walk_to); REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice); REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key); +REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton); #undef REGISTER_KEYBOARD_ACTION LLViewerInput::LLViewerInput() @@ -1193,6 +1241,20 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const typedef boost::function<bool(EKeystate)> function_t; function_t function = NULL; + if (mouse == CLICK_LEFT + && mask == MASK_NONE + && function_name == script_mouse_handler_name) + { + // Special case + // Left click has script overrides and by default + // is handled via agent_control_lbutton as last option + // In case of mouselook and present overrides it has highest + // priority even over UI and is handled in LLToolCompGun::handleMouseDown + // so just mark it as having default handler + mLMouseDefaultHandling[mode] = true; + return TRUE; + } + LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name); if (result) { @@ -1269,7 +1331,8 @@ LLViewerInput::Keys::Keys() : first_person("first_person"), third_person("third_person"), sitting("sitting"), - edit_avatar("edit_avatar") + edit_avatar("edit_avatar"), + xml_version("xml_version", 0) {} void LLViewerInput::resetBindings() @@ -1280,6 +1343,7 @@ void LLViewerInput::resetBindings() mGlobalMouseBindings[i].clear(); mKeyBindings[i].clear(); mMouseBindings[i].clear(); + mLMouseDefaultHandling[i] = false; } } @@ -1298,6 +1362,65 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON); binding_count += loadBindingMode(keys.sitting, MODE_SITTING); binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR); + + // verify version + if (keys.xml_version < 1) + { + // updating from a version that was not aware of LMouse bindings + for (S32 i = 0; i < MODE_COUNT; i++) + { + mLMouseDefaultHandling[i] = true; + } + + // fix missing values + KeyBinding mouse_binding; + mouse_binding.key = ""; + mouse_binding.mask = "NONE"; + mouse_binding.mouse = "LMB"; + mouse_binding.command = script_mouse_handler_name; + + if (keys.third_person.isProvided()) + { + keys.third_person.bindings.add(mouse_binding); + } + + if (keys.first_person.isProvided()) + { + keys.first_person.bindings.add(mouse_binding); + } + + if (keys.sitting.isProvided()) + { + keys.sitting.bindings.add(mouse_binding); + } + + if (keys.edit_avatar.isProvided()) + { + keys.edit_avatar.bindings.add(mouse_binding); + } + + // fix version + keys.xml_version.set(keybindings_xml_version, true); + + // Write the resulting XML to file + LLXMLNodePtr output_node = new LLXMLNode("keys", false); + LLXUIParser write_parser; + write_parser.writeXUI(output_node, keys); + + if (!output_node->isNull()) + { + // file in app_settings is supposed to be up to date + // this is only for the file from user_settings + LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL; + LLFILE *fp = LLFile::fopen(filename, "w"); + if (fp != NULL) + { + LLXMLNode::writeHeaderToFile(fp); + output_node->writeToFile(fp); + fclose(fp); + } + } + } } return binding_count; } @@ -1469,17 +1592,6 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat); - if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask)) - { - if (key_down && !repeat) - { - res = agen_control_lbutton_handle(KEYSTATE_DOWN); - } - if (key_up) - { - res = agen_control_lbutton_handle(KEYSTATE_UP); - } - } return res; } @@ -1603,29 +1715,36 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const bool res = false; S32 mode = getMode(); MASK mask = gKeyboard->currentMask(TRUE); - - // By default mouse clicks require exact mask - // Todo: support for mIgnoreMasks because some functions like teleports - // expect to be canceled, but for voice it's prefered to ignore mask. res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state, false); - // no user defined actions found or those actions can't handle the key/button, handle control if nessesary - if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask)) + + // No user defined actions found or those actions can't handle the key/button, + // so handle CONTROL_LBUTTON if nessesary. + // + // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown, + // and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls + // are leftButtonGrabbed(), send a normal click otherwise. + + if (!res + && mLMouseDefaultHandling[mode] + && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed()) + && (click == CLICK_LEFT || click == CLICK_DOUBLELEFT) + ) { switch (state) { case MOUSE_STATE_DOWN: - agen_control_lbutton_handle(KEYSTATE_DOWN); + agent_control_lbutton_handle(KEYSTATE_DOWN); res = true; break; case MOUSE_STATE_CLICK: // might not work best with some functions, // but some function need specific states too specifically - agen_control_lbutton_handle(KEYSTATE_DOWN); - agen_control_lbutton_handle(KEYSTATE_UP); + agent_control_lbutton_handle(KEYSTATE_DOWN); + agent_control_lbutton_handle(KEYSTATE_UP); res = true; break; case MOUSE_STATE_UP: - agen_control_lbutton_handle(KEYSTATE_UP); + agent_control_lbutton_handle(KEYSTATE_UP); res = true; break; default: @@ -1655,7 +1774,7 @@ void LLViewerInput::scanMouse() } } -bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) +bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const { S32 size = mMouseBindings[mode].size(); for (S32 index = 0; index < size; index++) diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h index ca70ac76bf..52e95e2168 100644 --- a/indra/newview/llviewerinput.h +++ b/indra/newview/llviewerinput.h @@ -31,6 +31,8 @@ #include "llinitparam.h" const S32 MAX_KEY_BINDINGS = 128; // was 60 +const S32 keybindings_xml_version = 1; +const std::string script_mouse_handler_name = "script_trigger_lbutton"; class LLNamedFunction { @@ -100,7 +102,7 @@ public: third_person, sitting, edit_avatar; - + Optional<S32> xml_version; // 'xml', because 'version' appears to be reserved Keys(); }; @@ -131,7 +133,8 @@ public: BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down); void scanMouse(); - bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON); + bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const; + bool isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; } private: bool scanKey(const std::vector<LLKeyboardBinding> &binding, @@ -171,6 +174,7 @@ private: // to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown) std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT]; std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT]; + bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority // keybindings that do not consume event and are handled earlier, before floaters std::vector<LLKeyboardBinding> mGlobalKeyBindings[MODE_COUNT]; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 27d8df28c3..812f804ea9 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -3289,10 +3289,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD: { LL_DEBUGS("Media") << "Media event - file download requested - filename is " << plugin->getFileDownloadFilename() << LL_ENDL; - - //unblock media plugin - const std::vector<std::string> empty_response; - plugin->sendPickFileResponse(empty_response); } break; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a2d3f2c0cf..a95636ff23 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1278,6 +1278,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE); mTotalCRC = crc; + // Might need to update mSourceMuted here to properly pick up new radius mSoundCutOffRadius = cutoff; // Owner ID used for sound muting or particle system muting @@ -5884,7 +5885,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow else if (flags & LL_SOUND_FLAG_STOP) { // Just shut off the sound - mAudioSourcep->play(LLUUID::null); + mAudioSourcep->stop(); } return; } @@ -5923,7 +5924,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow mAudioSourcep->setQueueSounds(queue); if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG { - mAudioSourcep->play(LLUUID::null); + mAudioSourcep->stop(); } // Play this sound if region maturity permits diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 501148a112..67ad72e997 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3060,12 +3060,12 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ObjectAnimation"); capabilityNames.append("ObjectMedia"); capabilityNames.append("ObjectMediaNavigate"); - capabilityNames.append("ObjectNavMeshProperties"); capabilityNames.append("ParcelPropertiesUpdate"); capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); capabilityNames.append("ProvisionVoiceAccountRequest"); capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite + capabilityNames.append("RegionObjects"); capabilityNames.append("RemoteParcelRequest"); capabilityNames.append("RenderMaterials"); capabilityNames.append("RequestTextureDownload"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a54c29a404..42e21f7130 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2282,6 +2282,9 @@ void LLViewerWindow::initWorldUI() LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance(); panel_ssf_container->addChild(panel_stand_stop_flying); + LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance(); + panel_ssf_container->addChild(panel_hide_beacon); + panel_ssf_container->setVisible(TRUE); LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 5ee661f6c0..cb50390f60 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1334,7 +1334,8 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity"); + static LLCachedControl<S32> box_detail_cache(gSavedSettings, "AvatarBoundingBoxComplexity"); + S32 box_detail = box_detail_cache; if (getOverallAppearance() != AOA_NORMAL) { if (isControlAvatar()) @@ -2539,10 +2540,11 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) { LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL; return; - } + } + static LLCachedControl<bool> disable_all_render_types(gSavedSettings, "DisableAllRenderTypes"); if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)) - && !(gSavedSettings.getBOOL("DisableAllRenderTypes")) && !isSelf()) + && !disable_all_render_types && !isSelf()) { return; } @@ -2680,7 +2682,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) // Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. if(isSelf()) { - if(gAgentCamera.cameraMouselook() || gSavedSettings.getBOOL("VoiceDisableMic")) + static LLCachedControl<bool> voice_disable_mic(gSavedSettings, "VoiceDisableMic"); + if(gAgentCamera.cameraMouselook() || voice_disable_mic) { render_visualizer = false; } @@ -3181,11 +3184,14 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } const F32 time_visible = mTimeVisible.getElapsedTimeF32(); - const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds - const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds - BOOL visible_avatar = isVisible() || mNeedsAnimUpdate; - BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); - BOOL render_name = visible_chat || + + static LLCachedControl<F32> NAME_SHOW_TIME(gSavedSettings, "RenderNameShowTime"); // seconds + static LLCachedControl<F32> FADE_DURATION(gSavedSettings, "RenderNameFadeDuration"); // seconds + static LLCachedControl<bool> use_chat_bubbles(gSavedSettings, "UseChatBubbles"); + + bool visible_avatar = isVisible() || mNeedsAnimUpdate; + bool visible_chat = use_chat_bubbles && (mChats.size() || mTyping); + bool render_name = visible_chat || (visible_avatar && ((sRenderName == RENDER_NAME_ALWAYS) || (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); @@ -3193,10 +3199,11 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) // draw if we're specifically hiding our own name. if (isSelf()) { + static LLCachedControl<bool> render_name_show_self(gSavedSettings, "RenderNameShowSelf"); + static LLCachedControl<S32> name_tag_mode(gSavedSettings, "AvatarNameTagMode"); render_name = render_name && !gAgentCamera.cameraMouselook() - && (visible_chat || (gSavedSettings.getBOOL("RenderNameShowSelf") - && gSavedSettings.getS32("AvatarNameTagMode") )); + && (visible_chat || (render_name_show_self && name_tag_mode)); } if ( !render_name ) @@ -3211,7 +3218,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) return; } - BOOL new_name = FALSE; + bool new_name = FALSE; if (visible_chat != mVisibleChat) { mVisibleChat = visible_chat; @@ -3276,7 +3283,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) idleUpdateNameTagAlpha(new_name, alpha); } -void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) +void LLVOAvatar::idleUpdateNameTagText(bool new_name) { LLNameValue *title = getNVPair("Title"); LLNameValue* firstname = getNVPair("FirstName"); @@ -3586,7 +3593,7 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) mNameText->setPositionAgent(name_position); } -void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) +void LLVOAvatar::idleUpdateNameTagAlpha(bool new_name, F32 alpha) { llassert(mNameText); @@ -3729,7 +3736,8 @@ void LLVOAvatar::updateAppearanceMessageDebugText() { debug_line += llformat(" - cof: %d req: %d rcv:%d", curr_cof_version, last_request_cof_version, last_received_cof_version); - if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure")) + static LLCachedControl<bool> debug_force_failure(gSavedSettings, "DebugForceAppearanceRequestFailure"); + if (debug_force_failure) { debug_line += " FORCING ERRS"; } @@ -5945,7 +5953,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL //} //else { - LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping")); + static LLCachedControl<std::string> ui_snd_string(gSavedSettings, "UISndTyping"); + LLUUID sound_id = LLUUID(ui_snd_string); gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global); } } @@ -6013,7 +6022,7 @@ void LLVOAvatar::resetAnimations() // animations. LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) { - BOOL use_new_walk_run = gSavedSettings.getBOOL("UseNewWalkRun"); + static LLCachedControl<bool> use_new_walk_run(gSavedSettings, "UseNewWalkRun"); LLUUID result = id; // start special case female walk for female avatars @@ -8234,7 +8243,8 @@ BOOL LLVOAvatar::isFullyLoaded() const bool LLVOAvatar::isTooComplex() const { bool too_complex; - bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && gSavedSettings.getBOOL("AlwaysRenderFriends")); + static LLCachedControl<bool> always_render_friends(gSavedSettings, "AlwaysRenderFriends"); + bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends); if (isSelf() || render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER) { @@ -9091,7 +9101,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe // Parse visual params, if any. S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); - bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing + static LLCachedControl<bool> block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams"); + bool drop_visual_params_debug = block_some_avatars && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing if( num_blocks > 1 && !drop_visual_params_debug) { //LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; @@ -9196,10 +9207,12 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32 void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { LL_DEBUGS("Avatar") << "starts" << LL_ENDL; - - bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); + + static LLCachedControl<bool> enable_verbose_dumps(gSavedSettings, "DebugAvatarAppearanceMessage"); + static LLCachedControl<bool> block_avatar_appearance_messages(gSavedSettings, "BlockAvatarAppearanceMessages"); + std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_"; - if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages")) + if (block_avatar_appearance_messages) { LL_WARNS() << "Blocking AvatarAppearance message" << LL_ENDL; return; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index ba67007fa9..3c3decaad6 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -282,9 +282,9 @@ public: void idleUpdateLoadingEffect(); void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); - void idleUpdateNameTagText(BOOL new_name); + void idleUpdateNameTagText(bool new_name); void idleUpdateNameTagPosition(const LLVector3& root_pos_last); - void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha); + void idleUpdateNameTagAlpha(bool new_name, F32 alpha); LLColor4 getNameTagColor(bool is_friend); void clearNameTag(); static void invalidateNameTag(const LLUUID& agent_id); @@ -938,7 +938,7 @@ public: void startTyping() { mTyping = TRUE; mTypingTimer.reset(); } void stopTyping() { mTyping = FALSE; } private: - BOOL mVisibleChat; + bool mVisibleChat; //-------------------------------------------------------------------- // Lip synch morphs diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f18f6b1116..35c415f9db 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -71,6 +71,8 @@ #include "llmediaentry.h" #include "llmediadataclient.h" #include "llmeshrepository.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llagent.h" #include "llviewermediafocus.h" #include "lldatapacker.h" @@ -2993,6 +2995,17 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, } } break; + + case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD: + { + // Media might be blocked, waiting for a file, + // send an empty response to unblock it + const std::vector<std::string> empty_response; + plugin->sendPickFileResponse(empty_response); + + LLNotificationsUtil::add("MediaFileDownloadUnsupported"); + } + break; default: break; diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index b8f1ec35f6..c4d873dd22 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -199,19 +199,16 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url, // find the grid std::string current_grid = LLGridManager::getInstance()->getGridId(); std::transform(current_grid.begin(), current_grid.end(), current_grid.begin(), ::tolower); - if (current_grid == "agni") + if (current_grid == "damballah") { - substitution["GRID"] = "secondlife.com"; - } - else if (current_grid == "damballah") - { - // Staging grid has its own naming scheme. - substitution["GRID"] = "secondlife-staging.com"; - } - else - { - substitution["GRID"] = llformat("%s.lindenlab.com", current_grid.c_str()); - } + // Staging grid has its own naming scheme. + substitution["GRID"] = "secondlife-staging.com"; + } + else + { + substitution["GRID"] = "secondlife.com"; + } + // expand all of the substitution strings and escape the url std::string expanded_url = url; LLStringUtil::format(expanded_url, substitution); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 6746a3a902..82629fd737 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1200,6 +1200,16 @@ public: return; } + if (gDisconnected) + { + return; + } + + if (!LLWorld::instanceExists()) + { + return; + } + if (!input["body"].has("agent-id") || !input["body"].has("sim-ip-and-port") || !input["body"].has("seed-capability")) @@ -1208,8 +1218,13 @@ public: return; } - LLHost sim(input["body"]["sim-ip-and-port"].asString()); - + LLHost sim(input["body"]["sim-ip-and-port"].asString()); + if (sim.isInvalid()) + { + LL_WARNS() << "Got EstablishAgentCommunication with invalid host" << LL_ENDL; + return; + } + LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim); if (!regionp) { @@ -1218,7 +1233,7 @@ public: return; } LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == " - << input["body"]["seed-capability"] << LL_ENDL; + << input["body"]["seed-capability"] << " for region " << regionp->getRegionID() << LL_ENDL; regionp->setSeedCapability(input["body"]["seed-capability"]); } }; diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml index ce5d3556b6..43e8d730cd 100644 --- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml +++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml @@ -73,4 +73,14 @@ name="lst_action" value="Start Gesture" /> </rows> + <rows + name="script_trigger_lbutton" + value="script_trigger_lbutton"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="Interact (Script LMB)" /> + </rows> </contents> diff --git a/indra/newview/skins/default/xui/en/floater_associate_listing.xml b/indra/newview/skins/default/xui/en/floater_associate_listing.xml index e019ed58dd..0f7ed24103 100644 --- a/indra/newview/skins/default/xui/en/floater_associate_listing.xml +++ b/indra/newview/skins/default/xui/en/floater_associate_listing.xml @@ -20,9 +20,10 @@ name="message"> Listing ID: </text> + <!--listing_id is a positive S32--> <line_editor type="string" - length="1" + max_length_bytes="10" follows="top|right" font="SansSerif" height="20" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 7b16374b72..e1f6dde6ff 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2309,6 +2309,7 @@ Please try again later. <notification icon="notifytip.tga" name="LandmarkCreated" + log_to_chat="false" type="notifytip"> You have added "[LANDMARK_NAME]" to your [FOLDER_NAME] folder. </notification> diff --git a/indra/newview/skins/default/xui/en/panel_hide_beacon.xml b/indra/newview/skins/default/xui/en/panel_hide_beacon.xml new file mode 100644 index 0000000000..7cab285f77 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_hide_beacon.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="25" + layout="topleft" + name="panel_hide_beacon" + mouse_opaque="false" + visible="true" + width="133"> + <button + follows="left|bottom" + height="19" + label="Hide beacon" + layout="topleft" + left="10" + name="hide_beacon_btn" + tool_tip="Stop tracking and hide beacon" + top="2" + visible="false" + width="113" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 2ea20570b1..42a34d171a 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -28,7 +28,7 @@ height="15" increment="0.025" initial_value="0.5" - label="Master volume" + label="All volume" label_width="120" layout="topleft" left="0" @@ -386,7 +386,7 @@ left="25" name="voice_chat_settings" width="200" - top_pad="7"> + top_pad="16"> Voice Chat Settings </text> <text diff --git a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml index f5c559fe1d..a3348f28c7 100644 --- a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml +++ b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml @@ -95,7 +95,7 @@ tab_stop="false" name="state_management_buttons_container" visible="false" - width="200"/> + width="350"/> </layout_panel> <layout_panel name="right_toolbar_panel" auto_resize="false" diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml index 2034409111..b4eb1ade94 100644 --- a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml +++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml @@ -19,7 +19,7 @@ height="15" increment="0.025" initial_value="0.5" - label="Master" + label="All" label_width="60" left="10" width="160" diff --git a/indra/test/sync.h b/indra/test/sync.h index ca8b7262d6..bd837cb730 100644 --- a/indra/test/sync.h +++ b/indra/test/sync.h @@ -89,25 +89,26 @@ public: /// suspend until "somebody else" has bumped mCond by n steps void yield(int n=1) { - return yield_until(STRINGIZE("Sync::yield_for(" << n << ") timed out after " - << int(mTimeout.value()) << "ms"), - mCond.get() + n); + return yield_until("Sync::yield_for", n, mCond.get() + n); } /// suspend until "somebody else" has bumped mCond to a specific value void yield_until(int until) { - return yield_until(STRINGIZE("Sync::yield_until(" << until << ") timed out after " - << int(mTimeout.value()) << "ms"), - until); + return yield_until("Sync::yield_until", until, until); } private: - void yield_until(const std::string& desc, int until) + void yield_until(const char* func, int arg, int until) { std::string name(llcoro::logname()); LL_DEBUGS() << name << " yield_until(" << until << ") suspending" << LL_ENDL; - tut::ensure(name + ' ' + desc, mCond.wait_for_equal(mTimeout, until)); + if (! mCond.wait_for_equal(mTimeout, until)) + { + tut::fail(STRINGIZE(name << ' ' << func << '(' << arg << ") timed out after " + << int(mTimeout.value()) << "ms (expected " << until + << ", actual " << mCond.get() << ')')); + } // each time we wake up, bump mCond bump(); } |