diff options
-rw-r--r-- | indra/llcharacter/llmultigesture.cpp | 2 | ||||
-rw-r--r-- | indra/llcharacter/llmultigesture.h | 10 | ||||
-rw-r--r-- | indra/newview/llgesturemgr.cpp | 76 | ||||
-rw-r--r-- | indra/newview/llgesturemgr.h | 11 | ||||
-rw-r--r-- | indra/newview/llpreviewgesture.cpp | 11 | ||||
-rw-r--r-- | indra/newview/llpreviewgesture.h | 1 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 9 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_preview_gesture.xml | 15 |
8 files changed, 126 insertions, 9 deletions
diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index 7ed242f90a..511d931569 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -68,6 +68,8 @@ void LLMultiGesture::reset() mCurrentStep = 0; mWaitTimer.reset(); mWaitingTimer = FALSE; + mTriggeredByKey = FALSE; + mKeyReleased = FALSE; mWaitingAnimations = FALSE; mWaitingAtEnd = FALSE; mRequestedAnimIDs.clear(); diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index 92820159d4..1865ec089c 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -83,9 +83,18 @@ public: // We're waiting for triggered animations to stop playing BOOL mWaitingAnimations; + // We're waiting for key release + BOOL mWaitingKeyRelease; + // We're waiting a fixed amount of time BOOL mWaitingTimer; + // We're waiting for triggered animations to stop playing + BOOL mTriggeredByKey; + + // Has the key been released? + BOOL mKeyReleased; + // Waiting after the last step played for all animations to complete BOOL mWaitingAtEnd; @@ -210,6 +219,7 @@ public: const U32 WAIT_FLAG_TIME = 0x01; const U32 WAIT_FLAG_ALL_ANIM = 0x02; +const U32 WAIT_FLAG_KEY_RELEASE = 0x04; class LLGestureStepWait : public LLGestureStep { diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index c0f773968d..ce00bf3a54 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -58,6 +58,9 @@ // Longest time, in seconds, to wait for all animations to stop playing const F32 MAX_WAIT_ANIM_SECS = 30.f; +// Longest time, in seconds, to wait for a key release. +// This should be relatively long, but not too long. 10 minutes is enough +const F32 MAX_WAIT_KEY_SECS = 60.f * 10.f; // Lightweight constructor. // init() does the heavy lifting. @@ -528,12 +531,13 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset LLGestureMgr::instance().replaceGesture(base_item_id, gesture, new_asset_id); } -void LLGestureMgr::playGesture(LLMultiGesture* gesture) +void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool fromKeyPress) { if (!gesture) return; // Reset gesture to first step gesture->mCurrentStep = 0; + gesture->mTriggeredByKey = fromKeyPress; // Add to list of playing gesture->mPlaying = TRUE; @@ -731,7 +735,8 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) if (!gesture) continue; if (gesture->mKey == key - && gesture->mMask == mask) + && gesture->mMask == mask + && gesture->mWaitingKeyRelease == FALSE) { matching.push_back(gesture); } @@ -744,13 +749,38 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) LLMultiGesture* gesture = matching[random]; - playGesture(gesture); + playGesture(gesture, TRUE); return TRUE; } return FALSE; } +BOOL LLGestureMgr::triggerGestureRelease(KEY key, MASK mask) +{ + std::vector <LLMultiGesture *> matching; + item_map_t::iterator it; + + // collect matching gestures + for (it = mActive.begin(); it != mActive.end(); ++it) + { + LLMultiGesture* gesture = (*it).second; + + // asset data might not have arrived yet + if (!gesture) continue; + + if (gesture->mKey == key + && gesture->mMask == mask) + { + gesture->mKeyReleased = TRUE; + } + } + + //If we found one, block. Otherwise tell them it's free to go. + return matching.size() > 0; +} + + S32 LLGestureMgr::getPlayingCount() const { return mPlaying.size(); @@ -899,6 +929,33 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) continue; } + // If we're waiting a fixed amount of time, check for timer + // expiration. + if (gesture->mWaitingKeyRelease) + { + // We're waiting for a certain amount of time to pass + LLGestureStepWait* wait_step = (LLGestureStepWait*)step; + if (gesture->mKeyReleased) + { + // wait is done, continue execution + gesture->mWaitingKeyRelease = FALSE; + gesture->mCurrentStep++; + } + else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_KEY_SECS) + { + LL_INFOS("GestureMgr") << "Waited too long for key release, continuing gesture." + << LL_ENDL; + gesture->mWaitingAnimations = FALSE; + gesture->mCurrentStep++; + } + else + { + // we're waiting, so execution is done for now + waiting = TRUE; + } + continue; + } + // If we're waiting on our animations to stop, poll for // completion. if (gesture->mWaitingAnimations) @@ -1015,7 +1072,18 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) case STEP_WAIT: { LLGestureStepWait* wait_step = (LLGestureStepWait*)step; - if (wait_step->mFlags & WAIT_FLAG_TIME) + if (gesture->mTriggeredByKey // Only wait here IF we were triggered by a key! + && gesture->mKeyReleased == FALSE // We can only do this once! Prevent gestures infinitely running + && wait_step->mFlags & WAIT_FLAG_KEY_RELEASE) + { + // Lets wait for the key release first so we don't hold up re-presses + + gesture->mWaitingKeyRelease = TRUE; + // Use the wait timer as a deadlock breaker for key release + // waits. + gesture->mWaitTimer.reset(); + } + else if (wait_step->mFlags & WAIT_FLAG_TIME) { gesture->mWaitingTimer = TRUE; gesture->mWaitTimer.reset(); diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 7c8e8279c2..e805c91145 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -102,7 +102,10 @@ public: const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being // previewed. - void playGesture(LLMultiGesture* gesture); + void playGesture(LLMultiGesture* gesture, bool fromKeyPress); + void playGesture(LLMultiGesture* gesture) { + playGesture(gesture, FALSE); + } void playGesture(const LLUUID& item_id); // Stop all requested or playing anims for this gesture @@ -118,10 +121,14 @@ public: { mCallbackMap[inv_item_id] = cb; } - // Trigger the first gesture that matches this key. + // Trigger a random gesture that matches this key. // Returns TRUE if it finds a gesture bound to that key. BOOL triggerGesture(KEY key, MASK mask); + // Trigger release wait on all gestures that matches this key. + // Returns TRUE if it finds a gesture bound to that key. + BOOL triggerGestureRelease(KEY key, MASK mask); + // Trigger all gestures referenced as substrings in this string BOOL triggerAndReviseString(const std::string &str, std::string *revised_string = NULL); diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 759e7859f2..5d5010e27e 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -433,6 +433,11 @@ BOOL LLPreviewGesture::postBuild() edit->setIgnoreTab(TRUE); mChatEditor = edit; + check = getChild<LLCheckBoxCtrl>( "wait_key_release_check"); + check->setVisible(FALSE); + check->setCommitCallback(onCommitWait, this); + mWaitKeyReleaseCheck = check; + check = getChild<LLCheckBoxCtrl>( "wait_anim_check"); check->setVisible(FALSE); check->setCommitCallback(onCommitWait, this); @@ -638,6 +643,7 @@ void LLPreviewGesture::refresh() mAnimationRadio->setEnabled(FALSE); mSoundCombo->setEnabled(FALSE); mChatEditor->setEnabled(FALSE); + mWaitKeyReleaseCheck->setEnabled(FALSE); mWaitAnimCheck->setEnabled(FALSE); mWaitTimeCheck->setEnabled(FALSE); mWaitTimeEditor->setEnabled(FALSE); @@ -660,6 +666,7 @@ void LLPreviewGesture::refresh() mAnimationRadio->setEnabled(modifiable); mSoundCombo->setEnabled(modifiable); mChatEditor->setEnabled(modifiable); + mWaitKeyReleaseCheck->setEnabled(modifiable); mWaitAnimCheck->setEnabled(modifiable); mWaitTimeCheck->setEnabled(modifiable); mWaitTimeEditor->setEnabled(modifiable); @@ -695,6 +702,7 @@ void LLPreviewGesture::refresh() mAnimationRadio->setVisible(FALSE); mSoundCombo->setVisible(FALSE); mChatEditor->setVisible(FALSE); + mWaitKeyReleaseCheck->setVisible(FALSE); mWaitAnimCheck->setVisible(FALSE); mWaitTimeCheck->setVisible(FALSE); mWaitTimeEditor->setVisible(FALSE); @@ -739,6 +747,8 @@ void LLPreviewGesture::refresh() { LLGestureStepWait* wait_step = (LLGestureStepWait*)step; optionstext = getString("step_wait"); + mWaitKeyReleaseCheck->setVisible(TRUE); + mWaitKeyReleaseCheck->set(wait_step->mFlags & WAIT_FLAG_KEY_RELEASE); mWaitAnimCheck->setVisible(TRUE); mWaitAnimCheck->set(wait_step->mFlags & WAIT_FLAG_ALL_ANIM); mWaitTimeCheck->setVisible(TRUE); @@ -1516,6 +1526,7 @@ void LLPreviewGesture::onCommitWait(LLUICtrl* ctrl, void* data) LLGestureStepWait* wait_step = (LLGestureStepWait*)step; U32 flags = 0x0; + if (self->mWaitKeyReleaseCheck->get()) flags |= WAIT_FLAG_KEY_RELEASE; if (self->mWaitAnimCheck->get()) flags |= WAIT_FLAG_ALL_ANIM; if (self->mWaitTimeCheck->get()) flags |= WAIT_FLAG_TIME; wait_step->mFlags = flags; diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index f5c47d71b8..d0fddaf49a 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -154,6 +154,7 @@ private: LLComboBox* mAnimationCombo; LLComboBox* mSoundCombo; LLLineEditor* mChatEditor; + LLCheckBoxCtrl* mWaitKeyReleaseCheck; LLCheckBoxCtrl* mWaitAnimCheck; LLCheckBoxCtrl* mWaitTimeCheck; LLLineEditor* mWaitTimeEditor; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d68d0cd92c..8012a934c9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2867,6 +2867,15 @@ BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) } } + // Try for a new-format gesture + if (LLGestureMgr::instance().triggerGestureRelease(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey new gesture release feature" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + //Old format gestures do not support this, so no need to implement it. + // don't pass keys on to world when something in ui has focus return gFocusMgr.childHasKeyboardFocus(mRootView) || LLMenuGL::getKeyboardMode() diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml index c4ac936334..28b735d297 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - height="460" - min_height="460" + height="475" + min_height="475" layout="topleft" name="gesture_preview" help_topic="gesture_preview" @@ -297,11 +297,20 @@ <check_box follows="top|left" height="20" + label="until key is released" + layout="topleft" + left="28" + name="wait_key_release_check" + top="330" + width="100" /> + <check_box + follows="top|left" + height="20" label="until animations are done" layout="topleft" left="28" name="wait_anim_check" - top="330" + top_delta="20" width="100" /> <check_box follows="top|left" |