Merge branch 'DRTVWR-588-maint-W' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/newview/llviewermenu.cpp
#	indra/newview/skins/default/xui/en/floater_scene_load_stats.xml
#	indra/newview/skins/default/xui/en/floater_world_map.xml
#	indra/newview/skins/default/xui/en/menu_viewer.xml
#	indra/newview/skins/default/xui/en/notifications.xml
#	indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
#	indra/newview/skins/default/xui/en/panel_preferences_sound.xml
#	indra/newview/skins/default/xui/en/panel_profile_pick.xml
#	indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
#	indra/newview/skins/default/xui/en/sidepanel_item_info.xml
master
Ansariel 2024-01-26 14:29:44 +01:00
commit 04d32cf7eb
38 changed files with 258 additions and 137 deletions

View File

@ -24,6 +24,7 @@ jobs:
outputs: outputs:
viewer_channel: ${{ steps.build.outputs.viewer_channel }} viewer_channel: ${{ steps.build.outputs.viewer_channel }}
viewer_version: ${{ steps.build.outputs.viewer_version }} viewer_version: ${{ steps.build.outputs.viewer_version }}
viewer_branch: ${{ steps.which-branch.outputs.branch }}
imagename: ${{ steps.build.outputs.imagename }} imagename: ${{ steps.build.outputs.imagename }}
env: env:
AUTOBUILD_ADDRSIZE: 64 AUTOBUILD_ADDRSIZE: 64
@ -33,6 +34,9 @@ jobs:
AUTOBUILD_GITHUB_TOKEN: ${{ secrets.SHARED_AUTOBUILD_GITHUB_TOKEN }} AUTOBUILD_GITHUB_TOKEN: ${{ secrets.SHARED_AUTOBUILD_GITHUB_TOKEN }}
AUTOBUILD_INSTALLABLE_CACHE: ${{ github.workspace }}/.autobuild-installables AUTOBUILD_INSTALLABLE_CACHE: ${{ github.workspace }}/.autobuild-installables
AUTOBUILD_VARIABLES_FILE: ${{ github.workspace }}/.build-variables/variables AUTOBUILD_VARIABLES_FILE: ${{ github.workspace }}/.build-variables/variables
# Direct autobuild to store vcs_url, vcs_branch and vcs_revision in
# autobuild-package.xml.
AUTOBUILD_VCS_INFO: "true"
AUTOBUILD_VSVER: "170" AUTOBUILD_VSVER: "170"
DEVELOPER_DIR: ${{ matrix.developer_dir }} DEVELOPER_DIR: ${{ matrix.developer_dir }}
# Ensure that Linden viewer builds engage Bugsplat. # Ensure that Linden viewer builds engage Bugsplat.
@ -70,7 +74,7 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
repository: secondlife/build-variables repository: secondlife/build-variables
ref: viewer ref: master
path: .build-variables path: .build-variables
- name: Checkout master-message-template - name: Checkout master-message-template
@ -96,10 +100,17 @@ jobs:
if: runner.os == 'Windows' if: runner.os == 'Windows'
run: choco install nsis-unicode run: choco install nsis-unicode
- name: Determine source branch
id: which-branch
uses: secondlife/viewer-build-util/which-branch@v1
with:
token: ${{ github.token }}
- name: Build - name: Build
id: build id: build
shell: bash shell: bash
env: env:
AUTOBUILD_VCS_BRANCH: ${{ steps.which-branch.outputs.branch }}
RUNNER_OS: ${{ runner.os }} RUNNER_OS: ${{ runner.os }}
run: | run: |
# set up things the viewer's build.sh script expects # set up things the viewer's build.sh script expects
@ -150,7 +161,7 @@ jobs:
} }
repo_branch() repo_branch()
{ {
git -C "$1" branch | grep '^* ' | cut -c 3- echo "$AUTOBUILD_VCS_BRANCH"
} }
record_dependencies_graph() record_dependencies_graph()
{ {
@ -324,7 +335,7 @@ jobs:
version: ${{ needs.build.outputs.viewer_version }} version: ${{ needs.build.outputs.viewer_version }}
release: release:
needs: [sign-and-package-windows, sign-and-package-mac] needs: [build, sign-and-package-windows, sign-and-package-mac]
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_') if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_')
steps: steps:
@ -365,8 +376,10 @@ jobs:
body: | body: |
${{ needs.build.outputs.viewer_channel }} ${{ needs.build.outputs.viewer_channel }}
${{ needs.build.outputs.viewer_version }} ${{ needs.build.outputs.viewer_version }}
${{ needs.build.outputs.viewer_branch }}
prerelease: true prerelease: true
generate_release_notes: true generate_release_notes: true
append_body: true
# the only reason we generate a GH release is to post build products # the only reason we generate a GH release is to post build products
fail_on_unmatched_files: true fail_on_unmatched_files: true
files: | files: |

View File

@ -112,7 +112,8 @@ installer_CYGWIN()
fi fi
} }
[[ -n "$GITHUB_OUTPUT" ]] || fatal "Need to export GITHUB_OUTPUT" # if someone wants to run build.sh outside the GitHub environment
[[ -n "$GITHUB_OUTPUT" ]] || export GITHUB_OUTPUT='/dev/null'
# The following is based on the Warning for GitHub multiline output strings: # The following is based on the Warning for GitHub multiline output strings:
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)

View File

@ -119,11 +119,11 @@ public:
* ClassicCallback must not itself be copied or moved! Once you've passed * ClassicCallback must not itself be copied or moved! Once you've passed
* get_userdata() to some API, this object MUST remain at that address. * get_userdata() to some API, this object MUST remain at that address.
*/ */
// However, we can't yet count on C++17 Class Template Argument Deduction, // However, makeClassicCallback() is useful for deducing the CALLABLE
// which means makeClassicCallback() is still useful, which means we MUST // type, which means we MUST be able to return one to construct into
// be able to return one to construct into caller's instance (move ctor). // caller's instance (move ctor). Possible defense: bool 'referenced' data
// Possible defense: bool 'referenced' data member set by get_userdata(), // member set by get_userdata(), with an llassert_always(! referenced)
// with an llassert_always(! referenced) check in the move constructor. // check in the move constructor.
ClassicCallback(ClassicCallback const&) = delete; ClassicCallback(ClassicCallback const&) = delete;
ClassicCallback(ClassicCallback&&) = default; // delete; ClassicCallback(ClassicCallback&&) = default; // delete;
ClassicCallback& operator=(ClassicCallback const&) = delete; ClassicCallback& operator=(ClassicCallback const&) = delete;

View File

@ -58,7 +58,9 @@
* to restore uniform distribution. * to restore uniform distribution.
*/ */
static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); // gRandomGenerator is a stateful static object, which is therefore not
// inherently thread-safe.
static thread_local LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed());
// no default implementation, only specific F64 and F32 specializations // no default implementation, only specific F64 and F32 specializations
template <typename REAL> template <typename REAL>
@ -71,7 +73,7 @@ inline F64 ll_internal_random<F64>()
// CPUs (or at least multi-threaded processes) seem to // CPUs (or at least multi-threaded processes) seem to
// occasionally give an obviously incorrect random number -- like // occasionally give an obviously incorrect random number -- like
// 5^15 or something. Sooooo, clamp it as described above. // 5^15 or something. Sooooo, clamp it as described above.
F64 rv = gRandomGenerator(); F64 rv{ gRandomGenerator() };
if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0); if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0);
return rv; return rv;
} }
@ -79,7 +81,13 @@ inline F64 ll_internal_random<F64>()
template <> template <>
inline F32 ll_internal_random<F32>() inline F32 ll_internal_random<F32>()
{ {
return F32(ll_internal_random<F64>()); // *HACK: clamp the result as described above.
// Per Monty, it's important to clamp using the correct fmodf() rather
// than expanding to F64 for fmod() and then truncating back to F32. Prior
// to this change, we were getting sporadic ll_frand() == 1.0 results.
F32 rv{ narrow(gRandomGenerator()) };
if(!((rv >= 0.0f) && (rv < 1.0f))) return fmodf(rv, 1.0f);
return rv;
} }
/*------------------------------ F64 aliases -------------------------------*/ /*------------------------------ F64 aliases -------------------------------*/

View File

@ -113,15 +113,16 @@ LL_COMMON_API bool on_main_thread()
return (LLThread::currentID() == main_thread()); return (LLThread::currentID() == main_thread());
} }
LL_COMMON_API void assert_main_thread() LL_COMMON_API bool assert_main_thread()
{ {
auto curr = LLThread::currentID(); auto curr = LLThread::currentID();
auto main = main_thread(); auto main = main_thread();
if (curr != main) if (curr == main)
{ return true;
LL_WARNS() << "Illegal execution from thread id " << curr
<< " outside main thread " << main << LL_ENDL; LL_WARNS() << "Illegal execution from thread id " << curr
} << " outside main thread " << main << LL_ENDL;
return false;
} }
// this function has become moot // this function has become moot

View File

@ -152,7 +152,7 @@ public:
//============================================================================ //============================================================================
extern LL_COMMON_API void assert_main_thread(); extern LL_COMMON_API bool assert_main_thread();
extern LL_COMMON_API bool on_main_thread(); extern LL_COMMON_API bool on_main_thread();
#endif // LL_LLTHREAD_H #endif // LL_LLTHREAD_H

View File

@ -156,18 +156,15 @@ typedef int intptr_t;
* type. * type.
*/ */
// narrow_holder is a struct that accepts the passed value as its original // narrow_holder is a struct that accepts the passed value as its original
// type and provides templated conversion functions to other types. Once we're // type and provides templated conversion functions to other types.
// building with compilers that support Class Template Argument Deduction, we
// can rename this class template 'narrow' and eliminate the narrow() factory
// function below.
template <typename FROM> template <typename FROM>
class narrow_holder class narrow
{ {
private: private:
FROM mValue; FROM mValue;
public: public:
narrow_holder(FROM value): mValue(value) {} narrow(FROM value): mValue(value) {}
/*---------------------- Narrowing unsigned to signed ----------------------*/ /*---------------------- Narrowing unsigned to signed ----------------------*/
template <typename TO, template <typename TO,
@ -207,13 +204,4 @@ public:
} }
}; };
/// narrow() factory function returns a narrow_holder<FROM>(), which can be
/// implicitly converted to the target type.
template <typename FROM>
inline
narrow_holder<FROM> narrow(FROM value)
{
return { value };
}
#endif #endif

View File

@ -60,12 +60,15 @@ struct sleepy_robin: public boost::fibers::algo::round_robin
/***************************************************************************** /*****************************************************************************
* ThreadPoolBase * ThreadPoolBase
*****************************************************************************/ *****************************************************************************/
LL::ThreadPoolBase::ThreadPoolBase(const std::string& name, size_t threads, LL::ThreadPoolBase::ThreadPoolBase(const std::string& name,
WorkQueueBase* queue): size_t threads,
WorkQueueBase* queue,
bool auto_shutdown):
super(name), super(name),
mName("ThreadPool:" + name), mName("ThreadPool:" + name),
mThreadCount(getConfiguredWidth(name, threads)), mThreadCount(getConfiguredWidth(name, threads)),
mQueue(queue) mQueue(queue),
mAutomaticShutdown(auto_shutdown)
{} {}
void LL::ThreadPoolBase::start() void LL::ThreadPoolBase::start()
@ -80,6 +83,14 @@ void LL::ThreadPoolBase::start()
run(tname); run(tname);
}); });
} }
if (!mAutomaticShutdown)
{
// Some threads, like main window's might need to run a bit longer
// to wait for a proper shutdown message
return;
}
// Listen on "LLApp", and when the app is shutting down, close the queue // Listen on "LLApp", and when the app is shutting down, close the queue
// and join the workers. // and join the workers.
LLEventPumps::instance().obtain("LLApp").listen( LLEventPumps::instance().obtain("LLApp").listen(

View File

@ -40,7 +40,7 @@ namespace LL
* overrides this parameter. * overrides this parameter.
*/ */
ThreadPoolBase(const std::string& name, size_t threads, ThreadPoolBase(const std::string& name, size_t threads,
WorkQueueBase* queue); WorkQueueBase* queue, bool auto_shutdown = true);
virtual ~ThreadPoolBase(); virtual ~ThreadPoolBase();
/** /**
@ -87,6 +87,7 @@ namespace LL
protected: protected:
std::unique_ptr<WorkQueueBase> mQueue; std::unique_ptr<WorkQueueBase> mQueue;
bool mAutomaticShutdown;
private: private:
void run(const std::string& name); void run(const std::string& name);
@ -117,8 +118,11 @@ namespace LL
* Constraining the queue can cause a submitter to block. Do not * Constraining the queue can cause a submitter to block. Do not
* constrain any ThreadPool accepting work from the main thread. * constrain any ThreadPool accepting work from the main thread.
*/ */
ThreadPoolUsing(const std::string& name, size_t threads=1, size_t capacity=1024*1024): ThreadPoolUsing(const std::string& name,
ThreadPoolBase(name, threads, new queue_t(name, capacity)) size_t threads=1,
size_t capacity=1024*1024,
bool auto_shutdown = true):
ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown)
{} {}
~ThreadPoolUsing() override {} ~ThreadPoolUsing() override {}

View File

@ -35,8 +35,10 @@ class ImageRequest
{ {
public: public:
ImageRequest(const LLPointer<LLImageFormatted>& image, ImageRequest(const LLPointer<LLImageFormatted>& image,
S32 discard, BOOL needs_aux, S32 discard,
const LLPointer<LLImageDecodeThread::Responder>& responder); BOOL needs_aux,
const LLPointer<LLImageDecodeThread::Responder>& responder,
U32 request_id);
virtual ~ImageRequest(); virtual ~ImageRequest();
/*virtual*/ bool processRequest(); /*virtual*/ bool processRequest();
@ -48,6 +50,7 @@ private:
// input // input
LLPointer<LLImageFormatted> mFormattedImage; LLPointer<LLImageFormatted> mFormattedImage;
S32 mDiscardLevel; S32 mDiscardLevel;
U32 mRequestId;
BOOL mNeedsAux; BOOL mNeedsAux;
// output // output
LLPointer<LLImageRaw> mDecodedImageRaw; LLPointer<LLImageRaw> mDecodedImageRaw;
@ -62,6 +65,7 @@ private:
// MAIN THREAD // MAIN THREAD
LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/) LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/)
: mDecodeCount(0)
{ {
mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8)); mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8));
mThreadPool->start(); mThreadPool->start();
@ -92,9 +96,10 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
U32 decode_id = ++mDecodeCount;
// Instantiate the ImageRequest right in the lambda, why not? // Instantiate the ImageRequest right in the lambda, why not?
bool posted = mThreadPool->getQueue().post( bool posted = mThreadPool->getQueue().post(
[req = ImageRequest(image, discard, needs_aux, responder)] [req = ImageRequest(image, discard, needs_aux, responder, decode_id)]
() mutable () mutable
{ {
auto done = req.processRequest(); auto done = req.processRequest();
@ -103,13 +108,10 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(
if (! posted) if (! posted)
{ {
LL_DEBUGS() << "Tried to start decoding on shutdown" << LL_ENDL; LL_DEBUGS() << "Tried to start decoding on shutdown" << LL_ENDL;
// should this return 0? return 0;
} }
// It's important to our consumer (LLTextureFetchWorker) that we return a return decode_id;
// nonzero handle. It is NOT important that the nonzero handle be unique:
// nothing is ever done with it except to compare it to zero, or zero it.
return 17;
} }
void LLImageDecodeThread::shutdown() void LLImageDecodeThread::shutdown()
@ -123,15 +125,18 @@ LLImageDecodeThread::Responder::~Responder()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ImageRequest::ImageRequest(const LLPointer<LLImageFormatted>& image, ImageRequest::ImageRequest(const LLPointer<LLImageFormatted>& image,
S32 discard, BOOL needs_aux, S32 discard,
const LLPointer<LLImageDecodeThread::Responder>& responder) BOOL needs_aux,
const LLPointer<LLImageDecodeThread::Responder>& responder,
U32 request_id)
: mFormattedImage(image), : mFormattedImage(image),
mDiscardLevel(discard), mDiscardLevel(discard),
mNeedsAux(needs_aux), mNeedsAux(needs_aux),
mDecodedRaw(FALSE), mDecodedRaw(FALSE),
mDecodedAux(FALSE), mDecodedAux(FALSE),
mResponder(responder) mResponder(responder),
mRequestId(request_id)
{ {
} }
@ -211,7 +216,7 @@ void ImageRequest::finishRequest(bool completed)
if (mResponder.notNull()) if (mResponder.notNull())
{ {
bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux);
mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux); mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux, mRequestId);
} }
// Will automatically be deleted // Will automatically be deleted
} }

View File

@ -39,7 +39,7 @@ public:
protected: protected:
virtual ~Responder(); virtual ~Responder();
public: public:
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0;
}; };
public: public:
@ -53,6 +53,7 @@ public:
const LLPointer<Responder>& responder); const LLPointer<Responder>& responder);
size_t getPending(); size_t getPending();
size_t update(F32 max_time_ms); size_t update(F32 max_time_ms);
S32 getTotalDecodeCount() { return mDecodeCount; }
void shutdown(); void shutdown();
private: private:
@ -60,6 +61,7 @@ private:
// LLQueuedThread - instead this is the API by which we submit work to the // LLQueuedThread - instead this is the API by which we submit work to the
// "ImageDecode" ThreadPool. // "ImageDecode" ThreadPool.
std::unique_ptr<LL::ThreadPool> mThreadPool; std::unique_ptr<LL::ThreadPool> mThreadPool;
LLAtomicU32 mDecodeCount;
}; };
#endif #endif

View File

@ -386,12 +386,3 @@ std::ostream& operator<< (std::ostream& os, LLXfer &hh)
os << hh.getFileName() ; os << hh.getFileName() ;
return os; return os;
} }

View File

@ -412,8 +412,8 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
using FuncType = std::function<void()>; using FuncType = std::function<void()>;
// call GetMessage() and pull enqueue messages for later processing // call GetMessage() and pull enqueue messages for later processing
void gatherInput(); void gatherInput();
HWND mWindowHandle = NULL; HWND mWindowHandleThrd = NULL;
HDC mhDC = 0; HDC mhDCThrd = 0;
// *HACK: Attempt to prevent startup crashes by deferring memory accounting // *HACK: Attempt to prevent startup crashes by deferring memory accounting
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18 // until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
@ -989,23 +989,23 @@ void LLWindowWin32::close()
LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
mWindowThread->post([=]() mWindowThread->post([this, self = mWindowThread]()
{ {
if (IsWindow(mWindowHandle)) if (IsWindow(self->mWindowHandleThrd))
{ {
if (mhDC) if (self->mhDCThrd)
{ {
if (!ReleaseDC(mWindowHandle, mhDC)) if (!ReleaseDC(self->mWindowHandleThrd, self->mhDCThrd))
{ {
LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL; LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
} }
} }
// Make sure we don't leave a blank toolbar button. // Make sure we don't leave a blank toolbar button.
ShowWindow(mWindowHandle, SW_HIDE); ShowWindow(self->mWindowHandleThrd, SW_HIDE);
// This causes WM_DESTROY to be sent *immediately* // This causes WM_DESTROY to be sent *immediately*
if (!destroy_window_handler(mWindowHandle)) if (!destroy_window_handler(self->mWindowHandleThrd))
{ {
OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"),
mCallbacks->translateString("MBShutdownErr"), mCallbacks->translateString("MBShutdownErr"),
@ -1017,17 +1017,18 @@ void LLWindowWin32::close()
// Something killed the window while we were busy destroying gl or handle somehow got broken // Something killed the window while we were busy destroying gl or handle somehow got broken
LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
} }
self->mWindowHandleThrd = NULL;
self->mhDCThrd = NULL;
self->mGLReady = false;
}); });
mhDC = NULL;
mWindowHandle = NULL;
// Window thread might be waiting for a getMessage(), give it // Window thread might be waiting for a getMessage(), give it
// a push to enshure it will process destroy_window_handler // a push to enshure it will process destroy_window_handler
kickWindowThread(); kickWindowThread();
// Even though the above lambda might not yet have run, we've already
// bound mWindowHandle into it by value, which should suffice for the
// operations we're asking. That's the last time WE should touch it.
mhDC = NULL;
mWindowHandle = NULL;
mWindowThread->close(); mWindowThread->close();
} }
@ -1781,8 +1782,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
() ()
{ {
LL_DEBUGS("Window") << "recreateWindow(): window_work entry" << LL_ENDL; LL_DEBUGS("Window") << "recreateWindow(): window_work entry" << LL_ENDL;
self->mWindowHandle = 0; self->mWindowHandleThrd = 0;
self->mhDC = 0; self->mhDCThrd = 0;
if (oldWindowHandle) if (oldWindowHandle)
{ {
@ -1816,20 +1817,20 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
{ {
// Failed to create window: clear the variables. This // Failed to create window: clear the variables. This
// assignment is valid because we're running on mWindowThread. // assignment is valid because we're running on mWindowThread.
self->mWindowHandle = NULL; self->mWindowHandleThrd = NULL;
self->mhDC = 0; self->mhDCThrd = 0;
} }
else else
{ {
// Update mWindowThread's own mWindowHandle and mhDC. // Update mWindowThread's own mWindowHandle and mhDC.
self->mWindowHandle = handle; self->mWindowHandleThrd = handle;
self->mhDC = GetDC(handle); self->mhDCThrd = GetDC(handle);
} }
updateWindowRect(); updateWindowRect();
// It's important to wake up the future either way. // It's important to wake up the future either way.
promise.set_value(std::make_pair(self->mWindowHandle, self->mhDC)); promise.set_value(std::make_pair(self->mWindowHandleThrd, self->mhDCThrd));
LL_DEBUGS("Window") << "recreateWindow(): window_work done" << LL_ENDL; LL_DEBUGS("Window") << "recreateWindow(): window_work done" << LL_ENDL;
}; };
// But how we pass window_work to the window thread depends on whether we // But how we pass window_work to the window thread depends on whether we
@ -4699,7 +4700,7 @@ void LLWindowWin32::getWindowChrome( U32 &aChromeW, U32 &aChromeH )
#endif // LL_WINDOWS #endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
: LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
{ {
LL::ThreadPool::start(); LL::ThreadPool::start();
} }
@ -4855,7 +4856,7 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D()
{ {
if (!mGLReady) { return; } if (!mGLReady) { return; }
if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandle != 0) if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandleThrd != 0)
{ {
mD3D = Direct3DCreate9(D3D_SDK_VERSION); mD3D = Direct3DCreate9(D3D_SDK_VERSION);
@ -4865,7 +4866,7 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D()
d3dpp.Windowed = TRUE; d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice); HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandleThrd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice);
if (FAILED(res)) if (FAILED(res))
{ {
@ -4970,7 +4971,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
// lazily call initD3D inside this loop to catch when mGLReady has been set to true // lazily call initD3D inside this loop to catch when mGLReady has been set to true
initDX(); initDX();
if (mWindowHandle != 0) if (mWindowHandleThrd != 0)
{ {
// lazily call initD3D inside this loop to catch when mWindowHandle has been set, and mGLReady has been set to true // lazily call initD3D inside this loop to catch when mWindowHandle has been set, and mGLReady has been set to true
// *TODO: Shutdown if this fails when mWindowHandle exists // *TODO: Shutdown if this fails when mWindowHandle exists
@ -4978,16 +4979,16 @@ void LLWindowWin32::LLWindowWin32Thread::run()
MSG msg; MSG msg;
BOOL status; BOOL status;
if (mhDC == 0) if (mhDCThrd == 0)
{ {
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - PeekMessage"); LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - PeekMessage");
logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")"); logger.onChange("PeekMessage(", std::hex, mWindowHandleThrd, ")");
status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); status = PeekMessage(&msg, mWindowHandleThrd, 0, 0, PM_REMOVE);
} }
else else
{ {
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - GetMessage"); LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - GetMessage");
logger.always("GetMessage(", std::hex, mWindowHandle, ")"); logger.always("GetMessage(", std::hex, mWindowHandleThrd, ")");
status = GetMessage(&msg, NULL, 0, 0); status = GetMessage(&msg, NULL, 0, 0);
} }
if (status > 0) if (status > 0)

View File

@ -2214,6 +2214,9 @@ bool LLAppViewer::cleanup()
LL_INFOS() << "ViewerWindow deleted" << LL_ENDL; LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
} }
LLSplashScreen::show();
LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL; LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone // viewer UI relies on keyboard so keep it aound until viewer UI isa gone
@ -2530,6 +2533,8 @@ bool LLAppViewer::cleanup()
// deleteSingleton() methods. // deleteSingleton() methods.
LLSingletonBase::deleteAll(); LLSingletonBase::deleteAll();
LLSplashScreen::hide();
LL_INFOS() << "Goodbye!" << LL_ENDL; LL_INFOS() << "Goodbye!" << LL_ENDL;
removeDumpDir(); removeDumpDir();
@ -5918,6 +5923,9 @@ void LLAppViewer::idleShutdown()
&& gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
&& !logoutRequestSent()) && !logoutRequestSent())
{ {
gViewerWindow->setShowProgress(TRUE, !gSavedSettings.getBOOL("FSDisableLogoutScreens"));
gViewerWindow->setProgressPercent(100.f);
gViewerWindow->setProgressString(LLTrans::getString("LoggingOut"));
return; return;
} }
@ -6336,6 +6344,13 @@ void LLAppViewer::forceErrorSoftwareException()
LLTHROW(LLException("User selected Force Software Exception")); LLTHROW(LLException("User selected Force Software Exception"));
} }
void LLAppViewer::forceErrorOSSpecificException()
{
// Virtual, MacOS only
const std::string exception_text = "User selected Force OS Exception, Not implemented on this OS";
throw std::runtime_error(exception_text);
}
void LLAppViewer::forceErrorDriverCrash() void LLAppViewer::forceErrorDriverCrash()
{ {
LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL; LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL;

View File

@ -153,6 +153,7 @@ public:
virtual void forceErrorBadMemoryAccess(); virtual void forceErrorBadMemoryAccess();
virtual void forceErrorInfiniteLoop(); virtual void forceErrorInfiniteLoop();
virtual void forceErrorSoftwareException(); virtual void forceErrorSoftwareException();
virtual void forceErrorOSSpecificException();
virtual void forceErrorDriverCrash(); virtual void forceErrorDriverCrash();
// <FS:Ansariel> Wrongly merged back in by LL // <FS:Ansariel> Wrongly merged back in by LL
//virtual void forceErrorCoroutineCrash(); //virtual void forceErrorCoroutineCrash();

View File

@ -33,4 +33,6 @@
//Why? Because BOOL //Why? Because BOOL
void launchApplication(const std::string* app_name, const std::vector<std::string>* args); void launchApplication(const std::string* app_name, const std::vector<std::string>* args);
void force_ns_sxeption();
#endif // LL_LLAPPVIEWERMACOSX_OBJC_H #endif // LL_LLAPPVIEWERMACOSX_OBJC_H

View File

@ -71,3 +71,9 @@ void launchApplication(const std::string* app_name, const std::vector<std::strin
[pool release]; [pool release];
return; return;
} }
void force_ns_sxeption()
{
NSException *exception = [NSException exceptionWithName:@"Forced NSException" reason:nullptr userInfo:nullptr];
@throw exception;
}

View File

@ -250,6 +250,11 @@ bool LLAppViewerMacOSX::init()
return LLAppViewer::init(); return LLAppViewer::init();
} }
void LLAppViewerMacOSX::forceErrorOSSpecificException()
{
force_ns_sxeption();
}
// MacOSX may add and addition command line arguement for the process serial number. // MacOSX may add and addition command line arguement for the process serial number.
// The option takes a form like '-psn_0_12345'. The following method should be able to recognize // The option takes a form like '-psn_0_12345'. The following method should be able to recognize
// and either ignore or return a pair of values for the option. // and either ignore or return a pair of values for the option.

View File

@ -42,6 +42,8 @@ public:
// //
virtual bool init(); // Override to do application initialization virtual bool init(); // Override to do application initialization
virtual void forceErrorOSSpecificException();
protected: protected:
virtual bool restoreErrorTrap(); virtual bool restoreErrorTrap();

View File

@ -352,13 +352,13 @@ private:
} }
// Threads: Tid // Threads: Tid
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id)
{ {
LL_PROFILE_ZONE_SCOPED; LL_PROFILE_ZONE_SCOPED;
LLTextureFetchWorker* worker = mFetcher->getWorker(mID); LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker) if (worker)
{ {
worker->callbackDecoded(success, raw, aux); worker->callbackDecoded(success, raw, aux, request_id);
} }
} }
private: private:
@ -402,7 +402,7 @@ public:
void callbackCacheWrite(bool success); void callbackCacheWrite(bool success);
// Threads: Tid // Threads: Tid
void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id);
// Threads: T* // Threads: T*
void setGetStatus(LLCore::HttpStatus status, const std::string& reason) void setGetStatus(LLCore::HttpStatus status, const std::string& reason)
@ -1961,8 +1961,22 @@ bool LLTextureFetchWorker::doWork(S32 param)
setState(DECODE_IMAGE_UPDATE); setState(DECODE_IMAGE_UPDATE);
LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard
<< " All Data: " << mHaveAllData << LL_ENDL; << " All Data: " << mHaveAllData << LL_ENDL;
mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux,
new DecodeResponder(mFetcher, mID, this)); // In case worked manages to request decode, be shut down,
// then init and request decode again with first decode
// still in progress, assign a sufficiently unique id
mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage,
discard,
mNeedsAux,
new DecodeResponder(mFetcher, mID, this));
if (mDecodeHandle == 0)
{
// Abort, failed to put into queue.
// Happens if viewer is shutting down
setState(DONE);
LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: failed to post for decoding" << LL_ENDL;
return true;
}
// fall though // fall though
} }
@ -2530,16 +2544,24 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Threads: Tid // Threads: Tid
void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id)
{ {
LLMutexLock lock(&mWorkMutex); // +Mw LLMutexLock lock(&mWorkMutex); // +Mw
if (mDecodeHandle == 0) if (mDecodeHandle == 0)
{ {
return; // aborted, ignore return; // aborted, ignore
} }
if (mDecodeHandle != decode_id)
{
// Queue doesn't support canceling old requests.
// This shouldn't normally happen, but in case it's possible that a worked
// will request decode, be aborted, reinited then start a new decode
LL_DEBUGS(LOG_TXT) << mID << " received obsolete decode's callback" << LL_ENDL;
return; // ignore
}
if (mState != DECODE_IMAGE_UPDATE) if (mState != DECODE_IMAGE_UPDATE)
{ {
// LL_WARNS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; LL_DEBUGS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL;
mDecodeHandle = 0; mDecodeHandle = 0;
return; return;
} }

View File

@ -355,6 +355,7 @@ void force_error_llerror(void *);
void force_error_bad_memory_access(void *); void force_error_bad_memory_access(void *);
void force_error_infinite_loop(void *); void force_error_infinite_loop(void *);
void force_error_software_exception(void *); void force_error_software_exception(void *);
void force_error_os_exception(void*);
void force_error_driver_crash(void *); void force_error_driver_crash(void *);
void force_error_coroutine_crash(void *); void force_error_coroutine_crash(void *);
void force_error_thread_crash(void *); void force_error_thread_crash(void *);
@ -2738,6 +2739,15 @@ class LLAdvancedForceErrorSoftwareException : public view_listener_t
} }
}; };
class LLAdvancedForceOSException: public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
force_error_os_exception(NULL);
return true;
}
};
class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t
{ {
bool handleEvent(const LLSD& userdata) bool handleEvent(const LLSD& userdata)
@ -3891,6 +3901,15 @@ bool enable_object_select_in_pathfinding_characters()
return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters();
} }
bool enable_os_exception()
{
#if LL_DARWIN
return true;
#else
return false;
#endif
}
class LLSelfRemoveAllAttachments : public view_listener_t class LLSelfRemoveAllAttachments : public view_listener_t
{ {
bool handleEvent(const LLSD& userdata) bool handleEvent(const LLSD& userdata)
@ -10724,6 +10743,11 @@ void force_error_software_exception(void *)
LLAppViewer::instance()->forceErrorSoftwareException(); LLAppViewer::instance()->forceErrorSoftwareException();
} }
void force_error_os_exception(void*)
{
LLAppViewer::instance()->forceErrorOSSpecificException();
}
void force_error_driver_crash(void *) void force_error_driver_crash(void *)
{ {
LLAppViewer::instance()->forceErrorDriverCrash(); LLAppViewer::instance()->forceErrorDriverCrash();
@ -12402,6 +12426,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro");
view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
view_listener_t::addMenu(new LLAdvancedForceOSException(), "Advanced.ForceErrorOSException");
view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro");
view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
// <FS:Ansariel> Wrongly merged back in by LL // <FS:Ansariel> Wrongly merged back in by LL
@ -12629,6 +12654,7 @@ void initialize_menus()
enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets)); enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets));
commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects)); commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects));
enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters)); enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters));
enable.add("Advanced.EnableErrorOSException", boost::bind(&enable_os_exception));
enable.add("EnableBridgeFunction", boost::bind(&enable_bridge_function)); // <FS:CR> enable.add("EnableBridgeFunction", boost::bind(&enable_bridge_function)); // <FS:CR>
view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible"); view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");

View File

@ -880,10 +880,17 @@ void LLViewerRegion::saveObjectCache()
mCacheDirty = FALSE; mCacheDirty = FALSE;
} }
// Map of LLVOCacheEntry takes time to release, store map for cleanup on idle if (LLAppViewer::instance()->isQuitting())
sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end()); {
mImpl->mCacheMap.clear(); mImpl->mCacheMap.clear();
// TODO - probably need to do the same for overrides cache }
else
{
// Map of LLVOCacheEntry takes time to release, store map for cleanup on idle
sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end());
mImpl->mCacheMap.clear();
// TODO - probably need to do the same for overrides cache
}
} }
void LLViewerRegion::sendMessage() void LLViewerRegion::sendMessage()

View File

@ -20,7 +20,7 @@
<check_box label="Soundquellen" name="sounds"/> <check_box label="Soundquellen" name="sounds"/>
<check_box label="Partikelquellen" name="particles"/> <check_box label="Partikelquellen" name="particles"/>
<check_box label="Medienquellen" name="moapbeacon"/> <check_box label="Medienquellen" name="moapbeacon"/>
<text name="label_objects"> <text name="label_direction">
Zeige Richtung zu: Zeige Richtung zu:
</text> </text>
<check_box label="Sonne" name="sun"/> <check_box label="Sonne" name="sun"/>

View File

@ -17,6 +17,8 @@
<stat_view label="Textur" name="texture"> <stat_view label="Textur" name="texture">
<stat_bar label="Cache-Trefferrate" name="texture_cache_hits"/> <stat_bar label="Cache-Trefferrate" name="texture_cache_hits"/>
<stat_bar label="Cache-Leselatenz" name="texture_cache_read_latency"/> <stat_bar label="Cache-Leselatenz" name="texture_cache_read_latency"/>
<stat_bar label="Cache-Dekodierlatenz" name="texture_decode_latency"/>
<stat_bar label="Cache-Schreiblatenz" name="texture_write_latency"/>
<stat_bar label="Anzahl" name="numimagesstat"/> <stat_bar label="Anzahl" name="numimagesstat"/>
<stat_bar label="Rohanzahl" name="numrawimagesstat"/> <stat_bar label="Rohanzahl" name="numrawimagesstat"/>
</stat_view> </stat_view>

View File

@ -49,7 +49,7 @@
<radio_item label="Google Translate" name="google"/> <radio_item label="Google Translate" name="google"/>
<radio_item label="DeepL Translator" name="deepl"/> <radio_item label="DeepL Translator" name="deepl"/>
</radio_group> </radio_group>
<text name="google_links_text"> <text name="azure_links_text">
[https://learn.microsoft.com/de-de/azure/cognitive-services/translator/create-translator-resource Einrichtung] [https://learn.microsoft.com/de-de/azure/cognitive-services/translator/create-translator-resource Einrichtung]
</text> </text>
<text name="azure_api_endoint_label"> <text name="azure_api_endoint_label">

View File

@ -18,8 +18,8 @@
Laden... Laden...
</line_editor> </line_editor>
</layout_panel> </layout_panel>
<layout_panel name="actions_lp"> <layout_panel name="util_buttons_lp">
<layout_stack name="actions_stack"> <layout_stack name="util_buttons_stack">
<layout_panel name="map_btn_lp"> <layout_panel name="map_btn_lp">
<button label="Auf Karte zeigen" name="show_on_map_btn"/> <button label="Auf Karte zeigen" name="show_on_map_btn"/>
</layout_panel> </layout_panel>

View File

@ -56,10 +56,10 @@
</layout_panel> </layout_panel>
<layout_panel name="layout_item_permissions_sale"> <layout_panel name="layout_item_permissions_sale">
<text name="permissions_label"> <text name="perm_modify">
Berechtigungen Berechtigungen
</text> </text>
<text name="perm_modify"> <text name="you_perm_modify">
Sie können: Sie können:
</text> </text>
<check_box label="Bearbeiten" name="CheckOwnerModify"/> <check_box label="Bearbeiten" name="CheckOwnerModify"/>

View File

@ -308,7 +308,7 @@ Loading...
image_pressed="Info_Press" image_pressed="Info_Press"
image_unselected="Info_Over" image_unselected="Info_Over"
left_pad="3" left_pad="3"
name="info_btn1" name="info_btn"
top_delta="-2" top_delta="-2"
width="16" /> width="16" />
<button <button

View File

@ -183,7 +183,7 @@
font="SansSerif" font="SansSerif"
left="0" left="0"
top_pad="7" top_pad="7"
name="label_objects1" name="label_direction"
text_color="White" text_color="White"
type="string"> type="string">
Show direction to: Show direction to:

View File

@ -118,7 +118,7 @@
tick_spacing="100" tick_spacing="100"
show_history="true" show_history="true"
show_bar="false"/> show_bar="false"/>
<stat_bar name="texture_decode_latency" <stat_bar name="texture_write_latency"
label="Cache Write Latency" label="Cache Write Latency"
orientation="horizontal" orientation="horizontal"
unit_label="sec" unit_label="sec"

View File

@ -161,7 +161,7 @@
layout="topleft" layout="topleft"
left="185" left="185"
length="1" length="1"
name="google_links_text" name="azure_links_text"
top_pad="-262" top_pad="-262"
type="string" type="string"
width="100"> width="100">

View File

@ -293,7 +293,7 @@
image_name="legend.tga" image_name="legend.tga"
layout="topleft" layout="topleft"
mouse_opaque="true" mouse_opaque="true"
name="square2" name="square2_auction"
left="20" left="20"
top_pad="2" top_pad="2"
width="16" /> width="16" />
@ -316,7 +316,7 @@
image_name="legend.tga" image_name="legend.tga"
layout="topleft" layout="topleft"
mouse_opaque="true" mouse_opaque="true"
name="square2" name="square2_owner"
left="20" left="20"
top_pad="-5" top_pad="-5"
width="16" /> width="16" />

View File

@ -51,19 +51,19 @@
</os> </os>
</font> </font>
<font name="SansSerif1" <font name="SansSerif"
comment="Name of bold sans-serif font" comment="Name of bold sans-serif font"
font_style="BOLD"> font_style="BOLD">
<file>DejaVuSans-Bold.ttf</file> <file>DejaVuSans-Bold.ttf</file>
</font> </font>
<font name="SansSerif2" <font name="SansSerif"
comment="Name of italic sans-serif font" comment="Name of italic sans-serif font"
font_style="ITALIC"> font_style="ITALIC">
<file>DejaVuSans-Oblique.ttf</file> <file>DejaVuSans-Oblique.ttf</file>
</font> </font>
<font name="SansSerif3" <font name="SansSerif"
comment="Name of bold italic sans-serif font" comment="Name of bold italic sans-serif font"
font_style="BOLD|ITALIC"> font_style="BOLD|ITALIC">
<file>DejaVuSans-BoldOblique.ttf</file> <file>DejaVuSans-BoldOblique.ttf</file>
@ -79,19 +79,19 @@
<file>DejaVuSans.ttf</file> <file>DejaVuSans.ttf</file>
</font> </font>
<font name="DejaVu1" <font name="DejaVu"
comment="Name of DejaVu font (bold)" comment="Name of DejaVu font (bold)"
font_style="BOLD"> font_style="BOLD">
<file>DejaVuSans-Bold.ttf</file> <file>DejaVuSans-Bold.ttf</file>
</font> </font>
<font name="DejaVu2" <font name="DejaVu"
comment="Name of DejaVu font (italic)" comment="Name of DejaVu font (italic)"
font_style="ITALIC"> font_style="ITALIC">
<file>DejaVuSans-Oblique.ttf</file> <file>DejaVuSans-Oblique.ttf</file>
</font> </font>
<font name="DejaVu3" <font name="DejaVu"
comment="Name of DejaVu font (bold italic)" comment="Name of DejaVu font (bold italic)"
font_style="BOLD|ITALIC"> font_style="BOLD|ITALIC">
<file>DejaVuSans-BoldOblique.ttf</file> <file>DejaVuSans-BoldOblique.ttf</file>
@ -108,7 +108,7 @@
</os> </os>
</font> </font>
<font name="Helvetica1" <font name="Helvetica"
comment="Name of Helvetica font (bold)" comment="Name of Helvetica font (bold)"
font_style="BOLD"> font_style="BOLD">
<file>DejaVuSans-Bold.ttf</file> <file>DejaVuSans-Bold.ttf</file>
@ -120,7 +120,7 @@
</os> </os>
</font> </font>
<font name="Helvetica2" <font name="Helvetica"
comment="Name of Helvetica font (italic)" comment="Name of Helvetica font (italic)"
font_style="ITALIC"> font_style="ITALIC">
<file>DejaVuSans-Oblique.ttf</file> <file>DejaVuSans-Oblique.ttf</file>
@ -132,7 +132,7 @@
</os> </os>
</font> </font>
<font name="Helvetica3" <font name="Helvetica"
comment="Name of Helvetica font (bold italic)" comment="Name of Helvetica font (bold italic)"
font_style="BOLD|ITALIC"> font_style="BOLD|ITALIC">
<file>DejaVuSans-BoldOblique.ttf</file> <file>DejaVuSans-BoldOblique.ttf</file>

View File

@ -4032,6 +4032,14 @@
<menu_item_call.on_click <menu_item_call.on_click
function="Advanced.ForceErrorSoftwareException" /> function="Advanced.ForceErrorSoftwareException" />
</menu_item_call> </menu_item_call>
<menu_item_call
label="Force OS Exception"
name="Force OS Exception">
<menu_item_call.on_click
function="Advanced.ForceErrorOSException" />
<menu_item_call.on_visible
function="Advanced.EnableErrorOSException" />
</menu_item_call>
<menu_item_call <menu_item_call
label="Force Software Exception in Coroutine" label="Force Software Exception in Coroutine"
name="Force Software Exception in Coroutine"> name="Force Software Exception in Coroutine">

View File

@ -6764,17 +6764,17 @@ Your trash is overflowing. This may cause problems logging in.
</notification> </notification>
<notification <notification
icon="alertmodal.tga" icon="notifytip.tga"
name="InventoryLimitReachedAISAlert" name="InventoryLimitReachedAIS"
type="alertmodal"> type="notifytip">
Your inventory is experiencing issues. Please contact support of your grid. Your inventory is experiencing issues. Please contact support of your grid.
<tag>fail</tag> <tag>fail</tag>
</notification> </notification>
<notification <notification
icon="notifytip.tga" icon="alertmodal.tga"
name="InventoryLimitReachedAIS" name="InventoryLimitReachedAISAlert"
type="notifytip"> type="alertmodal">
Your inventory is experiencing issues. Please contact support of your grid. Your inventory is experiencing issues. Please contact support of your grid.
<tag>fail</tag> <tag>fail</tag>
</notification> </notification>

View File

@ -156,7 +156,7 @@
layout="topleft" layout="topleft"
left_pad="10" left_pad="10"
top_delta="1" top_delta="1"
name="quality_lbl1" name="best_quality_lbl"
width="70"> width="70">
Best quality Best quality
</text> </text>
@ -416,7 +416,7 @@
layout="topleft" layout="topleft"
top_delta="3" top_delta="3"
left_pad="10" left_pad="10"
name="photo_desc1" name="photo_dist_det_desc"
width="180"> width="180">
(Enter value between 0.0 and 4.0) (Enter value between 0.0 and 4.0)
</text> </text>

View File

@ -138,11 +138,11 @@
<layout_panel <layout_panel
follows="all" follows="all"
layout="bottomleft" layout="bottomleft"
name="actions_lp" name="util_buttons_lp"
auto_resize="false" auto_resize="false"
height="25"> height="25">
<layout_stack <layout_stack
name="actions_stack" name="util_buttons_stack"
left="1" left="1"
right="-1" right="-1"
top="0" top="0"

View File

@ -273,7 +273,7 @@ TestString PleaseIgnore
height="15" height="15"
follows="left|top" follows="left|top"
layout="topleft" layout="topleft"
name="permissions_label" name="perm_modify"
width="200"> width="200">
Permissions Permissions
</text> </text>
@ -286,7 +286,7 @@ TestString PleaseIgnore
height="15" height="15"
follows="left|top" follows="left|top"
layout="topleft" layout="topleft"
name="perm_modify" name="you_perm_modify"
width="200"> width="200">
You can: You can:
</text> </text>