phoenix-firestorm/indra/newview/llavatarrendernotifier.cpp

221 lines
6.3 KiB
C++

/**
* @file llavatarrendernotifier.cpp
* @author andreykproductengine
* @date 2015-08-05
* @brief
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Pre-compiled headers
#include "llviewerprecompiledheaders.h"
// STL headers
// std headers
// external library headers
// other Linden headers
#include "llagentwearables.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llnotificationtemplate.h"
#include "lltimer.h"
#include "llviewercontrol.h"
#include "lltrans.h"
// associated header
#include "llavatarrendernotifier.h"
// when change exceeds this ration, notification is shown
static const F32 RENDER_ALLOWED_CHANGE_PCT = 0.1;
// wait seconds before processing over limit updates after last complexity change
static const U32 OVER_LIMIT_UPDATE_DELAY = 70;
LLAvatarRenderNotifier::LLAvatarRenderNotifier() :
mAgentsCount(0),
mOverLimitAgents(0),
mAgentComplexity(0),
mOverLimitPct(0.0f),
mLatestAgentsCount(0),
mLatestOverLimitAgents(0),
mLatestAgentComplexity(0),
mLatestOverLimitPct(0.0f),
mShowOverLimitAgents(false)
{
}
std::string LLAvatarRenderNotifier::overLimitMessage()
{
static const char* everyone_now = "av_render_everyone_now";
static const char* not_everyone = "av_render_not_everyone";
static const char* over_half = "av_render_over_half";
static const char* most = "av_render_most_of";
static const char* anyone = "av_render_anyone";
std::string message;
if ( mLatestOverLimitPct >= 99.0 )
{
message = anyone;
}
else if ( mLatestOverLimitPct >= 75.0 )
{
message = most;
}
else if ( mLatestOverLimitPct >= 50.0 )
{
message = over_half;
}
else if ( mLatestOverLimitPct > 10.0 )
{
message = not_everyone;
}
else
{
// Will be shown only after overlimit was > 0
message = everyone_now;
}
return LLTrans::getString(message);
}
void LLAvatarRenderNotifier::displayNotification()
{
static LLCachedControl<U32> expire_delay(gSavedSettings, "ShowMyComplexityChanges", 20);
LLDate expire_date(LLDate::now().secondsSinceEpoch() + expire_delay);
LLSD args;
args["AGENT_COMPLEXITY"] = LLSD::Integer(mLatestAgentComplexity);
std::string notification_name;
if (mShowOverLimitAgents)
{
std::string notification_message = overLimitMessage();
notification_name = "RegionAndAgentComplexity";
args["OVERLIMIT_MSG"] = notification_message;
}
else
{
notification_name = "AgentComplexity";
}
if (mNotificationPtr != NULL && mNotificationPtr->getName() != notification_name)
{
// since unique tag works only for same notification,
// old notification needs to be canceled manually
LLNotifications::instance().cancel(mNotificationPtr);
}
mNotificationPtr = LLNotifications::instance().add(LLNotification::Params()
.name(notification_name)
.expiry(expire_date)
.substitutions(args));
}
bool LLAvatarRenderNotifier::isNotificationVisible()
{
return mNotificationPtr != NULL && mNotificationPtr->isActive();
}
void LLAvatarRenderNotifier::updateNotification()
{
if (mAgentsCount == mLatestAgentsCount
&& mOverLimitAgents == mLatestOverLimitAgents
&& mAgentComplexity == mLatestAgentComplexity)
{
//no changes since last notification
return;
}
if (mLatestAgentComplexity == 0
|| !gAgentWearables.areWearablesLoaded())
{
// data not ready, nothing to show.
return;
}
bool display_notification = false;
bool is_visible = isNotificationVisible();
if (mLatestOverLimitPct > 0 || mOverLimitPct > 0)
{
//include 'over limit' information into notification
mShowOverLimitAgents = true;
}
else
{
// make sure that 'over limit' won't be displayed only to be hidden in a second
mShowOverLimitAgents &= is_visible;
}
if (mAgentComplexity != mLatestAgentComplexity)
{
// if we have an agent complexity update, we always display it
display_notification = true;
// next 'over limit' update should be displayed after delay to make sure information got updated at server side
mPopUpDelayTimer.resetWithExpiry(OVER_LIMIT_UPDATE_DELAY);
}
else if ( (mPopUpDelayTimer.hasExpired() || is_visible)
&& (mOverLimitPct > 0 || mLatestOverLimitPct > 0)
&& std::abs(mOverLimitPct - mLatestOverLimitPct) > mLatestOverLimitPct * RENDER_ALLOWED_CHANGE_PCT
)
{
// display in case of drop to/from zero and in case of significant (RENDER_ALLOWED_CHANGE_PCT) changes
display_notification = true;
// default timeout before next notification
static LLCachedControl<U32> pop_up_delay(gSavedSettings, "ComplexityChangesPopUpDelay", 300);
mPopUpDelayTimer.resetWithExpiry(pop_up_delay);
}
if (display_notification)
{
mAgentComplexity = mLatestAgentComplexity;
mAgentsCount = mLatestAgentsCount;
mOverLimitAgents = mLatestOverLimitAgents;
mOverLimitPct = mLatestOverLimitPct;
displayNotification();
}
}
void LLAvatarRenderNotifier::updateNotificationRegion(U32 agentcount, U32 overLimit)
{
if (agentcount == 0)
{
// Data not ready
return;
}
// save current values for later use
mLatestAgentsCount = agentcount > overLimit ? agentcount - 1 : agentcount; // subtract self
mLatestOverLimitAgents = overLimit;
mLatestOverLimitPct = mLatestAgentsCount != 0 ? ((F32)overLimit / (F32)mLatestAgentsCount) * 100.0 : 0;
updateNotification();
}
void LLAvatarRenderNotifier::updateNotificationAgent(U32 agentComplexity)
{
// save the value for use in following messages
mLatestAgentComplexity = agentComplexity;
updateNotification();
}