Merge branch 'develop' of https://github.com/secondlife/viewer
# Conflicts: # indra/llui/lltextbase.cpp # indra/newview/llappviewerwin32.cpp # indra/newview/lleventpoll.cppmaster
commit
5e5a3f4102
|
|
@ -97,7 +97,7 @@ jobs:
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
repository: secondlife/build-variables
|
repository: secondlife/build-variables
|
||||||
ref: universal
|
ref: master
|
||||||
path: .build-variables
|
path: .build-variables
|
||||||
|
|
||||||
- name: Checkout master-message-template
|
- name: Checkout master-message-template
|
||||||
|
|
@ -309,7 +309,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Sign and package Windows viewer
|
- name: Sign and package Windows viewer
|
||||||
if: env.AZURE_KEY_VAULT_URI && env.AZURE_CERT_NAME && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET && env.AZURE_TENANT_ID
|
if: env.AZURE_KEY_VAULT_URI && env.AZURE_CERT_NAME && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET && env.AZURE_TENANT_ID
|
||||||
uses: secondlife/viewer-build-util/sign-pkg-windows@v2
|
uses: secondlife/viewer-build-util/sign-pkg-windows@v2.0.4
|
||||||
with:
|
with:
|
||||||
vault_uri: "${{ env.AZURE_KEY_VAULT_URI }}"
|
vault_uri: "${{ env.AZURE_KEY_VAULT_URI }}"
|
||||||
cert_name: "${{ env.AZURE_CERT_NAME }}"
|
cert_name: "${{ env.AZURE_CERT_NAME }}"
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,17 @@ public:
|
||||||
<< childout.peek(0, peeklen) << "..." << LL_ENDL;
|
<< childout.peek(0, peeklen) << "..." << LL_ENDL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle any remaining stderr data (partial lines) the same way as we do
|
||||||
|
// for stdout: log it.
|
||||||
|
LLProcess::ReadPipe& childerr(mChild->getReadPipe(LLProcess::STDERR));
|
||||||
|
if (childerr.size())
|
||||||
|
{
|
||||||
|
LLProcess::ReadPipe::size_type
|
||||||
|
peeklen((std::min)(LLProcess::ReadPipe::size_type(50), childerr.size()));
|
||||||
|
LL_WARNS("LLLeap") << "Final stderr " << childerr.size() << " bytes: "
|
||||||
|
<< childerr.peek(0, peeklen) << "..." << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
// Kill this instance. MUST BE LAST before return!
|
// Kill this instance. MUST BE LAST before return!
|
||||||
delete this;
|
delete this;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -557,11 +557,6 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opj_setup_encoder(encoder, ¶meters, image))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
U32 width_tiles = (rawImageIn.getWidth() >> 6);
|
U32 width_tiles = (rawImageIn.getWidth() >> 6);
|
||||||
U32 height_tiles = (rawImageIn.getHeight() >> 6);
|
U32 height_tiles = (rawImageIn.getHeight() >> 6);
|
||||||
|
|
||||||
|
|
@ -575,6 +570,19 @@ public:
|
||||||
height_tiles = 1;
|
height_tiles = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (width_tiles == 1 || height_tiles == 1)
|
||||||
|
{
|
||||||
|
// Images with either dimension less than 32 need less number of resolutions otherwise they error
|
||||||
|
int min_dim = rawImageIn.getWidth() < rawImageIn.getHeight() ? rawImageIn.getWidth() : rawImageIn.getHeight();
|
||||||
|
int max_res = 1 + (int)floor(log2(min_dim));
|
||||||
|
parameters.numresolution = max_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opj_setup_encoder(encoder, ¶meters, image))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
U32 tile_count = width_tiles * height_tiles;
|
U32 tile_count = width_tiles * height_tiles;
|
||||||
U32 data_size_guess = tile_count * TILE_SIZE;
|
U32 data_size_guess = tile_count * TILE_SIZE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1604,6 +1604,7 @@ bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
|
||||||
&& ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible
|
&& ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible
|
||||||
!hide_folder_menu)
|
!hide_folder_menu)
|
||||||
{
|
{
|
||||||
|
LL_INFOS("Inventory") << "Opening inventory menu from path: " << getPathname() << LL_ENDL;
|
||||||
if (mCallbackRegistrar)
|
if (mCallbackRegistrar)
|
||||||
{
|
{
|
||||||
mCallbackRegistrar->pushScope();
|
mCallbackRegistrar->pushScope();
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
|
||||||
mURLClickSignal(NULL),
|
mURLClickSignal(NULL),
|
||||||
mIsFriendSignal(NULL),
|
mIsFriendSignal(NULL),
|
||||||
mIsObjectBlockedSignal(NULL),
|
mIsObjectBlockedSignal(NULL),
|
||||||
|
mIsObjectReachableSignal(NULL),
|
||||||
mMaxTextByteLength( p.max_text_length ),
|
mMaxTextByteLength( p.max_text_length ),
|
||||||
mFont(p.font),
|
mFont(p.font),
|
||||||
mFontShadow(p.font_shadow),
|
mFontShadow(p.font_shadow),
|
||||||
|
|
@ -320,6 +321,7 @@ LLTextBase::~LLTextBase()
|
||||||
delete mURLClickSignal;
|
delete mURLClickSignal;
|
||||||
delete mIsFriendSignal;
|
delete mIsFriendSignal;
|
||||||
delete mIsObjectBlockedSignal;
|
delete mIsObjectBlockedSignal;
|
||||||
|
delete mIsObjectReachableSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLTextBase::initFromParams(const LLTextBase::Params& p)
|
void LLTextBase::initFromParams(const LLTextBase::Params& p)
|
||||||
|
|
@ -2510,6 +2512,15 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mIsObjectReachableSignal)
|
||||||
|
{
|
||||||
|
bool is_reachable = *(*mIsObjectReachableSignal)(LLUUID(LLUrlAction::getObjectId(url)));
|
||||||
|
if (LLView* zoom_btn = menu->getChild<LLView>("zoom_in"))
|
||||||
|
{
|
||||||
|
zoom_btn->setEnabled(is_reachable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// <FS:Zi> hide the moderation tools in the context menu unless we are in a group IM floater
|
// <FS:Zi> hide the moderation tools in the context menu unless we are in a group IM floater
|
||||||
LLFloater* parent_floater = getParentByType<LLFloater>();
|
LLFloater* parent_floater = getParentByType<LLFloater>();
|
||||||
if (!parent_floater || parent_floater->getName() != "panel_im")
|
if (!parent_floater || parent_floater->getName() != "panel_im")
|
||||||
|
|
@ -3740,6 +3751,15 @@ boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_bloc
|
||||||
return mIsObjectBlockedSignal->connect(cb);
|
return mIsObjectBlockedSignal->connect(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::signals2::connection LLTextBase::setIsObjectReachableCallback(const is_obj_reachable_signal_t::slot_type& cb)
|
||||||
|
{
|
||||||
|
if (!mIsObjectReachableSignal)
|
||||||
|
{
|
||||||
|
mIsObjectReachableSignal = new is_obj_reachable_signal_t();
|
||||||
|
}
|
||||||
|
return mIsObjectReachableSignal->connect(cb);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// LLTextSegment
|
// LLTextSegment
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ public:
|
||||||
|
|
||||||
typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t;
|
typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t;
|
||||||
typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t;
|
typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t;
|
||||||
|
typedef boost::signals2::signal<bool (const LLUUID& obj_id)> is_obj_reachable_signal_t;
|
||||||
|
|
||||||
struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>
|
struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>
|
||||||
{
|
{
|
||||||
|
|
@ -572,6 +573,7 @@ public:
|
||||||
boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb);
|
boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb);
|
||||||
boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
|
boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
|
||||||
boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
|
boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
|
||||||
|
boost::signals2::connection setIsObjectReachableCallback(const is_obj_reachable_signal_t::slot_type& cb);
|
||||||
|
|
||||||
void setWordWrap(bool wrap);
|
void setWordWrap(bool wrap);
|
||||||
LLScrollContainer* getScrollContainer() const { return mScroller; }
|
LLScrollContainer* getScrollContainer() const { return mScroller; }
|
||||||
|
|
@ -841,6 +843,7 @@ protected:
|
||||||
// Used to check if user with given ID is avatar's friend
|
// Used to check if user with given ID is avatar's friend
|
||||||
is_friend_signal_t* mIsFriendSignal;
|
is_friend_signal_t* mIsFriendSignal;
|
||||||
is_blocked_signal_t* mIsObjectBlockedSignal;
|
is_blocked_signal_t* mIsObjectBlockedSignal;
|
||||||
|
is_obj_reachable_signal_t* mIsObjectReachableSignal;
|
||||||
|
|
||||||
LLUIString mLabel; // text label that is visible when no user text provided
|
LLUIString mLabel; // text label that is visible when no user text provided
|
||||||
// <FS:Ansariel> Optional icon position
|
// <FS:Ansariel> Optional icon position
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,16 @@ void LLWebRTCImpl::init()
|
||||||
|
|
||||||
void LLWebRTCImpl::terminate()
|
void LLWebRTCImpl::terminate()
|
||||||
{
|
{
|
||||||
|
mWorkerThread->BlockingCall(
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
if (mDeviceModule)
|
||||||
|
{
|
||||||
|
mDeviceModule->ForceStopRecording();
|
||||||
|
mDeviceModule->StopPlayout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (auto &connection : mPeerConnections)
|
for (auto &connection : mPeerConnections)
|
||||||
{
|
{
|
||||||
connection->terminate();
|
connection->terminate();
|
||||||
|
|
@ -368,8 +378,6 @@ void LLWebRTCImpl::terminate()
|
||||||
{
|
{
|
||||||
if (mDeviceModule)
|
if (mDeviceModule)
|
||||||
{
|
{
|
||||||
mDeviceModule->StopRecording();
|
|
||||||
mDeviceModule->StopPlayout();
|
|
||||||
mDeviceModule->Terminate();
|
mDeviceModule->Terminate();
|
||||||
}
|
}
|
||||||
mDeviceModule = nullptr;
|
mDeviceModule = nullptr;
|
||||||
|
|
@ -442,11 +450,7 @@ void LLWebRTCImpl::unsetDevicesObserver(LLWebRTCDevicesObserver *observer)
|
||||||
void LLWebRTCImpl::workerDeployDevices()
|
void LLWebRTCImpl::workerDeployDevices()
|
||||||
{
|
{
|
||||||
int16_t recordingDevice = RECORD_DEVICE_DEFAULT;
|
int16_t recordingDevice = RECORD_DEVICE_DEFAULT;
|
||||||
#if WEBRTC_WIN
|
|
||||||
int16_t recording_device_start = 0;
|
int16_t recording_device_start = 0;
|
||||||
#else
|
|
||||||
int16_t recording_device_start = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mRecordingDevice != "Default")
|
if (mRecordingDevice != "Default")
|
||||||
{
|
{
|
||||||
|
|
@ -455,6 +459,12 @@ void LLWebRTCImpl::workerDeployDevices()
|
||||||
if (mRecordingDeviceList[i].mID == mRecordingDevice)
|
if (mRecordingDeviceList[i].mID == mRecordingDevice)
|
||||||
{
|
{
|
||||||
recordingDevice = i;
|
recordingDevice = i;
|
||||||
|
#if !WEBRTC_WIN
|
||||||
|
// linux and mac devices range from 1 to the end of the list, with the index 0 being the
|
||||||
|
// 'default' device. Windows has a special 'default' device and other devices are indexed
|
||||||
|
// from 0
|
||||||
|
recordingDevice++;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -479,11 +489,7 @@ void LLWebRTCImpl::workerDeployDevices()
|
||||||
mDeviceModule->InitRecording();
|
mDeviceModule->InitRecording();
|
||||||
|
|
||||||
int16_t playoutDevice = PLAYOUT_DEVICE_DEFAULT;
|
int16_t playoutDevice = PLAYOUT_DEVICE_DEFAULT;
|
||||||
#if WEBRTC_WIN
|
|
||||||
int16_t playout_device_start = 0;
|
int16_t playout_device_start = 0;
|
||||||
#else
|
|
||||||
int16_t playout_device_start = 1;
|
|
||||||
#endif
|
|
||||||
if (mPlayoutDevice != "Default")
|
if (mPlayoutDevice != "Default")
|
||||||
{
|
{
|
||||||
for (int16_t i = playout_device_start; i < mPlayoutDeviceList.size(); i++)
|
for (int16_t i = playout_device_start; i < mPlayoutDeviceList.size(); i++)
|
||||||
|
|
@ -491,6 +497,12 @@ void LLWebRTCImpl::workerDeployDevices()
|
||||||
if (mPlayoutDeviceList[i].mID == mPlayoutDevice)
|
if (mPlayoutDeviceList[i].mID == mPlayoutDevice)
|
||||||
{
|
{
|
||||||
playoutDevice = i;
|
playoutDevice = i;
|
||||||
|
#if !WEBRTC_WIN
|
||||||
|
// linux and mac devices range from 1 to the end of the list, with the index 0 being the
|
||||||
|
// 'default' device. Windows has a special 'default' device and other devices are indexed
|
||||||
|
// from 0
|
||||||
|
playoutDevice++;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -546,20 +558,14 @@ void LLWebRTCImpl::workerDeployDevices()
|
||||||
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
|
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (mRecordingDevice != id)
|
mRecordingDevice = id;
|
||||||
{
|
deployDevices();
|
||||||
mRecordingDevice = id;
|
|
||||||
deployDevices();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLWebRTCImpl::setRenderDevice(const std::string &id)
|
void LLWebRTCImpl::setRenderDevice(const std::string &id)
|
||||||
{
|
{
|
||||||
if (mPlayoutDevice != id)
|
mPlayoutDevice = id;
|
||||||
{
|
deployDevices();
|
||||||
mPlayoutDevice = id;
|
|
||||||
deployDevices();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateDevices needs to happen on the worker thread.
|
// updateDevices needs to happen on the worker thread.
|
||||||
|
|
@ -609,7 +615,7 @@ void LLWebRTCImpl::updateDevices()
|
||||||
|
|
||||||
void LLWebRTCImpl::OnDevicesUpdated()
|
void LLWebRTCImpl::OnDevicesUpdated()
|
||||||
{
|
{
|
||||||
deployDevices();
|
updateDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,8 +239,10 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int32_t StopRecording() override {
|
int32_t StopRecording() override {
|
||||||
if (tuning_) return 0; // if we're tuning, disregard the StopRecording we get from disabling the streams
|
// ignore stop recording as webrtc.lib will send one when streams shut down,
|
||||||
return inner_->StopRecording();
|
// even if there are other streams in place. Start/Stop recording are entirely
|
||||||
|
// controlled by the app
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
int32_t ForceStartRecording() { return inner_->StartRecording(); }
|
int32_t ForceStartRecording() { return inner_->StartRecording(); }
|
||||||
int32_t ForceStopRecording() { return inner_->StopRecording(); }
|
int32_t ForceStopRecording() { return inner_->StopRecording(); }
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,13 @@ void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLWindowCallbacks::handleCloseRequest(LLWindow *window)
|
bool LLWindowCallbacks::handleCloseRequest(LLWindow *window, bool from_user)
|
||||||
|
{
|
||||||
|
//allow the window to close
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLWindowCallbacks::handleSessionExit(LLWindow* window)
|
||||||
{
|
{
|
||||||
//allow the window to close
|
//allow the window to close
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ public:
|
||||||
virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
|
virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
|
||||||
virtual void handleMouseLeave(LLWindow *window);
|
virtual void handleMouseLeave(LLWindow *window);
|
||||||
// return true to allow window to close, which will then cause handleQuit to be called
|
// return true to allow window to close, which will then cause handleQuit to be called
|
||||||
virtual bool handleCloseRequest(LLWindow *window);
|
virtual bool handleCloseRequest(LLWindow *window, bool from_user);
|
||||||
|
virtual bool handleSessionExit(LLWindow* window);
|
||||||
// window is about to be destroyed, clean up your business
|
// window is about to be destroyed, clean up your business
|
||||||
virtual void handleQuit(LLWindow *window);
|
virtual void handleQuit(LLWindow *window);
|
||||||
virtual bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
|
virtual bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,7 @@ void callQuitHandler()
|
||||||
{
|
{
|
||||||
if (gWindowImplementation && gWindowImplementation->getCallbacks())
|
if (gWindowImplementation && gWindowImplementation->getCallbacks())
|
||||||
{
|
{
|
||||||
if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
|
if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation, true))
|
||||||
{
|
{
|
||||||
gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
|
gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2170,7 +2170,7 @@ void LLWindowSDL::gatherInput()
|
||||||
{
|
{
|
||||||
// *FIX: More informative dialog?
|
// *FIX: More informative dialog?
|
||||||
LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
|
LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
|
||||||
if(mCallbacks->handleCloseRequest(this))
|
if(mCallbacks->handleCloseRequest(this, false))
|
||||||
{
|
{
|
||||||
// Get the app to initiate cleanup.
|
// Get the app to initiate cleanup.
|
||||||
mCallbacks->handleQuit(this);
|
mCallbacks->handleQuit(this);
|
||||||
|
|
@ -2220,7 +2220,7 @@ void LLWindowSDL::gatherInput()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
if(mCallbacks->handleCloseRequest(this))
|
if(mCallbacks->handleCloseRequest(this, true))
|
||||||
{
|
{
|
||||||
// Get the app to initiate cleanup.
|
// Get the app to initiate cleanup.
|
||||||
mCallbacks->handleQuit(this);
|
mCallbacks->handleQuit(this);
|
||||||
|
|
|
||||||
|
|
@ -2556,10 +2556,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
|
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
|
||||||
|
// todo: WM_CLOSE can be caused by user and by task manager,
|
||||||
|
// distinguish these cases.
|
||||||
|
// For now assume it is always user.
|
||||||
window_imp->post([=]()
|
window_imp->post([=]()
|
||||||
{
|
{
|
||||||
// Will the app allow the window to close?
|
// Will the app allow the window to close?
|
||||||
if (window_imp->mCallbacks->handleCloseRequest(window_imp))
|
if (window_imp->mCallbacks->handleCloseRequest(window_imp, true))
|
||||||
{
|
{
|
||||||
// Get the app to initiate cleanup.
|
// Get the app to initiate cleanup.
|
||||||
window_imp->mCallbacks->handleQuit(window_imp);
|
window_imp->mCallbacks->handleQuit(window_imp);
|
||||||
|
|
@ -2577,6 +2580,50 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case WM_QUERYENDSESSION:
|
||||||
|
{
|
||||||
|
// Generally means that OS is going to shut down or user is going to log off.
|
||||||
|
// Can use ShutdownBlockReasonCreate here.
|
||||||
|
LL_INFOS("Window") << "Received WM_QUERYENDSESSION with wParam: " << (U32)w_param << " lParam: " << (U32)l_param << LL_ENDL;
|
||||||
|
return TRUE; // 1 = ok to end session. 0 no longer works by itself, use ShutdownBlockReasonCreate
|
||||||
|
}
|
||||||
|
case WM_ENDSESSION:
|
||||||
|
{
|
||||||
|
// OS session is shutting down, initiate cleanup.
|
||||||
|
// Comes after WM_QUERYENDSESSION
|
||||||
|
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ENDSESSION");
|
||||||
|
LL_INFOS("Window") << "Received WM_ENDSESSION with wParam: " << (U32)w_param << " lParam: " << (U32)l_param << LL_ENDL;
|
||||||
|
unsigned int end_session_flags = (U32)w_param;
|
||||||
|
if (end_session_flags == 0)
|
||||||
|
{
|
||||||
|
// session is not actually ending
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((end_session_flags & ENDSESSION_CLOSEAPP)
|
||||||
|
|| (end_session_flags & ENDSESSION_CRITICAL)
|
||||||
|
|| (end_session_flags & ENDSESSION_LOGOFF))
|
||||||
|
{
|
||||||
|
window_imp->post([=]()
|
||||||
|
{
|
||||||
|
// Check if app needs cleanup or can be closed immediately.
|
||||||
|
if (window_imp->mCallbacks->handleSessionExit(window_imp))
|
||||||
|
{
|
||||||
|
// Get the app to initiate cleanup.
|
||||||
|
window_imp->mCallbacks->handleQuit(window_imp);
|
||||||
|
// The app is responsible for calling destroyWindow when done with GL
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Give app a second to finish up. That's not enough for a clean exit,
|
||||||
|
// but better than nothing.
|
||||||
|
// Todo: sync this better, some kind of waitForResult? Can't wait forever,
|
||||||
|
// but can potentially use ShutdownBlockReasonCreate for a bigger delay.
|
||||||
|
ms_sleep(1000);
|
||||||
|
}
|
||||||
|
// Don't need to post quit or destroy window,
|
||||||
|
// if session is ending OS is going to take care of it.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
{
|
{
|
||||||
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_COMMAND");
|
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_COMMAND");
|
||||||
|
|
|
||||||
|
|
@ -12680,7 +12680,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
||||||
<key>RenderQualityPerformance</key>
|
<key>RenderQualityPerformance</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
<string>Which graphics settings you've chosen</string>
|
<string>Which graphics settings you've chosen. Don't use this setting to change quality directly from debug settings.</string>
|
||||||
<key>Persist</key>
|
<key>Persist</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
|
|
@ -12688,7 +12688,18 @@ Change of this parameter will affect the layout of buttons in notification toast
|
||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
</map>
|
</map>
|
||||||
|
<key>DebugQualityPerformance</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Allows to change performance quality directly from debug settings.</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>U32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</map>
|
||||||
|
|
||||||
<key>RenderReflectionDetail</key>
|
<key>RenderReflectionDetail</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,8 @@ public:
|
||||||
LLUUID obj_id = mObjectData["object_id"];
|
LLUUID obj_id = mObjectData["object_id"];
|
||||||
if (obj_id.notNull())
|
if (obj_id.notNull())
|
||||||
{
|
{
|
||||||
return nullptr != gObjectList.findObject(mAvatarID);
|
LLViewerObject* object = gObjectList.findObject(obj_id);
|
||||||
|
return object && object->isReachable();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1280,6 +1281,11 @@ FSChatHistory::FSChatHistory(const FSChatHistory::Params& p)
|
||||||
mUseColor = true;
|
mUseColor = true;
|
||||||
|
|
||||||
setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
|
setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
|
||||||
|
setIsObjectReachableCallback([](const LLUUID& obj_id)
|
||||||
|
{
|
||||||
|
LLViewerObject* object = gObjectList.findObject(obj_id);
|
||||||
|
return object && object->isReachable();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LLSD FSChatHistory::getValue() const
|
LLSD FSChatHistory::getValue() const
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,11 @@ bool Buffer::prep(Asset& asset)
|
||||||
{
|
{
|
||||||
std::string dir = gDirUtilp->getDirName(asset.mFilename);
|
std::string dir = gDirUtilp->getDirName(asset.mFilename);
|
||||||
std::string bin_file = dir + gDirUtilp->getDirDelimiter() + mUri;
|
std::string bin_file = dir + gDirUtilp->getDirDelimiter() + mUri;
|
||||||
|
if (!gDirUtilp->fileExists(bin_file))
|
||||||
|
{
|
||||||
|
// Characters might be escaped in the URI
|
||||||
|
bin_file = dir + gDirUtilp->getDirDelimiter() + LLURI::unescape(mUri);
|
||||||
|
}
|
||||||
|
|
||||||
llifstream file(bin_file.c_str(), std::ios::binary);
|
llifstream file(bin_file.c_str(), std::ios::binary);
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
|
|
|
||||||
|
|
@ -652,6 +652,14 @@ std::string LLGLTFLoader::processTexture(S32 texture_index, const std::string& t
|
||||||
filename = filename.substr(pos + 1);
|
filename = filename.substr(pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string dir = gDirUtilp->getDirName(mFilename);
|
||||||
|
std::string full_path = dir + gDirUtilp->getDirDelimiter() + filename;
|
||||||
|
if (!gDirUtilp->fileExists(full_path) && filename.find("data:") == std::string::npos)
|
||||||
|
{
|
||||||
|
// Uri might be escaped
|
||||||
|
filename = LLURI::unescape(filename);
|
||||||
|
}
|
||||||
|
|
||||||
LL_INFOS("GLTF_IMPORT") << "Found texture: " << filename << " for material: " << material_name << LL_ENDL;
|
LL_INFOS("GLTF_IMPORT") << "Found texture: " << filename << " for material: " << material_name << LL_ENDL;
|
||||||
|
|
||||||
LLSD args;
|
LLSD args;
|
||||||
|
|
|
||||||
|
|
@ -1427,19 +1427,10 @@ bool LLAppViewer::init()
|
||||||
LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
|
LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
|
||||||
LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
|
LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
|
||||||
|
|
||||||
// <FS:Ansariel> Always override AM/PM because otherwise AM/PM indicator might be empty strings when calling using
|
LLStringOps::sAM = LLTrans::getString("dateTimeAM");
|
||||||
// [ampm,datetime,...] formatting depending on locale
|
LLStringOps::sPM = LLTrans::getString("dateTimePM");
|
||||||
// LLStringOps::sAM = LLTrans::getString("dateTimeAM");
|
|
||||||
// LLStringOps::sPM = LLTrans::getString("dateTimePM");
|
|
||||||
// </FS:Ansariel>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// <FS:Ansariel> Always override AM/PM because otherwise AM/PM indicator might be empty strings when calling using [ampm,datetime,...]
|
|
||||||
// formatting depending on locale
|
|
||||||
LLStringOps::sAM = LLTrans::getString("dateTimeAM");
|
|
||||||
LLStringOps::sPM = LLTrans::getString("dateTimePM");
|
|
||||||
// </FS:Ansariel>
|
|
||||||
|
|
||||||
LLAgentLanguage::init();
|
LLAgentLanguage::init();
|
||||||
|
|
||||||
/// Tell the Coprocedure manager how to discover and store the pool sizes
|
/// Tell the Coprocedure manager how to discover and store the pool sizes
|
||||||
|
|
@ -1487,6 +1478,7 @@ bool LLAppViewer::init()
|
||||||
LLViewerCamera::createInstance();
|
LLViewerCamera::createInstance();
|
||||||
LL::GLTFSceneManager::createInstance();
|
LL::GLTFSceneManager::createInstance();
|
||||||
|
|
||||||
|
gSavedSettings.setU32("DebugQualityPerformance", gSavedSettings.getU32("RenderQualityPerformance"));
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
if (!mSecondInstance)
|
if (!mSecondInstance)
|
||||||
|
|
@ -4738,8 +4730,15 @@ void LLAppViewer::processMarkerFiles()
|
||||||
else if (marker_is_same_version)
|
else if (marker_is_same_version)
|
||||||
{
|
{
|
||||||
// the file existed, is ours, and matched our version, so we can report on what it says
|
// the file existed, is ours, and matched our version, so we can report on what it says
|
||||||
LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
|
LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed or froze" << LL_ENDL;
|
||||||
|
#if LL_WINDOWS && LL_BUGSPLAT
|
||||||
|
// bugsplat will set correct state in bugsplatSendLog
|
||||||
|
// Might be more accurate to rename this one into 'unknown'
|
||||||
|
gLastExecEvent = LAST_EXEC_FROZE;
|
||||||
|
#else
|
||||||
gLastExecEvent = LAST_EXEC_OTHER_CRASH;
|
gLastExecEvent = LAST_EXEC_OTHER_CRASH;
|
||||||
|
#endif // LL_WINDOWS
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -4999,7 +4998,7 @@ void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
|
||||||
// case where we need the viewer to exit without any need for notifications
|
// case where we need the viewer to exit without any need for notifications
|
||||||
void LLAppViewer::earlyExitNoNotify()
|
void LLAppViewer::earlyExitNoNotify()
|
||||||
{
|
{
|
||||||
LL_WARNS() << "app_early_exit with no notification: " << LL_ENDL;
|
LL_WARNS() << "app_early_exit with no notification." << LL_ENDL;
|
||||||
gDoDisconnect = true;
|
gDoDisconnect = true;
|
||||||
finish_early_exit( LLSD(), LLSD() );
|
finish_early_exit( LLSD(), LLSD() );
|
||||||
}
|
}
|
||||||
|
|
@ -6330,6 +6329,12 @@ void LLAppViewer::createErrorMarker(eLastExecEvent error_code) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLAppViewer::errorMarkerExists() const
|
||||||
|
{
|
||||||
|
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
|
||||||
|
return LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB);
|
||||||
|
}
|
||||||
|
|
||||||
void LLAppViewer::outOfMemorySoftQuit()
|
void LLAppViewer::outOfMemorySoftQuit()
|
||||||
{
|
{
|
||||||
if (!mQuitRequested)
|
if (!mQuitRequested)
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,12 @@ public:
|
||||||
std::string getWindowTitle() const; // The window display name.
|
std::string getWindowTitle() const; // The window display name.
|
||||||
|
|
||||||
void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user.
|
void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user.
|
||||||
|
|
||||||
|
// sendSimpleLogoutRequest does not create a marker file.
|
||||||
|
// Meant for lost network case, and for forced shutdowns,
|
||||||
|
// to at least attempt to remove the ghost from the world.
|
||||||
|
void sendSimpleLogoutRequest();
|
||||||
|
|
||||||
void badNetworkHandler(); // Cause a crash state due to bad network packet.
|
void badNetworkHandler(); // Cause a crash state due to bad network packet.
|
||||||
|
|
||||||
bool hasSavedFinalSnapshot() { return mSavedFinalSnapshot; }
|
bool hasSavedFinalSnapshot() { return mSavedFinalSnapshot; }
|
||||||
|
|
@ -246,6 +252,7 @@ public:
|
||||||
|
|
||||||
// Writes an error code into the error_marker file for use on next startup.
|
// Writes an error code into the error_marker file for use on next startup.
|
||||||
void createErrorMarker(eLastExecEvent error_code) const;
|
void createErrorMarker(eLastExecEvent error_code) const;
|
||||||
|
bool errorMarkerExists() const;
|
||||||
|
|
||||||
// Attempt a 'soft' quit with disconnect and saving of settings/cache.
|
// Attempt a 'soft' quit with disconnect and saving of settings/cache.
|
||||||
// Intended to be thread safe.
|
// Intended to be thread safe.
|
||||||
|
|
@ -314,10 +321,6 @@ private:
|
||||||
void sendLogoutRequest();
|
void sendLogoutRequest();
|
||||||
void disconnectViewer();
|
void disconnectViewer();
|
||||||
|
|
||||||
// Does not create a marker file. For lost network case,
|
|
||||||
// to at least attempt to remove the ghost from the world.
|
|
||||||
void sendSimpleLogoutRequest();
|
|
||||||
|
|
||||||
// *FIX: the app viewer class should be some sort of singleton, no?
|
// *FIX: the app viewer class should be some sort of singleton, no?
|
||||||
// Perhaps its child class is the singleton and this should be an abstract base.
|
// Perhaps its child class is the singleton and this should be an abstract base.
|
||||||
static LLAppViewer* sInstance;
|
static LLAppViewer* sInstance;
|
||||||
|
|
|
||||||
|
|
@ -233,10 +233,20 @@ namespace
|
||||||
BugSplatAttributes::instance().setAttribute("Location", std::string(fullLocation));
|
BugSplatAttributes::instance().setAttribute("Location", std::string(fullLocation));
|
||||||
// </FS:Beq>
|
// </FS:Beq>
|
||||||
}
|
}
|
||||||
|
|
||||||
// <FS:Beq> Improve bugsplat reporting with attributes
|
// <FS:Beq> Improve bugsplat reporting with attributes
|
||||||
LLAppViewer::instance()->writeDebugInfo();
|
LLAppViewer::instance()->writeDebugInfo();
|
||||||
sBugSplatSender->sendAdditionalFile(WCSTR(BugSplatAttributes::getCrashContextFileName())); // <FS:Beq/> Add the new attributes file
|
sBugSplatSender->sendAdditionalFile(WCSTR(BugSplatAttributes::getCrashContextFileName())); // <FS:Beq/> Add the new attributes file
|
||||||
// </FS:Beq>
|
// </FS:Beq>
|
||||||
|
|
||||||
|
LLAppViewer* app = LLAppViewer::instance();
|
||||||
|
if (!app->isSecondInstance() && !app->errorMarkerExists())
|
||||||
|
{
|
||||||
|
// If marker doesn't exist, create a marker with 'other' code for next launch
|
||||||
|
// otherwise don't override existing file
|
||||||
|
// Any unmarked crashes will be considered as freezes
|
||||||
|
app->createErrorMarker(LAST_EXEC_OTHER_CRASH);
|
||||||
|
}
|
||||||
} // MDSCB_EXCEPTIONCODE
|
} // MDSCB_EXCEPTIONCODE
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,8 @@ public:
|
||||||
LLUUID obj_id = mObjectData["object_id"];
|
LLUUID obj_id = mObjectData["object_id"];
|
||||||
if (obj_id.notNull())
|
if (obj_id.notNull())
|
||||||
{
|
{
|
||||||
return nullptr != gObjectList.findObject(mAvatarID);
|
LLViewerObject* object = gObjectList.findObject(obj_id);
|
||||||
|
return object && object->isReachable();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1178,7 +1179,11 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
|
||||||
mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);
|
mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);
|
||||||
mEditor->setIsFriendCallback(LLAvatarActions::isFriend);
|
mEditor->setIsFriendCallback(LLAvatarActions::isFriend);
|
||||||
mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
|
mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
|
||||||
|
mEditor->setIsObjectReachableCallback([](const LLUUID& obj_id)
|
||||||
|
{
|
||||||
|
LLViewerObject* object = gObjectList.findObject(obj_id);
|
||||||
|
return object && object->isReachable();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LLSD LLChatHistory::getValue() const
|
LLSD LLChatHistory::getValue() const
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,6 @@ namespace Details
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
|
|
||||||
// This means we attempt to recover relatively quickly but back off giving more time to recover
|
|
||||||
// until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts.
|
|
||||||
static const F32 EVENT_POLL_ERROR_RETRY_SECONDS;
|
|
||||||
static const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC;
|
|
||||||
static const S32 MAX_EVENT_POLL_HTTP_ERRORS;
|
|
||||||
|
|
||||||
void eventPollCoro(std::string url);
|
void eventPollCoro(std::string url);
|
||||||
|
|
||||||
void handleMessage(const LLSD &content);
|
void handleMessage(const LLSD &content);
|
||||||
|
|
@ -71,7 +64,6 @@ namespace Details
|
||||||
bool mDone;
|
bool mDone;
|
||||||
LLCore::HttpRequest::ptr_t mHttpRequest;
|
LLCore::HttpRequest::ptr_t mHttpRequest;
|
||||||
LLCore::HttpRequest::policy_t mHttpPolicy;
|
LLCore::HttpRequest::policy_t mHttpPolicy;
|
||||||
LLCore::HttpOptions::ptr_t mHttpOptions; // <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
|
||||||
std::string mSenderIp;
|
std::string mSenderIp;
|
||||||
int mCounter;
|
int mCounter;
|
||||||
LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mAdapter;
|
LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mAdapter;
|
||||||
|
|
@ -80,9 +72,13 @@ namespace Details
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const F32 LLEventPollImpl::EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout.
|
// We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
|
||||||
const F32 LLEventPollImpl::EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout.
|
// This means we attempt to recover relatively quickly but back off giving more time to recover
|
||||||
const S32 LLEventPollImpl::MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules.
|
// until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts.
|
||||||
|
constexpr F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout.
|
||||||
|
constexpr F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout.
|
||||||
|
constexpr S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules.
|
||||||
|
constexpr F64 MIN_SECONDS_PASSED = 10.0; // Minimum time we expect the server to hold the request.
|
||||||
|
|
||||||
int LLEventPollImpl::sNextCounter = 1;
|
int LLEventPollImpl::sNextCounter = 1;
|
||||||
|
|
||||||
|
|
@ -91,7 +87,6 @@ namespace Details
|
||||||
mDone(false),
|
mDone(false),
|
||||||
mHttpRequest(),
|
mHttpRequest(),
|
||||||
mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||||
mHttpOptions(), // <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
|
||||||
mSenderIp(),
|
mSenderIp(),
|
||||||
mCounter(sNextCounter++)
|
mCounter(sNextCounter++)
|
||||||
|
|
||||||
|
|
@ -100,16 +95,6 @@ namespace Details
|
||||||
|
|
||||||
mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
|
mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
|
||||||
mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_LONG_POLL);
|
mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_LONG_POLL);
|
||||||
// <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
|
||||||
mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
|
|
||||||
#ifdef OPENSIM
|
|
||||||
if (LLGridManager::instance().isInOpenSim())
|
|
||||||
{
|
|
||||||
mHttpOptions->setRetries(0);
|
|
||||||
mHttpOptions->setTransferTimeout(60);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// </FS:Ansariel>
|
|
||||||
mSenderIp = sender.getIPandPort();
|
mSenderIp = sender.getIPandPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,13 +107,11 @@ namespace Details
|
||||||
{
|
{
|
||||||
message["sender"] = mSenderIp;
|
message["sender"] = mSenderIp;
|
||||||
// <FS:ND> Guard against messages with no "body"
|
// <FS:ND> Guard against messages with no "body"
|
||||||
|
|
||||||
// message["body"] = content["body"];
|
// message["body"] = content["body"];
|
||||||
|
if (content.has("body"))
|
||||||
if( content.has( "body" ) )
|
|
||||||
message["body"] = content["body"];
|
message["body"] = content["body"];
|
||||||
else
|
else
|
||||||
LL_WARNS() << "Malformed content? " << ll_pretty_print_sd( content ) << LL_ENDL;
|
LL_WARNS() << "Malformed content? " << ll_pretty_print_sd(content) << LL_ENDL;
|
||||||
// <FS:ND>
|
// <FS:ND>
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc&)
|
catch (std::bad_alloc&)
|
||||||
|
|
@ -174,11 +157,25 @@ namespace Details
|
||||||
LLSD acknowledge;
|
LLSD acknowledge;
|
||||||
int errorCount = 0;
|
int errorCount = 0;
|
||||||
int counter = mCounter; // saved on the stack for logging.
|
int counter = mCounter; // saved on the stack for logging.
|
||||||
|
LLTimer message_time;
|
||||||
|
|
||||||
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL;
|
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL;
|
||||||
|
|
||||||
mAdapter = httpAdapter;
|
mAdapter = httpAdapter;
|
||||||
|
|
||||||
|
// This is a loop with its own waitToRetry implementation,
|
||||||
|
// so disable retries.
|
||||||
|
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||||
|
httpOpts->setRetries(0);
|
||||||
|
// <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
||||||
|
#ifdef OPENSIM
|
||||||
|
if (LLGridManager::instance().isInOpenSim())
|
||||||
|
{
|
||||||
|
httpOpts->setTransferTimeout(60);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// </FS:Ansariel>
|
||||||
|
|
||||||
LL::WorkQueue::ptr_t main_queue = nullptr;
|
LL::WorkQueue::ptr_t main_queue = nullptr;
|
||||||
|
|
||||||
// HACK -- grab the mainloop workqueue to move execution of the handler
|
// HACK -- grab the mainloop workqueue to move execution of the handler
|
||||||
|
|
@ -195,14 +192,13 @@ namespace Details
|
||||||
request["ack"] = acknowledge;
|
request["ack"] = acknowledge;
|
||||||
request["done"] = mDone;
|
request["done"] = mDone;
|
||||||
|
|
||||||
|
message_time.reset();
|
||||||
|
|
||||||
// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = "
|
// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = "
|
||||||
// << LLSDXMLStreamer(request) << LL_ENDL;
|
// << LLSDXMLStreamer(request) << LL_ENDL;
|
||||||
|
|
||||||
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL;
|
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL;
|
||||||
// <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
LLSD result = httpAdapter->postAndSuspend(mHttpRequest, url, request, httpOpts);
|
||||||
//LLSD result = httpAdapter->postAndSuspend(mHttpRequest, url, request);
|
|
||||||
LLSD result = httpAdapter->postAndSuspend(mHttpRequest, url, request, mHttpOptions);
|
|
||||||
// </FS:Ansariel>
|
|
||||||
|
|
||||||
// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = "
|
// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = "
|
||||||
// << LLSDXMLStreamer(result) << LL_ENDL;
|
// << LLSDXMLStreamer(result) << LL_ENDL;
|
||||||
|
|
@ -220,11 +216,30 @@ namespace Details
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
if (status == LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT))
|
if (status == LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT) // A standard timeout, no events.
|
||||||
{ // A standard timeout response we get this when there are no events.
|
|| status == LLCore::HttpStatus(HTTP_BAD_GATEWAY) // An expected 'No events' case.
|
||||||
LL_DEBUGS("LLEventPollImpl") << "All is very quiet on target server. It may have gone idle?" << LL_ENDL;
|
|| status == LLCore::HttpStatus(HTTP_INTERNAL_ERROR)
|
||||||
errorCount = 0;
|
|| status == LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE)
|
||||||
continue;
|
|| status == LLCore::HttpStatus(HTTP_GATEWAY_TIME_OUT))
|
||||||
|
{
|
||||||
|
if (message_time.getElapsedSeconds() < MIN_SECONDS_PASSED)
|
||||||
|
{
|
||||||
|
// Server is supposed to hold request for 20 to 30 seconds.
|
||||||
|
// If it didn't hold the request at least for 10s, treat as an error.
|
||||||
|
LL_WARNS("LLEventPollImpl") << "Response arrived too early, status: " << status.toTerseString()
|
||||||
|
<< ", time passed: " << message_time.getElapsedSeconds() << LL_ENDL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Timeout, expected and means 'no events'. Request is to be re-issued immediately.
|
||||||
|
// Current definition of a timeout is any of :
|
||||||
|
// - libcurl easy 28 status code
|
||||||
|
// - Linden 499 special http status code
|
||||||
|
// - RFC - standard 502 - 504 http status codes
|
||||||
|
LL_DEBUGS("LLEventPollImpl") << "No events, from: " << mSenderIp <<" status: " << (S32)status.getStatus() << LL_ENDL;
|
||||||
|
errorCount = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
// <FS:Ansariel> Restore pre-coro behavior (60s timeout, no retries)
|
||||||
#ifdef OPENSIM
|
#ifdef OPENSIM
|
||||||
|
|
@ -243,13 +258,13 @@ namespace Details
|
||||||
// some cases the server gets ahead of the viewer and will
|
// some cases the server gets ahead of the viewer and will
|
||||||
// return a 404 error (Not Found) before the cancel event
|
// return a 404 error (Not Found) before the cancel event
|
||||||
// comes back in the queue
|
// comes back in the queue
|
||||||
LL_WARNS("LLEventPollImpl") << "Canceling coroutine" << LL_ENDL;
|
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Canceling coroutine, status: " << status.toTerseString() << LL_ENDL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (!status.isHttpStatus())
|
else if (!status.isHttpStatus())
|
||||||
{
|
{
|
||||||
/// Some LLCore or LIBCurl error was returned. This is unlikely to be recoverable
|
/// Some LLCore or LIBCurl error was returned. This is unlikely to be recoverable
|
||||||
LL_WARNS("LLEventPollImpl") << "Critical error from poll request returned from libraries. Canceling coroutine." << LL_ENDL;
|
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Critical error from poll request returned from libraries. Canceling coroutine." << LL_ENDL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
|
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
|
||||||
|
|
@ -292,6 +307,10 @@ namespace Details
|
||||||
LL_WARNS("LLEventPollImpl") << "< " << counter << "> Forcing disconnect due to stalled main region event poll." << LL_ENDL;
|
LL_WARNS("LLEventPollImpl") << "< " << counter << "> Forcing disconnect due to stalled main region event poll." << LL_ENDL;
|
||||||
LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection"));
|
LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection"));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LL_WARNS("LLEventPollImpl") << "< " << counter << "> Stopping event poll for " << mSenderIp << " due to failures." << LL_ENDL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,30 @@ namespace Details
|
||||||
|
|
||||||
|
|
||||||
class LLEventPoll
|
class LLEventPoll
|
||||||
///< implements the viewer side of server-to-viewer pushed events.
|
///< Implements the viewer side of server-to-viewer pushed events.
|
||||||
|
///
|
||||||
|
/// This class implements the sole consumer of the EventQueueGet capability
|
||||||
|
/// and delivers data, including llsd-encoded llmessage payloads, from
|
||||||
|
/// simulator to viewer.
|
||||||
|
///
|
||||||
|
/// https://wiki.secondlife.com/wiki/EventQueueGet
|
||||||
|
/// The wiki page is neither complete nor entirely correct. Request timeouts
|
||||||
|
/// became the de facto method of returning an empty event set to the viewer.
|
||||||
|
/// But the timeout behavior was never defined. It was simply whatever
|
||||||
|
/// behavior a given grid implementation implemented.
|
||||||
|
///
|
||||||
|
/// In SL's case, the path may include reverse proxies, http caches, http and
|
||||||
|
/// socks proxies, transparent hijacking, and other horrors. A pitfall for
|
||||||
|
/// implementors.
|
||||||
|
///
|
||||||
|
/// Current definition of a timeout is any of :
|
||||||
|
/// - libcurl easy 28 status code
|
||||||
|
/// - Linden 499 special http status code
|
||||||
|
/// - RFC - standard 502 - 504 http status codes
|
||||||
|
/// If requests are failing too quickly with the above errors, they are treated
|
||||||
|
/// as actual errors and not an empty payload. These will count towards a final
|
||||||
|
/// error declaration and can lead to disconnection from a simulator or the
|
||||||
|
/// entire grid.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LLEventPoll(const std::string& pollURL, const LLHost& sender);
|
LLEventPoll(const std::string& pollURL, const LLHost& sender);
|
||||||
|
|
|
||||||
|
|
@ -2421,6 +2421,7 @@ void LLFloaterPreference::onChangeQuality(const LLSD& data)
|
||||||
}
|
}
|
||||||
mLastQualityLevel = level;
|
mLastQualityLevel = level;
|
||||||
LLFeatureManager::getInstance()->setGraphicsLevel(level, true);
|
LLFeatureManager::getInstance()->setGraphicsLevel(level, true);
|
||||||
|
gSavedSettings.setU32("DebugQualityPerformance", level);
|
||||||
refreshEnabledGraphics();
|
refreshEnabledGraphics();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,13 +240,38 @@ void LLPanelVoiceDeviceSettings::refresh()
|
||||||
if(mCtrlInputDevices)
|
if(mCtrlInputDevices)
|
||||||
{
|
{
|
||||||
mCtrlInputDevices->removeall();
|
mCtrlInputDevices->removeall();
|
||||||
mCtrlInputDevices->add(getLocalizedDeviceName(mInputDevice), mInputDevice, ADD_BOTTOM);
|
auto it = mLocalizedDeviceNames.find(mInputDevice);
|
||||||
|
if (it != mLocalizedDeviceNames.end())
|
||||||
|
{
|
||||||
|
mCtrlInputDevices->add(getLocalizedDeviceName(mInputDevice), mInputDevice, ADD_BOTTOM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Display name generaly doesn't match value.
|
||||||
|
// Value is an id so it's not nessesary readable,
|
||||||
|
// might not even be valid (disconnected usb).
|
||||||
|
// Until we get the data, don't change the device,
|
||||||
|
// otherwise box might override the control.
|
||||||
|
// But show a readable placeholder.
|
||||||
|
// Combo is disabled so it's safe to show
|
||||||
|
// a placeholder.
|
||||||
|
mCtrlInputDevices->add(getString("device_not_loaded"), mInputDevice, ADD_BOTTOM);
|
||||||
|
}
|
||||||
mCtrlInputDevices->setValue(mInputDevice);
|
mCtrlInputDevices->setValue(mInputDevice);
|
||||||
}
|
}
|
||||||
if(mCtrlOutputDevices)
|
if(mCtrlOutputDevices)
|
||||||
{
|
{
|
||||||
mCtrlOutputDevices->removeall();
|
mCtrlOutputDevices->removeall();
|
||||||
mCtrlOutputDevices->add(getLocalizedDeviceName(mOutputDevice), mOutputDevice, ADD_BOTTOM);
|
auto it = mLocalizedDeviceNames.find(mOutputDevice);
|
||||||
|
if (it != mLocalizedDeviceNames.end())
|
||||||
|
{
|
||||||
|
mCtrlOutputDevices->add(getLocalizedDeviceName(mOutputDevice), mOutputDevice, ADD_BOTTOM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Don't change the device, only the label
|
||||||
|
mCtrlOutputDevices->add(getString("device_not_loaded"), mOutputDevice, ADD_BOTTOM);
|
||||||
|
}
|
||||||
mCtrlOutputDevices->setValue(mOutputDevice);
|
mCtrlOutputDevices->setValue(mOutputDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,11 @@ void LLFloaterSettingsPicker::onClose(bool app_quitting)
|
||||||
owner->setFocus(true);
|
owner->setFocus(true);
|
||||||
}
|
}
|
||||||
mSettingItemID.setNull();
|
mSettingItemID.setNull();
|
||||||
mInventoryPanel->getRootFolder()->clearSelection();
|
mInventoryPanel->clearSelection();
|
||||||
|
if (mInventoryPanel->getRootFolder())
|
||||||
|
{
|
||||||
|
mInventoryPanel->getRootFolder()->clearSelection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLFloaterSettingsPicker::setValue(const LLSD& value)
|
void LLFloaterSettingsPicker::setValue(const LLSD& value)
|
||||||
|
|
|
||||||
|
|
@ -696,7 +696,26 @@ bool idle_startup()
|
||||||
system = osString.substr (begIdx, endIdx - begIdx);
|
system = osString.substr (begIdx, endIdx - begIdx);
|
||||||
system += "Locale";
|
system += "Locale";
|
||||||
|
|
||||||
LLStringUtil::setLocale (LLTrans::getString(system));
|
std::string locale = LLTrans::getString(system);
|
||||||
|
if (locale != LLStringUtil::getLocale()) // is there a reason to do this on repeat?
|
||||||
|
{
|
||||||
|
LLStringUtil::setLocale(locale);
|
||||||
|
|
||||||
|
// Not all locales have AMPM, test it
|
||||||
|
if (LLStringOps::sAM.empty()) // Might already be overriden from LLAppViewer::init()
|
||||||
|
{
|
||||||
|
LLDate datetime(0.0);
|
||||||
|
std::string val = datetime.toHTTPDateString("%p");
|
||||||
|
if (val.empty())
|
||||||
|
{
|
||||||
|
LL_DEBUGS("InitInfo") << "Current locale \"" << locale << "\" "
|
||||||
|
<< "doesn't support AM/PM time format" << LL_ENDL;
|
||||||
|
// fallback to declarations in strings.xml
|
||||||
|
LLStringOps::sAM = LLTrans::getString("dateTimeAM");
|
||||||
|
LLStringOps::sPM = LLTrans::getString("dateTimePM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//note: Removing this line will cause incorrect button size in the login screen. -- bao.
|
//note: Removing this line will cause incorrect button size in the login screen. -- bao.
|
||||||
gTextureList.updateImages(0.01f) ;
|
gTextureList.updateImages(0.01f) ;
|
||||||
|
|
|
||||||
|
|
@ -1081,6 +1081,8 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
|
||||||
{
|
{
|
||||||
self->setImageID( self->getDefaultImageAssetID() );
|
self->setImageID( self->getDefaultImageAssetID() );
|
||||||
self->setTentative(false);
|
self->setTentative(false);
|
||||||
|
// Deselect in case inventory has a selected item with the same id
|
||||||
|
self->mInventoryPanel->getRootFolder()->clearSelection();
|
||||||
}
|
}
|
||||||
self->commitIfImmediateSet();
|
self->commitIfImmediateSet();
|
||||||
}
|
}
|
||||||
|
|
@ -1092,6 +1094,8 @@ void LLFloaterTexturePicker::onBtnBlank(void* userdata)
|
||||||
self->setCanApply(true, true);
|
self->setCanApply(true, true);
|
||||||
self->setImageID( self->getBlankImageAssetID() );
|
self->setImageID( self->getBlankImageAssetID() );
|
||||||
self->setTentative(false);
|
self->setTentative(false);
|
||||||
|
// Deselect in case inventory has a selected item with the same id
|
||||||
|
self->mInventoryPanel->getRootFolder()->clearSelection();
|
||||||
self->commitIfImmediateSet();
|
self->commitIfImmediateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1113,6 +1117,8 @@ void LLFloaterTexturePicker::onBtnNone(void* userdata)
|
||||||
self->setCanApply(true, true);
|
self->setCanApply(true, true);
|
||||||
self->setImageID( LLUUID::null );
|
self->setImageID( LLUUID::null );
|
||||||
self->setTentative(false);
|
self->setTentative(false);
|
||||||
|
// Deselect in case inventory has a selected item with null id
|
||||||
|
self->mInventoryPanel->getRootFolder()->clearSelection();
|
||||||
self->commitIfImmediateSet();
|
self->commitIfImmediateSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@
|
||||||
#include "llrender.h"
|
#include "llrender.h"
|
||||||
#include "llnavigationbar.h"
|
#include "llnavigationbar.h"
|
||||||
#include "llnotificationsutil.h"
|
#include "llnotificationsutil.h"
|
||||||
|
#include "llfloaterpreference.h"
|
||||||
|
#include "llfloaterreg.h"
|
||||||
#include "llfloatertools.h"
|
#include "llfloatertools.h"
|
||||||
#include "llpaneloutfitsinventory.h"
|
#include "llpaneloutfitsinventory.h"
|
||||||
// <FS:Ansariel> [FS Login Panel]
|
// <FS:Ansariel> [FS Login Panel]
|
||||||
|
|
@ -229,6 +231,21 @@ static bool handleDebugAvatarJointsChanged(const LLSD& newvalue)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool handleDebugQualityPerformanceChanged(const LLSD& newvalue)
|
||||||
|
{
|
||||||
|
// control was set directly or after adjusting Preference setting, no need to update
|
||||||
|
if (gSavedSettings.getU32("RenderQualityPerformance") != gSavedSettings.getU32("DebugQualityPerformance"))
|
||||||
|
{
|
||||||
|
LLFloaterPreference* instance = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences");
|
||||||
|
if (instance)
|
||||||
|
{
|
||||||
|
gSavedSettings.setU32("RenderQualityPerformance", newvalue.asInteger());
|
||||||
|
instance->onChangeQuality(newvalue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool handleAvatarHoverOffsetChanged(const LLSD& newvalue)
|
static bool handleAvatarHoverOffsetChanged(const LLSD& newvalue)
|
||||||
{
|
{
|
||||||
if (isAgentAvatarValid())
|
if (isAgentAvatarValid())
|
||||||
|
|
@ -1420,6 +1437,7 @@ void settings_setup_listeners()
|
||||||
setting_setup_signal_listener(gSavedSettings, "SpellCheckDictionary", handleSpellCheckChanged);
|
setting_setup_signal_listener(gSavedSettings, "SpellCheckDictionary", handleSpellCheckChanged);
|
||||||
setting_setup_signal_listener(gSavedSettings, "LoginLocation", handleLoginLocationChanged);
|
setting_setup_signal_listener(gSavedSettings, "LoginLocation", handleLoginLocationChanged);
|
||||||
setting_setup_signal_listener(gSavedSettings, "DebugAvatarJoints", handleDebugAvatarJointsChanged);
|
setting_setup_signal_listener(gSavedSettings, "DebugAvatarJoints", handleDebugAvatarJointsChanged);
|
||||||
|
setting_setup_signal_listener(gSavedSettings, "DebugQualityPerformance", handleDebugQualityPerformanceChanged);
|
||||||
|
|
||||||
setting_setup_signal_listener(gSavedSettings, "TargetFPS", handleTargetFPSChanged);
|
setting_setup_signal_listener(gSavedSettings, "TargetFPS", handleTargetFPSChanged);
|
||||||
setting_setup_signal_listener(gSavedSettings, "AutoTuneFPS", handleAutoTuneFPSChanged);
|
setting_setup_signal_listener(gSavedSettings, "AutoTuneFPS", handleAutoTuneFPSChanged);
|
||||||
|
|
|
||||||
|
|
@ -8096,7 +8096,7 @@ bool handle_zoom_to_object(const LLUUID& object_id, const std::optional<LLVector
|
||||||
|
|
||||||
LLViewerObject* object = gObjectList.findObject(object_id);
|
LLViewerObject* object = gObjectList.findObject(object_id);
|
||||||
|
|
||||||
if (object)
|
if (object && object->isReachable())
|
||||||
{
|
{
|
||||||
gAgentCamera.setFocusOnAvatar(false, ANIMATE);
|
gAgentCamera.setFocusOnAvatar(false, ANIMATE);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8026,6 +8026,51 @@ void LLViewerObject::clearTEWaterExclusion(const U8 te)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLViewerObject::isReachable()
|
||||||
|
{
|
||||||
|
LLViewerRegion* agent_region = gAgent.getRegion();
|
||||||
|
LLViewerRegion* object_region = getRegion();
|
||||||
|
|
||||||
|
if (!agent_region || !object_region)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (agent_region == object_region)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<LLViewerRegion*> visited;
|
||||||
|
std::queue<LLViewerRegion*> pending;
|
||||||
|
visited.insert(agent_region);
|
||||||
|
pending.push(agent_region);
|
||||||
|
|
||||||
|
while (!pending.empty())
|
||||||
|
{
|
||||||
|
LLViewerRegion* current = pending.front();
|
||||||
|
pending.pop();
|
||||||
|
|
||||||
|
std::vector<LLViewerRegion*> neighbors;
|
||||||
|
current->getNeighboringRegions(neighbors);
|
||||||
|
|
||||||
|
for (LLViewerRegion* neighbor : neighbors)
|
||||||
|
{
|
||||||
|
if (!neighbor) continue;
|
||||||
|
|
||||||
|
if (neighbor == object_region)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// region's neighbors were not checked
|
||||||
|
if (visited.insert(neighbor).second)
|
||||||
|
{
|
||||||
|
pending.push(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class ObjectPhysicsProperties : public LLHTTPNode
|
class ObjectPhysicsProperties : public LLHTTPNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,9 @@ public:
|
||||||
// Accessor functions
|
// Accessor functions
|
||||||
LLViewerRegion* getRegion() const { return mRegionp; }
|
LLViewerRegion* getRegion() const { return mRegionp; }
|
||||||
|
|
||||||
|
// Check if object is reachable from agent region by traversing loaded neighboring regions
|
||||||
|
bool isReachable();
|
||||||
|
|
||||||
bool isSelected() const { return mUserSelected; }
|
bool isSelected() const { return mUserSelected; }
|
||||||
// Check whole linkset
|
// Check whole linkset
|
||||||
bool isAnySelected() const;
|
bool isAnySelected() const;
|
||||||
|
|
|
||||||
|
|
@ -1568,18 +1568,43 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window)
|
||||||
LLToolTipMgr::instance().blockToolTips();
|
LLToolTipMgr::instance().blockToolTips();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLViewerWindow::handleCloseRequest(LLWindow *window)
|
bool LLViewerWindow::handleCloseRequest(LLWindow *window, bool from_user)
|
||||||
{
|
{
|
||||||
if (!LLApp::isExiting() && !LLApp::isStopped())
|
if (!LLApp::isExiting() && !LLApp::isStopped())
|
||||||
{
|
{
|
||||||
// User has indicated they want to close, but we may need to ask
|
if (from_user)
|
||||||
// about modified documents.
|
{
|
||||||
LLAppViewer::instance()->userQuit();
|
// User has indicated they want to close, but we may need to ask
|
||||||
// Don't quit immediately
|
// about modified documents.
|
||||||
|
LLAppViewer::instance()->userQuit();
|
||||||
|
// Don't quit immediately
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OS is asking us to quit, assume we have time and start cleanup
|
||||||
|
LLAppViewer::instance()->requestQuit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLViewerWindow::handleSessionExit(LLWindow* window)
|
||||||
|
{
|
||||||
|
if (!LLApp::isExiting() && !LLApp::isStopped())
|
||||||
|
{
|
||||||
|
// Viewer received WM_ENDSESSION and app will be killed soon if it doesn't respond
|
||||||
|
LLAppViewer* app = LLAppViewer::instance();
|
||||||
|
app->sendSimpleLogoutRequest();
|
||||||
|
app->earlyExitNoNotify();
|
||||||
|
|
||||||
|
// Not viewer's fault, remove marker files so
|
||||||
|
// that statistics won't consider this to be a crash
|
||||||
|
app->removeMarkerFiles();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void LLViewerWindow::handleQuit(LLWindow *window)
|
void LLViewerWindow::handleQuit(LLWindow *window)
|
||||||
{
|
{
|
||||||
if (gNonInteractive)
|
if (gNonInteractive)
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,8 @@ public:
|
||||||
/*virtual*/ bool handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended
|
/*virtual*/ bool handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended
|
||||||
/*virtual*/ bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
|
/*virtual*/ bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
|
||||||
/*virtual*/ bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
|
/*virtual*/ bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
|
||||||
/*virtual*/ bool handleCloseRequest(LLWindow *window);
|
/*virtual*/ bool handleCloseRequest(LLWindow *window, bool from_user);
|
||||||
|
/*virtual*/ bool handleSessionExit(LLWindow* window);
|
||||||
/*virtual*/ void handleQuit(LLWindow *window);
|
/*virtual*/ void handleQuit(LLWindow *window);
|
||||||
/*virtual*/ bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
|
/*virtual*/ bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
|
||||||
/*virtual*/ bool handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
|
/*virtual*/ bool handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,8 @@ void LLWebRTCVoiceClient::terminate()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LL_INFOS("Voice") << "Terminating WebRTC" << LL_ENDL;
|
||||||
|
|
||||||
mVoiceEnabled = false;
|
mVoiceEnabled = false;
|
||||||
llwebrtc::terminate();
|
llwebrtc::terminate();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12115,21 +12115,24 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Called from LLViewHighlightTransparent when "Highlight Transparent" is toggled
|
||||||
void LLPipeline::rebuildDrawInfo()
|
void LLPipeline::rebuildDrawInfo()
|
||||||
{
|
{
|
||||||
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
|
const U32 types_to_traverse[] =
|
||||||
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
|
|
||||||
{
|
{
|
||||||
LLViewerRegion* region = *iter;
|
LLViewerRegion::PARTITION_VOLUME,
|
||||||
|
LLViewerRegion::PARTITION_BRIDGE,
|
||||||
|
LLViewerRegion::PARTITION_AVATAR
|
||||||
|
};
|
||||||
|
|
||||||
LLOctreeDirty dirty;
|
LLOctreeDirty dirty;
|
||||||
|
for (LLViewerRegion* region : LLWorld::getInstance()->getRegionList())
|
||||||
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME);
|
{
|
||||||
dirty.traverse(part->mOctree);
|
for (U32 type : types_to_traverse)
|
||||||
|
{
|
||||||
part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
|
LLSpatialPartition* part = region->getSpatialPartition(type);
|
||||||
dirty.traverse(part->mOctree);
|
dirty.traverse(part->mOctree);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
<string name="name_default_system_device">
|
<string name="name_default_system_device">
|
||||||
Standardsystemgerät
|
Standardsystemgerät
|
||||||
</string>
|
</string>
|
||||||
|
<string name="device_not_loaded">
|
||||||
|
Gerät nicht geladen
|
||||||
|
</string>
|
||||||
<text name="Input">
|
<text name="Input">
|
||||||
Eingabe
|
Eingabe
|
||||||
</text>
|
</text>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@
|
||||||
name="name_default_system_device">
|
name="name_default_system_device">
|
||||||
Default System Device
|
Default System Device
|
||||||
</string>
|
</string>
|
||||||
|
<string
|
||||||
|
name="device_not_loaded">
|
||||||
|
Device not loaded
|
||||||
|
</string>
|
||||||
<icon
|
<icon
|
||||||
follows="left|top"
|
follows="left|top"
|
||||||
height="18"
|
height="18"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue