diff options
48 files changed, 650 insertions, 247 deletions
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index b5d0c93376..ea9475ed69 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -110,9 +110,8 @@ void LLExperienceCache::initSingleton() LLCoprocedureManager::instance().initializePool("ExpCache"); - LLCoros::instance().launch("LLExperienceCache::idleCoro", - boost::bind(&LLExperienceCache::idleCoro, this)); - + const F32 SECS_BETWEEN_REQUESTS = 0.5f; + mExpirationTimerHandle = LL::Timers::instance().scheduleEvery([this]() { expirationTimer(); return false; }, SECS_BETWEEN_REQUESTS); } void LLExperienceCache::cleanup() @@ -125,6 +124,8 @@ void LLExperienceCache::cleanup() cache_stream << (*this); } sShutdown = true; + + LL::Timers::instance().cancel(mExpirationTimerHandle); } //------------------------------------------------------------------------- @@ -392,30 +393,20 @@ void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t } -void LLExperienceCache::idleCoro() +void LLExperienceCache::expirationTimer() { - const F32 SECS_BETWEEN_REQUESTS = 0.5f; + LL_PROFILE_ZONE_SCOPED; const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; - do + if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) { - if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) - { - eraseExpired(); - } - - if (!mRequestQueue.empty()) - { - requestExperiences(); - } - - llcoro::suspendUntilTimeout(SECS_BETWEEN_REQUESTS); - - } while (!sShutdown); + eraseExpired(); + } - // The coroutine system will likely be shut down by the time we get to this point - // (or at least no further cycling will occur on it since the user has decided to quit.) + if (!mRequestQueue.empty()) + { + requestExperiences(); + } } void LLExperienceCache::erase(const LLUUID& key) diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 81e904107f..b10c24efe4 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -30,10 +30,13 @@ #define LL_LLEXPERIENCECACHE_H #include "linden_common.h" -#include "llsingleton.h" + +#include "llcallbacklist.h" // LL::Timers::handle_t +#include "llcorehttputil.h" #include "llframetimer.h" +#include "llsingleton.h" #include "llsd.h" -#include "llcorehttputil.h" + #include <boost/signals2.hpp> #include <boost/function.hpp> @@ -144,7 +147,9 @@ private: std::string mCacheFileName; static bool sShutdown; // control for coroutines, they exist out of LLExperienceCache's scope, so they need a static control - void idleCoro(); + LL::Timers::handle_t mExpirationTimerHandle; + void expirationTimer(); + void eraseExpired(); void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); void requestExperiences(); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 66b274c33f..c0abba4358 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -122,6 +122,7 @@ LLLineEditor::Params::Params() LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) : LLUICtrl(p), + mDefaultText(p.default_text), mMaxLengthBytes(p.max_length.bytes), mMaxLengthChars(p.max_length.chars), mCursorPos( 0 ), diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 7533f76f1d..65f167bc6b 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -202,6 +202,7 @@ public: void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } + void setDefaultText() { setText(mDefaultText); } void setText(const LLStringExplicit &new_text); const std::string& getText() const override { return mText.getString(); } @@ -347,6 +348,7 @@ protected: LLFontVertexBuffer mFontBufferSelection; LLFontVertexBuffer mFontBufferPostSelection; LLFontVertexBuffer mFontBufferLabel; + std::string mDefaultText; S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes S32 mMaxLengthChars; // Maximum number of characters in the string S32 mCursorPos; // I-beam is just after the mCursorPos-th character. diff --git a/indra/llwindow/llsdl.cpp b/indra/llwindow/llsdl.cpp index 6161bd2972..3f7992a1d7 100644 --- a/indra/llwindow/llsdl.cpp +++ b/indra/llwindow/llsdl.cpp @@ -56,6 +56,7 @@ void init_sdl() std::initializer_list<std::tuple< char const*, char const * > > hintList = { {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"}, + {SDL_HINT_VIDEODRIVER,"wayland,x11"}, {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"}, {SDL_HINT_IME_INTERNAL_EDITING,"1"} }; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 9d736a9970..4793ab4fc7 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -147,7 +147,7 @@ struct wl_proxy* (*ll_wl_proxy_marshal_flags)(struct wl_proxy *proxy, uint32_t o bool loadWaylandClient() { - auto *pSO = dlopen( "libwayland-client.so", RTLD_NOW); + auto *pSO = dlopen( "libwayland-client.so.0", RTLD_NOW); if( !pSO ) return false; @@ -506,6 +506,7 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b /* Save the information for later use */ if ( info.subsystem == SDL_SYSWM_X11 ) { + SDL_SetHint(SDL_HINT_VIDEODRIVER, "x11"); mX11Data.mDisplay = info.info.x11.display; mX11Data.mXWindowID = info.info.x11.window; mServerProtocol = X11; @@ -514,8 +515,12 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b else if ( info.subsystem == SDL_SYSWM_WAYLAND ) { #ifdef LL_WAYLAND - if( !loadWaylandClient() ) + if( !loadWaylandClient() ) { + SDL_SetHint(SDL_HINT_VIDEODRIVER, "x11"); LL_ERRS() << "Failed to load wayland-client.so or grab required functions" << LL_ENDL; + } else { + SDL_SetHint(SDL_HINT_VIDEODRIVER, "wayland"); + } mWaylandData.mSurface = info.info.wl.surface; mServerProtocol = Wayland; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f8294f063f..f349c4aea8 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -403,6 +403,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool // until after some graphics setup. See SL-20177. -Cosmic,2023-09-18 bool mGLReady = false; bool mGotGLBuffer = false; + bool mShuttingDown = false; }; @@ -4576,14 +4577,14 @@ inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() void LLWindowWin32::LLWindowWin32Thread::close() { - if (!mQueue->isClosed()) + LL::ThreadPool::close(); + if (!mShuttingDown) { LL_WARNS() << "Closing window thread without using destroy_window_handler" << LL_ENDL; - LL::ThreadPool::close(); - // Workaround for SL-18721 in case window closes too early and abruptly LLSplashScreen::show(); LLSplashScreen::update("..."); // will be updated later + mShuttingDown = true; } } @@ -4795,6 +4796,8 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy() return; } + mShuttingDown = true; + // Make sure we don't leave a blank toolbar button. // Also hiding window now prevents user from suspending it // via some action (like dragging it around) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ea8d268721..c086399375 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4133,6 +4133,17 @@ <key>Value</key> <array /> </map> + <key>LuaDebugShowSource</key> + <map> + <key>Comment</key> + <string>Show source info in Lua Debug Console output</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>GridStatusRSS</key> <map> <key>Comment</key> @@ -4641,6 +4652,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>MapShowGridCoords</key> + <map> + <key>Comment</key> + <string>Shows/hides the grid coordinates of each region on the world map.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MiniMapAutoCenter</key> <map> <key>Comment</key> diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 14e443ec4e..6c539ade9b 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -32,11 +32,14 @@ #include "llagent.h" #include "llagentcamera.h" +#include "llavatarname.h" +#include "llavatarnamecache.h" #include "llvoavatar.h" #include "llcommandhandler.h" #include "llinventorymodel.h" #include "llslurl.h" #include "llurldispatcher.h" +#include "llviewercontrol.h" #include "llviewernetwork.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" @@ -46,7 +49,8 @@ #include "llsdutil_math.h" #include "lltoolgrab.h" #include "llhudeffectlookat.h" -#include "llagentcamera.h" +#include "llviewercamera.h" +#include "resultset.h" #include <functional> static const F64 PLAY_ANIM_THROTTLE_PERIOD = 1.f; @@ -176,6 +180,32 @@ LLAgentListener::LLAgentListener(LLAgent &agent) "Return information about [\"item_id\"] animation", &LLAgentListener::getAnimationInfo, llsd::map("item_id", LLSD(), "reply", LLSD())); + + add("getID", + "Return your own avatar ID", + &LLAgentListener::getID, + llsd::map("reply", LLSD())); + + add("getNearbyAvatarsList", + "Return result set key [\"result\"] for nearby avatars in a range of [\"dist\"]\n" + "if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n" + "reply contains \"result\" table with \"id\", \"name\", \"global_pos\", \"region_pos\", \"region_id\" fields", + &LLAgentListener::getNearbyAvatarsList, + llsd::map("reply", LLSD())); + + add("getNearbyObjectsList", + "Return result set key [\"result\"] for nearby objects in a range of [\"dist\"]\n" + "if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n" + "reply contains \"result\" table with \"id\", \"global_pos\", \"region_pos\", \"region_id\" fields", + &LLAgentListener::getNearbyObjectsList, + llsd::map("reply", LLSD())); + + add("getAgentScreenPos", + "Return screen position of the [\"avatar_id\"] avatar or own avatar if not specified\n" + "reply contains \"x\", \"y\" coordinates and \"onscreen\" flag to indicate if it's actually in within the current window\n" + "avatar render position is used as the point", + &LLAgentListener::getAgentScreenPos, + llsd::map("reply", LLSD())); } void LLAgentListener::requestTeleport(LLSD const & event_data) const @@ -693,3 +723,126 @@ void LLAgentListener::getAnimationInfo(LLSD const &event_data) "priority", motion->getPriority()); } } + +void LLAgentListener::getID(LLSD const& event_data) +{ + Response response(llsd::map("id", gAgentID), event_data); +} + +struct AvResultSet : public LL::ResultSet +{ + AvResultSet() : LL::ResultSet("nearby_avatars") {} + std::vector<LLVOAvatar*> mAvatars; + + int getLength() const override { return narrow(mAvatars.size()); } + LLSD getSingle(int index) const override + { + auto av = mAvatars[index]; + LLAvatarName av_name; + LLAvatarNameCache::get(av->getID(), &av_name); + LLVector3 region_pos = av->getCharacterPosition(); + return llsd::map("id", av->getID(), + "global_pos", ll_sd_from_vector3d(av->getPosGlobalFromAgent(region_pos)), + "region_pos", ll_sd_from_vector3(region_pos), + "name", av_name.getUserName(), + "region_id", av->getRegion()->getRegionID()); + } +}; + +struct ObjResultSet : public LL::ResultSet +{ + ObjResultSet() : LL::ResultSet("nearby_objects") {} + std::vector<LLViewerObject*> mObjects; + + int getLength() const override { return narrow(mObjects.size()); } + LLSD getSingle(int index) const override + { + auto obj = mObjects[index]; + return llsd::map("id", obj->getID(), + "global_pos", ll_sd_from_vector3d(obj->getPositionGlobal()), + "region_pos", ll_sd_from_vector3(obj->getPositionRegion()), + "region_id", obj->getRegion()->getRegionID()); + } +}; + + +F32 get_search_radius(LLSD const& event_data) +{ + static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64); + F32 dist = render_far_clip; + if (event_data.has("dist")) + { + dist = llclamp((F32)event_data["dist"].asReal(), 1, 512); + } + return dist * dist; +} + +void LLAgentListener::getNearbyAvatarsList(LLSD const& event_data) +{ + Response response(LLSD(), event_data); + auto avresult = new AvResultSet; + + F32 radius = get_search_radius(event_data); + LLVector3d agent_pos = gAgent.getPositionGlobal(); + for (LLCharacter* character : LLCharacter::sInstances) + { + LLVOAvatar* avatar = (LLVOAvatar*)character; + if (!avatar->isDead() && !avatar->isControlAvatar() && !avatar->isSelf()) + { + if ((dist_vec_squared(avatar->getPositionGlobal(), agent_pos) <= radius)) + { + avresult->mAvatars.push_back(avatar); + } + } + } + response["result"] = avresult->getKeyLength(); +} + +void LLAgentListener::getNearbyObjectsList(LLSD const& event_data) +{ + Response response(LLSD(), event_data); + auto objresult = new ObjResultSet; + + F32 radius = get_search_radius(event_data); + S32 num_objects = gObjectList.getNumObjects(); + LLVector3d agent_pos = gAgent.getPositionGlobal(); + for (S32 i = 0; i < num_objects; ++i) + { + LLViewerObject* object = gObjectList.getObject(i); + if (object && object->getVolume() && !object->isAttachment()) + { + if ((dist_vec_squared(object->getPositionGlobal(), agent_pos) <= radius)) + { + objresult->mObjects.push_back(object); + } + } + } + response["result"] = objresult->getKeyLength(); +} + +void LLAgentListener::getAgentScreenPos(LLSD const& event_data) +{ + Response response(LLSD(), event_data); + LLVector3 render_pos; + if (event_data.has("avatar_id") && (event_data["avatar_id"] != gAgentID)) + { + LLUUID avatar_id(event_data["avatar_id"]); + for (LLCharacter* character : LLCharacter::sInstances) + { + LLVOAvatar* avatar = (LLVOAvatar*)character; + if (!avatar->isDead() && (avatar->getID() == avatar_id)) + { + render_pos = avatar->getRenderPosition(); + break; + } + } + } + else if (gAgentAvatarp.notNull() && gAgentAvatarp->isValid()) + { + render_pos = gAgentAvatarp->getRenderPosition(); + } + LLCoordGL screen_pos; + response["onscreen"] = LLViewerCamera::getInstance()->projectPosAgentToScreen(render_pos, screen_pos, false); + response["x"] = screen_pos.mX; + response["y"] = screen_pos.mY; +} diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index 05724ff443..8801c9f7ea 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -67,6 +67,11 @@ private: void stopAnimation(LLSD const &event_data); void getAnimationInfo(LLSD const &event_data); + void getID(LLSD const& event_data); + void getNearbyAvatarsList(LLSD const& event_data); + void getNearbyObjectsList(LLSD const& event_data); + void getAgentScreenPos(LLSD const& event_data); + LLViewerObject * findObjectClosestTo( const LLVector3 & position, bool sit_target = false ) const; private: diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 6f6b89ea81..aff959d279 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -285,25 +285,18 @@ void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids, const LLUUID& floate make_ui_sound("UISndStartIM"); } -/* AD *TODO: Is this function needed any more? - I fixed it a bit(added check for canCall), but it appears that it is not used - anywhere. Maybe it should be removed? // static -bool LLAvatarActions::isCalling(const LLUUID &id) +bool LLAvatarActions::canCall() { - if (id.isNull() || !canCall()) - { - return false; - } - - LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id); - return (LLIMModel::getInstance()->findIMSession(session_id) != NULL); -}*/ + LLVoiceClient* voice_client = LLVoiceClient::getInstance(); + return voice_client->voiceEnabled() && voice_client->isVoiceWorking(); +} -//static -bool LLAvatarActions::canCall() +// static +bool LLAvatarActions::canCallTo(const LLUUID& id) { - return LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); + LLVoiceClient* voice_client = LLVoiceClient::getInstance(); + return voice_client->voiceEnabled() && voice_client->isVoiceWorking() && voice_client->getVoiceEnabled(id); } // static diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 1f5a42ed22..6f469e96ce 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -172,18 +172,15 @@ public: static bool canBlock(const LLUUID& id); /** - * Return true if the avatar is in a P2P voice call with a given user + * @return true if voice calls are available */ - /* AD *TODO: Is this function needed any more? - I fixed it a bit(added check for canCall), but it appears that it is not used - anywhere. Maybe it should be removed? - static bool isCalling(const LLUUID &id);*/ + static bool canCall(); /** * @return true if call to the resident can be made */ + static bool canCallTo(const LLUUID& id); - static bool canCall(); /** * Invite avatar to a group. */ diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index d56e6cdf20..2a4f1ddd12 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -56,7 +56,7 @@ LLFloaterBump::LLFloaterBump(const LLSD& key) mCommitCallbackRegistrar.add("ShowAgentProfile", { boost::bind(&LLFloaterBump::showProfile, this), cb_info::UNTRUSTED_THROTTLE }); mCommitCallbackRegistrar.add("Avatar.InviteToGroup", { boost::bind(&LLFloaterBump::inviteToGroup, this), cb_info::UNTRUSTED_THROTTLE }); mCommitCallbackRegistrar.add("Avatar.Call", { boost::bind(&LLFloaterBump::startCall, this), cb_info::UNTRUSTED_BLOCK }); - mEnableCallbackRegistrar.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall)); + mEnableCallbackRegistrar.add("Avatar.EnableCall", { boost::bind(&LLFloaterBump::canCall, this), cb_info::UNTRUSTED_BLOCK }); mCommitCallbackRegistrar.add("Avatar.AddFriend", { boost::bind(&LLFloaterBump::addFriend, this), cb_info::UNTRUSTED_THROTTLE }); mEnableCallbackRegistrar.add("Avatar.EnableAddFriend", boost::bind(&LLFloaterBump::enableAddFriend, this)); mCommitCallbackRegistrar.add("Avatar.Mute", { boost::bind(&LLFloaterBump::muteAvatar, this), cb_info::UNTRUSTED_BLOCK }); @@ -214,6 +214,11 @@ void LLFloaterBump::startCall() LLAvatarActions::startCall(mItemUUID); } +bool LLFloaterBump::canCall() +{ + return LLAvatarActions::canCallTo(mItemUUID); +} + void LLFloaterBump::reportAbuse() { LLFloaterReporter::showFromAvatar(mItemUUID, "av_name"); diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index 53e730d73f..48d6f7e33e 100644 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -52,6 +52,7 @@ public: void startIM(); void startCall(); + bool canCall(); void reportAbuse(); void showProfile(); void addFriend(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 1e2d790cfc..ed24a8af57 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1592,15 +1592,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v } else if ("can_call" == item) { + if (is_single_select) + { + return LLAvatarActions::canCallTo(single_id); + } return LLAvatarActions::canCall(); } else if ("can_open_voice_conversation" == item) { - return is_single_select && LLAvatarActions::canCall(); - } - else if ("can_open_voice_conversation" == item) - { - return is_single_select && LLAvatarActions::canCall(); + return is_single_select && LLAvatarActions::canCallTo(single_id); } else if ("can_zoom_in" == item) { diff --git a/indra/newview/llfloaterluadebug.cpp b/indra/newview/llfloaterluadebug.cpp index 06877df816..7a7824c7e6 100644 --- a/indra/newview/llfloaterluadebug.cpp +++ b/indra/newview/llfloaterluadebug.cpp @@ -58,7 +58,9 @@ bool LLFloaterLUADebug::postBuild() .listen("LLFloaterLUADebug", [mResultOutput=mResultOutput](const LLSD& data) { - mResultOutput->pasteTextWithLinebreaks(data.asString()); + LLCachedControl<bool> show_source_info(gSavedSettings, "LuaDebugShowSource", false); + std::string source_info = show_source_info ? data["source_info"].asString() : ""; + mResultOutput->pasteTextWithLinebreaks(stringize(data["level"].asString(), source_info, data["msg"].asString())); mResultOutput->addLineBreakChar(true); return false; }); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index df4acfac5e..ac3e942e15 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -504,6 +504,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid)); panel->setCtrlsEnabled(allow_modify); + panel->getChild<LLLineEditor>("estate_id")->setValue((S32)region_info.mEstateID); + + if (region) + { + panel->getChild<LLLineEditor>("grid_position_x")->setValue((S32)(region->getOriginGlobal()[VX] / 256)); + panel->getChild<LLLineEditor>("grid_position_y")->setValue((S32)(region->getOriginGlobal()[VY] / 256)); + } + else + { + panel->getChild<LLLineEditor>("grid_position_x")->setDefaultText(); + panel->getChild<LLLineEditor>("grid_position_y")->setDefaultText(); + } // DEBUG PANEL panel = tab->getChild<LLPanel>("Debug"); @@ -863,6 +875,9 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region, ERefres getChildView("apply_btn")->setEnabled(false); getChildView("access_text")->setEnabled(allow_modify); // getChildView("access_combo")->setEnabled(allow_modify); + getChildView("estate_id")->setEnabled(false); + getChildView("grid_position_x")->setEnabled(false); + getChildView("grid_position_y")->setEnabled(false); // now set in processRegionInfo for teen grid detection getChildView("kick_btn")->setEnabled(allow_modify); getChildView("kick_all_btn")->setEnabled(allow_modify); diff --git a/indra/newview/llinventorylistener.cpp b/indra/newview/llinventorylistener.cpp index 79726c3e0b..88b07c0b0b 100644 --- a/indra/newview/llinventorylistener.cpp +++ b/indra/newview/llinventorylistener.cpp @@ -116,7 +116,8 @@ struct CatResultSet: public LL::ResultSet LLSD getSingle(int index) const override { auto cat = mCategories[index]; - return llsd::map("name", cat->getName(), + return llsd::map("id", cat->getUUID(), + "name", cat->getName(), "parent_id", cat->getParentUUID(), "type", LLFolderType::lookup(cat->getPreferredType())); } @@ -133,7 +134,8 @@ struct ItemResultSet: public LL::ResultSet LLSD getSingle(int index) const override { auto item = mItems[index]; - return llsd::map("name", item->getName(), + return llsd::map("id", item->getUUID(), + "name", item->getName(), "parent_id", item->getParentUUID(), "desc", item->getDescription(), "inv_type", LLInventoryType::lookup(item->getInventoryType()), diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp index 7fe5c1ece0..4a65276384 100644 --- a/indra/newview/llluamanager.cpp +++ b/indra/newview/llluamanager.cpp @@ -72,9 +72,10 @@ std::string lua_print_msg(lua_State* L, std::string_view level) lluau_checkstack(L, 2); luaL_where(L, 1); // start with the 'where' info at the top of the stack - std::ostringstream out; - out << lua_tostring(L, -1); + std::string source_info{ lua_tostring(L, -1) }; lua_pop(L, 1); + + std::ostringstream out; const char* sep = ""; // 'where' info ends with ": " // now iterate over arbitrary args, calling Lua tostring() on each and // concatenating with separators @@ -101,10 +102,10 @@ std::string lua_print_msg(lua_State* L, std::string_view level) // capture message string std::string msg{ out.str() }; // put message out there for any interested party (*koff* LLFloaterLUADebug *koff*) - LLEventPumps::instance().obtain("lua output").post(stringize(level, ": ", msg)); + LLEventPumps::instance().obtain("lua output").post(llsd::map("msg", msg, "level", stringize(level, ": "), "source_info", source_info)); llcoro::suspend(); - return msg; + return source_info + msg; } lua_function(print_debug, "print_debug(args...): DEBUG level logging") diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 2086706bf8..5c54a3fc27 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -754,8 +754,6 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) resetData(); - LLUUID avatar_id = getAvatarId(); - bool own_profile = getSelfProfile(); mGroupList->setShowNone(!own_profile); @@ -793,7 +791,6 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) if (!own_profile) { - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); updateOnlineStatus(); fillRightsData(); } @@ -1214,17 +1211,6 @@ void LLPanelProfileSecondLife::changed(U32 mask) } } -// virtual, called by LLVoiceClient -void LLPanelProfileSecondLife::onChange(EStatusType status, const LLSD& channelInfo, bool proximal) -{ - if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) - { - return; - } - - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : true); -} - void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) { if (avatar_id.notNull()) @@ -1502,7 +1488,7 @@ bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) } else if (item_name == "voice_call") { - return mVoiceStatus; + return LLAvatarActions::canCallTo(agent_id); } else if (item_name == "chat_history") { diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index c207a4162a..ba00e12441 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -33,7 +33,6 @@ #include "llpanel.h" #include "llpanelavatar.h" #include "llmediactrl.h" -#include "llvoiceclient.h" // class LLPanelProfileClassifieds; // class LLTabContainer; @@ -70,7 +69,6 @@ class LLViewerFetchedTexture; class LLPanelProfileSecondLife : public LLPanelProfilePropertiesProcessorTab , public LLFriendObserver - , public LLVoiceClientStatusObserver { public: LLPanelProfileSecondLife(); @@ -89,10 +87,6 @@ public: */ void changed(U32 mask) override; - // Implements LLVoiceClientStatusObserver::onChange() to enable the call - // button when voice is available - void onChange(EStatusType status, const LLSD& channelInfo, bool proximal) override; - void setAvatarId(const LLUUID& avatar_id) override; bool postBuild() override; @@ -203,7 +197,6 @@ private: LLHandle<LLFloater> mFloaterTexturePickerHandle; bool mHasUnsavedDescriptionChanges; - bool mVoiceStatus; bool mWaitingForImageUpload; bool mAllowPublish; bool mHideAge; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 1f4502323c..cb741e4af9 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -79,6 +79,7 @@ #include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llviewershadermgr.h" +#include "llviewerstats.h" #include "llviewertexturelist.h" #include "llviewerwindow.h" #include "llvoavatarself.h" @@ -1085,6 +1086,9 @@ void getProfileStatsContext(boost::json::object& stats) context.emplace("parcelid", parcel->getLocalID()); } context.emplace("time", LLDate::now().toHTTPDateString("%Y-%m-%dT%H:%M:%S")); + + // supplement with stats packet + stats.emplace("stats", LlsdToJson(capture_viewer_stats(true))); } std::string getProfileStatsFilename() diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 39213569a5..68c38c3692 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7808,15 +7808,29 @@ class LLAvatarSendIM : public view_listener_t class LLAvatarCall : public view_listener_t { + static LLVOAvatar* findAvatar() + { + return find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + bool handleEvent(const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) + if (LLVOAvatar* avatar = findAvatar()) { LLAvatarActions::startCall(avatar->getID()); } return true; } + +public: + static bool isAvailable() + { + if (LLVOAvatar* avatar = findAvatar()) + { + return LLAvatarActions::canCallTo(avatar->getID()); + } + return LLAvatarActions::canCall(); + } }; namespace @@ -10075,7 +10089,7 @@ void initialize_menus() registrar.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector)); view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM"); view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call", cb_info::UNTRUSTED_BLOCK); - enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall)); + enable.add("Avatar.EnableCall", boost::bind(&LLAvatarCall::isAvailable)); view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse", cb_info::UNTRUSTED_THROTTLE); view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks"); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 9d4c072909..a4b06b1e1a 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -67,6 +67,7 @@ #include "lluiusage.h" #include "lltranslate.h" #include "llluamanager.h" +#include "scope_exit.h" // "Minimal Vulkan" to get max API Version @@ -510,7 +511,6 @@ void send_viewer_stats(bool include_preferences) return; } - LLSD body; std::string url = gAgent.getRegion()->getCapability("ViewerStats"); if (url.empty()) { @@ -518,8 +518,18 @@ void send_viewer_stats(bool include_preferences) return; } - LLViewerStats::instance().getRecording().pause(); + LLSD body = capture_viewer_stats(include_preferences); + LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, + "Statistics posted to sim", "Failed to post statistics to sim"); +} + +LLSD capture_viewer_stats(bool include_preferences) +{ + LLViewerStats& vstats{ LLViewerStats::instance() }; + vstats.getRecording().pause(); + LL::scope_exit cleanup([&vstats]{ vstats.getRecording().resume(); }); + LLSD body; LLSD &agent = body["agent"]; time_t ltime; @@ -791,10 +801,7 @@ void send_viewer_stats(bool include_preferences) body["session_id"] = gAgentSessionID; LLViewerStats::getInstance()->addToMessage(body); - - LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, - "Statistics posted to sim", "Failed to post statistics to sim"); - LLViewerStats::instance().getRecording().resume(); + return body; } LLTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name) diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 8aed1c537e..dd66fee436 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -281,6 +281,7 @@ static const F32 SEND_STATS_PERIOD = 300.0f; // The following are from (older?) statistics code found in appviewer. void update_statistics(); +LLSD capture_viewer_stats(bool include_preferences); void send_viewer_stats(bool include_preferences); void update_texture_time(); diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp index 52f413792a..45b4da0aac 100644 --- a/indra/newview/llviewerwindowlistener.cpp +++ b/indra/newview/llviewerwindowlistener.cpp @@ -35,6 +35,7 @@ // std headers // external library headers // other Linden headers +#include "llcallbacklist.h" #include "llviewerwindow.h" LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow): @@ -46,8 +47,7 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow): add("saveSnapshot", "Save screenshot: [\"filename\"] (extension may be specified: bmp, jpeg, png)\n" "[\"width\"], [\"height\"], [\"showui\"], [\"showhud\"], [\"rebuild\"], [\"type\"]\n" - "type: \"COLOR\", \"DEPTH\"\n" - "Post on [\"reply\"] an event containing [\"result\"]", + "type: \"COLOR\", \"DEPTH\"\n", &LLViewerWindowListener::saveSnapshot, llsd::map("filename", LLSD::String(), "reply", LLSD())); add("requestReshape", @@ -57,8 +57,6 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow): void LLViewerWindowListener::saveSnapshot(const LLSD& event) const { - Response response(LLSD(), event); - typedef std::map<LLSD::String, LLSnapshotModel::ESnapshotLayerType> TypeMap; TypeMap types; #define tp(name) types[#name] = LLSnapshotModel::SNAPSHOT_TYPE_##name @@ -88,7 +86,8 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const TypeMap::const_iterator found = types.find(event["type"]); if (found == types.end()) { - return response.error(stringize("Unrecognized type ", std::quoted(event["type"].asString()), " [\"COLOR\"] or [\"DEPTH\"] is expected.")); + sendReply(llsd::map("error", stringize("Unrecognized type ", std::quoted(event["type"].asString()), " [\"COLOR\"] or [\"DEPTH\"] is expected.")), event); + return; } type = found->second; } @@ -96,7 +95,8 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const std::string filename(event["filename"]); if (filename.empty()) { - return response.error(stringize("File path is empty.")); + sendReply(llsd::map("error", stringize("File path is empty.")), event); + return; } LLSnapshotModel::ESnapshotFormat format(LLSnapshotModel::SNAPSHOT_FORMAT_BMP); @@ -115,9 +115,13 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const } else if (ext != "bmp") { - return response.error(stringize("Unrecognized format. [\"png\"], [\"jpeg\"] or [\"bmp\"] is expected.")); + sendReply(llsd::map("error", stringize("Unrecognized format. [\"png\"], [\"jpeg\"] or [\"bmp\"] is expected.")), event); + return; } - response["result"] = mViewerWindow->saveSnapshot(filename, width, height, showui, showhud, rebuild, type, format); + // take snapshot on the main coro + doOnIdleOneTime([this, event, filename, width, height, showui, showhud, rebuild, type, format]() + { sendReply(llsd::map("result", mViewerWindow->saveSnapshot(filename, width, height, showui, showhud, rebuild, type, format)), event); }); + } void LLViewerWindowListener::requestReshape(LLSD const & event_data) const diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 4659fa5f71..bd0419f4dd 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -6637,13 +6637,13 @@ void LLVivoxVoiceClient::expireVoiceFonts() } } - LLSD args; - args["URL"] = LLTrans::getString("voice_morphing_url"); - args["PREMIUM_URL"] = LLTrans::getString("premium_voice_morphing_url"); - // Give a notification if any voice fonts have expired. if (have_expired) { + LLSD args; + args["URL"] = LLTrans::getString("voice_morphing_url"); + args["PREMIUM_URL"] = LLTrans::getString("premium_voice_morphing_url"); + if (expired_in_use) { LLNotificationsUtil::add("VoiceEffectsExpiredInUse", args); diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 7161f5af5e..dbeccb51d8 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -218,7 +218,7 @@ LLWebRTCVoiceClient::LLWebRTCVoiceClient() : mAvatarNameCacheConnection(), mIsInTuningMode(false), mIsProcessingChannels(false), - mIsCoroutineActive(false), + mIsTimerActive(false), mWebRTCPump("WebRTCClientPump"), mWebRTCDeviceInterface(nullptr) { @@ -295,6 +295,20 @@ void LLWebRTCVoiceClient::cleanUp() mNeighboringRegions.clear(); sessionState::for_each(boost::bind(predShutdownSession, _1)); LL_DEBUGS("Voice") << "Exiting" << LL_ENDL; + stopTimer(); +} + +void LLWebRTCVoiceClient::stopTimer() +{ + if (mIsTimerActive) + { + LLMuteList::instanceExists(); + { + LLMuteList::getInstance()->removeObserver(this); + } + mIsTimerActive = false; + LL::Timers::instance().cancel(mVoiceTimerHandle); + } } void LLWebRTCVoiceClient::LogMessage(llwebrtc::LLWebRTCLogCallback::LogLevel level, const std::string& message) @@ -443,8 +457,7 @@ void LLWebRTCVoiceClient::removeObserver(LLFriendObserver *observer) //--------------------------------------------------- // Primary voice loop. -// This voice loop is called every 100ms plus the time it -// takes to process the various functions called in the loop +// This voice loop is called every 100ms // The loop does the following: // * gates whether we do channel processing depending on // whether we're running a WebRTC voice channel or @@ -456,118 +469,102 @@ void LLWebRTCVoiceClient::removeObserver(LLFriendObserver *observer) // connection to various voice channels. // * Sends updates to the voice server when this agent's // voice levels, or positions have changed. -void LLWebRTCVoiceClient::voiceConnectionCoro() +void LLWebRTCVoiceClient::connectionTimer() { - LL_DEBUGS("Voice") << "starting" << LL_ENDL; - mIsCoroutineActive = true; - LLCoros::set_consuming(true); + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE; try { - LLMuteList::getInstance()->addObserver(this); - while (!sShuttingDown) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE("voiceConnectionCoroLoop") - // TODO: Doing some measurement and calculation here, - // we could reduce the timeout to take into account the - // time spent on the previous loop to have the loop - // cycle at exactly 100ms, instead of 100ms + loop - // execution time. - // Could help with voice updates making for smoother - // voice when we're busy. - llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS); - if (sShuttingDown) return; // 'this' migh already be invalid - bool voiceEnabled = mVoiceEnabled; - - if (!isAgentAvatarValid()) + bool voiceEnabled = mVoiceEnabled; + + if (!isAgentAvatarValid()) + { + if (sShuttingDown) { - continue; + cleanUp(); } + return; + } - LLViewerRegion *regionp = gAgent.getRegion(); - if (!regionp) + LLViewerRegion* regionp = gAgent.getRegion(); + if (!regionp) + { + if (sShuttingDown) { - continue; + cleanUp(); } + return; + } - if (!mProcessChannels) + if (!mProcessChannels) + { + // we've switched away from webrtc voice, so shut all channels down. + // leave channel can be called again and again without adverse effects. + // it merely tells channels to shut down if they're not already doing so. + leaveChannel(false); + } + else if (inSpatialChannel()) + { + bool useEstateVoice = true; + // add session for region or parcel voice. + if (!regionp || regionp->getRegionID().isNull()) { - // we've switched away from webrtc voice, so shut all channels down. - // leave channel can be called again and again without adverse effects. - // it merely tells channels to shut down if they're not already doing so. - leaveChannel(false); + // no region, no voice. + return; } - else if (inSpatialChannel()) - { - bool useEstateVoice = true; - // add session for region or parcel voice. - if (!regionp || regionp->getRegionID().isNull()) - { - // no region, no voice. - continue; - } - voiceEnabled = voiceEnabled && regionp->isVoiceEnabled(); + voiceEnabled = voiceEnabled && regionp->isVoiceEnabled(); - if (voiceEnabled) + if (voiceEnabled) + { + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + // check to see if parcel changed. + if (parcel && parcel->getLocalID() != INVALID_PARCEL_ID) { - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - // check to see if parcel changed. - if (parcel && parcel->getLocalID() != INVALID_PARCEL_ID) + // parcel voice + if (!parcel->getParcelFlagAllowVoice()) { - // parcel voice - if (!parcel->getParcelFlagAllowVoice()) - { - voiceEnabled = false; - } - else if (!parcel->getParcelFlagUseEstateVoiceChannel()) - { - // use the parcel-specific voice channel. - S32 parcel_local_id = parcel->getLocalID(); - std::string channelID = regionp->getRegionID().asString() + "-" + std::to_string(parcel->getLocalID()); - - useEstateVoice = false; - if (!inOrJoiningChannel(channelID)) - { - startParcelSession(channelID, parcel_local_id); - } - } + voiceEnabled = false; } - if (voiceEnabled && useEstateVoice && !inEstateChannel()) + else if (!parcel->getParcelFlagUseEstateVoiceChannel()) { - // estate voice - startEstateSession(); + // use the parcel-specific voice channel. + S32 parcel_local_id = parcel->getLocalID(); + std::string channelID = regionp->getRegionID().asString() + "-" + std::to_string(parcel->getLocalID()); + + useEstateVoice = false; + if (!inOrJoiningChannel(channelID)) + { + startParcelSession(channelID, parcel_local_id); + } } } - if (!voiceEnabled) - { - // voice is disabled, so leave and disable PTT - leaveChannel(true); - } - else + if (voiceEnabled && useEstateVoice && !inEstateChannel()) { - // we're in spatial voice, and voice is enabled, so determine positions in order - // to send position updates. - updatePosition(); + // estate voice + startEstateSession(); } } - LL::WorkQueue::postMaybe(mMainQueue, - [=] { - if (sShuttingDown) - { - return; - } - sessionState::processSessionStates(); - if (mProcessChannels && voiceEnabled && !mHidden) - { - sendPositionUpdate(false); - updateOwnVolume(); - } - }); + if (!voiceEnabled) + { + // voice is disabled, so leave and disable PTT + leaveChannel(true); + } + else + { + // we're in spatial voice, and voice is enabled, so determine positions in order + // to send position updates. + updatePosition(); + } + } + if (!sShuttingDown) + { + sessionState::processSessionStates(); + if (mProcessChannels && voiceEnabled && !mHidden) + { + sendPositionUpdate(false); + updateOwnVolume(); + } } - } - catch (const LLCoros::Stop&) - { - LL_DEBUGS("LLWebRTCVoiceClient") << "Received a shutdown exception" << LL_ENDL; } catch (const LLContinueError&) { @@ -582,7 +579,10 @@ void LLWebRTCVoiceClient::voiceConnectionCoro() throw; } - cleanUp(); + if (sShuttingDown) + { + cleanUp(); + } } // For spatial, determine which neighboring regions to connect to @@ -1340,7 +1340,7 @@ bool LLWebRTCVoiceClient::isVoiceWorking() const // webrtc is working if the coroutine is active in the case of // webrtc. WebRTC doesn't need to connect to a secondary process // or a login server to become active. - return mIsCoroutineActive; + return mIsTimerActive; } // Returns true if calling back the session URI after the session has closed is possible. @@ -1552,7 +1552,7 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled) LL_DEBUGS("Voice") << "( " << (enabled ? "enabled" : "disabled") << " )" << " was "<< (mVoiceEnabled ? "enabled" : "disabled") - << " coro "<< (mIsCoroutineActive ? "active" : "inactive") + << " coro "<< (mIsTimerActive ? "active" : "inactive") << LL_ENDL; if (enabled != mVoiceEnabled) @@ -1569,10 +1569,12 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled) status = LLVoiceClientStatusObserver::STATUS_VOICE_ENABLED; mSpatialCoordsDirty = true; updatePosition(); - if (!mIsCoroutineActive) + if (!mIsTimerActive) { - LLCoros::instance().launch("LLWebRTCVoiceClient::voiceConnectionCoro", - boost::bind(&LLWebRTCVoiceClient::voiceConnectionCoro, LLWebRTCVoiceClient::getInstance())); + LL_DEBUGS("Voice") << "Starting" << LL_ENDL; + mIsTimerActive = true; + LLMuteList::getInstance()->addObserver(this); + mVoiceTimerHandle = LL::Timers::instance().scheduleEvery([this]() { connectionTimer(); return false; }, UPDATE_THROTTLE_SECONDS); } else { diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index ff82d2739d..930018b123 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -30,6 +30,7 @@ class LLWebRTCProtocolParser; #include "lliopipe.h" #include "llpumpio.h" +#include "llcallbacklist.h" #include "llchainio.h" #include "lliosocket.h" #include "v3math.h" @@ -447,12 +448,15 @@ private: // Coroutine support methods //--- - void voiceConnectionCoro(); + void connectionTimer(); //--- /// Clean up objects created during a voice session. void cleanUp(); + // stop state machine + void stopTimer(); + LL::WorkQueue::weak_t mMainQueue; bool mTuningMode; @@ -534,7 +538,8 @@ private: bool mIsInTuningMode; bool mIsProcessingChannels; - bool mIsCoroutineActive; + bool mIsTimerActive; + LL::Timers::handle_t mVoiceTimerHandle; // These variables can last longer than WebRTC in coroutines so we need them as static static bool sShuttingDown; diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 5951d6a93a..2fd45337fc 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -118,6 +118,7 @@ LLVector3d LLSimInfo::getGlobalOrigin() const { return from_region_handle(mHandle); } + LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const { LLVector3d sim_origin = from_region_handle(mHandle); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 6b2bd3e6fb..1be6a6cfff 100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -517,26 +517,38 @@ void LLWorldMapView::draw() // Draw the region name in the lower left corner if (mMapScale >= DRAW_TEXT_THRESHOLD) { - std::string mesg; + static LLCachedControl<bool> print_coords(gSavedSettings, "MapShowGridCoords"); + static LLFontGL* font = LLFontGL::getFontSansSerifSmallBold(); + + auto print = [&](std::string text, F32 x, F32 y, bool use_ellipses) + { + font->renderUTF8(text, 0, + (F32)llfloor(left + x), (F32)llfloor(bottom + y), + LLColor4::white, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, + S32_MAX, //max_chars + (S32)mMapScale, //max_pixels + NULL, + use_ellipses); + }; + + std::string grid_name = info->getName(); if (info->isDown()) { - mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); + grid_name += " (" + sStringsMap["offline"] + ")"; } - else + + if (print_coords) { - mesg = info->getName(); + print(grid_name, 3, 14, true); + // Obtain and print the grid map coordinates + LLVector3d region_pos = info->getGlobalOrigin(); + std::string grid_coords = llformat("[%.0f, %.0f]", region_pos[VX] / 256, region_pos[VY] / 256); + print(grid_coords, 3, 2, false); } - if (!mesg.empty()) + else { - LLFontGL::getFontSansSerifSmallBold()->renderUTF8( - mesg, 0, - (F32)llfloor(left + 3), (F32)llfloor(bottom + 2), - LLColor4::white, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, - S32_MAX, //max_chars - (S32)mMapScale, //max_pixels - NULL, - /*use_ellipses*/true); + print(grid_name, 3, 2, true); } } } diff --git a/indra/newview/scripts/lua/require/LLAgent.lua b/indra/newview/scripts/lua/require/LLAgent.lua index 4a1132fe7e..6068a916ed 100644 --- a/indra/newview/scripts/lua/require/LLAgent.lua +++ b/indra/newview/scripts/lua/require/LLAgent.lua @@ -1,8 +1,26 @@ local leap = require 'leap' local mapargs = require 'mapargs' +local result_view = require 'result_view' + +local function result(keys) + local result_table = { + result=result_view(keys.result), + -- call result_table:close() to release result sets before garbage + -- collection or script completion + close = function(self) + result_view.close(keys.result[1]) + end + } + -- When the result_table is destroyed, close its result_views. + return LL.setdtor('LLAgent result', result_table, result_table.close) +end local LLAgent = {} +function LLAgent.getID() + return leap.request('LLAgent', {op = 'getID'}).id +end + function LLAgent.getRegionPosition() return leap.request('LLAgent', {op = 'getPosition'}).region end @@ -95,6 +113,33 @@ function LLAgent.requestStand() leap.send('LLAgent', {op = 'requestStand'}) end +-- Get the nearby avatars in a range of provided "dist", +-- if "dist" is not specified, "RenderFarClip" setting is used +-- reply will contain "result" table with following fields: +-- "id", "global_pos", "region_pos", "name", "region_id" +function LLAgent.getNearbyAvatarsList(...) + local args = mapargs('dist', ...) + args.op = 'getNearbyAvatarsList' + return result(leap.request('LLAgent', args)) +end + +-- reply will contain "result" table with following fields: +-- "id", "global_pos", "region_pos", "region_id" +function LLAgent.getNearbyObjectsList(...) + local args = mapargs('dist', ...) + args.op = 'getNearbyObjectsList' + return result(leap.request('LLAgent', args)) +end + +-- Get screen position of your own avatar or any other (if "avatar_id" is specified) +-- reply contains "x", "y" coordinates and "onscreen" flag to indicate if it's actually in within the current window +-- avatar render position is used as the point +function LLAgent.getAgentScreenPos(...) + local args = mapargs('avatar_id', ...) + args.op = 'getAgentScreenPos' + return leap.request('LLAgent', args) +end + -- *************************************************************************** -- Autopilot -- *************************************************************************** diff --git a/indra/newview/scripts/lua/require/UI.lua b/indra/newview/scripts/lua/require/UI.lua index cf2695917e..34f3fb75eb 100644 --- a/indra/newview/scripts/lua/require/UI.lua +++ b/indra/newview/scripts/lua/require/UI.lua @@ -222,8 +222,10 @@ function UI.hideFloater(floater_name) leap.send("LLFloaterReg", {op = "hideInstance", name = floater_name}) end -function UI.toggleFloater(floater_name) - leap.send("LLFloaterReg", {op = "toggleInstance", name = floater_name}) +function UI.toggleFloater(...) + local args = mapargs('name,key', ...) + args.op = 'toggleInstance' + leap.send("LLFloaterReg", args) end function UI.isFloaterVisible(floater_name) diff --git a/indra/newview/scripts/lua/test_LLChatListener.lua b/indra/newview/scripts/lua/test_LLChatListener.lua index 0f269b54e6..fa00b048b2 100644 --- a/indra/newview/scripts/lua/test_LLChatListener.lua +++ b/indra/newview/scripts/lua/test_LLChatListener.lua @@ -1,5 +1,6 @@ -local LLListener = require 'LLListener' +local LLAgent = require 'LLAgent' local LLChat = require 'LLChat' +local LLListener = require 'LLListener' local UI = require 'UI' -- Chat listener script allows to use the following commands in Nearby chat: @@ -23,9 +24,13 @@ function openOrEcho(message) end local listener = LLListener(LLChat.nearbyChatPump) +local agent_id = LLAgent.getID() function listener:handleMessages(event_data) - if string.find(event_data.message, '[LUA]') then + -- ignore messages and commands from other avatars + if event_data.from_id ~= agent_id then + return true + elseif string.find(event_data.message, '[LUA]') then return true elseif event_data.message == 'stop' then LLChat.sendNearby('Closing echo script.') diff --git a/indra/newview/scripts/lua/test_animation.lua b/indra/newview/scripts/lua/test_animation.lua index 37e7254a6c..ae5eabe148 100644 --- a/indra/newview/scripts/lua/test_animation.lua +++ b/indra/newview/scripts/lua/test_animation.lua @@ -7,8 +7,8 @@ animations_id = LLInventory.getBasicFolderID('animatn') anims = LLInventory.collectDescendentsIf{folder_id=animations_id, type="animatn"}.items local anim_ids = {} -for key in pairs(anims) do - table.insert(anim_ids, key) +for _, key in pairs(anims) do + table.insert(anim_ids, {id = key.id, name = key.name}) end if #anim_ids == 0 then @@ -16,17 +16,17 @@ if #anim_ids == 0 then else -- Start playing a random animation math.randomseed(os.time()) - local random_id = anim_ids[math.random(#anim_ids)] - local anim_info = LLAgent.getAnimationInfo(random_id) + local random_anim = anim_ids[math.random(#anim_ids)] + local anim_info = LLAgent.getAnimationInfo(random_anim.id) - print("Starting animation locally: " .. anims[random_id].name) - print("Loop: " .. anim_info.is_loop .. " Joints: " .. anim_info.num_joints .. " Duration " .. tonumber(string.format("%.2f", anim_info.duration))) - LLAgent.playAnimation{item_id=random_id} + print("Starting animation locally: " .. random_anim.name) + print("Loop: " .. tostring(anim_info.is_loop) .. " Joints: " .. anim_info.num_joints .. " Duration " .. tonumber(string.format("%.2f", anim_info.duration))) + LLAgent.playAnimation{item_id=random_anim.id} -- Stop animation after 3 sec if it's looped or longer than 3 sec - if anim_info.is_loop == 1 or anim_info.duration > 3 then + if anim_info.is_loop or anim_info.duration > 3 then LL.sleep(3) print("Stop animation.") - LLAgent.stopAnimation(random_id) + LLAgent.stopAnimation(random_anim.id) end end diff --git a/indra/newview/scripts/lua/test_luafloater_demo.lua b/indra/newview/scripts/lua/test_luafloater_demo.lua index 2158134511..23310c6176 100644 --- a/indra/newview/scripts/lua/test_luafloater_demo.lua +++ b/indra/newview/scripts/lua/test_luafloater_demo.lua @@ -14,7 +14,7 @@ function flt:handleEvents(event_data) end function flt:commit_disable_ctrl(event_data) - self:post({action="set_enabled", ctrl_name="open_btn", value = (1 - event_data.value)}) + self:post({action="set_enabled", ctrl_name="open_btn", value = not event_data.value}) end function flt:commit_title_cmb(event_data) diff --git a/indra/newview/scripts/lua/test_nearby_avatars.lua b/indra/newview/scripts/lua/test_nearby_avatars.lua new file mode 100644 index 0000000000..c7fa686076 --- /dev/null +++ b/indra/newview/scripts/lua/test_nearby_avatars.lua @@ -0,0 +1,25 @@ +inspect = require 'inspect' +LLAgent = require 'LLAgent' + +-- Get the list of nearby avatars and print the info +local nearby_avatars = LLAgent.getNearbyAvatarsList() +if nearby_avatars.result.length == 0 then + print("No avatars nearby") +else + print("Nearby avatars:") + for _, av in pairs(nearby_avatars.result) do + print(av.name ..' ID: ' .. av.id ..' Global pos:' .. inspect(av.global_pos)) + end +end + +-- Get the list of nearby objects in 3m range and print the info +local nearby_objects = LLAgent.getNearbyObjectsList(3) +if nearby_objects.result.length == 0 then + print("No objects nearby") +else + print("Nearby objects:") + local pos={} + for _, obj in pairs(nearby_objects.result) do + print('ID: ' .. obj.id ..' Global pos:' .. inspect(obj.global_pos)) + end +end diff --git a/indra/newview/scripts/lua/test_screen_position.lua b/indra/newview/scripts/lua/test_screen_position.lua new file mode 100644 index 0000000000..94d57339b1 --- /dev/null +++ b/indra/newview/scripts/lua/test_screen_position.lua @@ -0,0 +1,8 @@ +LLAgent = require 'LLAgent' + +local screen_pos = LLAgent.getAgentScreenPos() +if screen_pos.onscreen then + print("Avatar screen coordinates X: " .. screen_pos.x .. " Y: " .. screen_pos.y) +else + print("Avatar is not on the screen") +end diff --git a/indra/newview/scripts/lua/test_toolbars.lua b/indra/newview/scripts/lua/test_toolbars.lua index 7683fca8a3..9cd1043446 100644 --- a/indra/newview/scripts/lua/test_toolbars.lua +++ b/indra/newview/scripts/lua/test_toolbars.lua @@ -20,7 +20,7 @@ if response == 'OK' then UI.removeToolbarBtn(BUTTONS[i]) end end - popup:tip('Toolbars were reshuffled') + UI.popup:tip('Toolbars were reshuffled') else - popup:tip('Canceled') + UI.popup:tip('Canceled') end diff --git a/indra/newview/skins/default/xui/en/floater_lua_debug.xml b/indra/newview/skins/default/xui/en/floater_lua_debug.xml index 15027f1647..5efe1c958a 100644 --- a/indra/newview/skins/default/xui/en/floater_lua_debug.xml +++ b/indra/newview/skins/default/xui/en/floater_lua_debug.xml @@ -25,6 +25,17 @@ width="100"> LUA string: </text> + <check_box + control_name="LuaDebugShowSource" + follows="right|top" + height="15" + label="Show source info" + layout="topleft" + top="10" + right ="-70" + tool_tip="Show source info in Lua Debug Console output" + name="show_script_name" + width="70"/> <line_editor border_style="line" border_thickness="1" diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 5ab0177de6..6883ec1cd0 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -109,7 +109,7 @@ </panel> <panel follows="right|top" - height="126" + height="150" top_pad="4" width="238" left="1" @@ -285,6 +285,29 @@ by owner </text> + <check_box + name="grid_coords_chk" + control_name="MapShowGridCoords" + layout="topleft" + follows="top|right" + top_pad="2" + left="3" + height="16" + width="22" + /> + <text + name="grid_coords_label" + type="string" + layout="topleft" + follows="top|right" + top_delta="2" + left_pad="3" + height="16" + width="220" + halign="left" + length="1" + >Show grid map coordinates</text> + <button follows="top|right" height="22" @@ -455,7 +478,7 @@ <panel follows="right|top|bottom" - height="330" + height="306" top_pad="0" width="238" name="layout_panel_4"> @@ -576,7 +599,7 @@ draw_stripes="false" bg_writeable_color="MouseGray" follows="all" - height="145" + height="121" layout="topleft" left="28" name="search_results" diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index ca6e94397d..53551b2f79 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -156,6 +156,5 @@ mouse_opaque="true" name="speaking_indicator" tool_tip="Voice volume" - visible="true" width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index 7902588598..e0b7f71321 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -91,7 +91,6 @@ left_pad="5" mouse_opaque="true" name="speaking_indicator" - visible="false" width="20" /> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index 1a89d07cbb..48f6580d61 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -34,7 +34,6 @@ mouse_opaque="true" name="chat_zone_indicator" top="6" - visible="true" width="20" /> <button follows="right" diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 6ef1b6e44a..47e1e669d1 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -33,6 +33,28 @@ unknown </text> <text + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + right="-100" + name="estate_id_lbl" + width="80"> + Estate ID: + </text> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + name="estate_id" + enabled="false" + right="-10" + initial_value="unknown" + width="85" /> + <text follows="left|top" font="SansSerif" height="20" @@ -55,6 +77,39 @@ unknown </text> <text + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + right="-100" + name="grid_position_lbl" + width="80"> + Grid Position: + </text> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + right="-55" + name="grid_position_x" + enabled="false" + top_delta="0" + default_text="n/a" + width="40" /> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + right="-10" + name="grid_position_y" + enabled="false" + top_delta="0" + default_text="n/a" + width="40" /> + <text follows="left|top" font="SansSerif" height="20" diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index cf995e5833..180071a321 100644 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -37,6 +37,5 @@ right="-3" mouse_opaque="true" name="speaking_indicator" - visible="true" - width="20" /> + width="20" /> </conversation_view_participant> diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml index 788c733ca8..10e39fa030 100644 --- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml +++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml @@ -10,4 +10,5 @@ image_level_3="VoicePTT_Lvl3" mouse_opaque="false" name="output_monitor" + visible="false" /> diff --git a/indra/newview/skins/default/xui/en/widgets/person_view.xml b/indra/newview/skins/default/xui/en/widgets/person_view.xml index 82dbdf0dab..e07f340be1 100644 --- a/indra/newview/skins/default/xui/en/widgets/person_view.xml +++ b/indra/newview/skins/default/xui/en/widgets/person_view.xml @@ -111,7 +111,6 @@ right="-3" mouse_opaque="true" name="speaking_indicator" - visible="false" width="20" /> </person_view> |