summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-07-15 17:34:16 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-07-15 17:34:16 +0300
commita5675bedbb2bd34ce03dd16651dc74d8078efea9 (patch)
tree26d0cd120930c2c4fc864027121fd8e789add10a /indra
parentd3d0711f1da33665df63be41758fbc1480244811 (diff)
SL-443 Keybindings: Support reassigment of script interaction button
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/app_settings/key_bindings.xml8
-rw-r--r--indra/newview/llkeyconflict.cpp58
-rw-r--r--indra/newview/llkeyconflict.h4
-rw-r--r--indra/newview/lltoolcomp.cpp10
-rw-r--r--indra/newview/lltoolpie.cpp2
-rw-r--r--indra/newview/llviewerinput.cpp81
-rw-r--r--indra/newview/llviewerinput.h5
-rw-r--r--indra/newview/skins/default/xui/en/control_table_contents_media.xml10
8 files changed, 158 insertions, 20 deletions
diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml
index 4f6deb1f98..ffc1b2e7cc 100644
--- a/indra/newview/app_settings/key_bindings.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -33,6 +33,8 @@
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</first_person>
<third_person>
<binding key="A" mask="NONE" command="turn_left"/>
@@ -127,6 +129,8 @@
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</third_person>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>
@@ -224,6 +228,8 @@
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
@@ -251,5 +257,7 @@
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="sript_trigger_lbutton"/>
</edit_avatar>
</keys>
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index d7a17b237e..58a740e16a 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -868,7 +868,7 @@ void LLKeyConflictHandler::resetKeyboardBindings()
void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
{
- // These controls are meant to cause conflicts when user tries to assign same control somewhere else
+ // These placeholds are meant to cause conflict resolution when user tries to assign same control somewhere else
// also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks
if (load_mode == MODE_FIRST_PERSON)
@@ -928,25 +928,73 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
registerTemporaryControl("spin_around_ccw_sitting");
registerTemporaryControl("spin_around_cw_sitting");
}
+
+
+ // Special case, mouse clicks passed to scripts have 'lowest' piority
+ // thus do not conflict, everything else has a chance before them
+ // also in ML they have highest priority, but only when script-grabbed,
+ // thus do not conflict
+ // (see AGENT_CONTROL_ML_LBUTTON_DOWN and CONTROL_LBUTTON_DOWN_INDEX)
+ LLKeyConflict *type_data = &mControlsMap[script_mouse_handler_name];
+ type_data->mAssignable = true;
+ type_data->mConflictMask = U32_MAX - CONFLICT_LMOUSE;
}
-bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask)
+bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_mask)
{
if (conlict_mask == CONFLICT_NOTHING)
{
// Can't conflict
return true;
}
+
+ if (data.mMouse == CLICK_LEFT
+ && data.mMask == MASK_NONE
+ && data.mKey == KEY_NONE)
+ {
+ if ((conlict_mask & CONFLICT_LMOUSE) == 0)
+ {
+ // Can't conflict
+ return true;
+ }
+ else
+ {
+ // simplify conflict mask
+ conlict_mask = CONFLICT_LMOUSE;
+ }
+ }
+ else
+ {
+ // simplify conflict mask
+ conlict_mask &= ~CONFLICT_LMOUSE;
+ }
+
std::map<std::string, S32> conflict_list;
control_map_t::iterator cntrl_iter = mControlsMap.begin();
control_map_t::iterator cntrl_end = mControlsMap.end();
for (; cntrl_iter != cntrl_end; ++cntrl_iter)
{
+ const U32 cmp_mask = cntrl_iter->second.mConflictMask;
+ if ((cmp_mask & conlict_mask) == 0)
+ {
+ // can't conflict
+ continue;
+ }
S32 index = cntrl_iter->second.mKeyBind.findKeyData(data);
- if (index >= 0
- && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING
- && (cntrl_iter->second.mConflictMask & conlict_mask) != 0)
+ if (index >= 0)
{
+ if (cmp_mask != U32_MAX)
+ {
+ const LLKeyData cmp_data = cntrl_iter->second.mKeyBind.getKeyData(index);
+ if ((cmp_mask & CONFLICT_LMOUSE) == 0
+ && cmp_data.mMouse == CLICK_LEFT
+ && cmp_data.mMask == MASK_NONE
+ && cmp_data.mKey == KEY_NONE)
+ {
+ // Does not conflict
+ continue;
+ }
+ }
if (cntrl_iter->second.mAssignable)
{
// Potentially we can have multiple conflict flags conflicting
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 2926ca3aeb..e78d2fa33b 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -66,6 +66,7 @@ public:
};
const U32 CONFLICT_NOTHING = 0;
+ const U32 CONFLICT_LMOUSE = 0x1 << 1;
// at the moment this just means that key will conflict with everything that is identical
const U32 CONFLICT_ANY = U32_MAX;
@@ -145,6 +146,7 @@ private:
// at the moment these kind of control is not savable, but takes part in conflict resolution
void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
+ // conflict mask 0 means that any conflicts will be ignored
void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0);
typedef std::map<std::string, LLKeyConflict> control_map_t;
@@ -152,7 +154,7 @@ private:
bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
// returns false in case user is trying to reuse control that can't be reassigned
- bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
+ bool removeConflicts(const LLKeyData &data, U32 conlict_mask);
// removes flags and removes temporary file, returns 'true' if file was removed
bool clearUnsavedChanges();
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index f9c327b46e..9ac1810964 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -44,6 +44,7 @@
#include "lltoolmgr.h"
#include "lltoolselectrect.h"
#include "lltoolplacer.h"
+#include "llviewerinput.h"
#include "llviewermenu.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
@@ -743,7 +744,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
{
// if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
{
gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
return FALSE;
@@ -760,7 +761,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
{
gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
return FALSE;
@@ -794,7 +795,10 @@ BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask)
{
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ if (gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
setCurrentTool( (LLTool*) mGun );
return TRUE;
}
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 322d0bc727..543a93bf9b 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -746,7 +746,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
else if (!mMouseOutsideSlop
&& mMouseButtonDown
// disable camera steering if click on land is not used for moving
- && gViewerInput.isMouseBindUsed(CLICK_LEFT))
+ && gViewerInput.isMouseBindUsed(CLICK_LEFT, MASK_NONE, MODE_THIRD_PERSON))
{
S32 delta_x = x - mMouseDownX;
S32 delta_y = y - mMouseDownY;
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index c0eaa88f54..8b3d406b78 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -61,7 +61,7 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
struct LLKeyboardActionRegistry
-: public LLRegistrySingleton<std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
+: public LLRegistrySingleton<const std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
{
LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
};
@@ -836,7 +836,49 @@ bool voice_follow_key(EKeystate s)
return false;
}
-bool agen_control_lbutton_handle(EKeystate s)
+bool sript_trigger_lbutton(EKeystate s)
+{
+ // Check for script overriding/expecting left mouse button.
+ // Note that this does not pass event further and depends onto mouselook.
+ // Checks CONTROL_ML_LBUTTON_DOWN_INDEX for mouselook,
+ // CONTROL_LBUTTON_DOWN_INDEX for normal camera
+ if (gAgent.leftButtonGrabbed())
+ {
+ bool mouselook = gAgentCamera.cameraMouselook();
+ switch (s)
+ {
+ case KEYSTATE_DOWN:
+ // at the moment sript_trigger_lbutton is only intended for mouselook
+ // but handling other modes just in case
+ if (mouselook)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+ }
+ return true;
+ case KEYSTATE_UP:
+ if (mouselook)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+ }
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+// Used by scripts, for overriding/handling left mouse button
+// see mControlsTakenCount
+bool agent_control_lbutton_handle(EKeystate s)
{
switch (s)
{
@@ -905,6 +947,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice);
REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key);
+REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, sript_trigger_lbutton);
#undef REGISTER_KEYBOARD_ACTION
LLViewerInput::LLViewerInput()
@@ -1104,6 +1147,20 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
typedef boost::function<bool(EKeystate)> function_t;
function_t function = NULL;
+ if (mouse == CLICK_LEFT
+ && mask == MASK_NONE
+ && function_name == script_mouse_handler_name)
+ {
+ // Special case
+ // Left click has script overrides and by default
+ // is handled via agent_control_lbutton as last option
+ // In case of mouselook and present overrides it has highest
+ // priority even over UI and is handled in LLToolCompGun::handleMouseDown
+ // so just mark it as having default handler
+ mLMouseDefaultHandling[mode] = true;
+ return TRUE;
+ }
+
function_t* result = LLKeyboardActionRegistry::getValue(function_name);
if (result)
{
@@ -1164,6 +1221,7 @@ void LLViewerInput::resetBindings()
{
mKeyBindings[i].clear();
mMouseBindings[i].clear();
+ mLMouseDefaultHandling[i] = false;
}
}
@@ -1355,13 +1413,14 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask))
{
+ // pass mouse left button press to script
if (key_down && !repeat)
{
- res = agen_control_lbutton_handle(KEYSTATE_DOWN);
+ res = agent_control_lbutton_handle(KEYSTATE_DOWN);
}
if (key_up)
{
- res = agen_control_lbutton_handle(KEYSTATE_UP);
+ res = agent_control_lbutton_handle(KEYSTATE_UP);
}
}
return res;
@@ -1481,24 +1540,28 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
S32 mode = getMode();
MASK mask = gKeyboard->currentMask(TRUE);
res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state);
+
// no user defined actions found or those actions can't handle the key/button, handle control if nessesary
- if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
+ // This will pass AGENT_CONTROL_LBUTTON_DOWN to server, no idea why it doesn't do mouselook variant _ML_
+ // but it was set this way forever (moved as is from LLTool::handleMouseDown) so lots of scripts probably
+ // rely on this.
+ if (!res && mLMouseDefaultHandling[mode] && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
{
switch (state)
{
case MOUSE_STATE_DOWN:
- agen_control_lbutton_handle(KEYSTATE_DOWN);
+ agent_control_lbutton_handle(KEYSTATE_DOWN);
res = true;
break;
case MOUSE_STATE_CLICK:
// might not work best with some functions,
// but some function need specific states too specifically
- agen_control_lbutton_handle(KEYSTATE_DOWN);
- agen_control_lbutton_handle(KEYSTATE_UP);
+ agent_control_lbutton_handle(KEYSTATE_DOWN);
+ agent_control_lbutton_handle(KEYSTATE_UP);
res = true;
break;
case MOUSE_STATE_UP:
- agen_control_lbutton_handle(KEYSTATE_UP);
+ agent_control_lbutton_handle(KEYSTATE_UP);
res = true;
break;
default:
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
index 281a209896..32dd3c0e28 100644
--- a/indra/newview/llviewerinput.h
+++ b/indra/newview/llviewerinput.h
@@ -31,6 +31,7 @@
#include "llinitparam.h"
const S32 MAX_KEY_BINDINGS = 128; // was 60
+const std::string script_mouse_handler_name = "sript_trigger_lbutton";
class LLNamedFunction
{
@@ -124,7 +125,8 @@ public:
BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
void scanMouse();
- bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON);
+ bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode);
+ bool isLMouseHandlingDefault(const S32 mode) { return mLMouseDefaultHandling[mode]; }
private:
bool scanKey(const std::vector<LLKeyboardBinding> &binding,
@@ -163,6 +165,7 @@ private:
// to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
+ bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
index ce5d3556b6..a97c45dd6f 100644
--- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml
+++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
@@ -73,4 +73,14 @@
name="lst_action"
value="Start Gesture" />
</rows>
+ <rows
+ name="sript_trigger_lbutton"
+ value="sript_trigger_lbutton">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Interact (Script LMB)" />
+ </rows>
</contents>