diff options
Diffstat (limited to 'indra/newview/llviewerinput.cpp')
-rw-r--r-- | indra/newview/llviewerinput.cpp | 171 |
1 files changed, 145 insertions, 26 deletions
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 94ec534732..43b9cd90bd 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -816,13 +816,20 @@ bool toggle_enable_media(EKeystate s) bool walk_to(EKeystate s) { - if (KEYSTATE_DOWN != s) return true; + if (KEYSTATE_DOWN != s) + { + // teleport/walk is usually on mouseclick, mouseclick needs + // to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't, + // so return false, but if it causes issues, do some kind of + // "return !has_teleported" + return false; + } return LLToolPie::getInstance()->walkToClickedLocation(); } bool teleport_to(EKeystate s) { - if (KEYSTATE_DOWN != s) return true; + if (KEYSTATE_DOWN != s) return false; return LLToolPie::getInstance()->teleportToClickedLocation(); } @@ -850,7 +857,47 @@ bool voice_follow_key(EKeystate s) return false; } -bool agen_control_lbutton_handle(EKeystate s) +bool script_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: + 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) { @@ -922,6 +969,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to); REGISTER_KEYBOARD_ACTION("walk_to", walk_to); REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice); REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key); +REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton); #undef REGISTER_KEYBOARD_ACTION LLViewerInput::LLViewerInput() @@ -1193,6 +1241,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; + } + LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name); if (result) { @@ -1269,7 +1331,8 @@ LLViewerInput::Keys::Keys() : first_person("first_person"), third_person("third_person"), sitting("sitting"), - edit_avatar("edit_avatar") + edit_avatar("edit_avatar"), + xml_version("xml_version", 0) {} void LLViewerInput::resetBindings() @@ -1280,6 +1343,7 @@ void LLViewerInput::resetBindings() mGlobalMouseBindings[i].clear(); mKeyBindings[i].clear(); mMouseBindings[i].clear(); + mLMouseDefaultHandling[i] = false; } } @@ -1298,6 +1362,65 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename) binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON); binding_count += loadBindingMode(keys.sitting, MODE_SITTING); binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR); + + // verify version + if (keys.xml_version < 1) + { + // updating from a version that was not aware of LMouse bindings + for (S32 i = 0; i < MODE_COUNT; i++) + { + mLMouseDefaultHandling[i] = true; + } + + // fix missing values + KeyBinding mouse_binding; + mouse_binding.key = ""; + mouse_binding.mask = "NONE"; + mouse_binding.mouse = "LMB"; + mouse_binding.command = script_mouse_handler_name; + + if (keys.third_person.isProvided()) + { + keys.third_person.bindings.add(mouse_binding); + } + + if (keys.first_person.isProvided()) + { + keys.first_person.bindings.add(mouse_binding); + } + + if (keys.sitting.isProvided()) + { + keys.sitting.bindings.add(mouse_binding); + } + + if (keys.edit_avatar.isProvided()) + { + keys.edit_avatar.bindings.add(mouse_binding); + } + + // fix version + keys.xml_version.set(keybindings_xml_version, true); + + // Write the resulting XML to file + LLXMLNodePtr output_node = new LLXMLNode("keys", false); + LLXUIParser write_parser; + write_parser.writeXUI(output_node, keys); + + if (!output_node->isNull()) + { + // file in app_settings is supposed to be up to date + // this is only for the file from user_settings + LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL; + LLFILE *fp = LLFile::fopen(filename, "w"); + if (fp != NULL) + { + LLXMLNode::writeHeaderToFile(fp); + output_node->writeToFile(fp); + fclose(fp); + } + } + } } return binding_count; } @@ -1469,17 +1592,6 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat); - if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask)) - { - if (key_down && !repeat) - { - res = agen_control_lbutton_handle(KEYSTATE_DOWN); - } - if (key_up) - { - res = agen_control_lbutton_handle(KEYSTATE_UP); - } - } return res; } @@ -1603,29 +1715,36 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const bool res = false; S32 mode = getMode(); MASK mask = gKeyboard->currentMask(TRUE); - - // By default mouse clicks require exact mask - // Todo: support for mIgnoreMasks because some functions like teleports - // expect to be canceled, but for voice it's prefered to ignore mask. res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state, false); - // 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)) + + // No user defined actions found or those actions can't handle the key/button, + // so handle CONTROL_LBUTTON if nessesary. + // + // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown, + // and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls + // are leftButtonGrabbed(), send a normal click otherwise. + + if (!res + && mLMouseDefaultHandling[mode] + && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed()) + && (click == CLICK_LEFT || click == CLICK_DOUBLELEFT) + ) { 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: @@ -1655,7 +1774,7 @@ void LLViewerInput::scanMouse() } } -bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) +bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const { S32 size = mMouseBindings[mode].size(); for (S32 index = 0; index < size; index++) |