From 863ab7fa6ba90003bf40802ff6aa47c18478a56c Mon Sep 17 00:00:00 2001 From: Shyotl Date: Fri, 19 Aug 2011 02:15:22 -0500 Subject: [PATCH] Updated LLViewerParcelMgr. Added LLViewerParcelMgr::setTeleportFinishedCallback, setTeleportFailedCallback. Not hooked into anything yet, however. agentCanBuild, agentCanFly, etc, renamed. --- indra/newview/llfloaterbuyland.cpp | 19 ++-- indra/newview/llhoverview.cpp | 2 +- indra/newview/lltoolbar.cpp | 2 +- indra/newview/llviewermenu.cpp | 4 +- indra/newview/llviewermessage.cpp | 10 +- indra/newview/llviewerparcelmgr.cpp | 138 ++++++++++++++++++++++++---- indra/newview/llviewerparcelmgr.h | 52 +++++++++-- 7 files changed, 193 insertions(+), 34 deletions(-) diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 1340ad905..2d96c8228 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -334,9 +334,8 @@ LLFloaterBuyLandUI::LLFloaterBuyLandUI() LLFloaterBuyLandUI::~LLFloaterBuyLandUI() { + LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo); delete mTransaction; - - LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo); if (sInstance == this) { @@ -494,10 +493,18 @@ void LLFloaterBuyLandUI::updateParcelInfo() return; } - if (!authorizedBuyer.isNull() && buyer != authorizedBuyer) + if (!authorizedBuyer.isNull() && buyer != authorizedBuyer) { - mCannotBuyReason = getString("set_to_sell_to_other"); - return; + // Maybe the parcel is set for sale to a group we are in. + bool authorized_group = + gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_DEED) + && gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_SET_SALE_INFO); + + if (!authorized_group) + { + mCannotBuyReason = getString("set_to_sell_to_other"); + return; + } } } else @@ -807,7 +814,7 @@ void LLFloaterBuyLandUI::sendBuyLand() if (mParcelBuyInfo) { LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo); - LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo); + LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo); mBought = true; } } diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index 1821b7da7..171977066 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -179,7 +179,7 @@ void LLHoverView::pickCallback(const LLPickInfo& pick_info) { gHoverView->setHoverActive(TRUE); gHoverView->mHoverLandGlobal = pick_info.mPosGlobal; - LLViewerParcelMgr::getInstance()->requestHoverParcelProperties( gHoverView->mHoverLandGlobal ); + LLViewerParcelMgr::getInstance()->setHoverParcel( gHoverView->mHoverLandGlobal ); } else { diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index d3a8ea928..8f5c767a5 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -300,7 +300,7 @@ void LLToolBar::refresh() childSetEnabled("fly_btn", (gAgent.canFly() || gAgent.getFlying() || gSavedSettings.getBOOL("AscentFlyAlwaysEnabled")) && !sitting ); - childSetEnabled("build_btn", (LLViewerParcelMgr::getInstance()->agentCanBuild() || gSavedSettings.getBOOL("AscentBuildAlwaysEnabled")) ); + childSetEnabled("build_btn", (LLViewerParcelMgr::getInstance()->allowAgentBuild() || gSavedSettings.getBOOL("AscentBuildAlwaysEnabled")) ); // Check to see if we're in build mode BOOL build_mode = LLToolMgr::getInstance()->inEdit(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 002955008..b03001dd4 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2360,7 +2360,7 @@ class LLEnableEdit : public view_listener_t bool enable = true; if (gAgent.inPrelude()) { - enable = LLViewerParcelMgr::getInstance()->agentCanBuild() + enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() || LLSelectMgr::getInstance()->getSelection()->isAttachment(); } // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) @@ -7146,7 +7146,7 @@ class LLAttachmentEnableDrop : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->agentCanBuild()); + BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild()); //Add an inventory observer to only allow dropping the newly attached item //once it exists in your inventory. Look at Jira 2422. diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8442d924c..b01a9f51d 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6100,6 +6100,9 @@ void process_teleport_failed(LLMessageSystem *msg, void**) LLNotifications::instance().add("CouldNotTeleportReason", args); + // Let the interested parties know that teleport failed. + LLViewerParcelMgr::getInstance()->onTeleportFailed(); + if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); @@ -6159,9 +6162,14 @@ void process_teleport_local(LLMessageSystem *msg,void**) } // send camera update to new region - //gAgent.updateCamera(); + gAgentCamera.updateCamera(); send_agent_update(TRUE, TRUE); + + // Let the interested parties know we've teleported. + // Vadim *HACK: Agent position seems to get reset (to render position?) + // on each frame, so we have to pass the new position manually. + LLViewerParcelMgr::getInstance()->onTeleportFinished(true, gAgent.getPosGlobalFromAgent(pos)); } void send_simple_im(const LLUUID& to_id, diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index e68223285..1a697b778 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -160,6 +160,8 @@ LLViewerParcelMgr::LLViewerParcelMgr() { mAgentParcelOverlay[i] = 0; } + + mTeleportInProgress = TRUE; // the initial parcel update is treated like teleport } @@ -651,14 +653,13 @@ LLParcel *LLViewerParcelMgr::getAgentParcel() const } // Return whether the agent can build on the land they are on -BOOL LLViewerParcelMgr::agentCanBuild() const +bool LLViewerParcelMgr::allowAgentBuild() const { if (mAgentParcel) { - return (gAgent.isGodlike() - || (mAgentParcel->allowModifyBy( - gAgent.getID(), - gAgent.getGroupID()))); + return (gAgent.isGodlike() || + (mAgentParcel->allowModifyBy(gAgent.getID(), gAgent.getGroupID())) || + (isParcelOwnedByAgent(mAgentParcel, GP_LAND_ALLOW_CREATE))); } else { @@ -666,19 +667,53 @@ BOOL LLViewerParcelMgr::agentCanBuild() const } } -BOOL LLViewerParcelMgr::agentCanTakeDamage() const +// Return whether anyone can build on the given parcel +bool LLViewerParcelMgr::allowAgentBuild(const LLParcel* parcel) const { - return mAgentParcel->getAllowDamage(); + return parcel->getAllowModify(); } -BOOL LLViewerParcelMgr::agentCanFly() const +bool LLViewerParcelMgr::allowAgentVoice() const { - return TRUE; + return allowAgentVoice(gAgent.getRegion(), mAgentParcel); } -F32 LLViewerParcelMgr::agentDrawDistance() const +bool LLViewerParcelMgr::allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const { - return 512.f; + return region && region->isVoiceEnabled() + && parcel && parcel->getParcelFlagAllowVoice(); +} + +bool LLViewerParcelMgr::allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const +{ + return region && !region->getBlockFly() + && parcel && parcel->getAllowFly(); +} + +// Can the agent be pushed around by LLPushObject? +bool LLViewerParcelMgr::allowAgentPush(const LLViewerRegion* region, const LLParcel* parcel) const +{ + return region && !region->getRestrictPushObject() + && parcel && !parcel->getRestrictPushObject(); +} + +bool LLViewerParcelMgr::allowAgentScripts(const LLViewerRegion* region, const LLParcel* parcel) const +{ + // *NOTE: This code does not take into account group-owned parcels + // and the flag to allow group-owned scripted objects to run. + // This mirrors the traditional menu bar parcel icon code, but is not + // technically correct. + return region + && !(region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) + && !(region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) + && parcel + && parcel->getAllowOtherScripts(); +} + +bool LLViewerParcelMgr::allowAgentDamage(const LLViewerRegion* region, const LLParcel* parcel) const +{ + return (region && region->getAllowDamage()) + || (parcel && parcel->getAllowDamage()); } BOOL LLViewerParcelMgr::isOwnedAt(const LLVector3d& pos_global) const @@ -1167,10 +1202,11 @@ void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info) msg->sendReliable(info->mHost); } -void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info) +void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo* *info) { - delete info; - info = NULL; + // Must be here because ParcelBuyInfo is local to this .cpp file + delete *info; + *info = NULL; } void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id) @@ -1288,9 +1324,15 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag } -void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos) +void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos) { static U32 last_west, last_south; + + // only request parcel info when tooltip is shown + if (!gSavedSettings.getBOOL("ShowLandHoverTip")) + { + return; + } // only request parcel info if position has changed outside of the // last parcel grid step U32 west_parcel_step = (U32) floor( pos.mdV[VX] / PARCEL_GRID_STEP_METERS ); @@ -1542,9 +1584,19 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use LLViewerParcelMgr::getInstance()->writeAgentParcelFromBitmap(bitmap); delete[] bitmap; + + // Let interesting parties know about agent parcel change. + LLViewerParcelMgr* instance = LLViewerParcelMgr::getInstance(); + + instance->mAgentParcelChangedSignal(); + + if (instance->mTeleportInProgress) + { + instance->mTeleportInProgress = FALSE; + instance->mTeleportFinishedSignal(gAgent.getPositionGlobal()); + } } } - // Add any pending entry to the TP history now that we got the *new* parcel name. LLFloaterTeleportHistory::getInstance()->addEntry(LLViewerParcelMgr::getInstance()->getAgentParcelName()); @@ -2156,7 +2208,10 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const = parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID()); bool isAuthorized - = (authorizeBuyer.isNull() || (gAgent.getID() == authorizeBuyer)); + = (authorizeBuyer.isNull() + || (gAgent.getID() == authorizeBuyer) + || (gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_DEED) + && gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_SET_SALE_INFO))); return isForSale && !isOwner && isAuthorized && isEmpowered; } @@ -2478,3 +2533,52 @@ LLViewerTexture* LLViewerParcelMgr::getPassImage() const { return sPassImage; } + +boost::signals2::connection LLViewerParcelMgr::addAgentParcelChangedCallback(parcel_changed_callback_t cb) +{ + return mAgentParcelChangedSignal.connect(cb); +} +/* + * Set finish teleport callback. You can use it to observe all teleport events. + * NOTE: + * After local( in one region) teleports we + * cannot rely on gAgent.getPositionGlobal(), + * so the new position gets passed explicitly. + * Use args of this callback to get global position of avatar after teleport event. + */ +boost::signals2::connection LLViewerParcelMgr::setTeleportFinishedCallback(teleport_finished_callback_t cb) +{ + return mTeleportFinishedSignal.connect(cb); +} + +boost::signals2::connection LLViewerParcelMgr::setTeleportFailedCallback(parcel_changed_callback_t cb) +{ + return mTeleportFailedSignal.connect(cb); +} + +/* Ok, we're notified that teleport has been finished. + * We should now propagate the notification via mTeleportFinishedSignal + * to all interested parties. + */ +void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos) +{ + // Treat only teleports within the same parcel as local (EXT-3139). + if (local && LLViewerParcelMgr::getInstance()->inAgentParcel(new_pos)) + { + // Local teleport. We already have the agent parcel data. + // Emit the signal immediately. + getInstance()->mTeleportFinishedSignal(new_pos); + } + else + { + // Non-local teleport (inter-region or between different parcels of the same region). + // The agent parcel data has not been updated yet. + // Let's wait for the update and then emit the signal. + mTeleportInProgress = TRUE; + } +} + +void LLViewerParcelMgr::onTeleportFailed() +{ + mTeleportFailedSignal(); +} diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 236dbcbec..d5694d12c 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -68,6 +68,9 @@ const F32 PARCEL_POST_HEIGHT = 0.666f; // Base class for people who want to "observe" changes in the viewer // parcel selection. + +//FIXME: this should be done by grabbing a floating parcel selection and observing changes on it, not the parcel mgr +//--RN class LLParcelObserver { public: @@ -79,6 +82,11 @@ class LLViewerParcelMgr : public LLSingleton { public: + typedef boost::function teleport_finished_callback_t; + typedef boost::signals2::signal teleport_finished_signal_t; + typedef boost::function parcel_changed_callback_t; + typedef boost::signals2::signal parcel_changed_signal_t; + LLViewerParcelMgr(); ~LLViewerParcelMgr(); @@ -160,10 +168,31 @@ public: LLParcel* getCollisionParcel() const; - BOOL agentCanTakeDamage() const; - BOOL agentCanFly() const; - F32 agentDrawDistance() const; - BOOL agentCanBuild() const; + // Can this agent build on the parcel he is on? + // Used for parcel property icons in nav bar. + bool allowAgentBuild() const; + bool allowAgentBuild(const LLParcel* parcel) const; + + // Can this agent speak on the parcel he is on? + // Used for parcel property icons in nav bar. + bool allowAgentVoice() const; + bool allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can this agent start flying on this parcel? + // Used for parcel property icons in nav bar. + bool allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can this agent be pushed by llPushObject() on this parcel? + // Used for parcel property icons in nav bar. + bool allowAgentPush(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can scripts written by non-parcel-owners run on the agent's current + // parcel? Used for parcel property icons in nav bar. + bool allowAgentScripts(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can the agent be damaged here? + // Used for parcel property icons in nav bar. + bool allowAgentDamage(const LLViewerRegion* region, const LLParcel* parcel) const; F32 getHoverParcelWidth() const { return F32(mHoverEastNorth.mdV[VX] - mHoverWestSouth.mdV[VX]); } @@ -209,7 +238,7 @@ public: void sendParcelDwellRequest(); // If the point is outside the current hover parcel, request more data - void requestHoverParcelProperties(const LLVector3d& pos_global); + void setHoverParcel(const LLVector3d& pos_global); bool canAgentBuyParcel(LLParcel*, bool forGroup) const; @@ -235,7 +264,7 @@ public: BOOL remove_contribution); // callers responsibility to call deleteParcelBuy() on return value void sendParcelBuy(ParcelBuyInfo*); - void deleteParcelBuy(ParcelBuyInfo*&); + void deleteParcelBuy(ParcelBuyInfo* *); void sendParcelDeed(const LLUUID& group_id); @@ -261,6 +290,12 @@ public: // the agent is banned or not in the allowed group BOOL isCollisionBanned(); + boost::signals2::connection addAgentParcelChangedCallback(parcel_changed_callback_t cb); + boost::signals2::connection setTeleportFinishedCallback(teleport_finished_callback_t cb); + boost::signals2::connection setTeleportFailedCallback(parcel_changed_callback_t cb); + void onTeleportFinished(bool local, const LLVector3d& new_pos); + void onTeleportFailed(); + static BOOL isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power); static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power); @@ -308,6 +343,11 @@ private: LLDynamicArray mObservers; + BOOL mTeleportInProgress; + teleport_finished_signal_t mTeleportFinishedSignal; + parcel_changed_signal_t mTeleportFailedSignal; + parcel_changed_signal_t mAgentParcelChangedSignal; + // Array of pieces of parcel edges to potentially draw // Has (parcels_per_edge + 1) * (parcels_per_edge + 1) elements so // we can represent edges of the grid.