From 13221f67c465017f44ca46aeca23b0d820935825 Mon Sep 17 00:00:00 2001 From: Leviathan Linden Date: Tue, 19 Sep 2023 09:40:08 -0700 Subject: add GameControl feature and SDL2 dependency --- indra/llwindow/llgamecontrol.h | 86 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 indra/llwindow/llgamecontrol.h (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h new file mode 100644 index 0000000000..fe6d6f0138 --- /dev/null +++ b/indra/llwindow/llgamecontrol.h @@ -0,0 +1,86 @@ +/** + * @file llgamecontrol.h + * @brief GameController detection and management + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#pragma once + +#include + + +#include "llerror.h" +#include "llsingleton.h" +#include "stdtypes.h" + + +// LLGameControl is a singleton with pure static public interface +class LLGameControl : public LLSingleton +{ + LLSINGLETON_EMPTY_CTOR(LLGameControl); + virtual ~LLGameControl(); + LOG_CLASS(LLGameControl); + +public: + // State is a minimal class for storing axes and buttons values + class State + { + public: + State(); + bool onButton(U8 button, bool pressed); + std::vector mAxes; // [ -32768, 32767 ] + std::vector mPrevAxes; // value in last outgoing packet + U32 mButtons; + }; + + static bool isInitialized(); + static void init(); + static void terminate(); + + static void addKeyButtonMap(U16 key, U8 button); + static void removeKeyButtonMap(U16 key); + static void addKeyAxisMap(U16 key, U8 axis, bool positive); + static void removeKeyAxisMap(U16 key); + + static void onKeyDown(U16 key, U32 mask); + static void onKeyUp(U16 key, U32 mask); + + // returns 'true' if GameControlInput message needs to go out, + // which will be the case for new data or resend. Call this right + // before deciding to put a GameControlInput packet on the wire + // or not. + static bool computeFinalInputAndCheckForChanges(); + + static void clearAllInput(); + static void clearAllKeys(); + + static void processEvents(bool app_has_focus = true); + static const State& getState(); + + static void setIncludeKeyboardButtons(bool include); + static bool getIncludeKeyboardButtons(); + + // call this after putting a GameControlInput packet on the wire + static void updateResendPeriod(); +}; + -- cgit v1.2.3 From ed6ecca2a45e52d9be1d91107b9643b5ecdfb8bf Mon Sep 17 00:00:00 2001 From: Leviathan Linden Date: Thu, 16 Nov 2023 13:53:37 -0800 Subject: avatar_motion-->GameControl translation and flycam --- indra/llwindow/llgamecontrol.h | 156 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 142 insertions(+), 14 deletions(-) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index fe6d6f0138..50cb78a4ea 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -33,6 +33,36 @@ #include "llsingleton.h" #include "stdtypes.h" +// For reference, here are the RAW indices of the various input channels +// of a standard XBox controller. Button (N) is numbered in parentheses, +// whereas axisN has N+ and N- labels. +// +// leftpaddle rightpaddle +// _______ _______ +// / 4+ '-. .-' 5+ \ +// leftshoulder _(9)_________'-.____ ____.-'_________(10) rightshoulder +// / _________ \_________/ \ +// / / 1- \ (3) \ +// | | | (4) (5) (6) Y | +// | |0- (7) 0+| _________ (2)X B(1) | +// | | | / 3- \ A | +// | | 1+ | | | (0) | +// | \_________/ |2- (8) 2+| | +// | leftstick (11) | | | +// | (13) (14) | 3+ | | +// | (12) \_________/ | +// | d-pad rightstick | +// | ____________________ | +// | / \ | +// | / \ | +// | / \ | +// \__________/ \__________/ +// +// Note: the analog joystics provide NEGATIVE X,Y values for LEFT,FORWARD +// whereas those directions are actually POSITIVE in SL's local right-handed +// reference frame. This is why we implicitly negate those axes the moment +// they are extracted from SDL, before being used anywhere. See the +// implementation in LLGameControllerManager::onAxis(). // LLGameControl is a singleton with pure static public interface class LLGameControl : public LLSingleton @@ -42,11 +72,93 @@ class LLGameControl : public LLSingleton LOG_CLASS(LLGameControl); public: + enum AgentControlMode + { + CONTROL_MODE_AVATAR, + CONTROL_MODE_FLYCAM, + CONTROL_MODE_NONE + }; + + enum KeyboardAxis + { + AXIS_LEFTX = 0, + AXIS_LEFTY, + AXIS_RIGHTX, + AXIS_RIGHTY, + AXIS_TRIGGERLEFT, + AXIS_TRIGGERRIGHT, + AXIS_LAST + }; + + enum Button + { + BUTTON_A = 0, + BUTTON_B, + BUTTON_X, + BUTTON_Y, + BUTTON_BACK, + BUTTON_GUIDE, + BUTTON_START, + BUTTON_LEFTSTICK, + BUTTON_RIGHTSTICK, + BUTTON_LEFTSHOULDER, + BUTTON_RIGHTSHOULDER, // 10 + BUTTON_DPAD_UP, + BUTTON_DPAD_DOWN, + BUTTON_DPAD_LEFT, + BUTTON_DPAD_RIGHT, + BUTTON_MISC1, + BUTTON_PADDLE1, + BUTTON_PADDLE2, + BUTTON_PADDLE3, + BUTTON_PADDLE4, + BUTTON_TOUCHPAD, // 20 + BUTTON_21, + BUTTON_22, + BUTTON_23, + BUTTON_24, + BUTTON_25, + BUTTON_26, + BUTTON_27, + BUTTON_28, + BUTTON_29, + BUTTON_30, + BUTTON_31 + }; + + class InputChannel + { + public: + enum Type + { + TYPE_AXIS, + TYPE_BUTTON, + TYPE_NONE + }; + + InputChannel() {} + InputChannel(Type type, U8 index) : mType(type), mIndex(index) {} + InputChannel(Type type, U8 index, S32 sign) : mType(type), mSign(sign), mIndex(index) {} + + // these methods for readability + bool isAxis() const { return mType == TYPE_AXIS; } + bool isButton() const { return mType == TYPE_BUTTON; } + bool isNone() const { return mType == TYPE_NONE; } + + std::string getLocalName() const; // AXIS_0-, AXIS_0+, BUTTON_0, etc + std::string getRemoteName() const; // GAME_CONTROL_AXIS_LEFTX, GAME_CONTROL_BUTTON_A, etc + + Type mType { TYPE_NONE }; + S32 mSign { 0 }; + U8 mIndex { 255 }; + }; + // State is a minimal class for storing axes and buttons values class State { public: State(); + void clear(); bool onButton(U8 button, bool pressed); std::vector mAxes; // [ -32768, 32767 ] std::vector mPrevAxes; // value in last outgoing packet @@ -57,28 +169,44 @@ public: static void init(); static void terminate(); - static void addKeyButtonMap(U16 key, U8 button); - static void removeKeyButtonMap(U16 key); - static void addKeyAxisMap(U16 key, U8 axis, bool positive); - static void removeKeyAxisMap(U16 key); - - static void onKeyDown(U16 key, U32 mask); - static void onKeyUp(U16 key, U32 mask); - // returns 'true' if GameControlInput message needs to go out, // which will be the case for new data or resend. Call this right // before deciding to put a GameControlInput packet on the wire // or not. - static bool computeFinalInputAndCheckForChanges(); + static bool computeFinalStateAndCheckForChanges(); - static void clearAllInput(); - static void clearAllKeys(); + static void clearAllState(); static void processEvents(bool app_has_focus = true); static const State& getState(); - - static void setIncludeKeyboardButtons(bool include); - static bool getIncludeKeyboardButtons(); + static void getCameraInputs(std::vector& inputs_out); + + // these methods for accepting input from keyboard + static void enableSendToServer(bool enable); + static void enableControlAgent(bool enable); + static void enableTranslateAgentActions(bool enable); + static void setAgentControlMode(AgentControlMode mode); + + static bool willSendToServer(); + static bool willTranslateAgentActions(); + static bool willControlAvatar(); + static bool willControlFlycam(); + //static LocalControlMode getLocalControlMode(); + + // Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel + // If the axis name lacks the +/- postfix it assumes '+' postfix. + static LLGameControl::InputChannel getChannelByName(const std::string& name); + + // action_name = push+, strafe-, etc + static LLGameControl::InputChannel getChannelByActionName(const std::string& name); + + static bool updateActionMap(const std::string& action_name, LLGameControl::InputChannel channel); + + // Keyboard presses produce action_flags which can be translated into State + // and game_control devices produce State which can be translated into action_flags. + // These methods help exchange such translations. + static U32 computeInternalActionFlags(); + static void setExternalActionFlags(U32 action_flags); // call this after putting a GameControlInput packet on the wire static void updateResendPeriod(); -- cgit v1.2.3 From ec39ac89e8529da206dafd519d75ad5944888076 Mon Sep 17 00:00:00 2001 From: leviathan Date: Fri, 1 Mar 2024 14:04:54 -0800 Subject: more GameControl prefs UI --- indra/llwindow/llgamecontrol.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index 50cb78a4ea..104ae3a2c6 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -58,7 +58,7 @@ // | / \ | // \__________/ \__________/ // -// Note: the analog joystics provide NEGATIVE X,Y values for LEFT,FORWARD +// Note: the analog joysticks provide NEGATIVE X,Y values for LEFT,FORWARD // whereas those directions are actually POSITIVE in SL's local right-handed // reference frame. This is why we implicitly negate those axes the moment // they are extracted from SDL, before being used anywhere. See the @@ -156,8 +156,12 @@ public: // State is a minimal class for storing axes and buttons values class State { + int mJoystickID { -1 }; + void* mController { nullptr }; public: State(); + void setDevice(int joystickID, void* controller); + int getJoystickID() const { return mJoystickID; } void clear(); bool onButton(U8 button, bool pressed); std::vector mAxes; // [ -32768, 32767 ] @@ -166,7 +170,7 @@ public: }; static bool isInitialized(); - static void init(); + static void init(const std::string& gamecontrollerdb_path); static void terminate(); // returns 'true' if GameControlInput message needs to go out, @@ -175,11 +179,11 @@ public: // or not. static bool computeFinalStateAndCheckForChanges(); - static void clearAllState(); + static void clearAllStates(); static void processEvents(bool app_has_focus = true); static const State& getState(); - static void getCameraInputs(std::vector& inputs_out); + static void getFlycamInputs(std::vector& inputs_out); // these methods for accepting input from keyboard static void enableSendToServer(bool enable); @@ -187,11 +191,7 @@ public: static void enableTranslateAgentActions(bool enable); static void setAgentControlMode(AgentControlMode mode); - static bool willSendToServer(); - static bool willTranslateAgentActions(); static bool willControlAvatar(); - static bool willControlFlycam(); - //static LocalControlMode getLocalControlMode(); // Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel // If the axis name lacks the +/- postfix it assumes '+' postfix. @@ -206,7 +206,7 @@ public: // and game_control devices produce State which can be translated into action_flags. // These methods help exchange such translations. static U32 computeInternalActionFlags(); - static void setExternalActionFlags(U32 action_flags); + static void setExternalInput(U32 action_flags, U32 buttons_from_keys); // call this after putting a GameControlInput packet on the wire static void updateResendPeriod(); -- cgit v1.2.3 From 2daf175650cdda7cc8f820b6cb17b1475496e7ac Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 8 May 2024 23:32:58 +0200 Subject: Add GameControl UI for per device settings --- indra/llwindow/llgamecontrol.h | 156 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 138 insertions(+), 18 deletions(-) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index 104ae3a2c6..d75aa3a018 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -79,20 +79,30 @@ public: CONTROL_MODE_NONE }; - enum KeyboardAxis + enum ActionNameType { - AXIS_LEFTX = 0, + ACTION_NAME_UNKNOWN, + ACTION_NAME_ANALOG, // E.g., "push" + ACTION_NAME_ANALOG_POS, // E.g., "push+" + ACTION_NAME_ANALOG_NEG, // E.g., "push-" + ACTION_NAME_BINARY, // E.g., "stop" + ACTION_NAME_FLYCAM // E.g., "zoom" + }; + + enum KeyboardAxis : U8 + { + AXIS_LEFTX, AXIS_LEFTY, AXIS_RIGHTX, AXIS_RIGHTY, AXIS_TRIGGERLEFT, AXIS_TRIGGERRIGHT, - AXIS_LAST + NUM_AXES }; enum Button { - BUTTON_A = 0, + BUTTON_A, BUTTON_B, BUTTON_X, BUTTON_Y, @@ -123,17 +133,21 @@ public: BUTTON_28, BUTTON_29, BUTTON_30, - BUTTON_31 + BUTTON_31, + NUM_BUTTONS }; + static const U16 MAX_AXIS_DEAD_ZONE = 16384; + static const U16 MAX_AXIS_OFFSET = 16384; + class InputChannel { public: enum Type { + TYPE_NONE, TYPE_AXIS, - TYPE_BUTTON, - TYPE_NONE + TYPE_BUTTON }; InputChannel() {} @@ -141,11 +155,16 @@ public: InputChannel(Type type, U8 index, S32 sign) : mType(type), mSign(sign), mIndex(index) {} // these methods for readability + bool isNone() const { return mType == TYPE_NONE; } bool isAxis() const { return mType == TYPE_AXIS; } bool isButton() const { return mType == TYPE_BUTTON; } - bool isNone() const { return mType == TYPE_NONE; } - std::string getLocalName() const; // AXIS_0-, AXIS_0+, BUTTON_0, etc + bool isEqual(const InputChannel& other) + { + return mType == other.mType && mSign == other.mSign && mIndex == other.mIndex; + } + + std::string getLocalName() const; // AXIS_0-, AXIS_0+, BUTTON_0, NONE etc. std::string getRemoteName() const; // GAME_CONTROL_AXIS_LEFTX, GAME_CONTROL_BUTTON_A, etc Type mType { TYPE_NONE }; @@ -153,15 +172,58 @@ public: U8 mIndex { 255 }; }; + // Options is a data structure for storing device-specific settings + class Options + { + public: + struct AxisOptions + { + bool mInvert { false }; + U16 mDeadZone { 0 }; + S16 mOffset { 0 }; + + void resetToDefaults() + { + mInvert = false; + mDeadZone = 0; + mOffset = 0; + } + + std::string saveToString() const; + void loadFromString(std::string options); + }; + + Options(); + + void resetToDefaults(); + + U8 mapAxis(U8 axis) const; + U8 mapButton(U8 button) const; + + S16 fixAxisValue(U8 axis, S16 value) const; + + std::string saveToString(const std::string& name, bool force_empty = false) const; + bool loadFromString(std::string& name, std::string options); + bool loadFromString(std::string options); + + const std::vector& getAxisOptions() const { return mAxisOptions; } + std::vector& getAxisOptions() { return mAxisOptions; } + const std::vector& getAxisMap() const { return mAxisMap; } + std::vector& getAxisMap() { return mAxisMap; } + const std::vector& getButtonMap() const { return mButtonMap; } + std::vector& getButtonMap() { return mButtonMap; } + + private: + std::vector mAxisOptions; + std::vector mAxisMap; + std::vector mButtonMap; + }; + // State is a minimal class for storing axes and buttons values class State { - int mJoystickID { -1 }; - void* mController { nullptr }; public: State(); - void setDevice(int joystickID, void* controller); - int getJoystickID() const { return mJoystickID; } void clear(); bool onButton(U8 button, bool pressed); std::vector mAxes; // [ -32768, 32767 ] @@ -169,10 +231,43 @@ public: U32 mButtons; }; + // Device is a data structure for describing any detected controller + class Device + { + const int mJoystickID { -1 }; + const std::string mGUID; + const std::string mName; + Options mOptions; + State mState; + + public: + Device(int joystickID, const std::string& guid, const std::string& name); + int getJoystickID() const { return mJoystickID; } + std::string getGUID() const { return mGUID; } + std::string getName() const { return mName; } + const Options& getOptions() const { return mOptions; } + const State& getState() const { return mState; } + + void resetOptionsToDefaults() { mOptions.resetToDefaults(); } + std::string saveOptionsToString(bool force_empty = false) const { return mOptions.saveToString(mName, force_empty); } + void loadOptionsFromString(const std::string& options) { mOptions.loadFromString(options); } + + friend class LLGameControllerManager; + }; + static bool isInitialized(); - static void init(const std::string& gamecontrollerdb_path); + static void init(const std::string& gamecontrollerdb_path, + std::function loadBoolean, + std::function saveBoolean, + std::function loadString, + std::function saveString, + std::function loadObject, + std::function saveObject); static void terminate(); + static const std::list& getDevices(); + static const std::map& getDeviceOptions(); + // returns 'true' if GameControlInput message needs to go out, // which will be the case for new data or resend. Call this right // before deciding to put a GameControlInput packet on the wire @@ -183,14 +278,21 @@ public: static void processEvents(bool app_has_focus = true); static const State& getState(); + static InputChannel getActiveInputChannel(); static void getFlycamInputs(std::vector& inputs_out); // these methods for accepting input from keyboard - static void enableSendToServer(bool enable); - static void enableControlAgent(bool enable); - static void enableTranslateAgentActions(bool enable); + static void setSendToServer(bool enable); + static void setControlAgent(bool enable); + static void setTranslateAgentActions(bool enable); static void setAgentControlMode(AgentControlMode mode); + static bool getSendToServer(); + static bool getControlAgent(); + static bool getTranslateAgentActions(); + static AgentControlMode getAgentControlMode(); + static ActionNameType getActionNameType(const std::string& action); + static bool willControlAvatar(); // Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel @@ -198,7 +300,7 @@ public: static LLGameControl::InputChannel getChannelByName(const std::string& name); // action_name = push+, strafe-, etc - static LLGameControl::InputChannel getChannelByActionName(const std::string& name); + static LLGameControl::InputChannel getChannelByAction(const std::string& action); static bool updateActionMap(const std::string& action_name, LLGameControl::InputChannel channel); @@ -210,5 +312,23 @@ public: // call this after putting a GameControlInput packet on the wire static void updateResendPeriod(); + + using getChannel_t = std::function; + static std::string stringifyAnalogMappings(getChannel_t getChannel); + static std::string stringifyBinaryMappings(getChannel_t getChannel); + static std::string stringifyFlycamMappings(getChannel_t getChannel); + static void getDefaultMappings(std::vector>& mappings); + + static bool parseDeviceOptions(const std::string& options, std::string& name, + std::vector& axis_options, + std::vector& axis_map, std::vector& button_map); + static std::string stringifyDeviceOptions(const std::string& name, + const std::vector& axis_options, + const std::vector& axis_map, const std::vector& button_map, + bool force_empty = false); + + static void initByDefault(); + static void loadFromSettings(); + static void saveToSettings(); }; -- cgit v1.2.3 From 9c986bef6704ac07112e18dc82b870acf1847e41 Mon Sep 17 00:00:00 2001 From: leviathan Date: Thu, 27 Jun 2024 00:18:42 -0700 Subject: put GameControl behind a feature flag --- indra/llwindow/llgamecontrol.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index d75aa3a018..9398fb7f66 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -255,6 +255,9 @@ public: friend class LLGameControllerManager; }; + static bool isEnabled(); + static void setEnabled(bool enabled); + static bool isInitialized(); static void init(const std::string& gamecontrollerdb_path, std::function loadBoolean, -- cgit v1.2.3 From 8213a0fb6b3149042d6833c8f0c4a3c1bfdc8bc9 Mon Sep 17 00:00:00 2001 From: leviathan Date: Tue, 27 Aug 2024 16:18:57 -0700 Subject: more correct application of GameControl prefs --- indra/llwindow/llgamecontrol.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index 9398fb7f66..9dfce4c287 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -178,17 +178,23 @@ public: public: struct AxisOptions { - bool mInvert { false }; + S32 mMultiplier = 1; U16 mDeadZone { 0 }; S16 mOffset { 0 }; void resetToDefaults() { - mInvert = false; + mMultiplier = 1; mDeadZone = 0; mOffset = 0; } + S16 computeModifiedValue(S16 raw_value) const + { + S32 new_value = ((S32)raw_value + S32(mOffset)) * mMultiplier; + return (S16)(std::clamp(new_value, -32768, 32767)); + } + std::string saveToString() const; void loadFromString(std::string options); }; @@ -265,7 +271,8 @@ public: std::function loadString, std::function saveString, std::function loadObject, - std::function saveObject); + std::function saveObject, + std::function updateUI); static void terminate(); static const std::list& getDevices(); @@ -333,5 +340,6 @@ public: static void initByDefault(); static void loadFromSettings(); static void saveToSettings(); + static void setDeviceOptions(const std::string& guid, const Options& options); }; -- cgit v1.2.3 From 0617923ae7f450ece7288f8a73446c45a8ed32db Mon Sep 17 00:00:00 2001 From: leviathan Date: Tue, 3 Sep 2024 15:38:35 -0700 Subject: remove crashy LLSD ctor used by GameControl --- indra/llwindow/llgamecontrol.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index 9dfce4c287..5472a8ce6d 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -32,6 +32,7 @@ #include "llerror.h" #include "llsingleton.h" #include "stdtypes.h" +#include "SDL2/SDL_events.h" // For reference, here are the RAW indices of the various input channels // of a standard XBox controller. Button (N) is numbered in parentheses, @@ -287,6 +288,7 @@ public: static void clearAllStates(); static void processEvents(bool app_has_focus = true); + static void handleEvent(const SDL_Event& event, bool app_has_focus); static const State& getState(); static InputChannel getActiveInputChannel(); static void getFlycamInputs(std::vector& inputs_out); -- cgit v1.2.3 From ea650ac073aeb03ab99b88c41f51ce636ce37982 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 3 Oct 2024 12:08:26 -0700 Subject: fix GameControl save settings, fix linux build --- indra/llwindow/llgamecontrol.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llwindow/llgamecontrol.h') diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h index 5472a8ce6d..a4b47cc47f 100644 --- a/indra/llwindow/llgamecontrol.h +++ b/indra/llwindow/llgamecontrol.h @@ -40,10 +40,10 @@ // // leftpaddle rightpaddle // _______ _______ -// / 4+ '-. .-' 5+ \ +// / 4+ '-. .-' 5+ \. // leftshoulder _(9)_________'-.____ ____.-'_________(10) rightshoulder -// / _________ \_________/ \ -// / / 1- \ (3) \ +// / _________ \_________/ \. +// / / 1- \ (3) \. // | | | (4) (5) (6) Y | // | |0- (7) 0+| _________ (2)X B(1) | // | | | / 3- \ A | -- cgit v1.2.3