Files
SingularityViewer/indra/newview/llfloaterregioninfo.cpp
Liru Færs d277f1750d All places just av/group names were being used are now name ui
Since NameBoxes are clickable, remove redundant profile buttons.
Removes a ton of RLV logic, now centralized inside LLNameUI
Removes excess functions that went largely unused

May no longer show if parcel sale is pending under the owner field,
this is weird and it's hard to keep this behavior

Also includes the missing setValue and getValue so this compiles,
that should've been committed way earlier, oops

Also adds ability for name_box to have is_group attribute, too!
2019-10-10 02:32:47 -04:00

4323 lines
135 KiB
C++

/**
* @file llfloaterregioninfo.cpp
* @author Aaron Brashears
* @brief Implementation of the region info and controls floater and panels.
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterregioninfo.h"
#include <algorithm>
#include <functional>
#include "lldir.h"
#include "lldispatcher.h"
#include "llglheaders.h"
#include "llregionflags.h"
#include "llstl.h"
#include "indra_constants.h"
#include "message.h"
//#include "llloadingindicator.h" // Singu TODO: LLLoadingIndicator
#include "llradiogroup.h"
#include "llagent.h"
#include "llappviewer.h"
#include "llavatarnamecache.h"
#include "llfloateravatarpicker.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llclipboard.h"
#include "llcombobox.h"
#include "lldaycyclemanager.h"
#include "llenvmanager.h"
#include "llestateinfomodel.h"
#include "statemachine/aifilepicker.h"
#include "llfloatergodtools.h" // for send_sim_wide_deletes()
#include "llfloatertopobjects.h" // added to fix SL-32336
#include "llfloatergroups.h"
#include "llfloaterregiondebugconsole.h"
#include "llfloatertelehub.h"
#include "llinventorymodel.h"
#include "lllineeditor.h"
#include "llnamelistctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llregioninfomodel.h"
#include "llscrolllistitem.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "llinventory.h"
#include "lltexturectrl.h"
#include "lltrans.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "llvlcomposition.h"
#include "llwaterparammanager.h"
#include "llagentui.h"
#include "hippogridmanager.h"
// [RLVa:KB]
#include "rlvhandler.h"
// [/RLVa:KB]
const S32 TERRAIN_TEXTURE_COUNT = 4;
const S32 CORNER_COUNT = 4;
const U32 MAX_LISTED_NAMES = 100;
///----------------------------------------------------------------------------
/// Local class declaration
///----------------------------------------------------------------------------
class LLDispatchEstateUpdateInfo : public LLDispatchHandler
{
public:
LLDispatchEstateUpdateInfo() {}
virtual ~LLDispatchEstateUpdateInfo() {}
virtual bool operator()(
const LLDispatcher* dispatcher,
const std::string& key,
const LLUUID& invoice,
const sparam_t& strings);
};
class LLDispatchSetEstateAccess : public LLDispatchHandler
{
public:
LLDispatchSetEstateAccess() {}
virtual ~LLDispatchSetEstateAccess() {}
virtual bool operator()(
const LLDispatcher* dispatcher,
const std::string& key,
const LLUUID& invoice,
const sparam_t& strings);
};
/*
void unpack_request_params(
LLMessageSystem* msg,
LLDispatcher::sparam_t& strings,
LLDispatcher::iparam_t& integers)
{
char str_buf[MAX_STRING];
S32 str_count = msg->getNumberOfBlocksFast(_PREHASH_StringData);
S32 i;
for (i = 0; i < str_count; ++i)
{
// we treat the SParam as binary data (since it might be an
// LLUUID in compressed form which may have embedded \0's,)
str_buf[0] = '\0';
S32 data_size = msg->getSizeFast(_PREHASH_StringData, i, _PREHASH_SParam);
if (data_size >= 0)
{
msg->getBinaryDataFast(_PREHASH_StringData, _PREHASH_SParam,
str_buf, data_size, i, MAX_STRING - 1);
strings.push_back(std::string(str_buf, data_size));
}
}
U32 int_buf;
S32 int_count = msg->getNumberOfBlocksFast(_PREHASH_IntegerData);
for (i = 0; i < int_count; ++i)
{
msg->getU32("IntegerData", "IParam", int_buf, i);
integers.push_back(int_buf);
}
}
*/
namespace
{
void on_caps_received(LLTabContainer* tab)
{
if (!tab) return;
const LLViewerRegion* region = gAgent.getRegion();
tab->enableTabButton(tab->getIndexForPanel(tab->getPanelByName("panel_env_info")), region && !region->getCapability("EnvironmentSettings").empty());
}
void handle_opposite(const bool& off, LLUICtrl* opposite)
{
opposite->setEnabled(!off);
if (off) opposite->setValue(false);
}
void on_change_use_other_sun(const LLSD& param, LLUICtrl* opposite, LLUICtrl* slider)
{
handle_opposite(param.asBoolean(), opposite);
slider->setEnabled(false);
}
void on_change_fixed_sun(const LLSD& param, LLUICtrl* opposite, LLUICtrl* slider)
{
bool fixed_sun = param.asBoolean();
handle_opposite(fixed_sun, opposite);
slider->setEnabled(fixed_sun);
}
const float get_sun_hour(const LLUICtrl* sun_hour)
{
return sun_hour->getEnabled() ? sun_hour->getValue().asFloat() : 0.f;
}
}
bool estate_dispatch_initialized = false;
///----------------------------------------------------------------------------
/// LLFloaterRegionInfo
///----------------------------------------------------------------------------
//S32 LLFloaterRegionInfo::sRequestSerial = 0;
LLUUID LLFloaterRegionInfo::sRequestInvoice;
LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
: LLFloater()
, mTab(nullptr)
, mInfoPanels()
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_info.xml", NULL, FALSE);
}
BOOL LLFloaterRegionInfo::postBuild()
{
mTab = getChild<LLTabContainer>("region_panels");
mTab->setCommitCallback(boost::bind(&LLFloaterRegionInfo::onTabSelected, this, _2));
// contruct the panels
LLPanelRegionInfo* panel;
panel = new LLPanelEstateInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_estate.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelEstateAccess;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_access.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelEstateCovenant;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_covenant.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelRegionGeneralInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_general.xml");
mTab->addTabPanel(panel, panel->getLabel(), TRUE);
panel = new LLPanelRegionTerrainInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_terrain.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelEnvironmentInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_environment.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
panel = new LLPanelRegionDebugInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_debug.xml");
mTab->addTabPanel(panel, panel->getLabel(), FALSE);
gMessageSystem->setHandlerFunc(
"EstateOwnerMessage",
&processEstateOwnerRequest);
// Request region info when agent region changes.
gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionInfo::requestRegionInfo, this));
return TRUE;
}
LLFloaterRegionInfo::~LLFloaterRegionInfo()
{}
void LLFloaterRegionInfo::onOpen()
{
LLRect rect = gSavedSettings.getRect("FloaterRegionInfo");
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
rect.translate(left,top);
refreshFromRegion(gAgent.getRegion());
requestRegionInfo();
requestMeshRezInfo();
if (!mGodLevelChangeSlot.connected())
{
mGodLevelChangeSlot = gAgent.registerGodLevelChanageListener(boost::bind(&LLFloaterRegionInfo::onGodLevelChange, this, _1));
}
LLFloater::onOpen();
}
void LLFloaterRegionInfo::onClose(bool app_quitting)
{
if (mGodLevelChangeSlot.connected())
{
mGodLevelChangeSlot.disconnect();
}
LLFloater::onClose(app_quitting);
}
// static
void LLFloaterRegionInfo::requestRegionInfo()
{
LLTabContainer* tab = getChild<LLTabContainer>("region_panels");
tab->getChild<LLPanel>("General")->setCtrlsEnabled(FALSE);
tab->getChild<LLPanel>("Debug")->setCtrlsEnabled(FALSE);
tab->getChild<LLPanel>("Terrain")->setCtrlsEnabled(FALSE);
tab->getChild<LLPanel>("Estate")->setCtrlsEnabled(FALSE);
auto panel = tab->getChild<LLPanel>("Access");
panel->setCtrlsEnabled(FALSE);
panel->getChildView("tabs")->setEnabled(true);
// Must allow anyone to request the RegionInfo data
// so non-owners/non-gods can see the values.
// Therefore can't use an EstateOwnerMessage JC
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("RequestRegionInfo");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
gAgent.sendReliableMessage();
}
// static
void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
{
static LLDispatcher dispatch;
LLFloaterRegionInfo* floater = findInstance();
if(!floater)
{
return;
}
if (!estate_dispatch_initialized)
{
LLPanelEstateInfo::initDispatch(dispatch);
}
LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
// unpack the message
std::string request;
LLUUID invoice;
LLDispatcher::sparam_t strings;
LLDispatcher::unpackMessage(msg, request, invoice, strings);
if(invoice != getLastInvoice())
{
LL_WARNS() << "Mismatched Estate message: " << request << LL_ENDL;
return;
}
//dispatch the message
dispatch.dispatch(request, invoice, strings);
if (panel)
{
panel->updateControls(gAgent.getRegion());
}
}
// static
void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
{
LLPanel* panel;
LLFloaterRegionInfo* floater = findInstance();
if(!floater)
{
return;
}
// We need to re-request environment setting here,
// otherwise after we apply (send) updated region settings we won't get them back,
// so our environment won't be updated.
// This is also the way to know about externally changed region environment.
LLEnvManagerNew::instance().requestRegionSettings();
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLViewerRegion* region = gAgent.getRegion();
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
// *TODO: Replace parsing msg with accessing the region info model.
LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
// extract message
std::string sim_name;
std::string sim_type = LLTrans::getString("land_type_unknown");
U64 region_flags;
U8 agent_limit;
F32 object_bonus_factor;
U8 sim_access;
F32 water_height;
F32 terrain_raise_limit;
F32 terrain_lower_limit;
BOOL use_estate_sun;
F32 sun_hour;
msg->getString("RegionInfo", "SimName", sim_name);
msg->getU8("RegionInfo", "MaxAgents", agent_limit);
msg->getF32("RegionInfo", "ObjectBonusFactor", object_bonus_factor);
msg->getU8("RegionInfo", "SimAccess", sim_access);
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height);
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit);
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit);
msg->getBOOL("RegionInfo", "UseEstateSun", use_estate_sun);
// actually the "last set" sun hour, not the current sun hour. JC
msg->getF32("RegionInfo", "SunHour", sun_hour);
// the only reasonable way to decide if we actually have any data is to
// check to see if any of these fields have nonzero sizes
if (msg->getSize("RegionInfo2", "ProductSKU") > 0 ||
msg->getSize("RegionInfo2", "ProductName") > 0)
{
msg->getString("RegionInfo2", "ProductName", sim_type);
LLTrans::findString(sim_type, sim_type); // try localizing sim product name
}
if (msg->has(_PREHASH_RegionInfo3))
{
msg->getU64("RegionInfo3", "RegionFlagsExtended", region_flags);
}
else
{
U32 flags = 0;
msg->getU32("RegionInfo", "RegionFlags", flags);
region_flags = flags;
}
// Disable Environment Tab when not supported
if (region)
{
if (region->capabilitiesReceived())
on_caps_received(tab);
else
region->setCapabilitiesReceivedCallback(boost::bind(on_caps_received, tab));
}
// GENERAL PANEL
panel = tab->getChild<LLPanel>("General");
panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name));
panel->getChild<LLUICtrl>("region_type")->setValue(LLSD(sim_type));
panel->getChild<LLUICtrl>("version_channel_text")->setValue(gLastVersionChannel);
panel->getChild<LLUICtrl>("block_terraform_check")->setValue((region_flags & REGION_FLAGS_BLOCK_TERRAFORM) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("block_fly_check")->setValue((region_flags & REGION_FLAGS_BLOCK_FLY) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("block_fly_over_check")->setValue((region_flags & REGION_FLAGS_BLOCK_FLYOVER) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("allow_damage_check")->setValue((region_flags & REGION_FLAGS_ALLOW_DAMAGE) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("restrict_pushobject")->setValue((region_flags & REGION_FLAGS_RESTRICT_PUSHOBJECT) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("allow_land_resell_check")->setValue((region_flags & REGION_FLAGS_BLOCK_LAND_RESELL) ? FALSE : TRUE );
panel->getChild<LLUICtrl>("allow_parcel_changes_check")->setValue((region_flags & REGION_FLAGS_ALLOW_PARCEL_CHANGES) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("block_parcel_search_check")->setValue((region_flags & REGION_FLAGS_BLOCK_PARCEL_SEARCH) ? TRUE : FALSE );
panel->getChild<LLUICtrl>("agent_limit_spin")->setValue(LLSD((F32)agent_limit) );
panel->getChild<LLUICtrl>("object_bonus_spin")->setValue(LLSD(object_bonus_factor) );
panel->getChild<LLUICtrl>("access_combo")->setValue(LLSD(sim_access) );
// detect teen grid for maturity
U32 parent_estate_id;
msg->getU32("RegionInfo", "ParentEstateID", parent_estate_id);
BOOL teen_grid = (parent_estate_id == 5); // *TODO add field to estate table and test that
panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid));
panel->setCtrlsEnabled(allow_modify);
// DEBUG PANEL
panel = tab->getChild<LLPanel>("Debug");
panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name) );
panel->getChild<LLUICtrl>("disable_scripts_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SKIP_SCRIPTS)) );
panel->getChild<LLUICtrl>("disable_collisions_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SKIP_COLLISIONS)) );
panel->getChild<LLUICtrl>("disable_physics_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SKIP_PHYSICS)) );
panel->setCtrlsEnabled(allow_modify);
// TERRAIN PANEL
panel = tab->getChild<LLPanel>("Terrain");
panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name));
panel->getChild<LLUICtrl>("water_height_spin")->setValue(region_info.mWaterHeight);
panel->getChild<LLUICtrl>("terrain_raise_spin")->setValue(region_info.mTerrainRaiseLimit);
panel->getChild<LLUICtrl>("terrain_lower_spin")->setValue(region_info.mTerrainLowerLimit);
panel->setCtrlsEnabled(allow_modify);
floater->refreshFromRegion( gAgent.getRegion() );
}
// static
LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate()
{
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return NULL;
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate");
return panel;
}
// static
LLPanelEstateAccess* LLFloaterRegionInfo::getPanelAccess()
{
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return NULL;
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLPanelEstateAccess* panel = (LLPanelEstateAccess*)tab->getChild<LLPanel>("Access");
return panel;
}
// static
LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant()
{
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater) return NULL;
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)tab->getChild<LLPanel>("Covenant");
return panel;
}
// static
LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain()
{
LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
if (!floater)
{
llassert(floater);
return NULL;
}
LLTabContainer* tab_container = floater->getChild<LLTabContainer>("region_panels");
LLPanelRegionTerrainInfo* panel =
dynamic_cast<LLPanelRegionTerrainInfo*>(tab_container->getChild<LLPanel>("Terrain"));
llassert(panel);
return panel;
}
void LLFloaterRegionInfo::onTabSelected(const LLSD& param)
{
LLPanelRegionInfo* active_panel = getChild<LLPanelRegionInfo>(param.asString());
active_panel->onOpen(LLSD());
}
void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region)
{
if (!region)
{
return;
}
// call refresh from region on all panels
std::for_each(
mInfoPanels.begin(),
mInfoPanels.end(),
llbind2nd(
std::mem_fun(&LLPanelRegionInfo::refreshFromRegion),
region));
}
// public
void LLFloaterRegionInfo::refresh()
{
for(info_panels_t::iterator iter = mInfoPanels.begin();
iter != mInfoPanels.end(); ++iter)
{
(*iter)->refresh();
}
}
void LLFloaterRegionInfo::onGodLevelChange(U8 god_level)
{
LLFloaterRegionInfo* floater = getInstance();
if (floater && floater->getVisible())
{
refreshFromRegion(gAgent.getRegion());
}
}
///----------------------------------------------------------------------------
/// Local class implementation
///----------------------------------------------------------------------------
//
// LLPanelRegionInfo
//
LLPanelRegionInfo::LLPanelRegionInfo()
: LLPanel(std::string("Region Info Panel"))
{
}
void LLPanelRegionInfo::onBtnSet()
{
if (sendUpdate())
{
disableButton("apply_btn");
}
}
void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl)
{
updateChild(ctrl); // virtual function
}
// Enables the "set" button if it is not already enabled
void LLPanelRegionInfo::onChangeAnything()
{
enableButton("apply_btn");
refresh();
}
// static
// Enables set button on change to line editor
void LLPanelRegionInfo::onChangeText(LLLineEditor* caller, void* user_data)
{
LLPanelRegionInfo* panel = dynamic_cast<LLPanelRegionInfo*>(caller->getParent());
if(panel)
{
panel->enableButton("apply_btn");
panel->refresh();
}
}
// virtual
BOOL LLPanelRegionInfo::postBuild()
{
// If the panel has an Apply button, set a callback for it.
LLUICtrl* apply_btn = findChild<LLUICtrl>("apply_btn");
if (apply_btn)
{
apply_btn->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this));
}
refresh();
return TRUE;
}
// virtual
void LLPanelRegionInfo::updateChild(LLUICtrl* child_ctr)
{
}
// virtual
bool LLPanelRegionInfo::refreshFromRegion(LLViewerRegion* region)
{
if (region) mHost = region->getHost();
return true;
}
void LLPanelRegionInfo::sendEstateOwnerMessage(
LLMessageSystem* msg,
const std::string& request,
const LLUUID& invoice,
const strings_t& strings)
{
LL_INFOS() << "Sending estate request '" << request << "'" << LL_ENDL;
msg->newMessage("EstateOwnerMessage");
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
msg->nextBlock("MethodData");
msg->addString("Method", request);
msg->addUUID("Invoice", invoice);
if(strings.empty())
{
msg->nextBlock("ParamList");
msg->addString("Parameter", NULL);
}
else
{
strings_t::const_iterator it = strings.begin();
strings_t::const_iterator end = strings.end();
for(; it != end; ++it)
{
msg->nextBlock("ParamList");
msg->addString("Parameter", *it);
}
}
msg->sendReliable(mHost);
}
void LLPanelRegionInfo::enableButton(const std::string& btn_name, BOOL enable)
{
LLView* button = findChild<LLView>(btn_name);
if (button) button->setEnabled(enable);
}
void LLPanelRegionInfo::disableButton(const std::string& btn_name)
{
LLView* button = findChild<LLView>(btn_name);
if (button) button->setEnabled(FALSE);
}
void LLPanelRegionInfo::initCtrl(const std::string& name)
{
getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this));
}
// Singu TODO: Make this a callback registrar function instead.
void LLPanelRegionInfo::initHelpBtn(const std::string& name, const std::string& xml_alert)
{
getChild<LLButton>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onClickHelp, this, xml_alert));
}
void LLPanelRegionInfo::onClickHelp(const std::string& xml_alert)
{
LLNotifications::instance().add(xml_alert);
}
void LLPanelRegionInfo::onClickManageTelehub()
{
LLFloaterRegionInfo::getInstance()->close();
LLFloaterTelehub::show();
}
/////////////////////////////////////////////////////////////////////////////
// LLPanelRegionGeneralInfo
//
bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)
{
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
setCtrlsEnabled(allow_modify);
getChildView("apply_btn")->setEnabled(FALSE);
getChildView("access_text")->setEnabled(allow_modify);
// getChildView("access_combo")->setEnabled(allow_modify);
// now set in processRegionInfo for teen grid detection
getChildView("kick_btn")->setEnabled(allow_modify);
getChildView("kick_all_btn")->setEnabled(allow_modify);
getChildView("im_btn")->setEnabled(allow_modify);
getChildView("manage_telehub_btn")->setEnabled(allow_modify);
// Support Legacy Region Environment
{
const LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
bool estate_sun = region_info.mUseEstateSun;
getChild<LLUICtrl>("use_estate_sun_check")->setValue(estate_sun);
getChild<LLUICtrl>("fixed_sun_check")->setEnabled(allow_modify && !estate_sun);
getChild<LLUICtrl>("sun_hour_slider")->setEnabled(allow_modify && !estate_sun);
if (estate_sun)
{
getChild<LLUICtrl>("use_estate_sun_check")->setEnabled(allow_modify);
getChild<LLUICtrl>("fixed_sun_check")->setValue(false);
}
else
{
bool fixed_sun = region_info.getUseFixedSun();
getChild<LLUICtrl>("use_estate_sun_check")->setEnabled(allow_modify && !fixed_sun);
getChild<LLUICtrl>("fixed_sun_check")->setValue(fixed_sun);
getChild<LLUICtrl>("sun_hour_slider")->setValue(region_info.mSunHour);
}
}
// Data gets filled in by processRegionInfo
return LLPanelRegionInfo::refreshFromRegion(region);
}
BOOL LLPanelRegionGeneralInfo::postBuild()
{
// Enable the "Apply" button if something is changed. JC
initCtrl("block_terraform_check");
initCtrl("block_fly_check");
initCtrl("block_fly_over_check");
initCtrl("allow_damage_check");
initCtrl("allow_land_resell_check");
initCtrl("allow_parcel_changes_check");
initCtrl("agent_limit_spin");
initCtrl("object_bonus_spin");
initCtrl("access_combo");
initCtrl("restrict_pushobject");
initCtrl("block_parcel_search_check");
initCtrl("use_estate_sun_check");
initCtrl("fixed_sun_check");
initCtrl("sun_hour_slider");
initHelpBtn("terraform_help", "HelpRegionBlockTerraform");
initHelpBtn("fly_help", "HelpRegionBlockFly");
initHelpBtn("damage_help", "HelpRegionAllowDamage");
initHelpBtn("agent_limit_help", "HelpRegionAgentLimit");
initHelpBtn("object_bonus_help", "HelpRegionObjectBonus");
initHelpBtn("access_help", "HelpRegionMaturity");
initHelpBtn("restrict_pushobject_help", "HelpRegionRestrictPushObject");
initHelpBtn("land_resell_help", "HelpRegionLandResell");
initHelpBtn("parcel_changes_help", "HelpParcelChanges");
initHelpBtn("parcel_search_help", "HelpRegionSearch");
initHelpBtn("use_estate_sun_help", "HelpRegionUseEstateSun");
initHelpBtn("fixed_sun_help", "HelpRegionFixedSun");
childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this));
childSetAction("kick_all_btn", onClickKickAll, this);
childSetAction("im_btn", onClickMessage, this);
childSetAction("manage_telehub_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickManageTelehub, this));
// Set up the Legacy Region Environment checkboxes
{
LLUICtrl* estate_sun = getChild<LLUICtrl>("use_estate_sun_check");
LLUICtrl* fixed_sun = getChild<LLUICtrl>("fixed_sun_check");
LLUICtrl* hour_slider = getChild<LLUICtrl>("sun_hour_slider");
estate_sun->setCommitCallback(boost::bind(on_change_use_other_sun, _2, fixed_sun, hour_slider));
fixed_sun->setCommitCallback(boost::bind(on_change_fixed_sun, _2, estate_sun, hour_slider));
}
return LLPanelRegionInfo::postBuild();
}
void LLPanelRegionGeneralInfo::onClickKick()
{
LL_INFOS() << "LLPanelRegionGeneralInfo::onClickKick" << LL_ENDL;
// this depends on the grandparent view being a floater
// in order to set up floater dependency
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE);
if (child_floater)
{
parent_floater->addDependentFloater(child_floater);
}
}
void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids)
{
if (ids.empty()) return;
if(ids[0].notNull())
{
strings_t strings;
// [0] = our agent id
// [1] = target agent id
std::string buffer;
gAgent.getID().toString(buffer);
strings.push_back(buffer);
ids[0].toString(buffer);
strings.push_back(strings_t::value_type(buffer));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings);
}
}
// static
void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata)
{
LL_INFOS() << "LLPanelRegionGeneralInfo::onClickKickAll" << LL_ENDL;
LLNotificationsUtil::add("KickUsersFromRegion",
LLSD(),
LLSD(),
boost::bind(&LLPanelRegionGeneralInfo::onKickAllCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2));
}
bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
strings_t strings;
// [0] = our agent id
std::string buffer;
gAgent.getID().toString(buffer);
strings.push_back(buffer);
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
// historical message name
sendEstateOwnerMessage(gMessageSystem, "teleporthomeallusers", invoice, strings);
}
return false;
}
// static
void LLPanelRegionGeneralInfo::onClickMessage(void* userdata)
{
LL_INFOS() << "LLPanelRegionGeneralInfo::onClickMessage" << LL_ENDL;
LLNotificationsUtil::add("MessageRegion",
LLSD(),
LLSD(),
boost::bind(&LLPanelRegionGeneralInfo::onMessageCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2));
}
// static
bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const LLSD& response)
{
if(LLNotificationsUtil::getSelectedOption(notification, response) != 0) return false;
std::string text = response["message"].asString();
if (text.empty()) return false;
LL_INFOS() << "Message to everyone: " << text << LL_ENDL;
strings_t strings;
// [0] grid_x, unused here
// [1] grid_y, unused here
// [2] agent_id of sender
// [3] sender name
// [4] message
strings.push_back("-1");
strings.push_back("-1");
std::string buffer;
gAgent.getID().toString(buffer);
strings.push_back(buffer);
std::string name;
LLAgentUI::buildFullname(name);
strings.push_back(strings_t::value_type(name));
strings.push_back(strings_t::value_type(text));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "simulatormessage", invoice, strings);
return false;
}
class ConsoleRequestResponder : public LLHTTPClient::ResponderIgnoreBody
{
LOG_CLASS(ConsoleRequestResponder);
protected:
/*virtual*/
void httpFailure()
{
LL_WARNS() << "error requesting mesh_rez_enabled " << dumpResponse() << LL_ENDL;
}
/*virtual*/ const char* getName() const { return "ConsoleRequestResponder"; }
};
// called if this request times out.
class ConsoleUpdateResponder : public LLHTTPClient::ResponderIgnoreBody
{
LOG_CLASS(ConsoleUpdateResponder);
protected:
/* virtual */
void httpFailure()
{
LL_WARNS() << "error updating mesh enabled region setting " << dumpResponse() << LL_ENDL;
}
};
void LLFloaterRegionInfo::requestMeshRezInfo()
{
std::string sim_console_url = gAgent.getRegion()->getCapability("SimConsoleAsync");
if (!sim_console_url.empty())
{
std::string request_str = "get mesh_rez_enabled";
LLHTTPClient::post(
sim_console_url,
LLSD(request_str),
new ConsoleRequestResponder);
}
}
// setregioninfo
// strings[0] = 'Y' - block terraform, 'N' - not
// strings[1] = 'Y' - block fly, 'N' - not
// strings[2] = 'Y' - allow damage, 'N' - not
// strings[3] = 'Y' - allow land sale, 'N' - not
// strings[4] = agent limit
// strings[5] = object bonus
// strings[6] = sim access (0 = unknown, 13 = PG, 21 = Mature, 42 = Adult)
// strings[7] = restrict pushobject
// strings[8] = 'Y' - allow parcel subdivide, 'N' - not
// strings[9] = 'Y' - block parcel search, 'N' - allow
BOOL LLPanelRegionGeneralInfo::sendUpdate()
{
LL_INFOS() << "LLPanelRegionGeneralInfo::sendUpdate()" << LL_ENDL;
// First try using a Cap. If that fails use the old method.
LLSD body;
std::string url = gAgent.getRegion()->getCapability("DispatchRegionInfo");
if (!url.empty())
{
body["block_terraform"] = getChild<LLUICtrl>("block_terraform_check")->getValue();
body["block_fly"] = getChild<LLUICtrl>("block_fly_check")->getValue();
body["block_fly_over"] = getChild<LLUICtrl>("block_fly_over_check")->getValue();
body["allow_damage"] = getChild<LLUICtrl>("allow_damage_check")->getValue();
body["allow_land_resell"] = getChild<LLUICtrl>("allow_land_resell_check")->getValue();
body["agent_limit"] = getChild<LLUICtrl>("agent_limit_spin")->getValue();
body["prim_bonus"] = getChild<LLUICtrl>("object_bonus_spin")->getValue();
body["sim_access"] = getChild<LLUICtrl>("access_combo")->getValue();
body["restrict_pushobject"] = getChild<LLUICtrl>("restrict_pushobject")->getValue();
body["allow_parcel_changes"] = getChild<LLUICtrl>("allow_parcel_changes_check")->getValue();
body["block_parcel_search"] = getChild<LLUICtrl>("block_parcel_search_check")->getValue();
LLHTTPClient::post(url, body, new LLHTTPClient::ResponderIgnore);
}
else
{
strings_t strings;
std::string buffer;
buffer = llformat("%s", (getChild<LLUICtrl>("block_terraform_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(strings_t::value_type(buffer));
buffer = llformat("%s", (getChild<LLUICtrl>("block_fly_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(strings_t::value_type(buffer));
buffer = llformat("%s", (getChild<LLUICtrl>("allow_damage_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(strings_t::value_type(buffer));
buffer = llformat("%s", (getChild<LLUICtrl>("allow_land_resell_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(strings_t::value_type(buffer));
F32 value = (F32)getChild<LLUICtrl>("agent_limit_spin")->getValue().asReal();
buffer = llformat("%f", value);
strings.push_back(strings_t::value_type(buffer));
value = (F32)getChild<LLUICtrl>("object_bonus_spin")->getValue().asReal();
buffer = llformat("%f", value);
strings.push_back(strings_t::value_type(buffer));
buffer = llformat("%d", getChild<LLUICtrl>("access_combo")->getValue().asInteger());
strings.push_back(strings_t::value_type(buffer));
buffer = llformat("%s", (getChild<LLUICtrl>("restrict_pushobject")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(strings_t::value_type(buffer));
buffer = llformat("%s", (getChild<LLUICtrl>("allow_parcel_changes_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(strings_t::value_type(buffer));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings);
}
// Send the Legacy Region Environment
LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
region_info.mUseEstateSun = getChild<LLUICtrl>("use_estate_sun_check")->getValue().asBoolean();
region_info.setUseFixedSun(getChild<LLUICtrl>("fixed_sun_check")->getValue().asBoolean());
region_info.mSunHour = get_sun_hour(getChild<LLUICtrl>("sun_hour_slider"));
region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice());
// if we changed access levels, tell user about it
LLViewerRegion* region = gAgent.getRegion();
if (region && (getChild<LLUICtrl>("access_combo")->getValue().asInteger() != region->getSimAccess()) )
{
LLNotificationsUtil::add("RegionMaturityChange");
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// LLPanelRegionDebugInfo
/////////////////////////////////////////////////////////////////////////////
BOOL LLPanelRegionDebugInfo::postBuild()
{
LLPanelRegionInfo::postBuild();
initCtrl("disable_scripts_check");
initCtrl("disable_collisions_check");
initCtrl("disable_physics_check");
initHelpBtn("disable_scripts_help", "HelpRegionDisableScripts");
initHelpBtn("disable_collisions_help", "HelpRegionDisableCollisions");
initHelpBtn("disable_physics_help", "HelpRegionDisablePhysics");
initHelpBtn("top_colliders_help", "HelpRegionTopColliders");
initHelpBtn("top_scripts_help", "HelpRegionTopScripts");
initHelpBtn("restart_help", "HelpRegionRestart");
childSetAction("choose_avatar_btn", boost::bind(&LLPanelRegionDebugInfo::onClickChooseAvatar, this));
childSetAction("return_btn", onClickReturn, this);
childSetAction("top_colliders_btn", onClickTopColliders, this);
childSetAction("top_scripts_btn", onClickTopScripts, this);
childSetAction("restart_btn", onClickRestart, this);
childSetAction("cancel_restart_btn", onClickCancelRestart, this);
childSetAction("region_debug_console_btn", onClickDebugConsole, this);
return TRUE;
}
// virtual
bool LLPanelRegionDebugInfo::refreshFromRegion(LLViewerRegion* region)
{
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
setCtrlsEnabled(allow_modify);
getChildView("apply_btn")->setEnabled(FALSE);
getChildView("target_avatar_name")->setEnabled(FALSE);
getChildView("choose_avatar_btn")->setEnabled(allow_modify);
getChildView("return_scripts")->setEnabled(allow_modify && !mTargetAvatar.isNull());
getChildView("return_other_land")->setEnabled(allow_modify && !mTargetAvatar.isNull());
getChildView("return_estate_wide")->setEnabled(allow_modify && !mTargetAvatar.isNull());
getChildView("return_btn")->setEnabled(allow_modify && !mTargetAvatar.isNull());
getChildView("top_colliders_btn")->setEnabled(allow_modify);
getChildView("top_scripts_btn")->setEnabled(allow_modify);
getChildView("restart_btn")->setEnabled(allow_modify);
getChildView("cancel_restart_btn")->setEnabled(allow_modify);
getChildView("region_debug_console_btn")->setEnabled(allow_modify);
return LLPanelRegionInfo::refreshFromRegion(region);
}
// virtual
BOOL LLPanelRegionDebugInfo::sendUpdate()
{
LL_INFOS() << "LLPanelRegionDebugInfo::sendUpdate" << LL_ENDL;
strings_t strings;
std::string buffer;
buffer = llformat("%s", (getChild<LLUICtrl>("disable_scripts_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(buffer);
buffer = llformat("%s", (getChild<LLUICtrl>("disable_collisions_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(buffer);
buffer = llformat("%s", (getChild<LLUICtrl>("disable_physics_check")->getValue().asBoolean() ? "Y" : "N"));
strings.push_back(buffer);
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "setregiondebug", invoice, strings);
return TRUE;
}
void LLPanelRegionDebugInfo::onClickChooseAvatar()
{
LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE);
}
void LLPanelRegionDebugInfo::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName>& names)
{
if (ids.empty() || names.empty()) return;
mTargetAvatar = ids[0];
getChild<LLUICtrl>("target_avatar_name")->setValue(LLSD(names[0].getCompleteName()));
refreshFromRegion( gAgent.getRegion() );
}
// static
void LLPanelRegionDebugInfo::onClickReturn(void* data)
{
LLPanelRegionDebugInfo* panelp = (LLPanelRegionDebugInfo*) data;
if (panelp->mTargetAvatar.isNull()) return;
LLSD args;
args["USER_NAME"] = panelp->getChild<LLUICtrl>("target_avatar_name")->getValue().asString();
LLSD payload;
payload["avatar_id"] = panelp->mTargetAvatar;
U32 flags = SWD_ALWAYS_RETURN_OBJECTS;
if (panelp->getChild<LLUICtrl>("return_scripts")->getValue().asBoolean())
{
flags |= SWD_SCRIPTED_ONLY;
}
if (panelp->getChild<LLUICtrl>("return_other_land")->getValue().asBoolean())
{
flags |= SWD_OTHERS_LAND_ONLY;
}
payload["flags"] = int(flags);
payload["return_estate_wide"] = panelp->getChild<LLUICtrl>("return_estate_wide")->getValue().asBoolean();
LLNotificationsUtil::add("EstateObjectReturn", args, payload,
boost::bind(&LLPanelRegionDebugInfo::callbackReturn, panelp, _1, _2));
}
bool LLPanelRegionDebugInfo::callbackReturn(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
LLUUID target_avatar = notification["payload"]["avatar_id"].asUUID();
if (!target_avatar.isNull())
{
U32 flags = notification["payload"]["flags"].asInteger();
bool return_estate_wide = notification["payload"]["return_estate_wide"];
if (return_estate_wide)
{
// send as estate message - routed by spaceserver to all regions in estate
strings_t strings;
strings.push_back(llformat("%d", flags));
strings.push_back(target_avatar.asString());
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings);
}
else
{
// send to this simulator only
send_sim_wide_deletes(target_avatar, flags);
}
}
return false;
}
// static
void LLPanelRegionDebugInfo::onClickTopColliders(void* data)
{
LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
strings_t strings;
strings.push_back("1"); // one physics step
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
LLFloaterTopObjects* instance = LLFloaterTopObjects::getInstance();
if(!instance) return;
instance->open();
instance->clearList();
self->sendEstateOwnerMessage(gMessageSystem, "colliders", invoice, strings);
}
// static
void LLPanelRegionDebugInfo::onClickTopScripts(void* data)
{
LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
strings_t strings;
strings.push_back("6"); // top 5 scripts
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
LLFloaterTopObjects* instance = LLFloaterTopObjects::getInstance();
if(!instance) return;
instance->open();
instance->clearList();
self->sendEstateOwnerMessage(gMessageSystem, "scripts", invoice, strings);
}
// static
void LLPanelRegionDebugInfo::onClickRestart(void* data)
{
LLNotificationsUtil::add("ConfirmRestart", LLSD(), LLSD(),
boost::bind(&LLPanelRegionDebugInfo::callbackRestart, (LLPanelRegionDebugInfo*)data, _1, _2));
}
bool LLPanelRegionDebugInfo::callbackRestart(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
strings_t strings;
strings.push_back(llformat("%d", getChild<LLSpinCtrl>("rcount")->getValue().asInteger()));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings);
return false;
}
// static
void LLPanelRegionDebugInfo::onClickCancelRestart(void* data)
{
LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
strings_t strings;
strings.push_back("-1");
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
self->sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings);
}
// static
void LLPanelRegionDebugInfo::onClickDebugConsole(void* data)
{
LLFloaterRegionDebugConsole::getInstance()->open();
}
BOOL LLPanelRegionTerrainInfo::validateTextureSizes()
{
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
std::string buffer;
buffer = llformat("texture_detail_%d", i);
LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>(buffer);
if (!texture_ctrl) continue;
LLUUID image_asset_id = texture_ctrl->getImageAssetID();
LLViewerTexture* img = LLViewerTextureManager::getFetchedTexture(image_asset_id);
S32 components = img->getComponents();
// Must ask for highest resolution version's width. JC
S32 width = img->getFullWidth();
S32 height = img->getFullHeight();
//LL_INFOS() << "texture detail " << i << " is " << width << "x" << height << "x" << components << LL_ENDL;
if (components != 3)
{
LLSD args;
args["TEXTURE_NUM"] = i+1;
args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8);
LLNotificationsUtil::add("InvalidTerrainBitDepth", args);
return FALSE;
}
if (width > 1024 || height > 1024) // <alchemy/>
{
LLSD args;
args["TEXTURE_NUM"] = i+1;
args["TEXTURE_SIZE_X"] = width;
args["TEXTURE_SIZE_Y"] = height;
LLNotificationsUtil::add("InvalidTerrainSize", args);
return FALSE;
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// LLPanelRegionTerrainInfo
/////////////////////////////////////////////////////////////////////////////
// Initialize statics
BOOL LLPanelRegionTerrainInfo::postBuild()
{
LLPanelRegionInfo::postBuild();
initHelpBtn("water_height_help", "HelpRegionWaterHeight");
initHelpBtn("terrain_raise_help", "HelpRegionTerrainRaise");
initHelpBtn("terrain_lower_help", "HelpRegionTerrainLower");
initHelpBtn("upload_raw_help", "HelpRegionUploadRaw");
initHelpBtn("download_raw_help", "HelpRegionDownloadRaw");
initHelpBtn("bake_terrain_help", "HelpRegionBakeTerrain");
initCtrl("water_height_spin");
initCtrl("terrain_raise_spin");
initCtrl("terrain_lower_spin");
std::string buffer;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
initCtrl(buffer);
}
for(S32 i = 0; i < CORNER_COUNT; ++i)
{
buffer = llformat("height_start_spin_%d", i);
initCtrl(buffer);
buffer = llformat("height_range_spin_%d", i);
initCtrl(buffer);
}
childSetAction("download_raw_btn", onClickDownloadRaw, this);
childSetAction("upload_raw_btn", onClickUploadRaw, this);
childSetAction("bake_terrain_btn", onClickBakeTerrain, this);
return LLPanelRegionInfo::postBuild();
}
// virtual
bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
{
BOOL owner_or_god = gAgent.isGodlike()
|| (region && (region->getOwner() == gAgent.getID()));
BOOL owner_or_god_or_manager = owner_or_god
|| (region && region->isEstateManager());
setCtrlsEnabled(owner_or_god_or_manager);
getChildView("apply_btn")->setEnabled(FALSE);
if (region)
{
getChild<LLUICtrl>("region_text")->setValue(LLSD(region->getName()));
LLVLComposition* compp = region->getComposition();
LLTextureCtrl* texture_ctrl;
std::string buffer;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
texture_ctrl = getChild<LLTextureCtrl>(buffer);
if(texture_ctrl)
{
LL_DEBUGS() << "Detail Texture " << i << ": "
<< compp->getDetailTextureID(i) << LL_ENDL;
LLUUID tmp_id(compp->getDetailTextureID(i));
texture_ctrl->setImageAssetID(tmp_id);
}
}
for(S32 i = 0; i < CORNER_COUNT; ++i)
{
buffer = llformat("height_start_spin_%d", i);
getChild<LLUICtrl>(buffer)->setValue(LLSD(compp->getStartHeight(i)));
buffer = llformat("height_range_spin_%d", i);
getChild<LLUICtrl>(buffer)->setValue(LLSD(compp->getHeightRange(i)));
}
}
else
{
LL_DEBUGS() << "no region set" << LL_ENDL;
getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
}
getChildView("download_raw_btn")->setEnabled(owner_or_god);
getChildView("upload_raw_btn")->setEnabled(owner_or_god);
getChildView("bake_terrain_btn")->setEnabled(owner_or_god);
return LLPanelRegionInfo::refreshFromRegion(region);
}
// virtual
BOOL LLPanelRegionTerrainInfo::sendUpdate()
{
LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL;
std::string buffer;
strings_t strings;
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
// update the model
LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
region_info.mWaterHeight = (F32) getChild<LLUICtrl>("water_height_spin")->getValue().asReal();
region_info.mTerrainRaiseLimit = (F32) getChild<LLUICtrl>("terrain_raise_spin")->getValue().asReal();
region_info.mTerrainLowerLimit = (F32) getChild<LLUICtrl>("terrain_lower_spin")->getValue().asReal();
// and sync the region with it
region_info.sendRegionTerrain(invoice);
// =======================================
// Assemble and send texturedetail message
// Make sure user hasn't chosen wacky textures on sl grids.
if (gHippoGridManager->getConnectedGrid()->isSecondLife() && !validateTextureSizes())
{
return FALSE;
}
LLTextureCtrl* texture_ctrl;
std::string id_str;
LLMessageSystem* msg = gMessageSystem;
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
buffer = llformat("texture_detail_%d", i);
texture_ctrl = getChild<LLTextureCtrl>(buffer);
if(texture_ctrl)
{
LLUUID tmp_id(texture_ctrl->getImageAssetID());
tmp_id.toString(id_str);
buffer = llformat("%d %s", i, id_str.c_str());
strings.push_back(buffer);
}
}
sendEstateOwnerMessage(msg, "texturedetail", invoice, strings);
strings.clear();
// ========================================
// Assemble and send textureheights message
for(S32 i = 0; i < CORNER_COUNT; ++i)
{
buffer = llformat("height_start_spin_%d", i);
std::string buffer2 = llformat("height_range_spin_%d", i);
std::string buffer3 = llformat("%d %f %f", i, (F32)getChild<LLUICtrl>(buffer)->getValue().asReal(), (F32)getChild<LLUICtrl>(buffer2)->getValue().asReal());
strings.push_back(buffer3);
}
sendEstateOwnerMessage(msg, "textureheights", invoice, strings);
strings.clear();
// ========================================
// Send texturecommit message
sendEstateOwnerMessage(msg, "texturecommit", invoice, strings);
return TRUE;
}
// static
void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data)
{
LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("terrain.raw", FFSAVE_RAW);
filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickDownloadRaw_continued, self, filepicker));
}
void LLPanelRegionTerrainInfo::onClickDownloadRaw_continued(AIFilePicker* filepicker)
{
if (!filepicker->hasFilename())
{
return;
}
std::string filepath = filepicker->getFilename();
gXferManager->expectFileForRequest(filepath);
strings_t strings;
strings.push_back("download filename");
strings.push_back(filepath);
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
}
// static
void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data)
{
LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_RAW);
filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker));
}
void LLPanelRegionTerrainInfo::onClickUploadRaw_continued(AIFilePicker* filepicker)
{
if (!filepicker->hasFilename())
return;
std::string filepath = filepicker->getFilename();
gXferManager->expectFileForTransfer(filepath);
strings_t strings;
strings.push_back("upload filename");
strings.push_back(filepath);
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
LLNotificationsUtil::add("RawUploadStarted");
}
// static
void LLPanelRegionTerrainInfo::onClickBakeTerrain(void* data)
{
LLNotificationsUtil::add("ConfirmBakeTerrain", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2));
}
bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
strings_t strings;
strings.push_back("bake");
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
return false;
}
/////////////////////////////////////////////////////////////////////////////
// LLPanelEstateInfo
//
LLPanelEstateInfo::LLPanelEstateInfo()
: LLPanelRegionInfo(),
mEstateID(0) // invalid
{
LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
estate_info.setCommitCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this));
estate_info.setUpdateCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this));
}
// static
void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch)
{
std::string name;
name.assign("estateupdateinfo");
static LLDispatchEstateUpdateInfo estate_update_info;
dispatch.addHandler(name, &estate_update_info);
name.assign("setaccess");
static LLDispatchSetEstateAccess set_access;
dispatch.addHandler(name, &set_access);
estate_dispatch_initialized = true;
}
//---------------------------------------------------------------------------
// Kick from estate methods
//---------------------------------------------------------------------------
void LLPanelEstateInfo::onClickKickUser()
{
// this depends on the grandparent view being a floater
// in order to set up floater dependency
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1, _2), FALSE, TRUE);
if (child_floater)
{
parent_floater->addDependentFloater(child_floater);
}
}
void LLPanelEstateInfo::onKickUserCommit(const uuid_vec_t& ids, const std::vector<LLAvatarName>& names)
{
if (names.empty() || ids.empty()) return;
//check to make sure there is one valid user and id
if( ids[0].isNull() )
{
return;
}
//Bring up a confirmation dialog
LLSD args;
args["EVIL_USER"] = names[0].getCompleteName();
LLSD payload;
payload["agent_id"] = ids[0];
LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2));
}
bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
{
//Kick User
strings_t strings;
strings.push_back(notification["payload"]["agent_id"].asString());
sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings);
break;
}
default:
break;
}
return false;
}
//---------------------------------------------------------------------------
// Core Add/Remove estate access methods
// TODO: INTERNATIONAL: don't build message text here;
// instead, create multiple translatable messages and choose
// one based on the status.
//---------------------------------------------------------------------------
std::string all_estates_text()
{
LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
if (!panel) return "(" + LLTrans::getString("RegionInfoError") + ")";
LLStringUtil::format_map_t args;
std::string owner = panel->getOwnerName();
LLViewerRegion* region = gAgent.getRegion();
if (gAgent.isGodlike())
{
args["[OWNER]"] = owner.c_str();
return LLTrans::getString("RegionInfoAllEstatesOwnedBy", args);
}
else if (region && region->getOwner() == gAgent.getID())
{
return LLTrans::getString("RegionInfoAllEstatesYouOwn");
}
else if (region && region->isEstateManager())
{
args["[OWNER]"] = owner.c_str();
return LLTrans::getString("RegionInfoAllEstatesYouManage", args);
}
else
{
return "(" + LLTrans::getString("RegionInfoError") + ")";
}
}
// static
bool LLPanelEstateInfo::isLindenEstate()
{
U32 estate_id = LLEstateInfoModel::instance().getID();
return (estate_id <= ESTATE_LAST_LINDEN);
}
struct LLEstateAccessChangeInfo
{
LLEstateAccessChangeInfo(const LLSD& sd)
{
mDialogName = sd["dialog_name"].asString();
mOperationFlag = (U32)sd["operation"].asInteger();
LLSD::array_const_iterator end_it = sd["allowed_ids"].endArray();
for (LLSD::array_const_iterator id_it = sd["allowed_ids"].beginArray();
id_it != end_it;
++id_it)
{
mAgentOrGroupIDs.push_back(id_it->asUUID());
}
}
const LLSD asLLSD() const
{
LLSD sd;
sd["name"] = mDialogName;
sd["operation"] = (S32)mOperationFlag;
for (U32 i = 0; i < mAgentOrGroupIDs.size(); ++i)
{
sd["allowed_ids"].append(mAgentOrGroupIDs[i]);
if (mAgentNames.size() > i)
{
sd["allowed_names"].append(mAgentNames[i].asLLSD());
}
}
return sd;
}
U32 mOperationFlag; // ESTATE_ACCESS_BANNED_AGENT_ADD, _REMOVE, etc.
std::string mDialogName;
uuid_vec_t mAgentOrGroupIDs; // List of agent IDs to apply to this change
std::vector<LLAvatarName> mAgentNames; // Optional list of the agent names for notifications
};
// static
void LLPanelEstateInfo::updateEstateOwnerID(const LLUUID& id)
{
LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate();
if (panelp)
{
panelp->getChild<LLUICtrl>("estate_owner")->setValue(id);
}
}
// static
void LLPanelEstateInfo::updateEstateName(const std::string& name)
{
LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate();
if (panelp)
{
panelp->getChildRef<LLTextBox>("estate_name").setText(name);
}
}
void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
{
BOOL god = gAgent.isGodlike();
BOOL owner = (region && (region->getOwner() == gAgent.getID()));
BOOL manager = (region && region->isEstateManager());
setCtrlsEnabled(god || owner || manager);
getChildView("message_estate_btn")->setEnabled(god || owner || manager);
getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager);
refresh();
}
bool LLPanelEstateInfo::refreshFromRegion(LLViewerRegion* region)
{
updateControls(region);
// let the parent class handle the general data collection.
bool rv = LLPanelRegionInfo::refreshFromRegion(region);
// We want estate info. To make sure it works across region
// boundaries and multiple packets, we add a serial number to the
// integers and track against that on update.
strings_t strings;
//integers_t integers;
//LLFloaterRegionInfo::incrementSerial();
LLFloaterRegionInfo::nextInvoice();
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
//integers.push_back(LLFloaterRegionInfo::());::getPanelEstate();
sendEstateOwnerMessage(gMessageSystem, "getinfo", invoice, strings);
refresh();
return rv;
}
void LLPanelEstateInfo::updateChild(LLUICtrl* child_ctrl)
{
// Ensure appropriate state of the management ui.
updateControls(gAgent.getRegion());
}
bool LLPanelEstateInfo::estateUpdate(LLMessageSystem* msg)
{
LL_INFOS() << "LLPanelEstateInfo::estateUpdate()" << LL_ENDL;
return false;
}
BOOL LLPanelEstateInfo::postBuild()
{
// set up the callbacks for the generic controls
initCtrl("externally_visible_check");
initCtrl("use_global_time_check");
initCtrl("fixed_sun_check");
initCtrl("sun_hour_slider");
initCtrl("allow_direct_teleport");
initCtrl("limit_payment");
initCtrl("limit_age_verified");
initCtrl("voice_chat_check");
initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime");
initHelpBtn("fixed_sun_help", "HelpEstateFixedSun");
initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible");
initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport");
initHelpBtn("voice_chat_help", "HelpEstateVoiceChat");
// Set up the Legacy Estate Environment checkboxes
{
LLUICtrl* global_time = getChild<LLUICtrl>("use_global_time_check");
LLUICtrl* fixed_sun = getChild<LLUICtrl>("fixed_sun_check");
LLUICtrl* hour_slider = getChild<LLUICtrl>("sun_hour_slider");
global_time->setCommitCallback(boost::bind(on_change_use_other_sun, _2, fixed_sun, hour_slider));
fixed_sun->setCommitCallback(boost::bind(on_change_fixed_sun, _2, global_time, hour_slider));
}
childSetAction("message_estate_btn", boost::bind(&LLPanelEstateInfo::onClickMessageEstate, this));
childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this));
return LLPanelRegionInfo::postBuild();
}
void LLPanelEstateInfo::refresh()
{
// Disable access restriction controls if they make no sense.
bool public_access = getChild<LLUICtrl>("externally_visible_check")->getValue().asBoolean();
getChildView("Only Allow")->setEnabled(public_access);
getChildView("limit_payment")->setEnabled(public_access);
getChildView("limit_age_verified")->setEnabled(public_access);
// if this is set to false, then the limit fields are meaningless and should be turned off
if (public_access == false)
{
getChild<LLUICtrl>("limit_payment")->setValue(false);
getChild<LLUICtrl>("limit_age_verified")->setValue(false);
}
}
void LLPanelEstateInfo::refreshFromEstate()
{
const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
getChild<LLUICtrl>("estate_name")->setValue(estate_info.getName());
getChild<LLUICtrl>("estate_owner")->setValue(estate_info.getOwnerID());
getChild<LLUICtrl>("externally_visible_check")->setValue(estate_info.getIsExternallyVisible());
getChild<LLUICtrl>("voice_chat_check")->setValue(estate_info.getAllowVoiceChat());
getChild<LLUICtrl>("allow_direct_teleport")->setValue(estate_info.getAllowDirectTeleport());
getChild<LLUICtrl>("limit_payment")->setValue(estate_info.getDenyAnonymous());
getChild<LLUICtrl>("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified());
// Ensure appropriate state of the management UI
updateControls(gAgent.getRegion());
// Support Legacy Estate Environment
{
const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
bool global_time = estate_info.getGlobalTime();
getChild<LLUICtrl>("use_global_time_check")->setValue(global_time);
getChild<LLUICtrl>("fixed_sun_check")->setEnabled(!global_time);
getChild<LLUICtrl>("sun_hour_slider")->setEnabled(!global_time);
if (global_time)
{
getChild<LLUICtrl>("use_global_time_check")->setEnabled(true);
getChild<LLUICtrl>("fixed_sun_check")->setValue(false);
}
else
{
bool fixed_sun = estate_info.getUseFixedSun();
getChild<LLUICtrl>("use_global_time_check")->setEnabled(!fixed_sun);
getChild<LLUICtrl>("fixed_sun_check")->setValue(fixed_sun);
F32 sun_hour = estate_info.getSunHour();
if (sun_hour < 6.0f) sun_hour += 24.0f;
getChild<LLUICtrl>("sun_hour_slider")->setValue(sun_hour);
}
}
refresh();
}
BOOL LLPanelEstateInfo::sendUpdate()
{
LL_INFOS() << "LLPanelEstateInfo::sendUpdate()" << LL_ENDL;
LLNotification::Params params("ChangeLindenEstate");
params.functor(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2));
if (isLindenEstate())
{
// trying to change reserved estate, warn
LLNotifications::instance().add(params);
}
else
{
// for normal estates, just make the change
LLNotifications::instance().forceResponse(params, 0);
}
return TRUE;
}
bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
{
LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
// update model
estate_info.setIsExternallyVisible(getChild<LLUICtrl>("externally_visible_check")->getValue().asBoolean());
estate_info.setUseFixedSun(getChild<LLUICtrl>("fixed_sun_check")->getValue().asBoolean());
estate_info.setSunHour(get_sun_hour(getChild<LLUICtrl>("sun_hour_slider")));
estate_info.setAllowDirectTeleport(getChild<LLUICtrl>("allow_direct_teleport")->getValue().asBoolean());
estate_info.setDenyAnonymous(getChild<LLUICtrl>("limit_payment")->getValue().asBoolean());
estate_info.setDenyAgeUnverified(getChild<LLUICtrl>("limit_age_verified")->getValue().asBoolean());
estate_info.setAllowVoiceChat(getChild<LLUICtrl>("voice_chat_check")->getValue().asBoolean());
// send the update to sim
estate_info.sendEstateInfo();
}
// we don't want to do this because we'll get it automatically from the sim
// after the spaceserver processes it
// else
// {
// // caps method does not automatically send this info
// LLFloaterRegionInfo::requestRegionInfo();
// }
break;
case 1:
default:
// do nothing
break;
}
return false;
}
/*
// Request = "getowner"
// SParam[0] = "" (empty string)
// IParam[0] = serial
void LLPanelEstateInfo::getEstateOwner()
{
// TODO -- disable the panel
// and call this function whenever we cross a region boundary
// re-enable when owner matches, and get new estate info
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_EstateOwnerRequest);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->nextBlockFast(_PREHASH_RequestData);
msg->addStringFast(_PREHASH_Request, "getowner");
// we send an empty string so that the variable block is not empty
msg->nextBlockFast(_PREHASH_StringData);
msg->addStringFast(_PREHASH_SParam, "");
msg->nextBlockFast(_PREHASH_IntegerData);
msg->addS32Fast(_PREHASH_IParam, LLFloaterRegionInfo::getSerial());
gAgent.sendMessage();
}
*/
const std::string LLPanelEstateInfo::getOwnerName() const
{
return getChild<LLTextBox>("estate_owner")->getText();
}
// static
void LLPanelEstateInfo::onClickMessageEstate(void* userdata)
{
LL_INFOS() << "LLPanelEstateInfo::onClickMessageEstate" << LL_ENDL;
LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2));
}
bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
std::string text = response["message"].asString();
if(option != 0) return false;
if(text.empty()) return false;
LL_INFOS() << "Message to everyone: " << text << LL_ENDL;
strings_t strings;
//integers_t integers;
std::string name;
LLAgentUI::buildFullname(name);
strings.push_back(strings_t::value_type(name));
strings.push_back(strings_t::value_type(text));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings);
return false;
}
LLPanelEstateCovenant::LLPanelEstateCovenant()
: LLPanelRegionInfo()
, mEstateNameText(nullptr)
, mEstateOwnerText(nullptr)
, mLastModifiedText(nullptr)
, mCovenantID(LLUUID::null)
, mEditor(nullptr)
, mAssetStatus(ASSET_ERROR)
{
}
// virtual
bool LLPanelEstateCovenant::refreshFromRegion(LLViewerRegion* region)
{
LLTextBox* region_name = getChild<LLTextBox>("region_name_text");
if (region_name)
{
region_name->setText(region->getName());
}
LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
if (resellable_clause)
{
if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL))
{
resellable_clause->setText(getString("can_not_resell"));
}
else
{
resellable_clause->setText(getString("can_resell"));
}
}
LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause");
if (changeable_clause)
{
if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES))
{
changeable_clause->setText(getString("can_change"));
}
else
{
changeable_clause->setText(getString("can_not_change"));
}
}
LLTextBox* region_maturity = getChild<LLTextBox>("region_maturity_text");
if (region_maturity)
{
region_maturity->setText(region->getSimAccessString());
}
LLTextBox* region_landtype = getChild<LLTextBox>("region_landtype_text");
region_landtype->setText(region->getLocalizedSimProductName());
// let the parent class handle the general data collection.
bool rv = LLPanelRegionInfo::refreshFromRegion(region);
LLMessageSystem *msg = gMessageSystem;
msg->newMessage("EstateCovenantRequest");
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
msg->sendReliable(region->getHost());
return rv;
}
// virtual
bool LLPanelEstateCovenant::estateUpdate(LLMessageSystem* msg)
{
LL_INFOS() << "LLPanelEstateCovenant::estateUpdate()" << LL_ENDL;
return true;
}
// virtual
BOOL LLPanelEstateCovenant::postBuild()
{
initHelpBtn("covenant_help", "HelpEstateCovenant");
mEstateNameText = getChild<LLTextBox>("estate_name_text");
mEstateOwnerText = getChild<LLTextBox>("estate_owner_text");
mLastModifiedText = getChild<LLTextBox>("covenant_timestamp_text");
mEditor = getChild<LLViewerTextEditor>("covenant_editor");
if (mEditor) mEditor->setHandleEditKeysDirectly(TRUE);
LLButton* reset_button = getChild<LLButton>("reset_covenant");
reset_button->setEnabled(gAgent.canManageEstate());
reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, NULL);
return LLPanelRegionInfo::postBuild();
}
// virtual
void LLPanelEstateCovenant::updateChild(LLUICtrl* child_ctrl)
{
}
// virtual
BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
LLInventoryItem* item = (LLInventoryItem*)cargo_data;
if (!gAgent.canManageEstate())
{
*accept = ACCEPT_NO;
return TRUE;
}
switch(cargo_type)
{
case DAD_NOTECARD:
*accept = ACCEPT_YES_COPY_SINGLE;
if (item && drop)
{
LLSD payload;
payload["item_id"] = item->getUUID();
LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload,
LLPanelEstateCovenant::confirmChangeCovenantCallback);
}
break;
default:
*accept = ACCEPT_NO;
break;
}
return TRUE;
}
// static
bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant();
if (!item || !self) return false;
switch(option)
{
case 0:
self->loadInvItem(item);
break;
default:
break;
}
return false;
}
// static
void LLPanelEstateCovenant::resetCovenantID(void* userdata)
{
LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback);
}
// static
bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notification, const LLSD& response)
{
LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant();
if (!self) return false;
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
self->loadInvItem(NULL);
break;
default:
break;
}
return false;
}
void LLPanelEstateCovenant::loadInvItem(LLInventoryItem *itemp)
{
const BOOL high_priority = TRUE;
if (itemp)
{
gAssetStorage->getInvItemAsset(gAgent.getRegionHost(),
gAgent.getID(),
gAgent.getSessionID(),
itemp->getPermissions().getOwner(),
LLUUID::null,
itemp->getUUID(),
itemp->getAssetUUID(),
itemp->getType(),
onLoadComplete,
(void*)this,
high_priority);
mAssetStatus = ASSET_LOADING;
}
else
{
mAssetStatus = ASSET_LOADED;
setCovenantTextEditor(LLTrans::getString("RegionNoCovenant"));
sendChangeCovenantID(LLUUID::null);
}
}
// static
void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status)
{
LL_INFOS() << "LLPanelEstateCovenant::onLoadComplete()" << LL_ENDL;
LLPanelEstateCovenant* panelp = (LLPanelEstateCovenant*)user_data;
if( panelp )
{
if(0 == status)
{
LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
S32 file_length = file.getSize();
std::vector<char> buffer(file_length+1);
file.read((U8*)&buffer[0], file_length);
// put a EOS at the end
buffer[file_length] = 0;
if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) )
{
if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) )
{
LL_WARNS() << "Problem importing estate covenant." << LL_ENDL;
LLNotificationsUtil::add("ProblemImportingEstateCovenant");
}
else
{
panelp->sendChangeCovenantID(asset_uuid);
}
}
else
{
// Version 0 (just text, doesn't include version number)
panelp->sendChangeCovenantID(asset_uuid);
}
}
else
{
LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
LLNotificationsUtil::add("MissingNotecardAssetID");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
LLNotificationsUtil::add("NotAllowedToViewNotecard");
}
else
{
LLNotificationsUtil::add("UnableToLoadNotecardAsset");
}
LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL;
}
panelp->mAssetStatus = ASSET_LOADED;
panelp->setCovenantID(asset_uuid);
}
}
// key = "estatechangecovenantid"
// strings[0] = str(estate_id) (added by simulator before relay - not here)
// strings[1] = str(covenant_id)
void LLPanelEstateCovenant::sendChangeCovenantID(const LLUUID &asset_id)
{
if (asset_id != getCovenantID())
{
setCovenantID(asset_id);
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("EstateOwnerMessage");
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
msg->nextBlock("MethodData");
msg->addString("Method", "estatechangecovenantid");
msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice());
msg->nextBlock("ParamList");
msg->addString("Parameter", getCovenantID().asString());
gAgent.sendReliableMessage();
}
}
// virtual
BOOL LLPanelEstateCovenant::sendUpdate()
{
return TRUE;
}
std::string LLPanelEstateCovenant::getEstateName() const
{
return mEstateNameText->getText();
}
void LLPanelEstateCovenant::setEstateName(const std::string& name)
{
mEstateNameText->setText(name);
}
// static
void LLPanelEstateCovenant::updateCovenantText(const std::string& string, const LLUUID& asset_id)
{
LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant();
if( panelp )
{
panelp->mEditor->setText(string, false);
panelp->setCovenantID(asset_id);
}
}
// static
void LLPanelEstateCovenant::updateEstateName(const std::string& name)
{
LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant();
if( panelp )
{
panelp->mEstateNameText->setText(name);
}
}
// static
void LLPanelEstateCovenant::updateLastModified(const std::string& text)
{
LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant();
if( panelp )
{
panelp->mLastModifiedText->setText(text);
}
}
// static
void LLPanelEstateCovenant::updateEstateOwnerID(const LLUUID& id)
{
LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant();
if( panelp )
{
panelp->mEstateOwnerText->setValue(id);
}
}
std::string LLPanelEstateCovenant::getOwnerName() const
{
return mEstateOwnerText->getText();
}
void LLPanelEstateCovenant::setCovenantTextEditor(const std::string& text)
{
mEditor->setText(text, false);
}
// key = "estateupdateinfo"
// strings[0] = estate name
// strings[1] = str(owner_id)
// strings[2] = str(estate_id)
// strings[3] = str(estate_flags)
// strings[4] = str((S32)(sun_hour * 1024))
// strings[5] = str(parent_estate_id)
// strings[6] = str(covenant_id)
// strings[7] = str(covenant_timestamp)
// strings[8] = str(send_to_agent_only)
// strings[9] = str(abuse_email_addr)
bool LLDispatchEstateUpdateInfo::operator()(
const LLDispatcher* dispatcher,
const std::string& key,
const LLUUID& invoice,
const sparam_t& strings)
{
LL_DEBUGS() << "Received estate update" << LL_ENDL;
// Update estate info model.
// This will call LLPanelEstateInfo::refreshFromEstate().
// *TODO: Move estate message handling stuff to llestateinfomodel.cpp.
LLEstateInfoModel::instance().update(strings);
return true;
}
bool LLDispatchSetEstateAccess::operator()(
const LLDispatcher* dispatcher,
const std::string& key,
const LLUUID& invoice,
const sparam_t& strings)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return true;
S32 index = 1; // skip estate_id
U32 access_flags = strtoul(strings[index++].c_str(), NULL,10);
S32 num_allowed_agents = strtol(strings[index++].c_str(), NULL, 10);
S32 num_allowed_groups = strtol(strings[index++].c_str(), NULL, 10);
S32 num_banned_agents = strtol(strings[index++].c_str(), NULL, 10);
S32 num_estate_managers = strtol(strings[index++].c_str(), NULL, 10);
// sanity ckecks
if (num_allowed_agents > 0
&& !(access_flags & ESTATE_ACCESS_ALLOWED_AGENTS))
{
LL_WARNS() << "non-zero count for allowed agents, but no corresponding flag" << LL_ENDL;
}
if (num_allowed_groups > 0
&& !(access_flags & ESTATE_ACCESS_ALLOWED_GROUPS))
{
LL_WARNS() << "non-zero count for allowed groups, but no corresponding flag" << LL_ENDL;
}
if (num_banned_agents > 0
&& !(access_flags & ESTATE_ACCESS_BANNED_AGENTS))
{
LL_WARNS() << "non-zero count for banned agents, but no corresponding flag" << LL_ENDL;
}
if (num_estate_managers > 0
&& !(access_flags & ESTATE_ACCESS_MANAGERS))
{
LL_WARNS() << "non-zero count for managers, but no corresponding flag" << LL_ENDL;
}
// Build an LLSD to fake the http response on older grids
LLSD result;
// grab the UUID's out of the string fields
if (access_flags & ESTATE_ACCESS_ALLOWED_AGENTS)
{
LLNameListCtrl* allowed_agent_name_list = panel->getChild<LLNameListCtrl>("allowed_avatar_name_list");
if (allowed_agent_name_list)
{
auto& allowed_agents = result["AllowedAgents"];
for (const auto& id : allowed_agent_name_list->getAllIDs())
{
allowed_agents.append(LLSD().with("id", id));
}
for (S32 i = 0; i < num_allowed_agents; ++i)
{
LLUUID id;
memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */
allowed_agents.append(LLSD().with("id", id));
}
}
}
if (access_flags & ESTATE_ACCESS_ALLOWED_GROUPS)
{
auto& allowed_groups = result["AllowedGroups"];
for (S32 i = 0; i < num_allowed_groups; ++i)
{
LLUUID id;
memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */
allowed_groups.append(LLSD().with("id", id));
}
}
if (access_flags & ESTATE_ACCESS_BANNED_AGENTS)
{
if (LLNameListCtrl* banned_agent_name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list"))
{
auto& banned_agents = result["BannedAgents"];
for (const auto& id : banned_agent_name_list->getAllIDs())
{
banned_agents.append(LLSD().with("id", id));
}
for (S32 i = 0; i < num_banned_agents; i++)
{
LLUUID id;
memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */
banned_agents.append(LLSD().with("id", id));
}
}
}
if (access_flags & ESTATE_ACCESS_MANAGERS)
{
auto& managers = result["Managers"];
for (S32 i = 0; i < num_estate_managers; ++i)
{
LLUUID id;
memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */
managers.append(LLSD().with("id", id));
}
}
if (panel)
{
panel->onEstateAccessReceived(result); // Until HTTP response use UDP Result
if (panel->getPendingUpdate())
{
panel->setPendingUpdate(false);
panel->updateLists();
}
}
return true;
}
LLPanelEnvironmentInfo::LLPanelEnvironmentInfo()
: mEnableEditing(false),
mRegionSettingsRadioGroup(NULL),
mDayCycleSettingsRadioGroup(NULL),
mWaterPresetCombo(NULL),
mSkyPresetCombo(NULL),
mDayCyclePresetCombo(NULL)
{
}
// virtual
BOOL LLPanelEnvironmentInfo::postBuild()
{
mRegionSettingsRadioGroup = getChild<LLRadioGroup>("region_settings_radio_group");
mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchRegionSettings, this));
mDayCycleSettingsRadioGroup = getChild<LLRadioGroup>("sky_dayc_settings_radio_group");
mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchDayCycle, this));
mWaterPresetCombo = getChild<LLComboBox>("water_settings_preset_combo");
mWaterPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectWaterPreset, this));
mSkyPresetCombo = getChild<LLComboBox>("sky_settings_preset_combo");
mSkyPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectSkyPreset, this));
mDayCyclePresetCombo = getChild<LLComboBox>("dayc_settings_preset_combo");
mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectDayCycle, this));
getChild<LLButton>("apply_btn")->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onBtnApply, this));
//getChild<LLButton>("apply_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance()));
getChild<LLButton>("cancel_btn")->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onBtnCancel, this));
//getChild<LLButton>("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance()));
LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingschange, this));
LLEnvManagerNew::instance().setRegionSettingsAppliedCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingsApplied, this, _1));
LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLPanelEnvironmentInfo::populateDayCyclesList, this));
LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateSkyPresetsList, this));
LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateWaterPresetsList, this));
return TRUE;
}
// virtual
void LLPanelEnvironmentInfo::onOpen(const LLSD& key)
{
LL_DEBUGS("Windlight") << "Panel opened, refreshing" << LL_ENDL;
refresh();
}
// virtual
void LLPanelEnvironmentInfo::handleVisibilityChange(BOOL new_visibility)
{
// If hiding (user switched to another tab or closed the floater),
// display user's preferred environment.
if (!new_visibility)
{
LLEnvManagerNew::instance().usePrefs();
}
}
// virtual
bool LLPanelEnvironmentInfo::refreshFromRegion(LLViewerRegion* region)
{
LL_DEBUGS("Windlight") << "Region updated, enabling/disabling controls" << LL_ENDL;
BOOL owner_or_god = gAgent.isGodlike() || (region && (region->getOwner() == gAgent.getID()));
BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
// Don't refresh from region settings to avoid flicker after applying new region settings.
mEnableEditing = owner_or_god_or_manager;
setControlsEnabled(mEnableEditing);
return LLPanelRegionInfo::refreshFromRegion(region);
}
void LLPanelEnvironmentInfo::refresh()
{
populateWaterPresetsList();
populateSkyPresetsList();
populateDayCyclesList();
// Init radio groups.
const LLEnvironmentSettings& settings = LLEnvManagerNew::instance().getRegionSettings();
const LLSD& dc = settings.getWLDayCycle();
LLSD::Real first_frame_time = dc.size() > 0 ? dc[0][0].asReal() : 0.0f;
const bool use_fixed_sky = dc.size() == 1 && first_frame_time < 0;
mRegionSettingsRadioGroup->setSelectedIndex(settings.getSkyMap().size() == 0 ? 0 : 1);
mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1);
setControlsEnabled(mEnableEditing);
setDirty(false);
}
void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled)
{
mRegionSettingsRadioGroup->setEnabled(enabled);
mDayCycleSettingsRadioGroup->setEnabled(enabled);
mWaterPresetCombo->setEnabled(enabled);
mSkyPresetCombo->setEnabled(enabled);
mDayCyclePresetCombo->setEnabled(enabled);
getChildView("apply_btn")->setEnabled(enabled);
getChildView("cancel_btn")->setEnabled(enabled);
if (enabled)
{
// Enable/disable some controls based on currently selected radio buttons.
bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
getChild<LLView>("user_environment_settings")->setEnabled(!use_defaults);
bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
mSkyPresetCombo->setEnabled(is_fixed_sky);
mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
}
}
void LLPanelEnvironmentInfo::setApplyProgress(bool started)
{
LLTextBox* indicator = getChild<LLTextBox>("progress_indicator");
indicator->setVisible(started);
/* Singu TODO: LLLoadingIndicator
if (started)
{
indicator->start();
}
else
{
indicator->stop();
}
*/
}
void LLPanelEnvironmentInfo::setDirty(bool dirty)
{
getChildView("apply_btn")->setEnabled(dirty);
getChildView("cancel_btn")->setEnabled(dirty);
}
void LLPanelEnvironmentInfo::sendRegionSunUpdate()
{
LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
// If the region is being switched to fixed sky,
// change the region's sun hour according to the (fixed) sun position.
// This is needed for llGetSunDirection() LSL function to work properly (STORM-1330).
const LLSD& sky_map = mNewRegionSettings.getSkyMap();
bool region_use_fixed_sky = sky_map.size() == 1;
if (region_use_fixed_sky)
{
LLWLParamSet param_set;
llassert(sky_map.isMap());
param_set.setAll(sky_map.beginMap()->second);
F32 sun_angle = param_set.getSunAngle();
LL_DEBUGS("Windlight Sync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL;
// convert value range from 0..2pi to 6..30
region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f;
}
region_info.setUseFixedSun(region_use_fixed_sky);
region_info.mUseEstateSun = !region_use_fixed_sky;
LL_DEBUGS("Windlight Sync") << "Sun hour: " << region_info.mSunHour << LL_ENDL;
region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice());
}
void LLPanelEnvironmentInfo::fixEstateSun()
{
// We don't support fixed sun estates anymore and need to fix
// such estates for region day cycle to take effect.
// *NOTE: Assuming that current estate settings have arrived already.
LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
if (estate_info.getUseFixedSun())
{
LL_INFOS() << "Switching estate to global sun" << LL_ENDL;
estate_info.setUseFixedSun(false);
estate_info.sendEstateInfo();
}
}
void LLPanelEnvironmentInfo::populateWaterPresetsList()
{
mWaterPresetCombo->removeall();
// If the region already has water params, add them to the list.
const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings();
if (region_settings.getWaterParams().size() != 0)
{
const std::string& region_name = gAgent.getRegion()->getName();
mWaterPresetCombo->add(region_name, LLWLParamKey(region_name, LLEnvKey::SCOPE_REGION).toLLSD());
mWaterPresetCombo->addSeparator();
}
std::list<std::string> user_presets, system_presets;
LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
// Add local user presets first.
for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
{
mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
}
if (user_presets.size() > 0)
{
mWaterPresetCombo->addSeparator();
}
// Add local system presets.
for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
{
mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
}
// There's no way to select current preset because its name is not stored on server.
}
void LLPanelEnvironmentInfo::populateSkyPresetsList()
{
mSkyPresetCombo->removeall();
LLWLParamManager::preset_name_list_t region_presets;
LLWLParamManager::preset_name_list_t user_presets, sys_presets;
LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
// Add region presets.
std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
{
std::string preset_name = *it;
std::string item_title = preset_name + " (" + region_name + ")";
mSkyPresetCombo->add(item_title, LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal());
}
if (!region_presets.empty())
{
mSkyPresetCombo->addSeparator();
}
// Add user presets.
for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
{
mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
}
if (!user_presets.empty())
{
mSkyPresetCombo->addSeparator();
}
// Add system presets.
for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
{
mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
}
// Select current preset.
LLSD sky_map = LLEnvManagerNew::instance().getRegionSettings().getSkyMap();
if (sky_map.size() == 1) // if the region is set to fixed sky
{
std::string preset_name = sky_map.beginMap()->first;
mSkyPresetCombo->selectByValue(LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal());
}
}
void LLPanelEnvironmentInfo::populateDayCyclesList()
{
mDayCyclePresetCombo->removeall();
// If the region already has env. settings, add its day cycle to the list.
const LLSD& cur_region_dc = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
if (cur_region_dc.size() != 0)
{
LLViewerRegion* region = gAgent.getRegion();
llassert(region != NULL);
LLWLParamKey key(region->getName(), LLEnvKey::SCOPE_REGION);
mDayCyclePresetCombo->add(region->getName(), key.toStringVal());
mDayCyclePresetCombo->addSeparator();
}
// Add local user day cycles.
LLDayCycleManager::preset_name_list_t user_days, sys_days;
LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
{
mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
}
if (user_days.size() > 0)
{
mDayCyclePresetCombo->addSeparator();
}
// Add local system day cycles.
for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
{
mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
}
// Current day cycle is already selected.
}
bool LLPanelEnvironmentInfo::getSelectedWaterParams(LLSD& water_params)
{
LLWLParamKey water_key(mWaterPresetCombo->getSelectedValue());
if (water_key.scope == LLEnvKey::SCOPE_REGION)
{
water_params = LLEnvManagerNew::instance().getRegionSettings().getWaterParams();
}
else
{
LLWaterParamSet param_set;
if (!LLWaterParamManager::instance().getParamSet(water_key.name, param_set))
{
LL_WARNS() << "Error getting water preset: " << water_key.name << LL_ENDL;
return false;
}
water_params = param_set.getAll();
}
return true;
}
bool LLPanelEnvironmentInfo::getSelectedSkyParams(LLSD& sky_params, std::string& preset_name)
{
std::string preset_key(mSkyPresetCombo->getValue().asString());
LLWLParamKey preset(preset_key);
// Get the preset sky params.
LLWLParamSet param_set;
if (!LLWLParamManager::instance().getParamSet(preset, param_set))
{
LL_WARNS() << "Error getting sky params: " << preset.toLLSD() << LL_ENDL;
return false;
}
sky_params = param_set.getAll();
preset_name = preset.name;
return true;
}
bool LLPanelEnvironmentInfo::getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope)
{
std::string preset_key(mDayCyclePresetCombo->getValue().asString());
LLWLParamKey dc(preset_key);
LL_DEBUGS("Windlight") << "Use day cycle: " << dc.toLLSD() << LL_ENDL;
if (dc.scope == LLEnvKey::SCOPE_REGION) // current region day cycle
{
const LLEnvironmentSettings& cur_region_settings = LLEnvManagerNew::instance().getRegionSettings();
day_cycle = cur_region_settings.getWLDayCycle();
sky_map = cur_region_settings.getSkyMap();
}
else // a local day cycle
{
if (!LLDayCycleManager::instance().getPreset(dc.name, day_cycle))
{
LL_WARNS() << "Error getting day cycle " << dc.name << LL_ENDL;
return false;
}
// Create sky map from the day cycle.
{
LLWLDayCycle tmp_day;
tmp_day.loadDayCycle(day_cycle, dc.scope);
tmp_day.getSkyMap(sky_map);
}
}
scope = dc.scope;
return true;
}
void LLPanelEnvironmentInfo::onSwitchRegionSettings()
{
bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
getChild<LLView>("user_environment_settings")->setEnabled(!use_defaults);
if (use_defaults)
{
LLEnvManagerNew::instance().useDefaults();
}
else
{
onSelectWaterPreset();
onSwitchDayCycle();
}
setDirty(true);
}
void LLPanelEnvironmentInfo::onSwitchDayCycle()
{
bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
mSkyPresetCombo->setEnabled(is_fixed_sky);
mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
if (is_fixed_sky)
{
onSelectSkyPreset();
}
else
{
onSelectDayCycle();
}
setDirty(true);
}
void LLPanelEnvironmentInfo::onSelectWaterPreset()
{
LLSD water_params;
if (getSelectedWaterParams(water_params))
{
LLEnvManagerNew::instance().useWaterParams(water_params);
}
setDirty(true);
}
void LLPanelEnvironmentInfo::onSelectSkyPreset()
{
LLSD params;
std::string dummy;
if (getSelectedSkyParams(params, dummy))
{
LLEnvManagerNew::instance().useSkyParams(params);
}
setDirty(true);
}
void LLPanelEnvironmentInfo::onSelectDayCycle()
{
LLSD day_cycle;
LLSD sky_map; // unused
short scope;
if (getSelectedDayCycleParams(day_cycle, sky_map, scope))
{
LLEnvManagerNew::instance().useDayCycleParams(day_cycle, (LLEnvKey::EScope) scope);
}
setDirty(true);
}
void LLPanelEnvironmentInfo::onBtnApply()
{
const bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
const bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
LLSD day_cycle;
LLSD sky_map;
LLSD water_params;
if (use_defaults)
{
// settings will be empty
LL_DEBUGS("Windlight") << "Defaults" << LL_ENDL;
}
else // use custom region settings
{
if (use_fixed_sky)
{
LL_DEBUGS("Windlight") << "Use fixed sky" << LL_ENDL;
// Get selected sky params.
LLSD params;
std::string preset_name;
if (!getSelectedSkyParams(params, preset_name))
{
return;
}
// Create a day cycle consisting of a single sky preset.
LLSD key(LLSD::emptyArray());
key.append(-1.0f); // indicate that user preference is actually fixed sky, not a day cycle
key.append(preset_name);
day_cycle.append(key);
// Create a sky map consisting of only the sky preset.
std::map<LLWLParamKey, LLWLParamSet> refs;
LLWLParamSet param_set;
param_set.setAll(params);
refs[LLWLParamKey(preset_name, LLEnvKey::SCOPE_LOCAL)] = param_set; // scope doesn't matter here
sky_map = LLWLParamManager::createSkyMap(refs);
}
else // use day cycle
{
LL_DEBUGS("Windlight") << "Use day cycle" << LL_ENDL;
short scope; // unused
if (!getSelectedDayCycleParams(day_cycle, sky_map, scope))
{
return;
}
// If it's a special single-preset day cycle meaning using a fixed sky,
// reset the frame time to a non-negative value,
// so that the region setting is displayed in the floater as
// a day cycle, not a preset. (STORM-1289)
if (day_cycle.size() == 1 && day_cycle[0][0].asReal() < 0.0f)
{
LL_DEBUGS("Windlight") << "Fixing negative time" << LL_ENDL;
day_cycle[0][0] = 0.0f;
}
}
// Get water params.
if (!getSelectedWaterParams(water_params))
{
// *TODO: show a notification?
return;
}
}
// Send settings apply request.
LLEnvironmentSettings new_region_settings;
new_region_settings.saveParams(day_cycle, sky_map, water_params, 0.0f);
if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings))
{
LL_WARNS() << "Error applying region environment settings" << LL_ENDL;
return;
}
// When the settings get applied, we'll also send the region sun position update.
// To determine the sun angle we're going to need the new settings.
mNewRegionSettings = new_region_settings;
// Start spinning the progress indicator.
setApplyProgress(true);
}
void LLPanelEnvironmentInfo::onBtnCancel()
{
// Reload last saved region settings.
refresh();
// Apply them.
LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
const LLEnvironmentSettings& cur_settings = env_mgr.getRegionSettings();
const LLSD& region_day_cycle = cur_settings.getWLDayCycle();
const LLSD& region_water = cur_settings.getWaterParams();
env_mgr.useWaterParams(region_water);
env_mgr.useDayCycleParams(region_day_cycle, LLEnvKey::SCOPE_REGION);
}
void LLPanelEnvironmentInfo::onRegionSettingschange()
{
LL_DEBUGS("Windlight") << "Region settings changed, refreshing" << LL_ENDL;
refresh();
// Stop applying progress indicator (it may be running if it's us who initiated settings update).
setApplyProgress(false);
}
void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok)
{
// If applying new settings has failed, stop the indicator right away.
// Otherwise it will be stopped when we receive the updated settings from server.
if (ok)
{
// Set the region sun phase/flags according to the chosen new preferences.
//
// If we do this earlier we may get jerky transition from fixed sky to a day cycle (STORM-1481).
// That is caused by the simulator re-sending the region info, which in turn makes us
// re-request and display old region environment settings while the new ones haven't been applied yet.
sendRegionSunUpdate();
// Switch estate to not using fixed sun for the region day cycle to work properly (STORM-1506).
fixEstateSun();
}
else
{
setApplyProgress(false);
// We need to re-request environment setting here,
// otherwise our subsequent attempts to change region settings will fail with the following error:
// "Unable to update environment settings because the last update your viewer saw was not the same
// as the last update sent from the simulator. Try sending your update again, and if this
// does not work, try leaving and returning to the region."
LLEnvManagerNew::instance().requestRegionSettings();
}
}
#if 0 // Singu TODO: Experiences
LLPanelRegionExperiences::LLPanelRegionExperiences()
: mTrusted(nullptr)
, mAllowed(nullptr)
, mBlocked(nullptr)
{
mFactoryMap["panel_trusted"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast<void*>(&mTrusted));
mFactoryMap["panel_allowed"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast<void*>(&mAllowed));
mFactoryMap["panel_blocked"] = LLCallbackMap(create_xp_list_editor, reinterpret_cast<void*>(&mBlocked));
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_region_experiences.xml", &mFactoryMap);
}
BOOL LLPanelRegionExperiences::postBuild()
{
setupList(mAllowed, "panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE);
setupList(mTrusted, "panel_trusted", ESTATE_EXPERIENCE_TRUSTED_ADD, ESTATE_EXPERIENCE_TRUSTED_REMOVE);
setupList(mBlocked, "panel_blocked", ESTATE_EXPERIENCE_BLOCKED_ADD, ESTATE_EXPERIENCE_BLOCKED_REMOVE);
getChild<LLLayoutPanel>("trusted_layout_panel")->setVisible(TRUE);
getChild<LLTextBox>("experiences_help_text")->setText(getString("estate_caption"));
getChild<LLTextBox>("trusted_text_help")->setText(getString("trusted_estate_text"));
getChild<LLTextBox>("allowed_text_help")->setText(getString("allowed_estate_text"));
getChild<LLTextBox>("blocked_text_help")->setText(getString("blocked_estate_text"));
return LLPanelRegionInfo::postBuild();
}
void LLPanelRegionExperiences::setupList(LLPanelExperienceListEditor* child, const char* control_name, U32 add_id, U32 remove_id )
{
//LLPanelExperienceListEditor* child = findChild<LLPanelExperienceListEditor>(control_name);
if(child)
{
child->getChild<LLTextBox>("text_name")->setText(child->getString(control_name));
child->setMaxExperienceIDs(ESTATE_MAX_EXPERIENCE_IDS);
child->setAddedCallback( boost::bind(&LLPanelRegionExperiences::itemChanged, this, add_id, _1));
child->setRemovedCallback(boost::bind(&LLPanelRegionExperiences::itemChanged, this, remove_id, _1));
}
//return child;
}
void LLPanelRegionExperiences::processResponse( const LLSD& content )
{
if(content.has("default"))
{
mDefaultExperience = content["default"].asUUID();
}
mAllowed->setExperienceIds(content["allowed"]);
mBlocked->setExperienceIds(content["blocked"]);
LLSD trusted = content["trusted"];
if(mDefaultExperience.notNull())
{
mTrusted->setStickyFunction(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience));
trusted.append(mDefaultExperience);
}
mTrusted->setExperienceIds(trusted);
mAllowed->refreshExperienceCounter();
mBlocked->refreshExperienceCounter();
mTrusted->refreshExperienceCounter();
}
// Used for both access add and remove operations, depending on the flag
// passed in (ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE, etc.)
// static
bool LLPanelRegionExperiences::experienceCoreConfirm(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger();
LLViewerRegion* region = gAgent.getRegion();
LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray();
for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray();
iter != end_it;
iter++)
{
U32 flags = originalFlags;
if (iter + 1 != end_it)
flags |= ESTATE_ACCESS_NO_REPLY;
const LLUUID id = iter->asUUID();
switch(option)
{
case 0:
// This estate
sendEstateExperienceDelta(flags, id);
break;
case 1:
{
// All estates, either than I own or manage for this owner.
// This will be verified on simulator. JC
if (!region) break;
if (region->getOwner() == gAgent.getID()
|| gAgent.isGodlike())
{
flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES;
sendEstateExperienceDelta(flags, id);
}
else if (region->isEstateManager())
{
flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES;
sendEstateExperienceDelta(flags, id);
}
break;
}
case 2:
default:
break;
}
}
return false;
}
// Send the actual "estateexperiencedelta" message
void LLPanelRegionExperiences::sendEstateExperienceDelta(U32 flags, const LLUUID& experience_id)
{
strings_t str(3, std::string());
gAgent.getID().toString(str[0]);
str[1] = llformat("%u", flags);
experience_id.toString(str[2]);
LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences();
if (panel)
{
panel->sendEstateOwnerMessage(gMessageSystem, "estateexperiencedelta", LLFloaterRegionInfo::getLastInvoice(), str);
}
}
void LLPanelRegionExperiences::infoCallback(LLHandle<LLPanelRegionExperiences> handle, const LLSD& content)
{
if (handle.isDead())
return;
LLPanelRegionExperiences* floater = handle.get();
if (floater)
{
floater->processResponse(content);
}
}
/*static*/
std::string LLPanelRegionExperiences::regionCapabilityQuery(LLViewerRegion* region, const std::string &cap)
{
// region->getHandle() How to get a region * from a handle?
return region->getCapability(cap);
}
bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
{
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
mAllowed->loading();
mAllowed->setReadonly(!allow_modify);
// remove grid-wide experiences
mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID));
// remove default experience
mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience));
mBlocked->loading();
mBlocked->setReadonly(!allow_modify);
// only grid-wide experiences
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID));
// but not privileged ones
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED));
// remove default experience
mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience));
mTrusted->loading();
mTrusted->setReadonly(!allow_modify);
LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1),
boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle<LLPanelRegionExperiences>(), _1));
return LLPanelRegionInfo::refreshFromRegion(region);
}
LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel)
{
LLSD ids;
const uuid_list_t& id_list = panel->getExperienceIds();
for(uuid_list_t::const_iterator it = id_list.begin(); it != id_list.end(); ++it)
{
ids.append(*it);
}
return ids;
}
BOOL LLPanelRegionExperiences::sendUpdate()
{
LLViewerRegion* region = gAgent.getRegion();
LLSD content;
content["allowed"]=addIds(mAllowed);
content["blocked"]=addIds(mBlocked);
content["trusted"]=addIds(mTrusted);
LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1),
content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle<LLPanelRegionExperiences>(), _1));
return TRUE;
}
void LLPanelRegionExperiences::itemChanged( U32 event_type, const LLUUID& id )
{
std::string dialog_name;
switch (event_type)
{
case ESTATE_EXPERIENCE_ALLOWED_ADD:
dialog_name = "EstateAllowedExperienceAdd";
break;
case ESTATE_EXPERIENCE_ALLOWED_REMOVE:
dialog_name = "EstateAllowedExperienceRemove";
break;
case ESTATE_EXPERIENCE_TRUSTED_ADD:
dialog_name = "EstateTrustedExperienceAdd";
break;
case ESTATE_EXPERIENCE_TRUSTED_REMOVE:
dialog_name = "EstateTrustedExperienceRemove";
break;
case ESTATE_EXPERIENCE_BLOCKED_ADD:
dialog_name = "EstateBlockedExperienceAdd";
break;
case ESTATE_EXPERIENCE_BLOCKED_REMOVE:
dialog_name = "EstateBlockedExperienceRemove";
break;
default:
return;
}
LLSD payload;
payload["operation"] = (S32)event_type;
payload["dialog_name"] = dialog_name;
payload["allowed_ids"].append(id);
LLSD args;
args["ALL_ESTATES"] = all_estates_text();
LLNotification::Params params(dialog_name);
params.payload(payload)
.substitutions(args)
.functor(LLPanelRegionExperiences::experienceCoreConfirm);
if (LLPanelEstateInfo::isLindenEstate())
{
LLNotifications::instance().forceResponse(params, 0);
}
else
{
LLNotifications::instance().add(params);
}
onChangeAnything();
}
#endif // Singu TODO: Experiences
LLPanelEstateAccess::LLPanelEstateAccess()
: LLPanelRegionInfo(), mPendingUpdate(false)
{}
BOOL LLPanelEstateAccess::postBuild()
{
// set up the callbacks for the generic controls
initHelpBtn("estate_manager_help", "HelpEstateEstateManager");
initHelpBtn("allow_resident_help", "HelpEstateAllowResident");
initHelpBtn("allow_group_help", "HelpEstateAllowGroup");
initHelpBtn("ban_resident_help", "HelpEstateBanResident");
getChild<LLUICtrl>("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl *avatar_name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list");
if (avatar_name_list)
{
avatar_name_list->setCommitOnSelectionChange(TRUE);
avatar_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS);
}
getChild<LLUICtrl>("allowed_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedSearchEdit, this, _2));
childSetAction("add_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddAllowedAgent, this));
childSetAction("remove_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedAgent, this));
childSetAction("copy_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedList, this));
getChild<LLUICtrl>("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl* group_name_list = getChild<LLNameListCtrl>("allowed_group_name_list");
if (group_name_list)
{
group_name_list->setCommitOnSelectionChange(TRUE);
group_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS);
}
getChild<LLUICtrl>("allowed_group_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedGroupsSearchEdit, this, _2));
getChild<LLUICtrl>("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onClickAddAllowedGroup, this));
childSetAction("remove_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedGroup, this));
childSetAction("copy_allowed_group_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedGroupList, this));
getChild<LLUICtrl>("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateAccess::updateChild, this, _1));
LLNameListCtrl* banned_name_list = getChild<LLNameListCtrl>("banned_avatar_name_list");
if (banned_name_list)
{
banned_name_list->setCommitOnSelectionChange(TRUE);
banned_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS);
}
getChild<LLUICtrl>("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2));
childSetAction("add_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddBannedAgent, this));
childSetAction("remove_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveBannedAgent, this));
childSetAction("copy_banned_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyBannedList, this));
getChild<LLUICtrl>("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateAccess::updateChild, this, _1));
LLNameListCtrl* manager_name_list = getChild<LLNameListCtrl>("estate_manager_name_list");
if (manager_name_list)
{
manager_name_list->setCommitOnSelectionChange(TRUE);
manager_name_list->setMaxItemCount(ESTATE_MAX_MANAGERS * 4); // Allow extras for dupe issue
}
childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickAddEstateManager, this));
childSetAction("remove_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveEstateManager, this));
return TRUE;
}
void LLPanelEstateAccess::updateControls(LLViewerRegion* region)
{
BOOL god = gAgent.isGodlike();
BOOL owner = (region && (region->getOwner() == gAgent.getID()));
BOOL manager = (region && region->isEstateManager());
bool enable_cotrols = god || owner || manager;
setCtrlsEnabled(enable_cotrols);
BOOL has_allowed_avatar = getChild<LLNameListCtrl>("allowed_avatar_name_list")->getFirstSelected() ? TRUE : FALSE;
BOOL has_allowed_group = getChild<LLNameListCtrl>("allowed_group_name_list")->getFirstSelected() ? TRUE : FALSE;
BOOL has_banned_agent = getChild<LLNameListCtrl>("banned_avatar_name_list")->getFirstSelected() ? TRUE : FALSE;
BOOL has_estate_manager = getChild<LLNameListCtrl>("estate_manager_name_list")->getFirstSelected() ? TRUE : FALSE;
getChildView("add_allowed_avatar_btn")->setEnabled(enable_cotrols);
getChildView("remove_allowed_avatar_btn")->setEnabled(has_allowed_avatar && enable_cotrols);
getChildView("allowed_avatar_name_list")->setEnabled(enable_cotrols);
getChildView("add_allowed_group_btn")->setEnabled(enable_cotrols);
getChildView("remove_allowed_group_btn")->setEnabled(has_allowed_group && enable_cotrols);
getChildView("allowed_group_name_list")->setEnabled(enable_cotrols);
// Can't ban people from mainland, orientation islands, etc. because this
// creates much network traffic and server load.
// Disable their accounts in CSR tool instead.
bool linden_estate = LLPanelEstateInfo::isLindenEstate();
bool enable_ban = enable_cotrols && !linden_estate;
getChildView("add_banned_avatar_btn")->setEnabled(enable_ban);
getChildView("remove_banned_avatar_btn")->setEnabled(has_banned_agent && enable_ban);
getChildView("banned_avatar_name_list")->setEnabled(enable_cotrols);
// estate managers can't add estate managers
getChildView("add_estate_manager_btn")->setEnabled(god || owner);
getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner));
getChildView("estate_manager_name_list")->setEnabled(god || owner);
if (enable_cotrols != mCtrlsEnabled)
{
mCtrlsEnabled = enable_cotrols;
updateLists(); // update the lists on the agent's access level change
}
}
//---------------------------------------------------------------------------
// Add/Remove estate access button callbacks
//---------------------------------------------------------------------------
void LLPanelEstateAccess::onClickAddAllowedAgent()
{
LLCtrlListInterface *list = childGetListInterface("allowed_avatar_name_list");
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
{
//args
LLSD args;
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args);
return;
}
accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd");
}
void LLPanelEstateAccess::onClickRemoveAllowedAgent()
{
accessRemoveCore(ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, "EstateAllowedAgentRemove", "allowed_avatar_name_list");
}
void LLPanelEstateAccess::onClickAddAllowedGroup()
{
LLCtrlListInterface *list = childGetListInterface("allowed_group_name_list");
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
{
LLSD args;
args["MAX_GROUPS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args);
return;
}
LLNotification::Params params("ChangeLindenAccess");
params.functor(boost::bind(&LLPanelEstateAccess::addAllowedGroup, this, _1, _2));
if (LLPanelEstateInfo::isLindenEstate())
{
LLNotifications::instance().add(params);
}
else
{
LLNotifications::instance().forceResponse(params, 0);
}
}
bool LLPanelEstateAccess::addAllowedGroup(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
LLFloaterGroupPicker* widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID()));
if (widget)
{
widget->removeNoneOption();
widget->setSelectGroupCallback(boost::bind(&LLPanelEstateAccess::addAllowedGroup2, this, _1));
if (parent_floater)
{
LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget);
widget->setOrigin(new_rect.mLeft, new_rect.mBottom);
parent_floater->addDependentFloater(widget);
}
}
return false;
}
void LLPanelEstateAccess::onClickRemoveAllowedGroup()
{
accessRemoveCore(ESTATE_ACCESS_ALLOWED_GROUP_REMOVE, "EstateAllowedGroupRemove", "allowed_group_name_list");
}
void LLPanelEstateAccess::onClickAddBannedAgent()
{
LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list");
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
{
LLSD args;
args["MAX_BANNED"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args);
return;
}
accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd");
}
void LLPanelEstateAccess::onClickRemoveBannedAgent()
{
accessRemoveCore(ESTATE_ACCESS_BANNED_AGENT_REMOVE, "EstateBannedAgentRemove", "banned_avatar_name_list");
}
void LLPanelEstateAccess::onClickCopyAllowedList()
{
copyListToClipboard("allowed_avatar_name_list");
}
void LLPanelEstateAccess::onClickCopyAllowedGroupList()
{
copyListToClipboard("allowed_group_name_list");
}
void LLPanelEstateAccess::onClickCopyBannedList()
{
copyListToClipboard("banned_avatar_name_list");
}
// static
void LLPanelEstateAccess::onClickAddEstateManager()
{
LLCtrlListInterface *list = childGetListInterface("estate_manager_name_list");
if (!list) return;
if (gHippoGridManager->getConnectedGrid()->isSecondLife() && list->getItemCount() >= ESTATE_MAX_MANAGERS)
{ // Tell user they can't add more managers
LLSD args;
args["MAX_MANAGER"] = llformat("%d",ESTATE_MAX_MANAGERS);
LLNotificationsUtil::add("MaxManagersOnRegion", args);
}
else
{ // Go pick managers to add
accessAddCore(ESTATE_ACCESS_MANAGER_ADD, "EstateManagerAdd");
}
}
// static
void LLPanelEstateAccess::onClickRemoveEstateManager()
{
accessRemoveCore(ESTATE_ACCESS_MANAGER_REMOVE, "EstateManagerRemove", "estate_manager_name_list");
}
// Special case callback for groups, since it has different callback format than names
void LLPanelEstateAccess::addAllowedGroup2(LLUUID id)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (panel)
{
LLNameListCtrl* group_list = panel->getChild<LLNameListCtrl>("allowed_group_name_list");
LLScrollListItem* item = group_list->getNameItemByAgentId(id);
if (item)
{
LLSD args;
args["GROUP"] = item->getColumn(0)->getValue().asString();
LLNotificationsUtil::add("GroupIsAlreadyInList", args);
return;
}
}
LLSD payload;
payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD;
payload["dialog_name"] = "EstateAllowedGroupAdd";
payload["allowed_ids"].append(id);
LLSD args;
args["ALL_ESTATES"] = all_estates_text();
LLNotification::Params params("EstateAllowedGroupAdd");
params.payload(payload)
.substitutions(args)
.functor(accessCoreConfirm);
if (LLPanelEstateInfo::isLindenEstate())
{
LLNotifications::instance().forceResponse(params, 0);
}
else
{
LLNotifications::instance().add(params);
}
}
// static
void LLPanelEstateAccess::accessAddCore(U32 operation_flag, const std::string& dialog_name)
{
LLSD payload;
payload["operation"] = (S32)operation_flag;
payload["dialog_name"] = dialog_name;
// agent id filled in after avatar picker
LLNotification::Params params("ChangeLindenAccess");
params.payload(payload)
.functor(accessAddCore2);
if (LLPanelEstateInfo::isLindenEstate())
{
LLNotifications::instance().add(params);
}
else
{
// same as clicking "OK"
LLNotifications::instance().forceResponse(params, 0);
}
}
// static
bool LLPanelEstateAccess::accessAddCore2(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0)
{
// abort change
return false;
}
LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]);
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL;
// avatar picker yes multi-select, yes close-on-select
LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateAccess::accessAddCore3, _1, _2, change_info), TRUE, TRUE);
//Allows the closed parent floater to close the child floater (avatar picker)
if (child_floater)
{
parent_floater->addDependentFloater(child_floater);
}
return false;
}
// static
void LLPanelEstateAccess::accessAddCore3(const uuid_vec_t& ids, const std::vector<LLAvatarName>& names, LLEstateAccessChangeInfo* change_info)
{
if (!change_info) return;
if (ids.empty())
{
// User didn't select a name.
delete change_info;
change_info = NULL;
return;
}
// User did select a name.
change_info->mAgentOrGroupIDs = ids;
// Can't put estate owner on ban list
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLViewerRegion* region = gAgent.getRegion();
if (!region) return;
if (change_info->mOperationFlag & ESTATE_ACCESS_ALLOWED_AGENT_ADD)
{
LLNameListCtrl* name_list = panel->getChild<LLNameListCtrl>("allowed_avatar_name_list");
int currentCount = (name_list ? name_list->getItemCount() : 0);
if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS)
{
LLSD args;
args["NUM_ADDED"] = llformat("%d",ids.size());
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents");
args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
}
uuid_vec_t ids_allowed;
std::vector<LLAvatarName> names_allowed;
std::string already_allowed;
bool single = true;
for (U32 i = 0; i < ids.size(); ++i)
{
LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]);
if (item)
{
if (!already_allowed.empty())
{
already_allowed += ", ";
single = false;
}
already_allowed += item->getColumn(0)->getValue().asString();
}
else
{
ids_allowed.push_back(ids[i]);
names_allowed.push_back(names[i]);
}
}
if (!already_allowed.empty())
{
LLSD args;
args["AGENT"] = already_allowed;
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents");
LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args);
if (ids_allowed.empty())
{
delete change_info;
return;
}
}
change_info->mAgentOrGroupIDs = ids_allowed;
change_info->mAgentNames = names_allowed;
}
if (change_info->mOperationFlag & ESTATE_ACCESS_BANNED_AGENT_ADD)
{
LLNameListCtrl* name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list");
LLNameListCtrl* em_list = panel->getChild<LLNameListCtrl>("estate_manager_name_list");
int currentCount = (name_list ? name_list->getItemCount() : 0);
if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS)
{
LLSD args;
args["NUM_ADDED"] = llformat("%d",ids.size());
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");
args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
}
uuid_vec_t ids_allowed;
std::vector<LLAvatarName> names_allowed;
std::string already_banned;
std::string em_ban;
bool single = true;
for (U32 i = 0; i < ids.size(); ++i)
{
bool is_allowed = true;
LLScrollListItem* em_item = em_list->getNameItemByAgentId(ids[i]);
if (em_item)
{
if (!em_ban.empty())
{
em_ban += ", ";
}
em_ban += em_item->getColumn(0)->getValue().asString();
is_allowed = false;
}
LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]);
if (item)
{
if (!already_banned.empty())
{
already_banned += ", ";
single = false;
}
already_banned += item->getColumn(0)->getValue().asString();
is_allowed = false;
}
if (is_allowed)
{
ids_allowed.push_back(ids[i]);
names_allowed.push_back(names[i]);
}
}
if (!em_ban.empty())
{
LLSD args;
args["AGENT"] = em_ban;
LLNotificationsUtil::add("ProblemBanningEstateManager", args);
if (ids_allowed.empty())
{
delete change_info;
return;
}
}
if (!already_banned.empty())
{
LLSD args;
args["AGENT"] = already_banned;
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");
LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args);
if (ids_allowed.empty())
{
delete change_info;
return;
}
}
change_info->mAgentOrGroupIDs = ids_allowed;
change_info->mAgentNames = names_allowed;
}
LLSD args;
args["ALL_ESTATES"] = all_estates_text();
LLNotification::Params params(change_info->mDialogName);
params.substitutions(args)
.payload(change_info->asLLSD())
.functor(accessCoreConfirm);
if (LLPanelEstateInfo::isLindenEstate())
{
// just apply to this estate
LLNotifications::instance().forceResponse(params, 0);
}
else
{
// ask if this estate or all estates with this owner
LLNotifications::instance().add(params);
}
}
// static
void LLPanelEstateAccess::accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLNameListCtrl* name_list = panel->getChild<LLNameListCtrl>(list_ctrl_name);
if (!name_list) return;
std::vector<LLScrollListItem*> list_vector = name_list->getAllSelected();
if (list_vector.size() == 0)
return;
LLSD payload;
payload["operation"] = (S32)operation_flag;
payload["dialog_name"] = dialog_name;
for (std::vector<LLScrollListItem*>::const_iterator iter = list_vector.begin();
iter != list_vector.end();
iter++)
{
LLScrollListItem *item = (*iter);
payload["allowed_ids"].append(item->getUUID());
}
LLNotification::Params params("ChangeLindenAccess");
params.payload(payload)
.functor(accessRemoveCore2);
if (LLPanelEstateInfo::isLindenEstate())
{
// warn on change linden estate
LLNotifications::instance().add(params);
}
else
{
// just proceed, as if clicking OK
LLNotifications::instance().forceResponse(params, 0);
}
}
// static
bool LLPanelEstateAccess::accessRemoveCore2(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0)
{
// abort
return false;
}
// If Linden estate, can only apply to "this" estate, not all estates
// owned by NULL.
if (LLPanelEstateInfo::isLindenEstate())
{
accessCoreConfirm(notification, response);
}
else
{
LLSD args;
args["ALL_ESTATES"] = all_estates_text();
LLNotificationsUtil::add(notification["payload"]["dialog_name"],
args,
notification["payload"],
accessCoreConfirm);
}
return false;
}
// Used for both access add and remove operations, depending on the mOperationFlag
// passed in (ESTATE_ACCESS_BANNED_AGENT_ADD, ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, etc.)
// static
bool LLPanelEstateAccess::accessCoreConfirm(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger();
U32 flags = originalFlags;
LLViewerRegion* region = gAgent.getRegion();
if (option == 2) // cancel
{
return false;
}
else if (option == 1)
{
// All estates, either than I own or manage for this owner.
// This will be verified on simulator. JC
if (!region) return false;
if (region->getOwner() == gAgent.getID()
|| gAgent.isGodlike())
{
flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES;
}
else if (region->isEstateManager())
{
flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES;
}
}
std::string names;
U32 listed_names = 0;
const auto& ids = notification["payload"]["allowed_ids"];
const auto& allowed_names = notification["payload"]["allowed_names"];
U32 size = ids.size();
for (U32 i = 0; i < size; ++i)
{
if (i + 1 != size)
{
flags |= ESTATE_ACCESS_NO_REPLY;
}
else
{
flags &= ~ESTATE_ACCESS_NO_REPLY;
}
const LLUUID id = ids[i].asUUID();
if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD)
&& region && (region->getOwner() == id))
{
LLNotificationsUtil::add("OwnerCanNotBeDenied");
break;
}
sendEstateAccessDelta(flags, id);
if ((flags & (ESTATE_ACCESS_ALLOWED_GROUP_ADD | ESTATE_ACCESS_ALLOWED_GROUP_REMOVE)) == 0)
{
// fill the name list for confirmation
if (listed_names < MAX_LISTED_NAMES)
{
if (!names.empty())
{
names += ", ";
}
const auto& display_name = allowed_names[i]["display_name"].asStringRef();
if (!display_name.empty())
{
names += display_name;
}
else
{ //try to get an agent name from cache
LLAvatarName av_name;
if (LLAvatarNameCache::get(id, &av_name))
{
names += av_name.getCompleteName();
}
}
}
listed_names++;
}
}
if (listed_names > MAX_LISTED_NAMES)
{
LLSD args;
args["EXTRA_COUNT"] = llformat("%d", listed_names - MAX_LISTED_NAMES);
names += " " + LLTrans::getString("AndNMore", args);
}
if (!names.empty()) // show the conirmation
{
LLSD args;
args["AGENT"] = names;
if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE))
{
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents");
}
else if (flags & (ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE))
{
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");
}
if (flags & ESTATE_ACCESS_APPLY_TO_ALL_ESTATES)
{
args["ESTATE"] = LLTrans::getString("RegionInfoAllEstates");
}
else if (flags & ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES)
{
args["ESTATE"] = LLTrans::getString("RegionInfoManagedEstates");
}
else
{
args["ESTATE"] = LLTrans::getString("RegionInfoThisEstate");
}
bool single = (listed_names == 1);
if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_ADD))
{
LLNotificationsUtil::add(single ? "AgentWasAddedToList" : "AgentsWereAddedToList", args);
}
else if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_BANNED_AGENT_REMOVE))
{
LLNotificationsUtil::add(single ? "AgentWasRemovedFromList" : "AgentsWereRemovedFromList", args);
}
}
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (panel)
{
panel->setPendingUpdate(true);
}
return false;
}
// key = "estateaccessdelta"
// str(estate_id) will be added to front of list by forward_EstateOwnerRequest_to_dataserver
// str[0] = str(agent_id) requesting the change
// str[1] = str(flags) (ESTATE_ACCESS_DELTA_*)
// str[2] = str(agent_id) to add or remove
// static
void LLPanelEstateAccess::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_group_id)
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("EstateOwnerMessage");
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
msg->nextBlock("MethodData");
msg->addString("Method", "estateaccessdelta");
msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice());
std::string buf;
gAgent.getID().toString(buf);
msg->nextBlock("ParamList");
msg->addString("Parameter", buf);
buf = llformat("%u", flags);
msg->nextBlock("ParamList");
msg->addString("Parameter", buf);
agent_or_group_id.toString(buf);
msg->nextBlock("ParamList");
msg->addString("Parameter", buf);
if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE |
ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE))
{
if (auto panel = LLFloaterRegionInfo::getPanelAccess())
{
// Clear these out before we ask for an update
if (auto name_list = panel->getChild<LLNameListCtrl>("allowed_avatar_name_list"))
name_list->deleteAllItems();
if (auto name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list"))
name_list->deleteAllItems();
}
}
gAgent.sendReliableMessage();
}
void LLPanelEstateAccess::updateChild(LLUICtrl* child_ctrl)
{
// Ensure appropriate state of the management ui.
updateControls(gAgent.getRegion());
}
struct RequestEstateGetAccessResponder : public LLHTTPClient::ResponderWithCompleted
{
void httpCompleted() override
{
LLPanelEstateAccess::onEstateAccessReceived(mContent);
}
char const* getName() const override { return "requestEstateGetAccessCoro"; }
};
void LLPanelEstateAccess::updateLists()
{
std::string cap_url = gAgent.getRegionCapability("EstateAccess");
if (!cap_url.empty())
{
LLHTTPClient::get(cap_url, new RequestEstateGetAccessResponder);
}
}
/*
LLCoros::instance().launch("LLFloaterRegionInfo::requestEstateGetAccessCoro", boost::bind(LLPanelEstateAccess::requestEstateGetAccessCoro, cap_url));
}
}
void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestEstateGetAccessoCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
onEstateAccessReceived(result);
}
*/
void LLPanelEstateAccess::onEstateAccessReceived(const LLSD& result)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLNameListCtrl* allowed_agent_name_list = panel->getChild<LLNameListCtrl>("allowed_avatar_name_list");
if (allowed_agent_name_list && result.has("AllowedAgents"))
{
LLStringUtil::format_map_t args;
args["[ALLOWEDAGENTS]"] = llformat("%d", result["AllowedAgents"].size());
args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args);
panel->getChild<LLUICtrl>("allow_resident_label")->setValue(LLSD(msg));
const auto order = allowed_agent_name_list->getSortOrder();
allowed_agent_name_list->clearSortOrder();
allowed_agent_name_list->deleteAllItems();
for (LLSD::array_const_iterator it = result["AllowedAgents"].beginArray(); it != result["AllowedAgents"].endArray(); ++it)
{
LLUUID id = (*it)["id"].asUUID();
allowed_agent_name_list->addNameItem(id);
}
allowed_agent_name_list->setSortOrder(order);
}
LLNameListCtrl* banned_agent_name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list");
if (banned_agent_name_list && result.has("BannedAgents"))
{
LLStringUtil::format_map_t args;
args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size());
args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);
panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));
const auto order = banned_agent_name_list->getSortOrder();
banned_agent_name_list->clearSortOrder();
banned_agent_name_list->deleteAllItems();
static const auto na = LLTrans::getString("na");
for (LLSD::array_const_iterator it = result["BannedAgents"].beginArray(); it != result["BannedAgents"].endArray(); ++it)
{
LLSD item;
item["id"] = (*it)["id"].asUUID();
LLSD& columns = item["columns"];
columns[0]["column"] = "name"; // to be populated later
columns[1]["column"] = "last_login_date";
columns[1]["value"] = (*it)["last_login_date"].asString().substr(0, 16); // cut the seconds
std::string ban_date = (*it)["ban_date"].asString();
columns[2]["column"] = "ban_date";
columns[2]["value"] = ban_date[0] != '0' ? ban_date.substr(0, 16) : na; // server returns the "0000-00-00 00:00:00" date in case it doesn't know it
columns[3]["column"] = "bannedby";
LLUUID banning_id = (*it)["banning_id"].asUUID();
LLAvatarName av_name;
if (banning_id.isNull())
{
columns[3]["value"] = na;
}
else if (LLAvatarNameCache::get(banning_id, &av_name))
{
columns[3]["value"] = av_name.getCompleteName(); //TODO: fetch the name if it wasn't cached
}
banned_agent_name_list->addElement(item);
}
banned_agent_name_list->setSortOrder(order);
}
LLNameListCtrl* allowed_group_name_list = panel->getChild<LLNameListCtrl>("allowed_group_name_list");
if (allowed_group_name_list && result.has("AllowedGroups"))
{
LLStringUtil::format_map_t args;
args["[ALLOWEDGROUPS]"] = llformat("%d", result["AllowedGroups"].size());
args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_GROUP_IDS);
std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args);
panel->getChild<LLUICtrl>("allow_group_label")->setValue(LLSD(msg));
const auto order = allowed_group_name_list->getSortOrder();
allowed_group_name_list->clearSortOrder();
allowed_group_name_list->deleteAllItems();
for (LLSD::array_const_iterator it = result["AllowedGroups"].beginArray(); it != result["AllowedGroups"].endArray(); ++it)
{
LLUUID id = (*it)["id"].asUUID();
allowed_group_name_list->addGroupNameItem(id);
}
allowed_group_name_list->setSortOrder(order);
}
LLNameListCtrl* estate_manager_name_list = panel->getChild<LLNameListCtrl>("estate_manager_name_list");
if (estate_manager_name_list && result.has("Managers"))
{
LLStringUtil::format_map_t args;
args["[ESTATEMANAGERS]"] = llformat("%d", result["Managers"].size());
args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS);
std::string msg = LLTrans::getString("RegionInfoEstateManagers", args);
panel->getChild<LLUICtrl>("estate_manager_label")->setValue(LLSD(msg));
const auto order = estate_manager_name_list->getSortOrder();
estate_manager_name_list->clearSortOrder();
estate_manager_name_list->deleteAllItems();
for (LLSD::array_const_iterator it = result["Managers"].beginArray(); it != result["Managers"].endArray(); ++it)
{
LLUUID id = (*it)["agent_id"].asUUID();
estate_manager_name_list->addNameItem(id);
}
estate_manager_name_list->setSortOrder(order);
}
panel->updateControls(gAgent.getRegion());
}
//---------------------------------------------------------------------------
// Access lists search
//---------------------------------------------------------------------------
void LLPanelEstateAccess::onAllowedSearchEdit(const std::string& search_string)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLNameListCtrl* allowed_agent_name_list = panel->getChild<LLNameListCtrl>("allowed_avatar_name_list");
searchAgent(allowed_agent_name_list, search_string);
}
void LLPanelEstateAccess::onAllowedGroupsSearchEdit(const std::string& search_string)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLNameListCtrl* allowed_group_name_list = panel->getChild<LLNameListCtrl>("allowed_group_name_list");
searchAgent(allowed_group_name_list, search_string);
}
void LLPanelEstateAccess::onBannedSearchEdit(const std::string& search_string)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLNameListCtrl* banned_agent_name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list");
searchAgent(banned_agent_name_list, search_string);
}
void LLPanelEstateAccess::searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string)
{
if (!listCtrl) return;
listCtrl->setFilter(search_string);
}
void LLPanelEstateAccess::copyListToClipboard(std::string list_name)
{
LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess();
if (!panel) return;
LLNameListCtrl* name_list = panel->getChild<LLNameListCtrl>(list_name);
if (!name_list) return;
std::vector<LLScrollListItem*> list_vector = name_list->getAllData();
if (list_vector.size() == 0) return;
LLSD::String list_to_copy;
for (std::vector<LLScrollListItem*>::const_iterator iter = list_vector.begin();
iter != list_vector.end();
iter++)
{
LLScrollListItem *item = (*iter);
if (item)
{
list_to_copy += item->getColumn(0)->getValue().asString();
}
if (std::next(iter) != list_vector.end())
{
list_to_copy += '\n';
}
}
auto wstr = utf8str_to_wstring(list_to_copy);
gClipboard.copyFromSubstring(wstr, 0, wstr.length());
}
bool LLPanelEstateAccess::refreshFromRegion(LLViewerRegion* region)
{
// Clear these out before we ask for an update
if (auto name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list"))
name_list->deleteAllItems();
if (auto name_list = getChild<LLNameListCtrl>("banned_avatar_name_list"))
name_list->deleteAllItems();
updateLists();
return LLPanelRegionInfo::refreshFromRegion(region);
}
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
void LLFloaterRegionInfo::open()
{
// We'll allow access to the estate tools for estate managers (and for the sim owner)
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
{
const LLViewerRegion* region(gAgent.getRegion());
// Should be able to call LLRegion::canManageEstate() but then we can fake god like
if (!(region && region->isEstateManager() && region->getOwner() == gAgentID))
return;
}
LLFloater::open();
}
// [/RLVa:KB]