482 lines
12 KiB
C++
482 lines
12 KiB
C++
/**
|
|
* @file llpanelpick.cpp
|
|
* @brief LLPanelPick class implementation
|
|
*
|
|
* $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$
|
|
*/
|
|
|
|
// Display of a "Top Pick" used both for the global top picks in the
|
|
// Find directory, and also for each individual user's picks in their
|
|
// profile.
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
#include "llpanel.h"
|
|
#include "message.h"
|
|
#include "llagent.h"
|
|
#include "llbutton.h"
|
|
#include "llparcel.h"
|
|
#include "llviewerparcelmgr.h"
|
|
#include "lltexturectrl.h"
|
|
#include "lluiconstants.h"
|
|
#include "llworldmap.h"
|
|
#include "llfloaterworldmap.h"
|
|
#include "llfloaterreg.h"
|
|
#include "llavatarpropertiesprocessor.h"
|
|
#include "llpanelpick.h"
|
|
|
|
|
|
#define XML_PANEL_EDIT_PICK "panel_edit_pick.xml"
|
|
#define XML_PANEL_PICK_INFO "panel_pick_info.xml"
|
|
|
|
#define XML_NAME "pick_name"
|
|
#define XML_DESC "pick_desc"
|
|
#define XML_SNAPSHOT "pick_snapshot"
|
|
#define XML_LOCATION "pick_location"
|
|
|
|
#define XML_BTN_SAVE "save_changes_btn"
|
|
|
|
#define SAVE_BTN_LABEL "[WHAT]"
|
|
#define LABEL_PICK = "Pick"
|
|
#define LABEL_CHANGES = "Changes"
|
|
|
|
|
|
LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */)
|
|
: LLPanel(), LLAvatarPropertiesObserver(), LLRemoteParcelInfoObserver(),
|
|
mEditMode(edit_mode),
|
|
mSnapshotCtrl(NULL),
|
|
mPickId(LLUUID::null),
|
|
mCreatorId(LLUUID::null),
|
|
mDataReceived(FALSE)
|
|
{
|
|
if (edit_mode)
|
|
{
|
|
LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK);
|
|
LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
|
|
}
|
|
else
|
|
{
|
|
LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_PICK_INFO);
|
|
}
|
|
|
|
}
|
|
|
|
LLPanelPick::~LLPanelPick()
|
|
{
|
|
if (mCreatorId.notNull()) LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorId, this);
|
|
}
|
|
|
|
void LLPanelPick::reset()
|
|
{
|
|
setEditMode(FALSE);
|
|
|
|
mPickId.setNull();
|
|
mCreatorId.setNull();
|
|
mParcelId.setNull();
|
|
|
|
setPickName("");
|
|
setPickDesc("");
|
|
setPickLocation("");
|
|
mSnapshotCtrl->setImageAssetID(LLUUID::null);
|
|
|
|
//*HACK just setting asset id to NULL not enough to clear
|
|
//the texture controls, w/o setValid(FALSE) it continues to
|
|
//draw the previously set image
|
|
mSnapshotCtrl->setValid(FALSE);
|
|
|
|
mDataReceived = FALSE;
|
|
|
|
mPosGlobal.clearVec();
|
|
|
|
childSetValue("maturity", "");
|
|
}
|
|
|
|
BOOL LLPanelPick::postBuild()
|
|
{
|
|
mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
|
|
|
|
if (mEditMode)
|
|
{
|
|
childSetAction("cancel_btn", boost::bind(&LLPanelPick::onClickCancel, this));
|
|
childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPick::onClickSet, this));
|
|
childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPick::onClickSave, this));
|
|
|
|
mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "edit_icon", true));
|
|
mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "edit_icon", false));
|
|
}
|
|
else
|
|
{
|
|
childSetAction("edit_btn", boost::bind(&LLPanelPick::onClickEdit, this));
|
|
childSetAction("teleport_btn", boost::bind(&LLPanelPick::onClickTeleport, this));
|
|
childSetAction("show_on_map_btn", boost::bind(&LLPanelPick::onClickMap, this));
|
|
|
|
if (!mBackCb.empty())
|
|
{
|
|
LLButton* button = findChild<LLButton>("back_btn");
|
|
if (button) button->setClickedCallback(mBackCb);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LLPanelPick::init(LLUUID creator_id, LLUUID pick_id)
|
|
{
|
|
mCreatorId = creator_id;
|
|
mPickId = pick_id;
|
|
|
|
//*TODO consider removing this, already called by setEditMode()
|
|
updateButtons();
|
|
|
|
requestData();
|
|
}
|
|
|
|
void LLPanelPick::requestData()
|
|
{
|
|
mDataReceived = FALSE;
|
|
LLAvatarPropertiesProcessor::instance().addObserver(mCreatorId, this);
|
|
LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorId, mPickId);
|
|
}
|
|
|
|
void LLPanelPick::init(LLPickData *pick_data)
|
|
{
|
|
mPickId = pick_data->pick_id;
|
|
mCreatorId = pick_data->creator_id;
|
|
|
|
setPickName(pick_data->name);
|
|
setPickDesc(pick_data->desc);
|
|
setPickLocation(pick_data->location_text);
|
|
mSnapshotCtrl->setImageAssetID(pick_data->snapshot_id);
|
|
|
|
//*HACK see reset() where the texture control was set to FALSE
|
|
mSnapshotCtrl->setValid(TRUE);
|
|
|
|
mPosGlobal = pick_data->pos_global;
|
|
mSimName = pick_data->sim_name;
|
|
mParcelId = pick_data->parcel_id;
|
|
}
|
|
|
|
// Fill in some reasonable defaults for a new pick.
|
|
void LLPanelPick::createNewPick()
|
|
{
|
|
mPickId.generate();
|
|
mCreatorId = gAgent.getID();
|
|
mPosGlobal = gAgent.getPositionGlobal();
|
|
|
|
// Try to fill in the current parcel
|
|
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
|
if (parcel)
|
|
{
|
|
setPickName(parcel->getName());
|
|
setPickDesc(parcel->getDesc());
|
|
mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID());
|
|
}
|
|
|
|
sendUpdate();
|
|
|
|
childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick"));
|
|
}
|
|
|
|
/*virtual*/ void LLPanelPick::processProperties(void* data, EAvatarProcessorType type)
|
|
{
|
|
if (APT_PICK_INFO != type) return;
|
|
if (!data) return;
|
|
|
|
LLPickData* pick_data = static_cast<LLPickData *>(data);
|
|
if (!pick_data) return;
|
|
if (mPickId != pick_data->pick_id) return;
|
|
|
|
init(pick_data);
|
|
mDataReceived = TRUE;
|
|
LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorId, this);
|
|
|
|
if (!mEditMode)
|
|
{
|
|
LLRemoteParcelInfoProcessor::getInstance()->addObserver(pick_data->parcel_id, this);
|
|
LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(pick_data->parcel_id);
|
|
}
|
|
}
|
|
|
|
|
|
void LLPanelPick::setEditMode( BOOL edit_mode )
|
|
{
|
|
if (mEditMode == edit_mode) return;
|
|
mEditMode = edit_mode;
|
|
|
|
// preserve data before killing controls
|
|
LLUUID snapshot_id = mSnapshotCtrl->getImageAssetID();
|
|
LLRect old_rect = getRect();
|
|
|
|
deleteAllChildren();
|
|
|
|
if (edit_mode)
|
|
{
|
|
LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK);
|
|
}
|
|
else
|
|
{
|
|
LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_PICK_INFO);
|
|
}
|
|
|
|
//*NOTE this code is from LLPanelMeProfile.togglePanel()... doubt this is a right way to do things
|
|
reshape(old_rect.getWidth(), old_rect.getHeight());
|
|
old_rect.setLeftTopAndSize(0, old_rect.getHeight(), old_rect.getWidth(), old_rect.getHeight());
|
|
setRect(old_rect);
|
|
|
|
// time to restore data
|
|
setPickName(mName);
|
|
setPickDesc(mDesc);
|
|
setPickLocation(mLocation);
|
|
mSnapshotCtrl->setImageAssetID(snapshot_id);
|
|
|
|
updateButtons();
|
|
}
|
|
|
|
void LLPanelPick::setPickName(std::string name)
|
|
{
|
|
if (mEditMode)
|
|
{
|
|
childSetValue(XML_NAME, name);
|
|
}
|
|
else
|
|
{
|
|
childSetWrappedText(XML_NAME, name);
|
|
}
|
|
|
|
//preserving non-wrapped text for info/edit modes switching
|
|
mName = name;
|
|
}
|
|
|
|
void LLPanelPick::setPickDesc(std::string desc)
|
|
{
|
|
if (mEditMode)
|
|
{
|
|
childSetValue(XML_DESC, desc);
|
|
}
|
|
else
|
|
{
|
|
childSetWrappedText(XML_DESC, desc);
|
|
}
|
|
|
|
//preserving non-wrapped text for info/edit modes switching
|
|
mDesc = desc;
|
|
}
|
|
|
|
void LLPanelPick::setPickLocation(std::string location)
|
|
{
|
|
childSetWrappedText(XML_LOCATION, location);
|
|
|
|
//preserving non-wrapped text for info/edit modes switching
|
|
mLocation = location;
|
|
}
|
|
|
|
std::string LLPanelPick::getPickName()
|
|
{
|
|
return childGetValue(XML_NAME).asString();
|
|
}
|
|
|
|
std::string LLPanelPick::getPickDesc()
|
|
{
|
|
return childGetValue(XML_DESC).asString();
|
|
}
|
|
|
|
std::string LLPanelPick::getPickLocation()
|
|
{
|
|
return childGetValue(XML_LOCATION).asString();
|
|
}
|
|
|
|
void LLPanelPick::sendUpdate()
|
|
{
|
|
LLPickData pick_data;
|
|
|
|
// If we don't have a pick id yet, we'll need to generate one,
|
|
// otherwise we'll keep overwriting pick_id 00000 in the database.
|
|
if (mPickId.isNull()) mPickId.generate();
|
|
|
|
pick_data.agent_id = gAgent.getID();
|
|
pick_data.session_id = gAgent.getSessionID();
|
|
pick_data.pick_id = mPickId;
|
|
pick_data.creator_id = gAgentID;
|
|
|
|
//legacy var need to be deleted
|
|
pick_data.top_pick = FALSE;
|
|
pick_data.parcel_id = mParcelId;
|
|
pick_data.name = getPickName();
|
|
pick_data.desc = getPickDesc();
|
|
pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
|
|
pick_data.pos_global = mPosGlobal;
|
|
pick_data.sort_order = 0;
|
|
pick_data.enabled = TRUE;
|
|
|
|
mDataReceived = FALSE;
|
|
LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
|
|
|
|
LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
|
|
}
|
|
|
|
|
|
//-----------------------------------------
|
|
// "PICK INFO" (VIEW MODE) BUTTON HANDLERS
|
|
//-----------------------------------------
|
|
|
|
//static
|
|
void LLPanelPick::onClickEdit()
|
|
{
|
|
if (mEditMode) return;
|
|
if (!mDataReceived) return;
|
|
setEditMode(TRUE);
|
|
}
|
|
|
|
//static
|
|
void LLPanelPick::onClickTeleport()
|
|
{
|
|
teleport(mPosGlobal);
|
|
}
|
|
|
|
//static
|
|
void LLPanelPick::onClickMap()
|
|
{
|
|
showOnMap(mPosGlobal);
|
|
}
|
|
|
|
|
|
//-----------------------------------------
|
|
// "EDIT PICK" (EDIT MODE) BUTTON HANDLERS
|
|
//-----------------------------------------
|
|
|
|
//static
|
|
void LLPanelPick::onClickCancel()
|
|
{
|
|
if (!mEditMode) return;
|
|
|
|
LLUUID pick_id = mPickId;
|
|
LLUUID creator_id = mCreatorId;
|
|
reset();
|
|
init(creator_id, pick_id);
|
|
}
|
|
|
|
// static
|
|
void LLPanelPick::onClickSet()
|
|
{
|
|
if (!mEditMode) return;
|
|
if (!mDataReceived) return;
|
|
|
|
// Save location for later.
|
|
mPosGlobal = gAgent.getPositionGlobal();
|
|
|
|
S32 region_x = llround((F32)mPosGlobal.mdV[VX]) % REGION_WIDTH_UNITS;
|
|
S32 region_y = llround((F32)mPosGlobal.mdV[VY]) % REGION_WIDTH_UNITS;
|
|
S32 region_z = llround((F32)mPosGlobal.mdV[VZ]);
|
|
|
|
std::string location_text = "(will update after save), ";
|
|
location_text.append(mSimName);
|
|
location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
|
|
|
|
setPickLocation(location_text);
|
|
}
|
|
|
|
// static
|
|
void LLPanelPick::onClickSave()
|
|
{
|
|
if (!mEditMode) return;
|
|
if (!mDataReceived) return;
|
|
|
|
sendUpdate();
|
|
setEditMode(FALSE);
|
|
}
|
|
|
|
void LLPanelPick::updateButtons()
|
|
{
|
|
|
|
// on Pick Info panel (for non-Agent picks) edit_btn should be invisible
|
|
if (mEditMode)
|
|
{
|
|
childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Changes"));
|
|
}
|
|
else
|
|
{
|
|
if (mCreatorId != gAgentID)
|
|
{
|
|
childSetEnabled("edit_btn", FALSE);
|
|
childSetVisible("edit_btn", FALSE);
|
|
}
|
|
else
|
|
{
|
|
childSetEnabled("edit_btn", TRUE);
|
|
childSetVisible("edit_btn", TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLPanelPick::setExitCallback(commit_callback_t cb)
|
|
{
|
|
mBackCb = cb;
|
|
if (!mEditMode)
|
|
{
|
|
LLButton* button = findChild<LLButton>("back_btn");
|
|
if (button) button->setClickedCallback(mBackCb);
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelPick::teleport(const LLVector3d& position)
|
|
{
|
|
if (!position.isExactlyZero())
|
|
{
|
|
gAgent.teleportViaLocation(position);
|
|
LLFloaterWorldMap::getInstance()->trackLocation(position);
|
|
}
|
|
}
|
|
|
|
//static
|
|
void LLPanelPick::showOnMap(const LLVector3d& position)
|
|
{
|
|
LLFloaterWorldMap::getInstance()->trackLocation(position);
|
|
LLFloaterReg::showInstance("world_map", "center");
|
|
}
|
|
|
|
void LLPanelPick::processParcelInfo(const LLParcelData& parcel_data)
|
|
{
|
|
if (mEditMode) return;
|
|
|
|
// HACK: Flag 0x2 == adult region,
|
|
// Flag 0x1 == mature region, otherwise assume PG
|
|
std::string rating_icon = "icon_event.tga";
|
|
if (parcel_data.flags & 0x2)
|
|
{
|
|
rating_icon = "icon_event_adult.tga";
|
|
}
|
|
else if (parcel_data.flags & 0x1)
|
|
{
|
|
rating_icon = "icon_event_mature.tga";
|
|
}
|
|
|
|
childSetValue("maturity", rating_icon);
|
|
|
|
//*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us
|
|
}
|