summaryrefslogtreecommitdiff
path: root/indra/newview/lltoolpie.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/lltoolpie.cpp
Print done when done.
Diffstat (limited to 'indra/newview/lltoolpie.cpp')
-rw-r--r--indra/newview/lltoolpie.cpp635
1 files changed, 635 insertions, 0 deletions
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
new file mode 100644
index 0000000000..89df9c5249
--- /dev/null
+++ b/indra/newview/lltoolpie.cpp
@@ -0,0 +1,635 @@
+/**
+ * @file lltoolpie.cpp
+ * @brief LLToolPie class implementation
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltoolpie.h"
+
+#include "indra_constants.h"
+#include "llclickaction.h"
+#include "llparcel.h"
+
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "llfirstuse.h"
+#include "llfloateravatarinfo.h"
+#include "llfloaterland.h"
+#include "llfloaterscriptdebug.h"
+#include "llhoverview.h"
+#include "llhudeffecttrail.h"
+#include "llhudmanager.h"
+#include "llmenugl.h"
+#include "llmutelist.h"
+#include "llselectmgr.h"
+#include "lltoolfocus.h"
+#include "lltoolgrab.h"
+#include "lltoolmgr.h"
+#include "lltoolselect.h"
+#include "llviewercamera.h"
+#include "llviewermenu.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerwindow.h"
+#include "llvoavatar.h"
+#include "llworld.h"
+#include "llui.h"
+
+LLToolPie *gToolPie = NULL;
+
+LLViewerObject* LLToolPie::sClickActionObject = NULL;
+
+extern void handle_buy(void*);
+
+extern BOOL gDebugClicks;
+
+LLToolPie::LLToolPie()
+: LLTool("Select"),
+ mPieMouseButtonDown( FALSE ),
+ mGrabMouseButtonDown( FALSE ),
+ mHitLand( FALSE ),
+ mHitObjectID(),
+ mMouseOutsideSlop( FALSE )
+{ }
+
+
+BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ // if buttons swapped, don't pick transparent so users can't "pay"
+ // transparent objects
+ gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, leftMouseCallback,
+ TRUE, TRUE);
+ mGrabMouseButtonDown = TRUE;
+ return TRUE;
+}
+
+// static
+void LLToolPie::leftMouseCallback(S32 x, S32 y, MASK mask)
+{
+ gToolPie->pickAndShowMenu(x, y, mask, FALSE);
+}
+
+BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ // Pick faces in case they select "Copy Texture" and need that info.
+ gPickFaces = TRUE;
+ // don't pick transparent so users can't "pay" transparent objects
+ gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, rightMouseCallback,
+ FALSE, TRUE);
+ mPieMouseButtonDown = TRUE;
+ // don't steal focus from UI
+ return FALSE;
+}
+
+// static
+void LLToolPie::rightMouseCallback(S32 x, S32 y, MASK mask)
+{
+ gToolPie->pickAndShowMenu(x, y, mask, TRUE);
+}
+
+// True if you selected an object.
+BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show)
+{
+ if (!always_show && gLastHitParcelWall)
+ {
+ LLParcel* parcel = gParcelMgr->getCollisionParcel();
+ if (parcel)
+ {
+ gParcelMgr->selectCollisionParcel();
+ if (parcel->getParcelFlag(PF_USE_PASS_LIST)
+ && !gParcelMgr->isCollisionBanned())
+ {
+ // if selling passes, just buy one
+ void* deselect_when_done = (void*)TRUE;
+ LLPanelLandGeneral::onClickBuyPass(deselect_when_done);
+ }
+ else
+ {
+ // not selling passes, get info
+ LLFloaterLand::show();
+ }
+ }
+
+ return LLTool::handleMouseDown(x, y, mask);
+ }
+
+ // didn't click in any UI object, so must have clicked in the world
+ LLViewerObject *object = gViewerWindow->lastObjectHit();
+ LLViewerObject *parent = NULL;
+
+ mHitLand = !object && !gLastHitPosGlobal.isExactlyZero();
+ if (!mHitLand)
+ {
+ gParcelMgr->deselectLand();
+ }
+
+ if (object)
+ {
+ mHitObjectID = object->mID;
+
+ parent = object->getRootEdit();
+ }
+ else
+ {
+ mHitObjectID.setNull();
+ }
+
+ BOOL touchable = (object && object->flagHandleTouch())
+ || (parent && parent->flagHandleTouch());
+
+ // If it's a left-click, and we have a special action, do it.
+ if (useClickAction(always_show, mask, object, parent))
+ {
+ U8 click_action = 0;
+ if (object && object->getClickAction())
+ {
+ click_action = object->getClickAction();
+ }
+ else if (parent && parent->getClickAction())
+ {
+ click_action = parent->getClickAction();
+ }
+
+ switch(click_action)
+ {
+ case CLICK_ACTION_TOUCH:
+ default:
+ // nothing
+ break;
+ case CLICK_ACTION_SIT:
+ handle_sit_or_stand();
+ return TRUE;
+ case CLICK_ACTION_PAY:
+ if (object && object->flagTakesMoney()
+ || parent && parent->flagTakesMoney())
+ {
+ sClickActionObject = parent;
+ LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE);
+ return TRUE;
+ }
+ break;
+ case CLICK_ACTION_BUY:
+ sClickActionObject = parent;
+ LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE);
+ return TRUE;
+ case CLICK_ACTION_OPEN:
+ if (parent && parent->allowOpen())
+ {
+ sClickActionObject = parent;
+ LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE);
+ }
+ return TRUE;
+ }
+ }
+
+ // Switch to grab tool if physical or triggerable
+ if (object &&
+ !object->isAvatar() &&
+ ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) &&
+ !always_show)
+ {
+ gGrabTransientTool = this;
+ gCurrentToolset->selectTool( gToolGrab );
+ return gToolGrab->handleObjectHit( object, x, y, mask);
+ }
+
+ if (!object && gLastHitHUDIcon && gLastHitHUDIcon->getSourceObject())
+ {
+ LLFloaterScriptDebug::show(gLastHitHUDIcon->getSourceObject()->getID());
+ }
+
+ // If left-click never selects or spawns a menu
+ // Eat the event.
+ if (!gSavedSettings.getBOOL("LeftClickShowMenu")
+ && !always_show)
+ {
+ // mouse already released
+ if (!mGrabMouseButtonDown)
+ {
+ return TRUE;
+ }
+
+ while( object && object->isAttachment() && !object->flagHandleTouch())
+ {
+ // don't pick avatar through hud attachment
+ if (object->isHUDAttachment())
+ {
+ break;
+ }
+ object = (LLViewerObject*)object->getParent();
+ }
+ if (object && object == gAgent.getAvatarObject())
+ {
+ // we left clicked on avatar, switch to focus mode
+ gToolMgr->setTransientTool(gToolCamera);
+ gViewerWindow->hideCursor();
+ gToolCamera->setMouseCapture(TRUE);
+ gToolCamera->pickCallback(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY(), mask);
+ gAgent.setFocusOnAvatar(TRUE, TRUE);
+
+ return TRUE;
+ }
+ // Could be first left-click on nothing
+ LLFirstUse::useLeftClickNoHit();
+
+ // Eat the event
+ return LLTool::handleMouseDown(x, y, mask);
+ }
+
+ if (!always_show && gAgent.leftButtonGrabbed())
+ {
+ // if the left button is grabbed, don't put up the pie menu
+ return LLTool::handleMouseDown(x, y, mask);
+ }
+
+ // Can't ignore children here.
+ LLToolSelect::handleObjectSelection(object, mask, FALSE, TRUE);
+
+ // Spawn pie menu
+ if (mHitLand)
+ {
+ gParcelMgr->selectParcelAt( gLastHitPosGlobal );
+
+ gPieLand->show(x, y, mPieMouseButtonDown);
+
+ // VEFFECT: ShowPie
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
+ effectp->setPositionGlobal(gLastHitPosGlobal);
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ effectp->setDuration(0.25f);
+ }
+ else if (mHitObjectID == gAgent.getID() )
+ {
+ gPieSelf->show(x, y, mPieMouseButtonDown);
+ }
+ else if (object)
+ {
+ if (object->isAvatar()
+ || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner()))
+ {
+ // Find the attachment's avatar
+ while( object && object->isAttachment())
+ {
+ object = (LLViewerObject*)object->getParent();
+ }
+
+ // Object is an avatar, so check for mute by id.
+ LLVOAvatar* avatar = (LLVOAvatar*)object;
+ LLString name = avatar->getFullname();
+ if (gMuteListp->isMuted(avatar->getID(), name))
+ {
+ gMenuHolder->childSetText("Avatar Mute", "Unmute");
+ //gMutePieMenu->setLabel("Unmute");
+ }
+ else
+ {
+ gMenuHolder->childSetText("Avatar Mute", "Mute");
+ //gMutePieMenu->setLabel("Mute");
+ }
+
+ gPieAvatar->show(x, y, mPieMouseButtonDown);
+ }
+ else if (object->isAttachment())
+ {
+ gPieAttachment->show(x, y, mPieMouseButtonDown);
+ }
+ else
+ {
+ // BUG: What about chatting child objects?
+ LLString name;
+ LLSelectNode* node = gSelectMgr->getFirstRootNode();
+ if (node)
+ {
+ name = node->mName;
+ }
+ if (gMuteListp->isMuted(object->getID(), name))
+ {
+ gMenuHolder->childSetText("Object Mute", "Unmute");
+ //gMuteObjectPieMenu->setLabel("Unmute");
+ }
+ else
+ {
+ gMenuHolder->childSetText("Object Mute", "Mute");
+ //gMuteObjectPieMenu->setLabel("Mute");
+ }
+
+ gPieObject->show(x, y, mPieMouseButtonDown);
+
+ // VEFFECT: ShowPie object
+ // Don't show when you click on someone else, it freaks them
+ // out.
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
+ effectp->setPositionGlobal(gLastHitPosGlobal);
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ effectp->setDuration(0.25f);
+ }
+ }
+
+ if (always_show)
+ {
+ // ignore return value
+ LLTool::handleRightMouseDown(x, y, mask);
+ }
+ else
+ {
+ // ignore return value
+ LLTool::handleMouseDown(x, y, mask);
+ }
+
+ // We handled the event.
+ return TRUE;
+}
+
+BOOL LLToolPie::useClickAction(BOOL always_show,
+ MASK mask,
+ LLViewerObject* object,
+ LLViewerObject* parent)
+{
+ return !always_show
+ && mask == MASK_NONE
+ && object
+ && !object->isAttachment()
+ && LLPrimitive::isPrimitive(object->getPCode())
+ && (object->getClickAction()
+ || parent->getClickAction());
+
+}
+
+U8 final_click_action(LLViewerObject* obj)
+{
+ if (!obj) return CLICK_ACTION_NONE;
+ if (obj->isAttachment()) return CLICK_ACTION_NONE;
+
+ U8 click_action = CLICK_ACTION_TOUCH;
+ LLViewerObject* parent = (obj ? obj->getRootEdit() : NULL);
+ if ((obj && obj->getClickAction())
+ || (parent && parent->getClickAction()))
+ {
+ if (obj && obj->getClickAction())
+ {
+ click_action = obj->getClickAction();
+ }
+ else if (parent && parent->getClickAction())
+ {
+ click_action = parent->getClickAction();
+ }
+ }
+ return click_action;
+}
+
+// When we get object properties after left-clicking on an object
+// with left-click = buy, if it's the same object, do the buy.
+// static
+void LLToolPie::selectionPropertiesReceived()
+{
+ // Make sure all data has been received.
+ // This function will be called repeatedly as the data comes in.
+ if (!gSelectMgr->selectGetAllValid())
+ {
+ return;
+ }
+
+ if (sClickActionObject
+ && !sClickActionObject->isDead())
+ {
+ LLViewerObject* root = gSelectMgr->getFirstRootObject();
+ if (root == sClickActionObject)
+ {
+ U8 action = root->getClickAction();
+ switch (action)
+ {
+ case CLICK_ACTION_BUY:
+ handle_buy(NULL);
+ break;
+ case CLICK_ACTION_PAY:
+ handle_give_money_dialog();
+ break;
+ case CLICK_ACTION_OPEN:
+ handle_object_open();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ sClickActionObject = NULL;
+}
+
+BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
+{
+ /*
+ // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag
+ // gets started.
+ const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() );
+ const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
+ const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
+ // ...normal modes can only yaw
+ if (x < ROTATE_H_MARGIN)
+ {
+ gAgent.yaw(rotate_angle);
+ mMouseOutsideSlop = TRUE;
+ }
+ else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
+ {
+ gAgent.yaw(-rotate_angle);
+ mMouseOutsideSlop = TRUE;
+ }
+ */
+
+ LLViewerObject *object = NULL;
+ LLViewerObject *parent = NULL;
+ if (gHoverView)
+ {
+ object = gHoverView->getLastHoverObject();
+ }
+
+ if (object)
+ {
+ parent = object->getRootEdit();
+ }
+
+ if (object && useClickAction(FALSE, mask, object, parent))
+ {
+ U8 click_action = final_click_action(object);
+ ECursorType cursor = UI_CURSOR_ARROW;
+ switch(click_action)
+ {
+ default: break;
+ case CLICK_ACTION_SIT: cursor = UI_CURSOR_TOOLSIT; break;
+ case CLICK_ACTION_BUY: cursor = UI_CURSOR_TOOLBUY; break;
+ case CLICK_ACTION_OPEN:
+ // Open always opens the parent.
+ if (parent && parent->allowOpen())
+ {
+ cursor = UI_CURSOR_TOOLOPEN;
+ }
+ break;
+ case CLICK_ACTION_PAY:
+ if ((object && object->flagTakesMoney())
+ || (parent && parent->flagTakesMoney()))
+ {
+ cursor = UI_CURSOR_TOOLPAY;
+ }
+ break;
+ }
+ gViewerWindow->getWindow()->setCursor(cursor);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
+ }
+ else if ((object && !object->isAvatar() && object->usePhysics())
+ || (parent && !parent->isAvatar() && parent->usePhysics()))
+ {
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
+ }
+ else if ( (object && object->flagHandleTouch())
+ || (parent && parent->flagHandleTouch()))
+ {
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
+ }
+ else
+ {
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
+ }
+
+ return TRUE;
+}
+
+BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLViewerObject* obj = gViewerWindow->lastObjectHit();
+ U8 click_action = final_click_action(obj);
+ if (click_action != CLICK_ACTION_NONE)
+ {
+ switch(click_action)
+ {
+ case CLICK_ACTION_BUY:
+ case CLICK_ACTION_PAY:
+ case CLICK_ACTION_OPEN:
+ // Because these actions open UI dialogs, we won't change
+ // the cursor again until the next hover and GL pick over
+ // the world. Keep the cursor an arrow, assuming that
+ // after the user moves off the UI, they won't be on the
+ // same object anymore.
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ // Make sure the hover-picked object is ignored.
+ gHoverView->resetLastHoverObject();
+ break;
+ default:
+ break;
+ }
+ }
+
+ mGrabMouseButtonDown = FALSE;
+ gToolMgr->clearTransientTool();
+ return LLTool::handleMouseUp(x, y, mask);
+}
+
+BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ mPieMouseButtonDown = FALSE;
+ gToolMgr->clearTransientTool();
+ return LLTool::handleRightMouseUp(x, y, mask);
+}
+
+
+BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ if (gDebugClicks)
+ {
+ llinfos << "LLToolPie handleDoubleClick (becoming mouseDown)" << llendl;
+ }
+
+ if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
+ {
+ if (gLastHitLand
+ && !gLastHitPosGlobal.isExactlyZero())
+ {
+ handle_go_to();
+ return TRUE;
+ }
+ else if (gLastHitObjectID.notNull()
+ && !gLastHitPosGlobal.isExactlyZero())
+ {
+ // Hit an object
+ // HACK: Call the last hit position the point we hit on the object
+ gLastHitPosGlobal += gLastHitObjectOffset;
+ handle_go_to();
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+ /* JC - don't do go-there, because then double-clicking on physical
+ objects gets you into trouble.
+
+ // If double-click on object or land, go there.
+ LLViewerObject *object = gViewerWindow->lastObjectHit();
+ if (object)
+ {
+ if (object->isAvatar())
+ {
+ LLFloaterAvatarInfo::showFromAvatar(object);
+ }
+ else
+ {
+ handle_go_to(NULL);
+ }
+ }
+ else if (!gLastHitPosGlobal.isExactlyZero())
+ {
+ handle_go_to(NULL);
+ }
+
+ return TRUE;
+ */
+}
+
+
+void LLToolPie::handleDeselect()
+{
+ if( hasMouseCapture() )
+ {
+ setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly
+ }
+ // remove temporary selection for pie menu
+ gSelectMgr->validateSelection();
+}
+
+
+void LLToolPie::stopEditing()
+{
+ if( hasMouseCapture() )
+ {
+ setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly
+ }
+}
+
+void LLToolPie::onMouseCaptureLost()
+{
+ mMouseOutsideSlop = FALSE;
+}
+
+
+// true if x,y outside small box around start_x,start_y
+BOOL LLToolPie::outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y)
+{
+ S32 dx = x - start_x;
+ S32 dy = y - start_y;
+
+ return (dx <= -2 || 2 <= dx || dy <= -2 || 2 <= dy);
+}
+
+
+void LLToolPie::render()
+{
+ return;
+}
+