diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8b55d30a3..008e1d420 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -253,6 +253,7 @@ set(viewer_SOURCE_FILES llfloaterproperties.cpp llfloaterregiondebugconsole.cpp llfloaterregioninfo.cpp + llfloaterregionrestarting.cpp llfloaterreporter.cpp llfloaterscriptdebug.cpp llfloaterscriptlimits.cpp @@ -774,6 +775,7 @@ set(viewer_HEADER_FILES llfloaterproperties.h llfloaterregiondebugconsole.h llfloaterregioninfo.h + llfloaterregionrestarting.h llfloaterreporter.h llfloaterscriptdebug.h llfloaterscriptlimits.h diff --git a/indra/newview/app_settings/settings_ascent.xml b/indra/newview/app_settings/settings_ascent.xml index 1e4a735df..a6aa6f443 100644 --- a/indra/newview/app_settings/settings_ascent.xml +++ b/indra/newview/app_settings/settings_ascent.xml @@ -91,6 +91,17 @@ Value 1 + AlchemyRegionRestartShake + + Comment + Shake the screen when the region restart floater is displayed + Persist + 1 + Type + Boolean + Value + 0 + AscentPowerfulWizard Comment diff --git a/indra/newview/llfloaterregionrestarting.cpp b/indra/newview/llfloaterregionrestarting.cpp new file mode 100644 index 000000000..a94591078 --- /dev/null +++ b/indra/newview/llfloaterregionrestarting.cpp @@ -0,0 +1,171 @@ +/** + * @file llfloaterregionrestarting.cpp + * @brief Shows countdown timer during region restart + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterregionrestarting.h" + +#include "lluictrlfactory.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llenvmanager.h" +#include "llviewercontrol.h" +#include "llviewerwindow.h" + + +enum shake_state +{ + SHAKE_START, + SHAKE_LEFT, + SHAKE_UP, + SHAKE_RIGHT, + SHAKE_DOWN, + SHAKE_DONE +}; +static shake_state sShakeState; + +LLFloaterRegionRestarting::LLFloaterRegionRestarting(const LLSD& key) : + LLEventTimer(1) +, mRestartSeconds(NULL) +, mSeconds(key["SECONDS"].asInteger()) +, mShakeIterations() +, mShakeMagnitude() +{ + //buildFromFile("floater_region_restarting.xml"); + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_restarting.xml"); + + LLStringUtil::format_map_t args; + args["[NAME]"] = key["NAME"].asString(); + getChild("region_name")->setValue(getString("RegionName", args)); + mRestartSeconds = getChild("restart_seconds"); + center(); + + refresh(); + + mRegionChangedConnection = LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterRegionRestarting::close, this, false)); +} + +LLFloaterRegionRestarting::~LLFloaterRegionRestarting() +{ + mRegionChangedConnection.disconnect(); +} + +BOOL LLFloaterRegionRestarting::postBuild() +{ + setBackgroundColor(gColors.getColor("NotifyCautionBoxColor")); + sShakeState = SHAKE_START; + return TRUE; +} + +BOOL LLFloaterRegionRestarting::tick() +{ + refresh(); + + return FALSE; +} + +void LLFloaterRegionRestarting::refresh() +{ + LLStringUtil::format_map_t args; + args["[SECONDS]"] = llformat("%d", mSeconds); + mRestartSeconds->setValue(getString("RestartSeconds", args)); + + if (!mSeconds) return; // Zero means we're done. + --mSeconds; +} + +void LLFloaterRegionRestarting::draw() +{ + LLFloater::draw(); + + static const LLCachedControl alchemyRegionShake(gSavedSettings, "AlchemyRegionRestartShake", true); + if (!alchemyRegionShake) + return; + + const F32 SHAKE_INTERVAL = 0.025; + const F32 SHAKE_TOTAL_DURATION = 1.8; // the length of the default alert tone for this + const F32 SHAKE_INITIAL_MAGNITUDE = 1.5; + const F32 SHAKE_HORIZONTAL_BIAS = 0.25; + F32 time_shaking; + + if (SHAKE_START == sShakeState) + { + mShakeTimer.setTimerExpirySec(SHAKE_INTERVAL); + sShakeState = SHAKE_LEFT; + mShakeIterations = 0; + mShakeMagnitude = SHAKE_INITIAL_MAGNITUDE; + } + + if (SHAKE_DONE != sShakeState && mShakeTimer.hasExpired()) + { + gAgentCamera.unlockView(); + + switch(sShakeState) + { + case SHAKE_LEFT: + gAgentCamera.setPanLeftKey(mShakeMagnitude * SHAKE_HORIZONTAL_BIAS); + sShakeState = SHAKE_UP; + break; + + case SHAKE_UP: + gAgentCamera.setPanUpKey(mShakeMagnitude); + sShakeState = SHAKE_RIGHT; + break; + + case SHAKE_RIGHT: + gAgentCamera.setPanRightKey(mShakeMagnitude * SHAKE_HORIZONTAL_BIAS); + sShakeState = SHAKE_DOWN; + break; + + case SHAKE_DOWN: + gAgentCamera.setPanDownKey(mShakeMagnitude); + mShakeIterations++; + time_shaking = SHAKE_INTERVAL * (mShakeIterations * 4 /* left, up, right, down */); + if (SHAKE_TOTAL_DURATION <= time_shaking) + { + sShakeState = SHAKE_DONE; + mShakeMagnitude = 0.0; + } + else + { + sShakeState = SHAKE_LEFT; + F32 percent_done_shaking = (SHAKE_TOTAL_DURATION - time_shaking) / SHAKE_TOTAL_DURATION; + mShakeMagnitude = SHAKE_INITIAL_MAGNITUDE * (percent_done_shaking * percent_done_shaking); // exponential decay + } + break; + + default: + break; + } + mShakeTimer.setTimerExpirySec(SHAKE_INTERVAL); + } +} + +void LLFloaterRegionRestarting::updateTime(const U32& time) +{ + mSeconds = time; + sShakeState = SHAKE_START; +} diff --git a/indra/newview/llfloaterregionrestarting.h b/indra/newview/llfloaterregionrestarting.h new file mode 100644 index 000000000..8e9c625c7 --- /dev/null +++ b/indra/newview/llfloaterregionrestarting.h @@ -0,0 +1,58 @@ +/** + * @file llfloaterregionrestarting.h + * @brief Shows countdown timer during region restart + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#ifndef LL_LLFLOATERREGIONRESTARTING_H +#define LL_LLFLOATERREGIONRESTARTING_H + +#include "llfloater.h" +#include "lleventtimer.h" + +class LLFloaterRegionRestarting : public LLFloater, public LLEventTimer +, public LLFloaterSingleton +{ + friend class LLFloaterReg; + +public: + void updateTime(const U32& time); + + LLFloaterRegionRestarting(const LLSD& key); +private: + virtual ~LLFloaterRegionRestarting(); + virtual BOOL postBuild(); + virtual BOOL tick(); + virtual void refresh(); + virtual void draw(); + + class LLTextBox* mRestartSeconds; + U32 mSeconds; + U32 mShakeIterations; + F32 mShakeMagnitude; + LLTimer mShakeTimer; + + boost::signals2::connection mRegionChangedConnection; +}; + +#endif // LL_LLFLOATERREGIONRESTARTING_H diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 7a6b74e35..8f7a0ed65 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -96,6 +96,7 @@ void precache_audio() gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTyping"))); gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowClose"))); gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowOpen"))); + gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndRestart"))); } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f532d5375..49bc3cbe1 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -67,6 +67,7 @@ #include "llfloatermute.h" #include "llfloaterpostcard.h" #include "llfloaterpreference.h" +#include "llfloaterregionrestarting.h" #include "llfloaterteleporthistory.h" #include "llgroupactions.h" #include "llhudeffecttrail.h" @@ -6582,15 +6583,32 @@ void home_position_set() gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE); } -void add_time_arg(LLSD& args) +void update_region_restart(const LLSD& llsdBlock) { - static const LLCachedControl show_local_time("LiruLocalTime"); - // Get current UTC time, adjusted for the user's clock - // being off. - time_t utc_time = show_local_time ? time(NULL) : time_corrected(); - std::string timeStr; - timeStructToFormattedString(show_local_time ? std::localtime(&utc_time) : utc_to_pacific_time(utc_time, gPacificDaylightTime), gSavedSettings.getString("ShortTimeFormat"), timeStr); - args["TIME"] = timeStr; + U32 seconds; + if (llsdBlock.has("MINUTES")) + { + seconds = 60U * static_cast(llsdBlock["MINUTES"].asInteger()); + } + else + { + seconds = static_cast(llsdBlock["SECONDS"].asInteger()); + } + + LLFloaterRegionRestarting* restarting_floater = LLFloaterRegionRestarting::findInstance(); + + if (restarting_floater) + { + restarting_floater->updateTime(seconds); + restarting_floater->center(); + } + else + { + LLSD params; + params["NAME"] = llsdBlock["NAME"]; + params["SECONDS"] = (LLSD::Integer)seconds; + LLFloaterRegionRestarting::showInstance(params); + } } bool attempt_standard_notification(LLMessageSystem* msgsystem) @@ -6666,8 +6684,9 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) } else if (notificationID == "RegionRestartMinutes" || notificationID == "RegionRestartSeconds") { - add_time_arg(llsdBlock); + update_region_restart(llsdBlock); send_sound_trigger(LLUUID(gSavedSettings.getString("UISndRestart")), 1.0f); + return true; // Floater is enough. } LLNotificationsUtil::add(notificationID, llsdBlock); @@ -6777,8 +6796,8 @@ void process_alert_core(const std::string& message, BOOL modal) S32 mins = 0; LLStringUtil::convertToS32(text.substr(18), mins); args["MINUTES"] = llformat("%d",mins); - add_time_arg(args); - LLNotificationsUtil::add("RegionRestartMinutes", args); + update_region_restart(args); + //LLNotificationsUtil::add("RegionRestartMinutes", args); // Floater is enough. send_sound_trigger(LLUUID(gSavedSettings.getString("UISndRestart")), 1.0f); } else if (text.substr(0,17) == "RESTART_X_SECONDS") @@ -6786,10 +6805,15 @@ void process_alert_core(const std::string& message, BOOL modal) S32 secs = 0; LLStringUtil::convertToS32(text.substr(18), secs); args["SECONDS"] = llformat("%d",secs); - add_time_arg(args); - LLNotificationsUtil::add("RegionRestartSeconds", args); + update_region_restart(args); + //LLNotificationsUtil::add("RegionRestartSeconds", args); // Floater is enough. send_sound_trigger(LLUUID(gSavedSettings.getString("UISndRestart")), 1.0f); } + // *NOTE: If the text from the server ever changes this line will need to be adjusted. + else if (text.substr(0, 25) == "Region restart cancelled.") + { + LLFloaterRegionRestarting::hideInstance(); + } else { std::string new_msg =LLNotificationTemplates::instance().getGlobalString(text); diff --git a/indra/newview/skins/default/xui/en-us/floater_region_restarting.xml b/indra/newview/skins/default/xui/en-us/floater_region_restarting.xml new file mode 100644 index 000000000..fdad11853 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/floater_region_restarting.xml @@ -0,0 +1,81 @@ + + + +The region you are in now +([NAME]) is about to restart. + +If you stay here, you'll be logged out. + + + Seconds Until Restart: +[SECONDS] + + + + + + + +The region you are in now +(-The longest region name-) is about to restart. + +If you stay here, you'll be logged out. + + +Seconds Until Restart: + 32767 + + + + diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 68df71296..037516e29 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -6942,18 +6942,20 @@ This will add a bookmark in your inventory so you can quickly IM this resident. -[TIME] This region will restart in [MINUTES] minutes. +This region will restart in [MINUTES] minutes. If you remain in this region you will be logged out. -[TIME] This region will restart in [SECONDS] seconds. +This region will restart in [SECONDS] seconds. If you remain in this region you will be logged out.