llinspectobject.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:18k
- /**
- * @file llinspectobject.cpp
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009-2010, 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 "llinspectobject.h"
- // Viewer
- #include "llinspect.h"
- #include "llmediaentry.h"
- #include "llnotificationsutil.h" // *TODO: Eliminate, add LLNotificationsUtil wrapper
- #include "llselectmgr.h"
- #include "llslurl.h"
- #include "llviewermenu.h" // handle_object_touch(), handle_buy()
- #include "llviewermedia.h"
- #include "llviewermediafocus.h"
- #include "llviewerobjectlist.h" // to select the requested object
- // Linden libraries
- #include "llbutton.h" // setLabel(), not virtual!
- #include "llclickaction.h"
- #include "llfloaterreg.h"
- #include "llmenubutton.h"
- #include "llresmgr.h" // getMonetaryString
- #include "llsafehandle.h"
- #include "llsidetray.h"
- #include "lltextbox.h" // for description truncation
- #include "lltrans.h"
- #include "llui.h" // positionViewNearMouse()
- #include "lluictrl.h"
- class LLViewerObject;
- //////////////////////////////////////////////////////////////////////////////
- // LLInspectObject
- //////////////////////////////////////////////////////////////////////////////
- // Object Inspector, a small information window used when clicking
- // in the ambient inspector widget for objects in the 3D world.
- class LLInspectObject : public LLInspect
- {
- friend class LLFloaterReg;
-
- public:
- // object_id - Root object ID for which to show information
- // Inspector will be positioned relative to current mouse position
- LLInspectObject(const LLSD& object_id);
- virtual ~LLInspectObject();
-
- /*virtual*/ BOOL postBuild(void);
-
- // Because floater is single instance, need to re-parse data on each spawn
- // (for example, inspector about same avatar but in different position)
- /*virtual*/ void onOpen(const LLSD& avatar_id);
-
- // Release the selection and do other cleanup
- /*virtual*/ void onClose(bool app_quitting);
-
- // override the inspector mouse leave so timer is only paused if
- // gear menu is not open
- /* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask);
-
- private:
- // Refresh displayed data with information from selection manager
- void update();
- void hideButtons();
- void updateButtons(LLSelectNode* nodep);
- void updateSitLabel(LLSelectNode* nodep);
- void updateTouchLabel(LLSelectNode* nodep);
- void updateName(LLSelectNode* nodep);
- void updateDescription(LLSelectNode* nodep);
- void updatePrice(LLSelectNode* nodep);
- void updateCreator(LLSelectNode* nodep);
-
- void updateMediaCurrentURL();
- void updateSecureBrowsing();
-
- void onClickBuy();
- void onClickPay();
- void onClickTakeFreeCopy();
- void onClickTouch();
- void onClickSit();
- void onClickOpen();
- void onClickMoreInfo();
- void onClickZoomIn();
-
- private:
- LLUUID mObjectID;
- S32 mObjectFace;
- viewer_media_t mMediaImpl;
- LLMediaEntry* mMediaEntry;
- LLSafeHandle<LLObjectSelection> mObjectSelection;
- };
- LLInspectObject::LLInspectObject(const LLSD& sd)
- : LLInspect( LLSD() ), // single_instance, doesn't really need key
- mObjectID(NULL), // set in onOpen()
- mObjectFace(0),
- mObjectSelection(NULL),
- mMediaImpl(NULL),
- mMediaEntry(NULL)
- {
- // can't make the properties request until the widgets are constructed
- // as it might return immediately, so do it in postBuild.
- mCommitCallbackRegistrar.add("InspectObject.Buy", boost::bind(&LLInspectObject::onClickBuy, this));
- mCommitCallbackRegistrar.add("InspectObject.Pay", boost::bind(&LLInspectObject::onClickPay, this));
- mCommitCallbackRegistrar.add("InspectObject.TakeFreeCopy", boost::bind(&LLInspectObject::onClickTakeFreeCopy, this));
- mCommitCallbackRegistrar.add("InspectObject.Touch", boost::bind(&LLInspectObject::onClickTouch, this));
- mCommitCallbackRegistrar.add("InspectObject.Sit", boost::bind(&LLInspectObject::onClickSit, this));
- mCommitCallbackRegistrar.add("InspectObject.Open", boost::bind(&LLInspectObject::onClickOpen, this));
- mCommitCallbackRegistrar.add("InspectObject.MoreInfo", boost::bind(&LLInspectObject::onClickMoreInfo, this));
- mCommitCallbackRegistrar.add("InspectObject.ZoomIn", boost::bind(&LLInspectObject::onClickZoomIn, this));
- }
- LLInspectObject::~LLInspectObject()
- {
- }
- /*virtual*/
- BOOL LLInspectObject::postBuild(void)
- {
- // The XML file has sample data in it. Clear that out so we don't
- // flicker when data arrives off network.
- getChild<LLUICtrl>("object_name")->setValue("");
- getChild<LLUICtrl>("object_creator")->setValue("");
- getChild<LLUICtrl>("object_description")->setValue("");
- getChild<LLUICtrl>("object_media_url")->setValue("");
- // Set buttons invisible until we know what this object can do
- hideButtons();
- // Hide floater when name links clicked
- LLTextBox* textbox = getChild<LLTextBox>("object_creator");
- textbox->mURLClickSignal.connect(
- boost::bind(&LLInspectObject::closeFloater, this, false) );
- // Hook up functionality
- getChild<LLUICtrl>("buy_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickBuy, this));
- getChild<LLUICtrl>("pay_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickPay, this));
- getChild<LLUICtrl>("take_free_copy_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickTakeFreeCopy, this));
- getChild<LLUICtrl>("touch_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickTouch, this));
- getChild<LLUICtrl>("sit_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickSit, this));
- getChild<LLUICtrl>("open_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickOpen, this));
- getChild<LLUICtrl>("more_info_btn")->setCommitCallback(
- boost::bind(&LLInspectObject::onClickMoreInfo, this));
- // Watch for updates to selection properties off the network
- LLSelectMgr::getInstance()->mUpdateSignal.connect(
- boost::bind(&LLInspectObject::update, this) );
- return TRUE;
- }
- // Multiple calls to showInstance("inspect_avatar", foo) will provide different
- // LLSD for foo, which we will catch here.
- //virtual
- void LLInspectObject::onOpen(const LLSD& data)
- {
- // Start animation
- LLInspect::onOpen(data);
- // Extract appropriate avatar id
- mObjectID = data["object_id"];
-
- if(data.has("object_face"))
- {
- mObjectFace = data["object_face"];
- }
- // Position the inspector relative to the mouse cursor
- // Similar to how tooltips are positioned
- // See LLToolTipMgr::createToolTip
- if (data.has("pos"))
- {
- LLUI::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger());
- }
- else
- {
- LLUI::positionViewNearMouse(this);
- }
- // Promote hovered object to a complete selection, which will also force
- // a request for selected object data off the network
- LLViewerObject* obj = gObjectList.findObject( mObjectID );
- if (obj)
- {
- // Media focus and this code fight over the select manager.
- // Make sure any media is unfocused before changing the selection here.
- LLViewerMediaFocus::getInstance()->clearFocus();
-
- LLSelectMgr::instance().deselectAll();
- mObjectSelection = LLSelectMgr::instance().selectObjectAndFamily(obj);
- // Mark this as a transient selection
- struct SetTransient : public LLSelectedNodeFunctor
- {
- bool apply(LLSelectNode* node)
- {
- node->setTransient(TRUE);
- return true;
- }
- } functor;
- mObjectSelection->applyToNodes(&functor);
-
- // Does this face have media?
- const LLTextureEntry* tep = obj->getTE(mObjectFace);
- if (!tep)
- return;
-
- mMediaEntry = tep->hasMedia() ? tep->getMediaData() : NULL;
- if(!mMediaEntry)
- return;
-
- mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mMediaEntry->getMediaID());
- }
- }
- // virtual
- void LLInspectObject::onClose(bool app_quitting)
- {
- // Release selection to deselect
- mObjectSelection = NULL;
- getChild<LLMenuButton>("gear_btn")->hideMenu();
- }
- void LLInspectObject::update()
- {
- // Performance optimization, because we listen to updates from select mgr
- // but we're never destroyed.
- if (!getVisible()) return;
- LLObjectSelection* selection = LLSelectMgr::getInstance()->getSelection();
- if (!selection) return;
- LLSelectNode* nodep = selection->getFirstRootNode();
- if (!nodep) return;
- updateButtons(nodep);
- updateName(nodep);
- updateDescription(nodep);
- updateCreator(nodep);
- updatePrice(nodep);
-
- LLViewerObject* obj = nodep->getObject();
- if(!obj)
- return;
-
- if ( mObjectFace < 0
- || mObjectFace >= obj->getNumTEs() )
- {
- return;
- }
-
- // Does this face have media?
- const LLTextureEntry* tep = obj->getTE(mObjectFace);
- if (!tep)
- return;
-
- mMediaEntry = tep->hasMedia() ? tep->getMediaData() : NULL;
- if(!mMediaEntry)
- return;
-
- mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mMediaEntry->getMediaID());
-
- updateMediaCurrentURL();
- updateSecureBrowsing();
- }
- void LLInspectObject::hideButtons()
- {
- getChild<LLUICtrl>("buy_btn")->setVisible(false);
- getChild<LLUICtrl>("pay_btn")->setVisible(false);
- getChild<LLUICtrl>("take_free_copy_btn")->setVisible(false);
- getChild<LLUICtrl>("touch_btn")->setVisible(false);
- getChild<LLUICtrl>("sit_btn")->setVisible(false);
- getChild<LLUICtrl>("open_btn")->setVisible(false);
- }
- // *TODO: Extract this method from lltoolpie.cpp and put somewhere shared
- extern U8 final_click_action(LLViewerObject*);
- // Choose the "most relevant" operation for this object, and show a button for
- // that operation as the left-most button in the inspector.
- void LLInspectObject::updateButtons(LLSelectNode* nodep)
- {
- // We'll start with everyone hidden and show the ones we need
- hideButtons();
-
- LLViewerObject* object = nodep->getObject();
- LLViewerObject *parent = (LLViewerObject*)object->getParent();
- bool for_copy = anyone_copy_selection(nodep);
- bool for_sale = enable_buy_object();
- S32 price = nodep->mSaleInfo.getSalePrice();
- U8 click_action = final_click_action(object);
- if (for_copy
- || (for_sale && price == 0))
- {
- // Free copies have priority over other operations
- getChild<LLUICtrl>("take_free_copy_btn")->setVisible(true);
- }
- else if (for_sale)
- {
- getChild<LLUICtrl>("buy_btn")->setVisible(true);
- }
- else if ( enable_pay_object() )
- {
- getChild<LLUICtrl>("pay_btn")->setVisible(true);
- }
- else if (click_action == CLICK_ACTION_SIT)
- {
- // Click-action sit must come before "open" because many objects on
- // which you can sit have scripts, and hence can be opened
- getChild<LLUICtrl>("sit_btn")->setVisible(true);
- updateSitLabel(nodep);
- }
- else if (object->flagHandleTouch()
- || (parent && parent->flagHandleTouch()))
- {
- getChild<LLUICtrl>("touch_btn")->setVisible(true);
- updateTouchLabel(nodep);
- }
- else if ( enable_object_open() )
- {
- // Open is last because anything with a script in it can be opened
- getChild<LLUICtrl>("open_btn")->setVisible(true);
- }
- else
- {
- // By default, we can sit on anything
- getChild<LLUICtrl>("sit_btn")->setVisible(true);
- updateSitLabel(nodep);
- }
- // No flash
- focusFirstItem(FALSE, FALSE);
- }
- void LLInspectObject::updateSitLabel(LLSelectNode* nodep)
- {
- LLButton* sit_btn = getChild<LLButton>("sit_btn");
- if (!nodep->mSitName.empty())
- {
- sit_btn->setLabel( nodep->mSitName );
- }
- else
- {
- sit_btn->setLabel( getString("Sit") );
- }
- }
- void LLInspectObject::updateTouchLabel(LLSelectNode* nodep)
- {
- LLButton* sit_btn = getChild<LLButton>("touch_btn");
- if (!nodep->mTouchName.empty())
- {
- sit_btn->setLabel( nodep->mTouchName );
- }
- else
- {
- sit_btn->setLabel( getString("Touch") );
- }
- }
- void LLInspectObject::updateName(LLSelectNode* nodep)
- {
- std::string name;
- if (!nodep->mName.empty())
- {
- name = nodep->mName;
- }
- else
- {
- name = LLTrans::getString("TooltipNoName");
- }
- getChild<LLUICtrl>("object_name")->setValue(name);
- }
- void LLInspectObject::updateDescription(LLSelectNode* nodep)
- {
- const char* const DEFAULT_DESC = "(No Description)";
- std::string desc;
- if (!nodep->mDescription.empty()
- && nodep->mDescription != DEFAULT_DESC)
- {
- desc = nodep->mDescription;
- }
- LLTextBox* textbox = getChild<LLTextBox>("object_description");
- textbox->setValue(desc);
- }
- void LLInspectObject::updateMediaCurrentURL()
- {
- if(!mMediaEntry)
- return;
- LLTextBox* textbox = getChild<LLTextBox>("object_media_url");
- std::string media_url = "";
- textbox->setValue(media_url);
- textbox->setToolTip(media_url);
- LLStringUtil::format_map_t args;
-
- if(mMediaImpl.notNull() && mMediaImpl->hasMedia())
- {
-
- LLPluginClassMedia* media_plugin = NULL;
- media_plugin = mMediaImpl->getMediaPlugin();
- if(media_plugin)
- {
- if(media_plugin->pluginSupportsMediaTime())
- {
- args["[CurrentURL]"] = mMediaImpl->getMediaURL();
- }
- else
- {
- args["[CurrentURL]"] = media_plugin->getLocation();
- }
- media_url = LLTrans::getString("CurrentURL", args);
- }
- }
- else if(mMediaEntry->getCurrentURL() != "")
- {
- args["[CurrentURL]"] = mMediaEntry->getCurrentURL();
- media_url = LLTrans::getString("CurrentURL", args);
- }
- textbox->setText(media_url);
- textbox->setToolTip(media_url);
- }
- void LLInspectObject::updateCreator(LLSelectNode* nodep)
- {
- // final information for display
- LLStringUtil::format_map_t args;
- std::string text;
-
- // Leave text blank until data loaded
- if (nodep->mValid)
- {
- // Utilize automatic translation of SLURL into name to display
- // a clickable link
- // Objects cannot be created by a group, so use agent URL format
- LLUUID creator_id = nodep->mPermissions->getCreator();
- std::string creator_url =
- LLSLURL::buildCommand("agent", creator_id, "about");
- args["[CREATOR]"] = creator_url;
-
- // created by one user but owned by another
- std::string owner_url;
- LLUUID owner_id;
- bool group_owned = nodep->mPermissions->isGroupOwned();
- if (group_owned)
- {
- owner_id = nodep->mPermissions->getGroup();
- owner_url = LLSLURL::buildCommand("group", owner_id, "about");
- }
- else
- {
- owner_id = nodep->mPermissions->getOwner();
- owner_url = LLSLURL::buildCommand("agent", owner_id, "about");
- }
- args["[OWNER]"] = owner_url;
-
- if (creator_id == owner_id)
- {
- // common case, created and owned by one user
- text = getString("Creator", args);
- }
- else
- {
- text = getString("CreatorAndOwner", args);
- }
- }
- getChild<LLUICtrl>("object_creator")->setValue(text);
- }
- void LLInspectObject::updatePrice(LLSelectNode* nodep)
- {
- // *TODO: Only look these up once and use for both updateButtons and here
- bool for_copy = anyone_copy_selection(nodep);
- bool for_sale = enable_buy_object();
- S32 price = nodep->mSaleInfo.getSalePrice();
-
- bool show_price_icon = false;
- std::string line;
- if (for_copy
- || (for_sale && price == 0))
- {
- line = getString("PriceFree");
- show_price_icon = true;
- }
- else if (for_sale)
- {
- LLStringUtil::format_map_t args;
- args["[AMOUNT]"] = LLResMgr::getInstance()->getMonetaryString(price);
- line = getString("Price", args);
- show_price_icon = true;
- }
- getChild<LLUICtrl>("price_text")->setValue(line);
- getChild<LLUICtrl>("price_icon")->setVisible(show_price_icon);
- }
- void LLInspectObject::updateSecureBrowsing()
- {
- bool is_secure_browsing = false;
-
- if(mMediaImpl.notNull()
- && mMediaImpl->hasMedia())
- {
- LLPluginClassMedia* media_plugin = NULL;
- std::string current_url = "";
- media_plugin = mMediaImpl->getMediaPlugin();
- if(media_plugin)
- {
- if(media_plugin->pluginSupportsMediaTime())
- {
- current_url = mMediaImpl->getMediaURL();
- }
- else
- {
- current_url = media_plugin->getLocation();
- }
- }
-
- std::string prefix = std::string("https://");
- std::string test_prefix = current_url.substr(0, prefix.length());
- LLStringUtil::toLower(test_prefix);
- if(test_prefix == prefix)
- {
- is_secure_browsing = true;
- }
- }
- getChild<LLUICtrl>("secure_browsing")->setVisible(is_secure_browsing);
- }
- // For the object inspector, only unpause the fade timer
- // if the gear menu is not open
- void LLInspectObject::onMouseLeave(S32 x, S32 y, MASK mask)
- {
- LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
- if ( gear_menu && gear_menu->getVisible() )
- {
- return;
- }
- if(childHasVisiblePopupMenu())
- {
- return;
- }
- mOpenTimer.unpause();
- }
- void LLInspectObject::onClickBuy()
- {
- handle_buy();
- closeFloater();
- }
- void LLInspectObject::onClickPay()
- {
- handle_give_money_dialog();
- closeFloater();
- }
- void LLInspectObject::onClickTakeFreeCopy()
- {
- LLObjectSelection* selection = LLSelectMgr::getInstance()->getSelection();
- if (!selection) return;
- LLSelectNode* nodep = selection->getFirstRootNode();
- if (!nodep) return;
- // Figure out if this is a "free buy" or a "take copy"
- bool for_copy = anyone_copy_selection(nodep);
- // Prefer to just take a free copy
- if (for_copy)
- {
- handle_take_copy();
- }
- else
- {
- // Buy for free (confusing, but that's how it is)
- handle_buy();
- }
- closeFloater();
- }
- void LLInspectObject::onClickTouch()
- {
- handle_object_touch();
- closeFloater();
- }
- void LLInspectObject::onClickSit()
- {
- handle_object_sit_or_stand();
- closeFloater();
- }
- void LLInspectObject::onClickOpen()
- {
- LLFloaterReg::showInstance("openobject");
- closeFloater();
- }
- void LLInspectObject::onClickMoreInfo()
- {
- LLSD key;
- key["task"] = "task";
- LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
- closeFloater();
- }
- void LLInspectObject::onClickZoomIn()
- {
- handle_look_at_selection("zoom");
- closeFloater();
- }
- //////////////////////////////////////////////////////////////////////////////
- // LLInspectObjectUtil
- //////////////////////////////////////////////////////////////////////////////
- void LLInspectObjectUtil::registerFloater()
- {
- LLFloaterReg::add("inspect_object", "inspect_object.xml",
- &LLFloaterReg::build<LLInspectObject>);
- }