Button remapping work
This commit is contained in:
287
Zennysoft.Game.Ma/addons/input_helper/InputHelper.cs
Normal file
287
Zennysoft.Game.Ma/addons/input_helper/InputHelper.cs
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.Collections;
|
||||||
|
|
||||||
|
namespace NathanHoad
|
||||||
|
{
|
||||||
|
public static class InputHelper
|
||||||
|
{
|
||||||
|
public delegate void DeviceChangedEventHandler(string device, int deviceIndex);
|
||||||
|
public delegate void KeyboardInputChangedEventHandler(string action, InputEvent input);
|
||||||
|
public delegate void JoypadInputChangedEventHandler(string action, InputEvent input);
|
||||||
|
public delegate void JoypadChangedEventHandler(int deviceIndex, bool isConnected);
|
||||||
|
|
||||||
|
public static DeviceChangedEventHandler? DeviceChanged;
|
||||||
|
public static KeyboardInputChangedEventHandler? KeyboardInputChanged;
|
||||||
|
public static JoypadInputChangedEventHandler? JoypadInputChanged;
|
||||||
|
public static JoypadChangedEventHandler? JoypadChanged;
|
||||||
|
|
||||||
|
|
||||||
|
public const string DEVICE_KEYBOARD = "keyboard";
|
||||||
|
public const string DEVICE_XBOX_CONTROLLER = "xbox";
|
||||||
|
public const string DEVICE_SWITCH_CONTROLLER = "switch";
|
||||||
|
public const string DEVICE_PLAYSTATION_CONTROLLER = "playstation";
|
||||||
|
public const string DEVICE_STEAMDECK_CONTROLLER = "steamdeck";
|
||||||
|
public const string DEVICE_GENERIC = "generic";
|
||||||
|
|
||||||
|
public const string SUB_DEVICE_XBOX_ONE_CONTROLLER = "xbox_one";
|
||||||
|
public const string SUB_DEVICE_XBOX_SERIES_CONTROLLER = "xbox_series";
|
||||||
|
public const string SUB_DEVICE_PLAYSTATION3_CONTROLLER = "playstation3";
|
||||||
|
public const string SUB_DEVICE_PLAYSTATION4_CONTROLLER = "playstation4";
|
||||||
|
public const string SUB_DEVICE_PLAYSTATION5_CONTROLLER = "playstation5";
|
||||||
|
public const string SUB_DEVICE_SWITCH_JOYCON_LEFT_CONTROLLER = "switch_left_joycon";
|
||||||
|
public const string SUB_DEVICE_SWITCH_JOYCON_RIGHT_CONTROLLER = "switch_right_joycon";
|
||||||
|
|
||||||
|
|
||||||
|
private static Node instance;
|
||||||
|
public static Node Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = (Node)Engine.GetSingleton("InputHelper");
|
||||||
|
instance.Connect("device_changed", Callable.From((string device, int deviceIndex) => DeviceChanged?.Invoke(device, deviceIndex)));
|
||||||
|
instance.Connect("keyboard_input_changed", Callable.From((string action, InputEvent input) => KeyboardInputChanged?.Invoke(action, input)));
|
||||||
|
instance.Connect("joypad_input_changed", Callable.From((string action, InputEvent input) => JoypadInputChanged?.Invoke(action, input)));
|
||||||
|
instance.Connect("joypad_changed", Callable.From((int deviceIndex, bool isConnected) => JoypadChanged?.Invoke(deviceIndex, isConnected)));
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string Device
|
||||||
|
{
|
||||||
|
get => (string)Instance.Get("device");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int DeviceIndex
|
||||||
|
{
|
||||||
|
get => (int)Instance.Get("device_index");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string LastKnownJoypadDevice
|
||||||
|
{
|
||||||
|
get => (string)Instance.Get("last_known_joypad_device");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string LastKnownJoypadIndex
|
||||||
|
{
|
||||||
|
get => (string)Instance.Get("last_known_joypad_index");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static float Deadzone
|
||||||
|
{
|
||||||
|
get => (float)Instance.Get("deadzone");
|
||||||
|
set => Instance.Set("deadzone", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int MouseMotionThreshold
|
||||||
|
{
|
||||||
|
get => (int)Instance.Get("mouse_motion_threshold");
|
||||||
|
set => Instance.Set("mouse_motion_threshold", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetSimplifiedDeviceName(string rawName)
|
||||||
|
{
|
||||||
|
return (string)Instance.Call("get_simplified_device_name", rawName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetDeviceFromEvent(InputEvent @event)
|
||||||
|
{
|
||||||
|
return (string)Instance.Call("get_device_from_event", @event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int GetDeviceIndexFromEvent(InputEvent @event)
|
||||||
|
{
|
||||||
|
return (int)Instance.Call("get_device_index_from_event", @event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static bool HasJoypad()
|
||||||
|
{
|
||||||
|
return (bool)Instance.Call("has_joypad");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GuessDeviceName()
|
||||||
|
{
|
||||||
|
return (string)Instance.Call("guess_device_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void ResetAllActions()
|
||||||
|
{
|
||||||
|
Instance.Call("reset_all_actions");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void SetKeyboardOrJoypadInputForAction(string action, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("set_keyboard_or_joypad_input_for_action", action, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static InputEvent GetKeyboardOrJoypadInputForAction(string action, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
return (InputEvent)Instance.Call("get_keyboard_or_joypad_input_for_action", action, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Array<InputEvent> GetKeyboardOrJoypadInputsForAction(string action)
|
||||||
|
{
|
||||||
|
return (Array<InputEvent>)Instance.Call("get_keyboard_or_joypad_inputs_for_action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string GetLabelForInput(InputEvent input)
|
||||||
|
{
|
||||||
|
return (string)Instance.Call("get_label_for_input", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string SerializeInputsForAction(string action)
|
||||||
|
{
|
||||||
|
return (string)Instance.Call("serialize_inputs_for_action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string SerializeInputsForActions(Array<string> actions = null)
|
||||||
|
{
|
||||||
|
if (actions == null)
|
||||||
|
{
|
||||||
|
actions = new Array<string>();
|
||||||
|
}
|
||||||
|
return (string)Instance.Call("serialize_inputs_for_actions", actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void DeserializeInputsForAction(string action, string serializedInputs)
|
||||||
|
{
|
||||||
|
Instance.Call("desserialize_inputs_for_action", action, serializedInputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeserializeInputsForActions(string serializedInputs)
|
||||||
|
{
|
||||||
|
Instance.Call("deserialize_inputs_for_actions", serializedInputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region Keyboard/Mouse
|
||||||
|
|
||||||
|
public static Array<InputEvent> GetKeyboardInputsForAction(string action)
|
||||||
|
{
|
||||||
|
return (Array<InputEvent>)Instance.Call("get_keyboard_inputs_for_action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static InputEvent GetKeyboardInputForAction(string action)
|
||||||
|
{
|
||||||
|
return (InputEvent)Instance.Call("get_keyboard_input_for_action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void SetKeyboardInputForAction(string action, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("set_keyboard_input_for_action", action, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void ReplaceKeyboardInputForAction(string action, InputEvent currentInput, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("replace_keyboard_input_for_action", action, currentInput, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void ReplaceKeyboardInputAtIndex(string action, int index, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("replace_keyboard_input_at_index", action, index, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Joypad
|
||||||
|
|
||||||
|
public static Array<InputEvent> GetJoypadInputsForAction(string action)
|
||||||
|
{
|
||||||
|
return (Array<InputEvent>)Instance.Call("get_joypad_inputs_for_action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static InputEvent GetJoypadInputForAction(string action)
|
||||||
|
{
|
||||||
|
return (InputEvent)Instance.Call("get_joypad_input_for_action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void SetJoypadInputForAction(string action, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("set_joypad_input_for_action", action, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void ReplaceJoypadInputForAction(string action, InputEvent currentInput, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("replace_joypad_input_for_action", action, currentInput, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void ReplaceJoypadInputAtIndex(string action, int index, InputEvent input, bool swapIfTaken = true)
|
||||||
|
{
|
||||||
|
Instance.Call("replace_joypad_input_at_index", action, index, input, swapIfTaken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void RumbleSmall(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("rumble_small", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void RumbleMedium(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("rumble_medium", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void RumbleLarge(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("rumble_large", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void StartRumbleSmall(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("start_rumble_small", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void StartRumbleMedium(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("start_rumble_medium", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void StartRumbleLarge(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("start_rumble_large", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void StopRumble(int targetDevice = 0)
|
||||||
|
{
|
||||||
|
Instance.Call("stop_rumble", targetDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Zennysoft.Game.Ma/addons/input_helper/InputHelper.cs.uid
Normal file
1
Zennysoft.Game.Ma/addons/input_helper/InputHelper.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cfs4dgwrfvb11
|
||||||
21
Zennysoft.Game.Ma/addons/input_helper/LICENSE
Normal file
21
Zennysoft.Game.Ma/addons/input_helper/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022-present Nathan Hoad
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
230
Zennysoft.Game.Ma/addons/input_helper/assets/update.svg
Normal file
230
Zennysoft.Game.Ma/addons/input_helper/assets/update.svg
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="300"
|
||||||
|
height="80"
|
||||||
|
viewBox="0 0 79.374999 21.166667"
|
||||||
|
version="1.1"
|
||||||
|
id="svg291"
|
||||||
|
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
|
||||||
|
sodipodi:docname="update.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview293"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="false"
|
||||||
|
width="1920px"
|
||||||
|
units="px"
|
||||||
|
borderlayer="true"
|
||||||
|
inkscape:showpageshadow="false"
|
||||||
|
inkscape:zoom="4"
|
||||||
|
inkscape:cx="121.625"
|
||||||
|
inkscape:cy="43.25"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="2552"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showguides="true">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-15.575132,19.553027"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide2089"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs288" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g2335"
|
||||||
|
transform="matrix(0.93072355,0,0,0.92874157,17.062816,18.409989)"
|
||||||
|
style="stroke-width:0.85374062;stroke-dasharray:none;stroke:none">
|
||||||
|
<path
|
||||||
|
id="rect2095"
|
||||||
|
style="fill:#349684;fill-opacity:1;stroke:#152f2c;stroke-width:0.56916041;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 24.364404,-16.012976 a 1.7811118,1.7811118 0 0 0 -1.568379,0.938961 1.7811118,1.7811118 0 0 0 -1.557528,-0.918291 1.7811118,1.7811118 0 0 0 -1.383895,0.660942 c -1.816891,-1.243302 -4.115395,-0.49791 -5.162476,1.678967 l -2.844787,5.914368 c -1.050638,2.1842718 -0.431729,4.957652 1.388029,6.2187419 1.819758,1.26108987 4.130958,0.5177068 5.181596,-1.666565 l 1.240234,-2.5786539 h 6.335531 l 1.240234,2.5786539 c 1.050638,2.1842718 3.361322,2.92765487 5.181079,1.666565 1.819758,-1.2610899 2.439184,-4.0344701 1.388546,-6.2187419 L 30.9578,-13.652397 c -1.050637,-2.184271 -3.361838,-2.927654 -5.181596,-1.666565 -1.97e-4,1.37e-4 -3.19e-4,3.8e-4 -5.16e-4,5.17e-4 a 1.7811118,1.7811118 0 0 0 -1.411284,-0.694531 z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="rect2101"
|
||||||
|
width="1.403165"
|
||||||
|
height="4.2796535"
|
||||||
|
x="17.394386"
|
||||||
|
y="-13.427068"
|
||||||
|
ry="0.75541198"
|
||||||
|
rx="0.75380331" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="rect2103"
|
||||||
|
width="1.403165"
|
||||||
|
height="4.2796535"
|
||||||
|
x="-11.988823"
|
||||||
|
y="-20.235798"
|
||||||
|
ry="0.75380331"
|
||||||
|
rx="0.75541198"
|
||||||
|
transform="rotate(90)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse2105"
|
||||||
|
cx="28.192503"
|
||||||
|
cy="2.7587082"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse2107"
|
||||||
|
cx="28.216581"
|
||||||
|
cy="4.7943339"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse2109"
|
||||||
|
cx="30.279696"
|
||||||
|
cy="2.6987464"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse2111"
|
||||||
|
cx="30.320311"
|
||||||
|
cy="4.767447"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85374062;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="rect2117"
|
||||||
|
width="1.109892"
|
||||||
|
height="2.1669323"
|
||||||
|
x="22.090807"
|
||||||
|
y="-10.531444"
|
||||||
|
ry="0.52878839"
|
||||||
|
rx="0.52766228" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="rect1625"
|
||||||
|
style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 50.52517,5.3570989 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606533 0,0.643061 0.590021,1.1611691 1.322916,1.1611691 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611691 0,-0.6430625 -0.590021,-1.1606533 -1.322916,-1.1606533 H 51.685823 V 6.6800155 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" />
|
||||||
|
<path
|
||||||
|
id="path2678"
|
||||||
|
style="fill:#50fa7b;fill-opacity:1;stroke:#0f451d;stroke-width:0.593381;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 57.791691,5.357099 c -0.643062,0 -1.160653,0.5900216 -1.160653,1.3229166 v 1.0764201 h -1.07642 c -0.732895,0 -1.322916,0.5175908 -1.322916,1.1606522 0,0.643062 0.590021,1.1611701 1.322916,1.1611701 h 1.07642 v 1.076421 c 0,0.732895 0.517591,1.322917 1.160653,1.322917 0.643062,0 1.160653,-0.590022 1.160653,-1.322917 v -1.076421 h 1.076937 c 0.732895,0 1.322916,-0.5181081 1.322916,-1.1611701 0,-0.6430614 -0.590021,-1.1606522 -1.322916,-1.1606522 H 58.952344 V 6.6800156 c 0,-0.732895 -0.517591,-1.3229166 -1.160653,-1.3229166 z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke-width:0.72829;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0.3;paint-order:markers stroke fill"
|
||||||
|
id="rect413"
|
||||||
|
width="10.200269"
|
||||||
|
height="8.7847834"
|
||||||
|
x="-21.316095"
|
||||||
|
y="3.0372066" />
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke-width:0.622475;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0.3;paint-order:markers stroke fill"
|
||||||
|
id="rect415"
|
||||||
|
width="7.9928446"
|
||||||
|
height="15.312933"
|
||||||
|
x="-20.546837"
|
||||||
|
y="12.977094"
|
||||||
|
ry="4.375123"
|
||||||
|
transform="matrix(0.82192626,0.56959391,-0.43346431,0.90117073,0,0)"
|
||||||
|
rx="4.375123" />
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke-width:0.622475;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0.3;paint-order:markers stroke fill"
|
||||||
|
id="rect471"
|
||||||
|
width="7.9928446"
|
||||||
|
height="15.312933"
|
||||||
|
x="9.1578636"
|
||||||
|
y="-5.7980561"
|
||||||
|
ry="4.375123"
|
||||||
|
transform="matrix(-0.82192626,0.56959391,0.43346431,0.90117073,0,0)"
|
||||||
|
rx="4.375123" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="rect1137"
|
||||||
|
width="1.403165"
|
||||||
|
height="4.2796535"
|
||||||
|
x="-22.240166"
|
||||||
|
y="3.9990206"
|
||||||
|
ry="0.70158249"
|
||||||
|
rx="0.70158249" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="rect1295"
|
||||||
|
width="1.403165"
|
||||||
|
height="4.2796535"
|
||||||
|
x="5.4372649"
|
||||||
|
y="19.398754"
|
||||||
|
ry="0.70158249"
|
||||||
|
rx="0.70158249"
|
||||||
|
transform="rotate(90)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse1297"
|
||||||
|
cx="-13.849753"
|
||||||
|
cy="-1.3102485"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse1299"
|
||||||
|
cx="-13.825675"
|
||||||
|
cy="0.72537726"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse1301"
|
||||||
|
cx="-11.762562"
|
||||||
|
cy="-1.3702103"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="ellipse1303"
|
||||||
|
cx="-11.721946"
|
||||||
|
cy="0.69849032"
|
||||||
|
rx="0.82257289"
|
||||||
|
ry="0.79261416"
|
||||||
|
transform="rotate(-30)" />
|
||||||
|
<circle
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="path2085"
|
||||||
|
cx="-17.863199"
|
||||||
|
cy="3.3752983"
|
||||||
|
r="1.7811118" />
|
||||||
|
<circle
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="circle2087"
|
||||||
|
cx="-14.737003"
|
||||||
|
cy="3.3542202"
|
||||||
|
r="1.7811118" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.32292;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0.3;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
id="rect2091"
|
||||||
|
width="0.98221546"
|
||||||
|
height="1.917659"
|
||||||
|
x="-16.946886"
|
||||||
|
y="7.1795278"
|
||||||
|
ry="0.49110773"
|
||||||
|
rx="0.49110773" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://ddixs2ish5bi6"
|
||||||
|
path="res://.godot/imported/update.svg-3137f1f7d53c08c0ae65aabe138d898b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/input_helper/assets/update.svg"
|
||||||
|
dest_files=["res://.godot/imported/update.svg-3137f1f7d53c08c0ae65aabe138d898b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
@tool
|
||||||
|
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
|
||||||
|
signal failed()
|
||||||
|
signal updated(updated_to_version: String)
|
||||||
|
|
||||||
|
|
||||||
|
const TEMP_FILE_NAME = "user://temp.zip"
|
||||||
|
|
||||||
|
|
||||||
|
@onready var logo: TextureRect = %Logo
|
||||||
|
@onready var label: Label = $VBox/Label
|
||||||
|
@onready var http_request: HTTPRequest = $HTTPRequest
|
||||||
|
@onready var download_button: Button = %DownloadButton
|
||||||
|
|
||||||
|
var next_version: String = "":
|
||||||
|
set(next_next_version):
|
||||||
|
next_version = next_next_version
|
||||||
|
label.text = "Version %s is available for download!" % next_version
|
||||||
|
get:
|
||||||
|
return next_version
|
||||||
|
|
||||||
|
|
||||||
|
func save_zip(bytes: PackedByteArray) -> void:
|
||||||
|
var file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
|
||||||
|
file.store_buffer(bytes)
|
||||||
|
file.flush()
|
||||||
|
|
||||||
|
|
||||||
|
### Signals
|
||||||
|
|
||||||
|
|
||||||
|
func _on_download_button_pressed() -> void:
|
||||||
|
# Safeguard the actual input helper repo from accidentally updating itself
|
||||||
|
if FileAccess.file_exists("res://examples/device_tester.gd"):
|
||||||
|
prints("You can't update the input helper from within itself.")
|
||||||
|
failed.emit()
|
||||||
|
return
|
||||||
|
|
||||||
|
http_request.request("https://github.com/nathanhoad/godot_input_helper/archive/refs/tags/v%s.zip" % next_version)
|
||||||
|
download_button.disabled = true
|
||||||
|
download_button.text = "Downloading..."
|
||||||
|
|
||||||
|
|
||||||
|
func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
|
||||||
|
if result != HTTPRequest.RESULT_SUCCESS:
|
||||||
|
failed.emit()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Save the downloaded zip
|
||||||
|
save_zip(body)
|
||||||
|
|
||||||
|
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/input_helper"))
|
||||||
|
|
||||||
|
var zip_reader: ZIPReader = ZIPReader.new()
|
||||||
|
zip_reader.open(TEMP_FILE_NAME)
|
||||||
|
var files: PackedStringArray = zip_reader.get_files()
|
||||||
|
|
||||||
|
var base_path = files[1]
|
||||||
|
# Remove archive folder
|
||||||
|
files.remove_at(0)
|
||||||
|
# Remove assets folder
|
||||||
|
files.remove_at(0)
|
||||||
|
|
||||||
|
for path in files:
|
||||||
|
var new_file_path: String = path.replace(base_path, "")
|
||||||
|
if path.ends_with("/"):
|
||||||
|
DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path)
|
||||||
|
else:
|
||||||
|
var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE)
|
||||||
|
file.store_buffer(zip_reader.read_file(path))
|
||||||
|
|
||||||
|
zip_reader.close()
|
||||||
|
|
||||||
|
DirAccess.remove_absolute(TEMP_FILE_NAME)
|
||||||
|
|
||||||
|
updated.emit(next_version)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_notes_button_pressed() -> void:
|
||||||
|
OS.shell_open("https://github.com/nathanhoad/godot_input_helper/releases/tag/v%s" % next_version)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dcff0mowkn6km
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://b7mst0qu7vjk1"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dcff0mowkn6km" path="res://addons/input_helper/components/download_update_panel.gd" id="1_4tm1k"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://ddixs2ish5bi6" path="res://addons/input_helper/assets/update.svg" id="2_j7shv"]
|
||||||
|
|
||||||
|
[node name="DownloadUpdatePanel" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_4tm1k")
|
||||||
|
|
||||||
|
[node name="HTTPRequest" type="HTTPRequest" parent="."]
|
||||||
|
|
||||||
|
[node name="VBox" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -1.0
|
||||||
|
offset_top = 9.0
|
||||||
|
offset_right = -1.0
|
||||||
|
offset_bottom = 9.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
|
[node name="Logo" type="TextureRect" parent="VBox"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
clip_contents = true
|
||||||
|
custom_minimum_size = Vector2(300, 80)
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("2_j7shv")
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "v1.2.3 is available for download."
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="Center" type="CenterContainer" parent="VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="DownloadButton" type="Button" parent="VBox/Center"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Download and install update"
|
||||||
|
|
||||||
|
[node name="Center2" type="CenterContainer" parent="VBox"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="NotesButton" type="LinkButton" parent="VBox/Center2"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Read release notes..."
|
||||||
|
|
||||||
|
[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"]
|
||||||
|
[connection signal="pressed" from="VBox/Center/DownloadButton" to="." method="_on_download_button_pressed"]
|
||||||
|
[connection signal="pressed" from="VBox/Center2/NotesButton" to="." method="_on_notes_button_pressed"]
|
||||||
601
Zennysoft.Game.Ma/addons/input_helper/input_helper.gd
Normal file
601
Zennysoft.Game.Ma/addons/input_helper/input_helper.gd
Normal file
@@ -0,0 +1,601 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
|
||||||
|
signal device_changed(device: String, device_index: int)
|
||||||
|
signal keyboard_input_changed(action: String, input: InputEvent)
|
||||||
|
signal joypad_input_changed(action: String, input: InputEvent)
|
||||||
|
signal joypad_changed(device_index: int, is_connected: bool)
|
||||||
|
|
||||||
|
|
||||||
|
const DEVICE_KEYBOARD = "keyboard"
|
||||||
|
const DEVICE_XBOX_CONTROLLER = "xbox"
|
||||||
|
const DEVICE_SWITCH_CONTROLLER = "switch"
|
||||||
|
const DEVICE_PLAYSTATION_CONTROLLER = "playstation"
|
||||||
|
const DEVICE_STEAMDECK_CONTROLLER = "steamdeck"
|
||||||
|
const DEVICE_GENERIC = "generic"
|
||||||
|
|
||||||
|
const SUB_DEVICE_XBOX_ONE_CONTROLLER = "xbox_one"
|
||||||
|
const SUB_DEVICE_XBOX_SERIES_CONTROLLER = "xbox_series"
|
||||||
|
|
||||||
|
const SUB_DEVICE_PLAYSTATION3_CONTROLLER = "playstation3"
|
||||||
|
const SUB_DEVICE_PLAYSTATION4_CONTROLLER = "playstation4"
|
||||||
|
const SUB_DEVICE_PLAYSTATION5_CONTROLLER = "playstation5"
|
||||||
|
|
||||||
|
const SUB_DEVICE_SWITCH_JOYCON_LEFT_CONTROLLER = "switch_left_joycon"
|
||||||
|
const SUB_DEVICE_SWITCH_JOYCON_RIGHT_CONTROLLER = "switch_right_joycon"
|
||||||
|
|
||||||
|
const XBOX_BUTTON_LABELS = ["A", "B", "X", "Y", "Back", "Guide", "Start", "Left Stick", "Right Stick", "LB", "RB", "Up", "Down", "Left", "Right", "Share", "Paddle 1", "Paddle 2", "Paddle 3", "Paddle 4"]
|
||||||
|
const XBOX_ONE_BUTTON_LABELS = ["A", "B", "X", "Y", "View", "Guide", "Menu", "Left Stick", "Right Stick", "LB", "RB", "Up", "Down", "Left", "Right", "Share", "Paddle 1", "Paddle 2", "Paddle 3", "Paddle 4"]
|
||||||
|
const XBOX_SERIES_BUTTON_LABELS = ["A", "B", "X", "Y", "View", "Guide", "Menu", "Left Stick", "Right Stick", "LB", "RB", "Up", "Down", "Left", "Right", "Share", "Paddle 1", "Paddle 2", "Paddle 3", "Paddle 4"]
|
||||||
|
const STEAMDECK_BUTTON_LABELS = ["A", "B", "X", "Y", "View", "?", "Options", "Left Stick", "Right Stick", "L1", "R1", "Up", "Down", "Left", "Right", "", "", "", "", ""]
|
||||||
|
# Note: share and home buttons are not recognized
|
||||||
|
const SWITCH_BUTTON_LABELS = ["B", "A", "Y", "X", "Minus", "", "Plus", "Left Stick", "Right Stick", "LS", "RS", "Up", "Down", "Left", "Right", "Capture"]
|
||||||
|
# Mapping for left and right joypad connected together (extended gamepad)
|
||||||
|
# Left Stick is Axis 0 and 1
|
||||||
|
# Right Stick is Axis 2 and 3
|
||||||
|
# ZL and ZR are Axis 4 and 5
|
||||||
|
const SWITCH_EXTENDED_GAMEPAD_BUTTON_LABELS = ["B", "A", "Y", "X", "Minus", "", "Plus", "Left Stick", "Right Stick", "L", "R", "Up", "Down", "Left", "Right", "Capture"]
|
||||||
|
const PLAYSTATION_3_4_BUTTON_LABELS = ["Cross", "Circle", "Square", "Triangle", "Share", "PS", "Options", "L3", "R3", "L1", "R1", "Up", "Down", "Left", "Right", "Microphone", "", "", "", "", "Touchpad"]
|
||||||
|
# Note: Microphone does not work on PC / touchpad is not recognized
|
||||||
|
const PLAYSTATION_5_BUTTON_LABELS = ["Cross", "Circle", "Square", "Triangle", "Create", "PS", "Options", "L3", "R3", "L1", "R1", "Up", "Down", "Left", "Right", "Microphone", "", "", "", "", "Touchpad"]
|
||||||
|
|
||||||
|
const SERIAL_VERSION = 1
|
||||||
|
|
||||||
|
## The deadzone to ignore for joypad motion
|
||||||
|
var deadzone: float = 0.5
|
||||||
|
## The mouse distance to ignore before movement is assumed
|
||||||
|
var mouse_motion_threshold: int = 100
|
||||||
|
## The last known joypad device name (or "" if no joypad detected)
|
||||||
|
var last_known_joypad_device: String = get_simplified_device_name(Input.get_joy_name(0))
|
||||||
|
## The last known joypad index
|
||||||
|
var last_known_joypad_index: int = 0 if Input.get_connected_joypads().size() > 0 else -1
|
||||||
|
|
||||||
|
## Used internally
|
||||||
|
var device_last_changed_at: int = 0
|
||||||
|
var _last_known_granular_joypad_device: String = get_simplified_device_name(Input.get_joy_name(0), true)
|
||||||
|
|
||||||
|
@onready var device: String = guess_device_name()
|
||||||
|
@onready var device_index: int = 0 if has_joypad() else -1
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||||
|
|
||||||
|
if not Engine.has_singleton("InputHelper"):
|
||||||
|
Engine.register_singleton("InputHelper", self)
|
||||||
|
|
||||||
|
Input.joy_connection_changed.connect(func(device_index, is_connected): joypad_changed.emit(device_index, is_connected))
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event: InputEvent) -> void:
|
||||||
|
var next_device: String = device
|
||||||
|
var next_device_index: int = device_index
|
||||||
|
|
||||||
|
# Did we just press a key on the keyboard or move the mouse?
|
||||||
|
if event is InputEventKey \
|
||||||
|
or event is InputEventMouseButton \
|
||||||
|
or (event is InputEventMouseMotion and (event as InputEventMouseMotion).relative.length_squared() > mouse_motion_threshold):
|
||||||
|
next_device = DEVICE_KEYBOARD
|
||||||
|
next_device_index = -1
|
||||||
|
|
||||||
|
# Did we just use a joypad?
|
||||||
|
elif event is InputEventJoypadButton \
|
||||||
|
or (event is InputEventJoypadMotion and abs(event.axis_value) > deadzone):
|
||||||
|
next_device = get_simplified_device_name(get_joy_name(event.device))
|
||||||
|
last_known_joypad_device = next_device
|
||||||
|
next_device_index = event.device
|
||||||
|
last_known_joypad_index = next_device_index
|
||||||
|
|
||||||
|
_last_known_granular_joypad_device = get_simplified_device_name(get_joy_name(event.device), true)
|
||||||
|
|
||||||
|
# Debounce changes for 1 second because some joypads register twice in Windows for some reason
|
||||||
|
var not_changed_in_last_second = Engine.get_frames_drawn() - device_last_changed_at > Engine.get_frames_per_second()
|
||||||
|
if (next_device != device or next_device_index != device_index) and not_changed_in_last_second:
|
||||||
|
device_last_changed_at = Engine.get_frames_drawn()
|
||||||
|
|
||||||
|
device = next_device
|
||||||
|
device_index = next_device_index
|
||||||
|
device_changed.emit(device, device_index)
|
||||||
|
|
||||||
|
|
||||||
|
## Get the name of a joypad
|
||||||
|
func get_joy_name(at_device_index: int) -> String:
|
||||||
|
var joy_name: String = Input.get_joy_name(at_device_index)
|
||||||
|
if joy_name == "" and Input.get_joy_info(at_device_index).size() > 0 and "xinput" in Input.get_joy_info(at_device_index).keys()[0]:
|
||||||
|
joy_name = "XInput"
|
||||||
|
return joy_name
|
||||||
|
|
||||||
|
|
||||||
|
## Get the device name for an event
|
||||||
|
func get_device_from_event(event: InputEvent) -> String:
|
||||||
|
if event is InputEventKey or event is InputEventMouseButton or event is InputEventMouseMotion:
|
||||||
|
return DEVICE_KEYBOARD
|
||||||
|
elif event is InputEventJoypadButton or event is InputEventJoypadMotion:
|
||||||
|
return get_simplified_device_name(get_joy_name(event.device))
|
||||||
|
else:
|
||||||
|
return DEVICE_GENERIC
|
||||||
|
|
||||||
|
|
||||||
|
## Get the device name for an event
|
||||||
|
func get_device_index_from_event(event: InputEvent) -> int:
|
||||||
|
if event is InputEventJoypadButton or event is InputEventJoypadMotion:
|
||||||
|
return event.device
|
||||||
|
else:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
## Convert a Godot device identifier to a simplified string
|
||||||
|
func get_simplified_device_name(raw_name: String, force_granular_identifier: bool = false) -> String:
|
||||||
|
var use_granular_identifier: bool = force_granular_identifier or InputHelperSettings.get_setting(InputHelperSettings.USE_GRANULAR_DEVICE_IDENTIFIERS, false)
|
||||||
|
|
||||||
|
var keywords: Dictionary = {
|
||||||
|
SUB_DEVICE_XBOX_ONE_CONTROLLER: ["Xbox One Controller"],
|
||||||
|
SUB_DEVICE_XBOX_SERIES_CONTROLLER: ["Xbox Series Controller", "Xbox Wireless Controller"],
|
||||||
|
DEVICE_XBOX_CONTROLLER: ["XInput", "XBox"],
|
||||||
|
SUB_DEVICE_PLAYSTATION3_CONTROLLER: ["PS3"],
|
||||||
|
SUB_DEVICE_PLAYSTATION4_CONTROLLER:["Nacon Revolution Unlimited Pro Controller", "PS4", "DUALSHOCK 4"],
|
||||||
|
SUB_DEVICE_PLAYSTATION5_CONTROLLER:["Sony DualSense", "PS5", "DualSense Wireless Controller"],
|
||||||
|
DEVICE_STEAMDECK_CONTROLLER: ["Steam"],
|
||||||
|
DEVICE_SWITCH_CONTROLLER: ["Switch", "Joy-Con (L/R)", "PowerA Core Controller"],
|
||||||
|
SUB_DEVICE_SWITCH_JOYCON_LEFT_CONTROLLER: ["Joy-Con (L)"],
|
||||||
|
SUB_DEVICE_SWITCH_JOYCON_RIGHT_CONTROLLER: ["joy-Con (R)"],
|
||||||
|
} if use_granular_identifier else {
|
||||||
|
DEVICE_XBOX_CONTROLLER: ["XBox", "XInput"],
|
||||||
|
DEVICE_PLAYSTATION_CONTROLLER: ["Sony", "PS3", "PS5", "PS4", "DUALSHOCK 4", "DualSense", "Nacon Revolution Unlimited Pro Controller"],
|
||||||
|
DEVICE_STEAMDECK_CONTROLLER: ["Steam"],
|
||||||
|
DEVICE_SWITCH_CONTROLLER: ["Switch", "Joy-Con", "PowerA Core Controller"],
|
||||||
|
}
|
||||||
|
|
||||||
|
for device_key in keywords:
|
||||||
|
for keyword in keywords[device_key]:
|
||||||
|
if keyword.to_lower() in raw_name.to_lower():
|
||||||
|
return device_key
|
||||||
|
|
||||||
|
return DEVICE_GENERIC
|
||||||
|
|
||||||
|
|
||||||
|
## Check if there is a connected joypad
|
||||||
|
func has_joypad() -> bool:
|
||||||
|
return Input.get_connected_joypads().size() > 0
|
||||||
|
|
||||||
|
|
||||||
|
## Guess the initial input device
|
||||||
|
func guess_device_name() -> String:
|
||||||
|
if has_joypad():
|
||||||
|
return get_simplified_device_name(get_joy_name(0))
|
||||||
|
else:
|
||||||
|
return DEVICE_KEYBOARD
|
||||||
|
|
||||||
|
|
||||||
|
#region Mapping
|
||||||
|
|
||||||
|
|
||||||
|
func reset_all_actions() -> void:
|
||||||
|
InputMap.load_from_project_settings()
|
||||||
|
for action in InputMap.get_actions():
|
||||||
|
var input: InputEvent = get_joypad_input_for_action(action)
|
||||||
|
if input != null:
|
||||||
|
joypad_input_changed.emit(action, input)
|
||||||
|
|
||||||
|
input = get_keyboard_input_for_action(action)
|
||||||
|
if input != null:
|
||||||
|
keyboard_input_changed.emit(action, input)
|
||||||
|
|
||||||
|
|
||||||
|
## Set the key or button for an action
|
||||||
|
func set_keyboard_or_joypad_input_for_action(action: String, event: InputEvent, swap_if_taken: bool = true) -> void:
|
||||||
|
if event is InputEventKey or event is InputEventMouse:
|
||||||
|
set_keyboard_input_for_action(action, event, swap_if_taken)
|
||||||
|
elif event is InputEventJoypadButton:
|
||||||
|
set_joypad_input_for_action(action, event, swap_if_taken)
|
||||||
|
|
||||||
|
|
||||||
|
## Get the key or button for a given action depending on the current device
|
||||||
|
func get_keyboard_or_joypad_input_for_action(action: String) -> InputEvent:
|
||||||
|
if device == DEVICE_KEYBOARD:
|
||||||
|
return get_keyboard_input_for_action(action)
|
||||||
|
else:
|
||||||
|
return get_joypad_input_for_action(action)
|
||||||
|
|
||||||
|
|
||||||
|
## Get the key or button for a given action depending on the current device
|
||||||
|
func get_keyboard_or_joypad_inputs_for_action(action: String) -> Array[InputEvent]:
|
||||||
|
if device == DEVICE_KEYBOARD:
|
||||||
|
return get_keyboard_inputs_for_action(action)
|
||||||
|
else:
|
||||||
|
return get_joypad_inputs_for_action(action)
|
||||||
|
|
||||||
|
|
||||||
|
## Get a text label for a given input
|
||||||
|
func get_label_for_input(input: InputEvent) -> String:
|
||||||
|
if input == null: return ""
|
||||||
|
|
||||||
|
if input is InputEventKey:
|
||||||
|
if input.physical_keycode > 0 :
|
||||||
|
var keycode: Key = DisplayServer.keyboard_get_keycode_from_physical(input.physical_keycode) if DisplayServer.keyboard_get_current_layout() > -1 else input.physical_keycode
|
||||||
|
return OS.get_keycode_string(keycode)
|
||||||
|
elif input.keycode > 0:
|
||||||
|
return OS.get_keycode_string(input.keycode)
|
||||||
|
else:
|
||||||
|
return input.as_text()
|
||||||
|
|
||||||
|
elif input is InputEventMouseButton:
|
||||||
|
match input.button_index:
|
||||||
|
MOUSE_BUTTON_LEFT:
|
||||||
|
return "Mouse Left Button"
|
||||||
|
MOUSE_BUTTON_MIDDLE:
|
||||||
|
return "Mouse Middle Button"
|
||||||
|
MOUSE_BUTTON_RIGHT:
|
||||||
|
return "Mouse Right Button"
|
||||||
|
return "Mouse Button %d" % input.button_index
|
||||||
|
|
||||||
|
elif input is InputEventJoypadButton:
|
||||||
|
var labels = []
|
||||||
|
match _last_known_granular_joypad_device:
|
||||||
|
DEVICE_XBOX_CONTROLLER, DEVICE_GENERIC:
|
||||||
|
labels = XBOX_BUTTON_LABELS
|
||||||
|
SUB_DEVICE_XBOX_ONE_CONTROLLER:
|
||||||
|
labels = XBOX_ONE_BUTTON_LABELS
|
||||||
|
SUB_DEVICE_XBOX_SERIES_CONTROLLER:
|
||||||
|
labels = XBOX_SERIES_BUTTON_LABELS
|
||||||
|
SUB_DEVICE_SWITCH_JOYCON_LEFT_CONTROLLER, SUB_DEVICE_SWITCH_JOYCON_RIGHT_CONTROLLER:
|
||||||
|
labels = SWITCH_BUTTON_LABELS
|
||||||
|
DEVICE_SWITCH_CONTROLLER:
|
||||||
|
labels = SWITCH_EXTENDED_GAMEPAD_BUTTON_LABELS
|
||||||
|
SUB_DEVICE_PLAYSTATION3_CONTROLLER, SUB_DEVICE_PLAYSTATION4_CONTROLLER:
|
||||||
|
labels = PLAYSTATION_3_4_BUTTON_LABELS
|
||||||
|
DEVICE_PLAYSTATION_CONTROLLER, SUB_DEVICE_PLAYSTATION5_CONTROLLER:
|
||||||
|
labels = PLAYSTATION_5_BUTTON_LABELS
|
||||||
|
DEVICE_STEAMDECK_CONTROLLER:
|
||||||
|
labels = STEAMDECK_BUTTON_LABELS
|
||||||
|
if input.button_index < labels.size():
|
||||||
|
return "%s Button" % labels[input.button_index]
|
||||||
|
else:
|
||||||
|
return "Button %d" % input.button_index
|
||||||
|
|
||||||
|
elif input is InputEventJoypadMotion:
|
||||||
|
var motion: InputEventJoypadMotion = input as InputEventJoypadMotion
|
||||||
|
match motion.axis:
|
||||||
|
JOY_AXIS_LEFT_X:
|
||||||
|
return "Left Stick %s" % ("Left" if motion.axis_value < 0 else "Right")
|
||||||
|
JOY_AXIS_LEFT_Y:
|
||||||
|
return "Left Stick %s" % ("Up" if motion.axis_value < 0 else "Down")
|
||||||
|
JOY_AXIS_RIGHT_X:
|
||||||
|
return "Right Stick %s" % ("Left" if motion.axis_value < 0 else "Right")
|
||||||
|
JOY_AXIS_RIGHT_Y:
|
||||||
|
return "Right Stick %s" % ("Up" if motion.axis_value < 0 else "Down")
|
||||||
|
JOY_AXIS_TRIGGER_LEFT:
|
||||||
|
return "Left Trigger"
|
||||||
|
JOY_AXIS_TRIGGER_RIGHT:
|
||||||
|
return "Right Trigger"
|
||||||
|
|
||||||
|
return input.as_text()
|
||||||
|
|
||||||
|
|
||||||
|
## Serialize a single action's inputs.
|
||||||
|
func serialize_inputs_for_action(action: StringName) -> String:
|
||||||
|
var action_inputs: PackedStringArray = []
|
||||||
|
var inputs: Array[InputEvent] = InputMap.action_get_events(action)
|
||||||
|
for input in inputs:
|
||||||
|
if input is InputEventKey:
|
||||||
|
var s: String = get_label_for_input(input)
|
||||||
|
var modifiers: Array[String] = []
|
||||||
|
if input.alt_pressed:
|
||||||
|
modifiers.append("alt")
|
||||||
|
if input.shift_pressed:
|
||||||
|
modifiers.append("shift")
|
||||||
|
if input.ctrl_pressed:
|
||||||
|
modifiers.append("ctrl")
|
||||||
|
if input.meta_pressed:
|
||||||
|
modifiers.append("meta")
|
||||||
|
if not modifiers.is_empty():
|
||||||
|
s += "|" + ",".join(modifiers)
|
||||||
|
action_inputs.append("key:%s" % s)
|
||||||
|
elif input is InputEventMouseButton:
|
||||||
|
action_inputs.append("mouse:%d" % input.button_index)
|
||||||
|
elif input is InputEventJoypadButton:
|
||||||
|
action_inputs.append("joypad:%d" % input.button_index)
|
||||||
|
elif input is InputEventJoypadMotion:
|
||||||
|
action_inputs.append("joypad:%d|%f" % [input.axis, input.axis_value])
|
||||||
|
|
||||||
|
return ";".join(action_inputs)
|
||||||
|
|
||||||
|
|
||||||
|
## Serialize a list of action inputs to string. If actions is empty then it will serialize
|
||||||
|
## all actions.
|
||||||
|
func serialize_inputs_for_actions(actions: PackedStringArray = []) -> String:
|
||||||
|
if actions == null or actions.is_empty():
|
||||||
|
actions = InputMap.get_actions()
|
||||||
|
|
||||||
|
var map: Dictionary = {}
|
||||||
|
for action in actions:
|
||||||
|
map[action] = serialize_inputs_for_action(action)
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
version = SERIAL_VERSION,
|
||||||
|
map = map
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
## Deserialize a single action's inputs.
|
||||||
|
func deserialize_inputs_for_action(action: String, string: String) -> void:
|
||||||
|
InputMap.action_erase_events(action)
|
||||||
|
var action_inputs: PackedStringArray = string.split(";")
|
||||||
|
for action_input in action_inputs:
|
||||||
|
var bits: PackedStringArray = action_input.split(":")
|
||||||
|
|
||||||
|
# Ignore any empty actions
|
||||||
|
if bits.size() < 2: continue
|
||||||
|
|
||||||
|
var input_type: String = bits[0]
|
||||||
|
var input_details: String = bits[1]
|
||||||
|
|
||||||
|
match input_type:
|
||||||
|
"key":
|
||||||
|
var keyboard_input = InputEventKey.new()
|
||||||
|
if "|" in input_details:
|
||||||
|
var detail_bits = input_details.split("|")
|
||||||
|
keyboard_input.keycode = OS.find_keycode_from_string(detail_bits[0])
|
||||||
|
detail_bits = detail_bits[1].split(",")
|
||||||
|
if detail_bits.has("alt"):
|
||||||
|
keyboard_input.alt_pressed = true
|
||||||
|
if detail_bits.has("shift"):
|
||||||
|
keyboard_input.shift_pressed = true
|
||||||
|
if detail_bits.has("ctrl"):
|
||||||
|
keyboard_input.ctrl_pressed = true
|
||||||
|
if detail_bits.has("meta"):
|
||||||
|
keyboard_input.meta_pressed = true
|
||||||
|
else:
|
||||||
|
keyboard_input.keycode = OS.find_keycode_from_string(input_details)
|
||||||
|
InputMap.action_add_event(action, keyboard_input)
|
||||||
|
keyboard_input_changed.emit(action, keyboard_input)
|
||||||
|
|
||||||
|
"mouse":
|
||||||
|
var mouse_input = InputEventMouseButton.new()
|
||||||
|
mouse_input.button_index = int(input_details)
|
||||||
|
InputMap.action_add_event(action, mouse_input)
|
||||||
|
keyboard_input_changed.emit(action, mouse_input)
|
||||||
|
|
||||||
|
"joypad":
|
||||||
|
if "|" in str(input_details):
|
||||||
|
var joypad_motion_input = InputEventJoypadMotion.new()
|
||||||
|
var joypad_bits = input_details.split("|")
|
||||||
|
joypad_motion_input.axis = int(joypad_bits[0])
|
||||||
|
joypad_motion_input.axis_value = float(joypad_bits[1])
|
||||||
|
InputMap.action_add_event(action, joypad_motion_input)
|
||||||
|
joypad_input_changed.emit(action, joypad_motion_input)
|
||||||
|
else:
|
||||||
|
var joypad_input = InputEventJoypadButton.new()
|
||||||
|
joypad_input.button_index = int(input_details)
|
||||||
|
InputMap.action_add_event(action, joypad_input)
|
||||||
|
joypad_input_changed.emit(action, joypad_input)
|
||||||
|
|
||||||
|
|
||||||
|
## Deserialise a list of actions' inputs.
|
||||||
|
func deserialize_inputs_for_actions(string: String) -> void:
|
||||||
|
var data: Dictionary = JSON.parse_string(string)
|
||||||
|
|
||||||
|
# Use legacy deserialization
|
||||||
|
if not data.has("version"):
|
||||||
|
_deprecated_deserialize_inputs_for_actions(string)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Version 1
|
||||||
|
for action in data.map.keys():
|
||||||
|
deserialize_inputs_for_action(action, data.map[action])
|
||||||
|
|
||||||
|
|
||||||
|
# Load inputs from a serialized string. [deprecated]
|
||||||
|
func _deprecated_deserialize_inputs_for_actions(string: String) -> void:
|
||||||
|
var map: Dictionary = JSON.parse_string(string)
|
||||||
|
for action in map.keys():
|
||||||
|
InputMap.action_erase_events(action)
|
||||||
|
|
||||||
|
for key in map[action]["keyboard"]:
|
||||||
|
var keyboard_input = InputEventKey.new()
|
||||||
|
if "|" in key:
|
||||||
|
var bits = key.split("|")
|
||||||
|
keyboard_input.keycode = OS.find_keycode_from_string(bits[0])
|
||||||
|
bits = bits[1].split(",")
|
||||||
|
if bits.has("alt"):
|
||||||
|
keyboard_input.alt_pressed = true
|
||||||
|
if bits.has("shift"):
|
||||||
|
keyboard_input.shift_pressed = true
|
||||||
|
if bits.has("ctrl"):
|
||||||
|
keyboard_input.ctrl_pressed = true
|
||||||
|
if bits.has("meta"):
|
||||||
|
keyboard_input.meta_pressed = true
|
||||||
|
else:
|
||||||
|
keyboard_input.keycode = OS.find_keycode_from_string(key)
|
||||||
|
InputMap.action_add_event(action, keyboard_input)
|
||||||
|
|
||||||
|
for button_index in map[action]["mouse"]:
|
||||||
|
var mouse_input = InputEventMouseButton.new()
|
||||||
|
mouse_input.button_index = int(button_index)
|
||||||
|
InputMap.action_add_event(action, mouse_input)
|
||||||
|
|
||||||
|
for button_index_or_motion in map[action]["joypad"]:
|
||||||
|
if "|" in str(button_index_or_motion):
|
||||||
|
var joypad_motion_input = InputEventJoypadMotion.new()
|
||||||
|
var bits = button_index_or_motion.split("|")
|
||||||
|
joypad_motion_input.axis = int(bits[0])
|
||||||
|
joypad_motion_input.axis_value = float(bits[1])
|
||||||
|
InputMap.action_add_event(action, joypad_motion_input)
|
||||||
|
else:
|
||||||
|
var joypad_input = InputEventJoypadButton.new()
|
||||||
|
joypad_input.button_index = int(button_index_or_motion)
|
||||||
|
InputMap.action_add_event(action, joypad_input)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Keyboard/mouse input
|
||||||
|
|
||||||
|
|
||||||
|
## Get all of the keys/mouse buttons used for an action.
|
||||||
|
func get_keyboard_inputs_for_action(action: String) -> Array[InputEvent]:
|
||||||
|
return InputMap.action_get_events(action).filter(func(event):
|
||||||
|
return event is InputEventKey or event is InputEventMouseButton
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
## Get the first key for an action
|
||||||
|
func get_keyboard_input_for_action(action: String) -> InputEvent:
|
||||||
|
var inputs: Array[InputEvent] = get_keyboard_inputs_for_action(action)
|
||||||
|
return null if inputs.is_empty() else inputs[0]
|
||||||
|
|
||||||
|
|
||||||
|
## Set the key used for an action
|
||||||
|
func set_keyboard_input_for_action(action: String, input: InputEvent, swap_if_taken: bool = true) -> Error:
|
||||||
|
return _update_keyboard_input_for_action(action, input, swap_if_taken, null)
|
||||||
|
|
||||||
|
|
||||||
|
## Replace a specific key with another key
|
||||||
|
func replace_keyboard_input_for_action(action: String, current_input: InputEvent, input: InputEvent, swap_if_taken: bool = true) -> Error:
|
||||||
|
return _update_keyboard_input_for_action(action, input, swap_if_taken, current_input)
|
||||||
|
|
||||||
|
|
||||||
|
## Replace a specific key, given its index
|
||||||
|
func replace_keyboard_input_at_index(action: String, index: int, input: InputEvent, swap_if_taken: bool = true) -> Error:
|
||||||
|
var inputs: Array[InputEvent] = get_keyboard_inputs_for_action(action)
|
||||||
|
var replacing_input = InputEventKey.new() if (inputs.is_empty() or inputs.size() <= index) else inputs[index]
|
||||||
|
return _update_keyboard_input_for_action(action, input, swap_if_taken, replacing_input)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_keyboard_input_for_action(action: String, input: InputEvent, swap_if_taken: bool, replacing_input: InputEvent = null) -> Error:
|
||||||
|
if not (input is InputEventKey or input is InputEventMouseButton): return ERR_INVALID_DATA
|
||||||
|
|
||||||
|
var is_valid_keyboard_event = func(event):
|
||||||
|
return event is InputEventKey or event is InputEventMouseButton
|
||||||
|
|
||||||
|
return _update_input_for_action(action, input, swap_if_taken, replacing_input, is_valid_keyboard_event, keyboard_input_changed)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Joypad input
|
||||||
|
|
||||||
|
|
||||||
|
## Get all buttons used for an action
|
||||||
|
func get_joypad_inputs_for_action(action: String) -> Array[InputEvent]:
|
||||||
|
return InputMap.action_get_events(action).filter(func(event):
|
||||||
|
return event is InputEventJoypadButton or event is InputEventJoypadMotion
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
## Get the first button for an action
|
||||||
|
func get_joypad_input_for_action(action: String) -> InputEvent:
|
||||||
|
var buttons: Array[InputEvent] = get_joypad_inputs_for_action(action)
|
||||||
|
return null if buttons.is_empty() else buttons[0]
|
||||||
|
|
||||||
|
|
||||||
|
## Set the button for an action
|
||||||
|
func set_joypad_input_for_action(action: String, input: InputEvent, swap_if_taken: bool = true) -> Error:
|
||||||
|
return _update_joypad_input_for_action(action, input, swap_if_taken, null)
|
||||||
|
|
||||||
|
|
||||||
|
## Replace a specific button for an action
|
||||||
|
func replace_joypad_input_for_action(action: String, current_input: InputEvent, input: InputEventJoypadButton, swap_if_taken: bool = true) -> Error:
|
||||||
|
return _update_joypad_input_for_action(action, input, swap_if_taken, current_input)
|
||||||
|
|
||||||
|
|
||||||
|
## Replace a button, given its index
|
||||||
|
func replace_joypad_input_at_index(action: String, index: int, input: InputEvent, swap_if_taken: bool = true) -> Error:
|
||||||
|
var inputs: Array[InputEvent] = get_joypad_inputs_for_action(action)
|
||||||
|
var replacing_input
|
||||||
|
if inputs.is_empty() or inputs.size() <= index:
|
||||||
|
replacing_input = InputEventJoypadButton.new()
|
||||||
|
replacing_input.button_index = JOY_BUTTON_INVALID
|
||||||
|
else:
|
||||||
|
replacing_input = inputs[index]
|
||||||
|
return _update_joypad_input_for_action(action, input, swap_if_taken, replacing_input)
|
||||||
|
|
||||||
|
|
||||||
|
## Set the action used for a button
|
||||||
|
func _update_joypad_input_for_action(action: String, input: InputEvent, swap_if_taken: bool = true, replacing_input: InputEvent = null) -> Error:
|
||||||
|
var is_valid_keyboard_event = func(event):
|
||||||
|
return event is InputEventJoypadButton or event is InputEventJoypadMotion
|
||||||
|
|
||||||
|
return _update_input_for_action(action, input, swap_if_taken, replacing_input, is_valid_keyboard_event, joypad_input_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_input_for_action(action: String, input: InputEvent, swap_if_taken: bool, replacing_input: InputEvent, check_is_valid: Callable, did_change_signal: Signal) -> Error:
|
||||||
|
# Find any action that is already mapped to this input
|
||||||
|
var clashing_action = ""
|
||||||
|
var clashing_event
|
||||||
|
if swap_if_taken:
|
||||||
|
for other_action in InputMap.get_actions():
|
||||||
|
if other_action == action: continue
|
||||||
|
|
||||||
|
for event in InputMap.action_get_events(other_action):
|
||||||
|
if event.is_match(input):
|
||||||
|
clashing_action = other_action
|
||||||
|
clashing_event = event
|
||||||
|
|
||||||
|
# Find the key based event for the target action
|
||||||
|
var action_events: Array[InputEvent] = InputMap.action_get_events(action)
|
||||||
|
var is_replacing: bool = false
|
||||||
|
for i in range(0, action_events.size()):
|
||||||
|
var event: InputEvent = action_events[i]
|
||||||
|
if check_is_valid.call(event):
|
||||||
|
if replacing_input != null and not event.is_match(replacing_input):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Remap the other event if there is a clashing one
|
||||||
|
if clashing_action:
|
||||||
|
_update_input_for_action(clashing_action, event, false, clashing_event, check_is_valid, did_change_signal)
|
||||||
|
|
||||||
|
# Replace the event
|
||||||
|
action_events[i] = input
|
||||||
|
is_replacing = true
|
||||||
|
break
|
||||||
|
|
||||||
|
# If we were trying to replace something but didn't find it then just add it to the end
|
||||||
|
if not is_replacing:
|
||||||
|
action_events.append(input)
|
||||||
|
|
||||||
|
# Apply the changes
|
||||||
|
InputMap.action_erase_events(action)
|
||||||
|
for event in action_events:
|
||||||
|
if event != null:
|
||||||
|
InputMap.action_add_event(action, event)
|
||||||
|
|
||||||
|
did_change_signal.emit(action, input)
|
||||||
|
|
||||||
|
return OK
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Rumbling
|
||||||
|
|
||||||
|
|
||||||
|
func rumble_small(target_device: int = 0) -> void:
|
||||||
|
Input.start_joy_vibration(target_device, 0.4, 0, 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
func rumble_medium(target_device: int = 0) -> void:
|
||||||
|
Input.start_joy_vibration(target_device, 0, 0.7, 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
func rumble_large(target_device: int = 0) -> void:
|
||||||
|
Input.start_joy_vibration(target_device, 0, 1, 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
func start_rumble_small(target_device: int = 0) -> void:
|
||||||
|
Input.start_joy_vibration(target_device, 0.4, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
func start_rumble_medium(target_device: int = 0) -> void:
|
||||||
|
Input.start_joy_vibration(target_device, 0, 0.7, 0)
|
||||||
|
|
||||||
|
|
||||||
|
func start_rumble_large(target_device: int = 0) -> void:
|
||||||
|
Input.start_joy_vibration(target_device, 0, 1, 0)
|
||||||
|
|
||||||
|
|
||||||
|
func stop_rumble(target_device: int = 0) -> void:
|
||||||
|
Input.stop_joy_vibration(target_device)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://cholww48njaeh
|
||||||
7
Zennysoft.Game.Ma/addons/input_helper/plugin.cfg
Normal file
7
Zennysoft.Game.Ma/addons/input_helper/plugin.cfg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="Input Helper"
|
||||||
|
description="Detect which input device the player is using and manage input actions"
|
||||||
|
author="Nathan Hoad"
|
||||||
|
version="4.7.0"
|
||||||
|
script="plugin.gd"
|
||||||
112
Zennysoft.Game.Ma/addons/input_helper/plugin.gd
Normal file
112
Zennysoft.Game.Ma/addons/input_helper/plugin.gd
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
|
||||||
|
const REMOTE_RELEASES_URL = "https://api.github.com/repos/nathanhoad/godot_input_helper/releases"
|
||||||
|
const LOCAL_CONFIG_PATH = "res://addons/input_helper/plugin.cfg"
|
||||||
|
|
||||||
|
const DownloadDialogScene = preload("res://addons/input_helper/views/download_dialog.tscn")
|
||||||
|
|
||||||
|
|
||||||
|
var http_request: HTTPRequest = HTTPRequest.new()
|
||||||
|
var next_version: String = ""
|
||||||
|
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
add_autoload_singleton("InputHelper", "res://addons/input_helper/input_helper.gd")
|
||||||
|
|
||||||
|
# Configure settings
|
||||||
|
InputHelperSettings.prepare()
|
||||||
|
|
||||||
|
# Check for updates on GitHub
|
||||||
|
get_editor_interface().get_base_control().add_child(http_request)
|
||||||
|
http_request.request_completed.connect(_on_http_request_request_completed)
|
||||||
|
http_request.request(REMOTE_RELEASES_URL)
|
||||||
|
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
remove_autoload_singleton("InputHelper")
|
||||||
|
|
||||||
|
if next_version != "":
|
||||||
|
remove_tool_menu_item("Update Input Helper to v%s" % next_version)
|
||||||
|
|
||||||
|
|
||||||
|
# Get the current version
|
||||||
|
func get_version() -> String:
|
||||||
|
var config: ConfigFile = ConfigFile.new()
|
||||||
|
config.load(LOCAL_CONFIG_PATH)
|
||||||
|
return config.get_value("plugin", "version")
|
||||||
|
|
||||||
|
|
||||||
|
# Convert a version number to an actually comparable number
|
||||||
|
func version_to_number(version: String) -> int:
|
||||||
|
var bits = version.split(".")
|
||||||
|
return bits[0].to_int() * 1000000 + bits[1].to_int() * 1000 + bits[2].to_int()
|
||||||
|
|
||||||
|
|
||||||
|
### Signals
|
||||||
|
|
||||||
|
|
||||||
|
func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
|
||||||
|
http_request.queue_free()
|
||||||
|
|
||||||
|
if result != HTTPRequest.RESULT_SUCCESS: return
|
||||||
|
|
||||||
|
var current_version: String = get_version()
|
||||||
|
|
||||||
|
# Work out the next version from the releases information on GitHub
|
||||||
|
var response = JSON.parse_string(body.get_string_from_utf8())
|
||||||
|
if typeof(response) != TYPE_ARRAY: return
|
||||||
|
|
||||||
|
# GitHub releases are in order of creation, not order of version
|
||||||
|
var versions = (response as Array).filter(func(release):
|
||||||
|
var version: String = release.tag_name.substr(1)
|
||||||
|
return version_to_number(version) > version_to_number(current_version)
|
||||||
|
)
|
||||||
|
if versions.size() > 0:
|
||||||
|
next_version = versions[0].tag_name.substr(1)
|
||||||
|
add_tool_menu_item("Update Input Helper to v%s" % next_version, _update_input_helper)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_input_helper() -> void:
|
||||||
|
var download_dialog := DownloadDialogScene.instantiate()
|
||||||
|
download_dialog.next_version = next_version
|
||||||
|
|
||||||
|
var scale: float = get_editor_interface().get_editor_scale()
|
||||||
|
download_dialog.min_size = Vector2(300, 250) * scale
|
||||||
|
|
||||||
|
download_dialog.update_finished.connect(_on_download_dialog_update_finished)
|
||||||
|
download_dialog.update_failed.connect(_on_download_dialog_update_failed)
|
||||||
|
|
||||||
|
get_editor_interface().get_base_control().add_child(download_dialog)
|
||||||
|
download_dialog.show()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_download_dialog_update_finished() -> void:
|
||||||
|
remove_tool_menu_item("Update Input Helper to v%s" % next_version)
|
||||||
|
|
||||||
|
get_editor_interface().get_resource_filesystem().scan()
|
||||||
|
|
||||||
|
print_rich("\n[b]Updated Input Helper to v%s[/b]\n" % next_version)
|
||||||
|
|
||||||
|
var finished_dialog: AcceptDialog = AcceptDialog.new()
|
||||||
|
finished_dialog.dialog_text = "Your Input Helper is now up to date."
|
||||||
|
|
||||||
|
var restart_addon = func():
|
||||||
|
finished_dialog.queue_free()
|
||||||
|
get_editor_interface().call_deferred("set_plugin_enabled", "input_helper", true)
|
||||||
|
get_editor_interface().set_plugin_enabled("input_helper", false)
|
||||||
|
|
||||||
|
finished_dialog.canceled.connect(restart_addon)
|
||||||
|
finished_dialog.confirmed.connect(restart_addon)
|
||||||
|
get_editor_interface().get_base_control().add_child(finished_dialog)
|
||||||
|
finished_dialog.popup_centered()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_download_dialog_update_failed() -> void:
|
||||||
|
var failed_dialog: AcceptDialog = AcceptDialog.new()
|
||||||
|
failed_dialog.dialog_text = "There was a problem downloading the update."
|
||||||
|
failed_dialog.canceled.connect(func(): failed_dialog.queue_free())
|
||||||
|
failed_dialog.confirmed.connect(func(): failed_dialog.queue_free())
|
||||||
|
get_editor_interface().get_base_control().add_child(failed_dialog)
|
||||||
|
failed_dialog.popup_centered()
|
||||||
1
Zennysoft.Game.Ma/addons/input_helper/plugin.gd.uid
Normal file
1
Zennysoft.Game.Ma/addons/input_helper/plugin.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cul6evy00vr55
|
||||||
42
Zennysoft.Game.Ma/addons/input_helper/settings.gd
Normal file
42
Zennysoft.Game.Ma/addons/input_helper/settings.gd
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
class_name InputHelperSettings extends Node
|
||||||
|
|
||||||
|
const USE_GRANULAR_DEVICE_IDENTIFIERS = "devices/use_granular_device_identifiers"
|
||||||
|
|
||||||
|
const SETTINGS_CONFIGURATION = {
|
||||||
|
USE_GRANULAR_DEVICE_IDENTIFIERS: {
|
||||||
|
value = false,
|
||||||
|
type = TYPE_BOOL,
|
||||||
|
is_advanced = true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static func prepare() -> void:
|
||||||
|
for key: String in SETTINGS_CONFIGURATION:
|
||||||
|
var setting_config: Dictionary = SETTINGS_CONFIGURATION[key]
|
||||||
|
var setting_name: String = "input_helper/%s" % key
|
||||||
|
if not ProjectSettings.has_setting(setting_name):
|
||||||
|
ProjectSettings.set_setting(setting_name, setting_config.value)
|
||||||
|
ProjectSettings.set_initial_value(setting_name, setting_config.value)
|
||||||
|
ProjectSettings.add_property_info({
|
||||||
|
"name" = setting_name,
|
||||||
|
"type" = setting_config.type,
|
||||||
|
"hint" = setting_config.get("hint", PROPERTY_HINT_NONE),
|
||||||
|
"hint_string" = setting_config.get("hint_string", "")
|
||||||
|
})
|
||||||
|
ProjectSettings.set_as_basic(setting_name, not setting_config.has("is_advanced"))
|
||||||
|
ProjectSettings.set_as_internal(setting_name, setting_config.has("is_hidden"))
|
||||||
|
|
||||||
|
|
||||||
|
static func set_setting(key: String, value) -> void:
|
||||||
|
if get_setting(key, value) != value:
|
||||||
|
ProjectSettings.set_setting("input_helper/%s" % key, value)
|
||||||
|
ProjectSettings.set_initial_value("input_helper/%s" % key, SETTINGS_CONFIGURATION[key].value)
|
||||||
|
ProjectSettings.save()
|
||||||
|
|
||||||
|
|
||||||
|
static func get_setting(key: String, default):
|
||||||
|
if ProjectSettings.has_setting("input_helper/%s" % key):
|
||||||
|
return ProjectSettings.get_setting("input_helper/%s" % key)
|
||||||
|
else:
|
||||||
|
return default
|
||||||
1
Zennysoft.Game.Ma/addons/input_helper/settings.gd.uid
Normal file
1
Zennysoft.Game.Ma/addons/input_helper/settings.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://yqplm6a6focp
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
@tool
|
||||||
|
|
||||||
|
extends AcceptDialog
|
||||||
|
|
||||||
|
|
||||||
|
signal update_finished()
|
||||||
|
signal update_failed()
|
||||||
|
|
||||||
|
|
||||||
|
@onready var download_update_panel := $DownloadUpdatePanel
|
||||||
|
|
||||||
|
|
||||||
|
var next_version: String
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
download_update_panel.next_version = next_version
|
||||||
|
|
||||||
|
|
||||||
|
### Signals
|
||||||
|
|
||||||
|
|
||||||
|
func _on_download_update_panel_updated(updated_to_version) -> void:
|
||||||
|
update_finished.emit()
|
||||||
|
queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_download_update_panel_failed() -> void:
|
||||||
|
update_failed.emit()
|
||||||
|
queue_free()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://1t3qhgrro2es
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://bownbkcmm43gn"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://b7mst0qu7vjk1" path="res://addons/input_helper/components/download_update_panel.tscn" id="1_37q37"]
|
||||||
|
[ext_resource type="Script" uid="uid://1t3qhgrro2es" path="res://addons/input_helper/views/download_dialog.gd" id="1_ltktf"]
|
||||||
|
|
||||||
|
[node name="DownloadDialog" type="AcceptDialog"]
|
||||||
|
initial_position = 2
|
||||||
|
ok_button_text = "Close"
|
||||||
|
script = ExtResource("1_ltktf")
|
||||||
|
|
||||||
|
[node name="DownloadUpdatePanel" parent="." instance=ExtResource("1_37q37")]
|
||||||
|
|
||||||
|
[connection signal="failed" from="DownloadUpdatePanel" to="." method="_on_download_update_panel_failed"]
|
||||||
|
[connection signal="updated" from="DownloadUpdatePanel" to="." method="_on_download_update_panel_updated"]
|
||||||
@@ -23,6 +23,7 @@ DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
|
|||||||
DialogueController="*res://src/game/DialogueController.cs"
|
DialogueController="*res://src/game/DialogueController.cs"
|
||||||
AudioManager="*res://src/audio/AudioManager.cs"
|
AudioManager="*res://src/audio/AudioManager.cs"
|
||||||
BgmPlayer="*res://src/audio/BGMPlayer.cs"
|
BgmPlayer="*res://src/audio/BGMPlayer.cs"
|
||||||
|
InputHelper="*res://addons/input_helper/input_helper.gd"
|
||||||
|
|
||||||
[dialogue_manager]
|
[dialogue_manager]
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ project/assembly_name="Ma"
|
|||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg")
|
enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg", "res://addons/input_helper/plugin.cfg")
|
||||||
|
|
||||||
[file_customization]
|
[file_customization]
|
||||||
|
|
||||||
@@ -72,9 +73,7 @@ texture={
|
|||||||
ui_accept={
|
ui_accept={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
ui_select={
|
ui_select={
|
||||||
@@ -83,34 +82,40 @@ ui_select={
|
|||||||
}
|
}
|
||||||
ui_cancel={
|
ui_cancel={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null)
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194309,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
ui_focus_next={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_focus_prev={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
ui_left={
|
ui_left={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
ui_right={
|
ui_right={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
ui_up={
|
ui_up={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
ui_down={
|
ui_down={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
MoveUp={
|
MoveUp={
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using Chickensoft.GodotNodeInterfaces;
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Godot.Collections;
|
using Godot.Collections;
|
||||||
|
using NathanHoad;
|
||||||
using SimpleInjector.Lifestyles;
|
using SimpleInjector.Lifestyles;
|
||||||
using System.IO;
|
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -47,11 +47,11 @@ public partial class App : Node, IApp
|
|||||||
private bool _loadingGame = false;
|
private bool _loadingGame = false;
|
||||||
private bool _loadingEnemyViewer = false;
|
private bool _loadingEnemyViewer = false;
|
||||||
private string _optionsSavePath = string.Empty;
|
private string _optionsSavePath = string.Empty;
|
||||||
|
private string _controllerSavePath = string.Empty;
|
||||||
private ISaveFileManager _saveFileManager;
|
private ISaveFileManager _saveFileManager;
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
MainMenu.Hide();
|
|
||||||
_container = new SimpleInjector.Container();
|
_container = new SimpleInjector.Container();
|
||||||
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
|
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
|
||||||
_container.RegisterSingleton<IAppRepo, AppRepo>();
|
_container.RegisterSingleton<IAppRepo, AppRepo>();
|
||||||
@@ -61,6 +61,7 @@ public partial class App : Node, IApp
|
|||||||
|
|
||||||
_saveFileManager = _container.GetInstance<ISaveFileManager>();
|
_saveFileManager = _container.GetInstance<ISaveFileManager>();
|
||||||
_optionsSavePath = $"{OS.GetUserDataDir()}/options.json";
|
_optionsSavePath = $"{OS.GetUserDataDir()}/options.json";
|
||||||
|
_controllerSavePath = $"{OS.GetUserDataDir()}/controls.json";
|
||||||
|
|
||||||
Task.Run(() => _saveFileManager.ReadFromFile<OptionsData>(_optionsSavePath).ContinueWith((data) =>
|
Task.Run(() => _saveFileManager.ReadFromFile<OptionsData>(_optionsSavePath).ContinueWith((data) =>
|
||||||
{
|
{
|
||||||
@@ -68,6 +69,12 @@ public partial class App : Node, IApp
|
|||||||
OptionsMenu.CallDeferred("Load", data.Result);
|
OptionsMenu.CallDeferred("Load", data.Result);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Task.Run(() => _saveFileManager.ReadFromFile<string>(_controllerSavePath).ContinueWith((data) =>
|
||||||
|
{
|
||||||
|
if (data.IsCompletedSuccessfully)
|
||||||
|
OptionsMenu.Controller.CallDeferred(nameof(OptionsMenu.Controller.LoadControllerInput), data.Result);
|
||||||
|
}));
|
||||||
|
|
||||||
MainMenu.StartGame += OnStartGame;
|
MainMenu.StartGame += OnStartGame;
|
||||||
MainMenu.EnemyViewer += OnEnemyViewer;
|
MainMenu.EnemyViewer += OnEnemyViewer;
|
||||||
MainMenu.Options += OnOptions;
|
MainMenu.Options += OnOptions;
|
||||||
@@ -91,8 +98,10 @@ public partial class App : Node, IApp
|
|||||||
{
|
{
|
||||||
var saveFileManager = _container.GetInstance<ISaveFileManager>();
|
var saveFileManager = _container.GetInstance<ISaveFileManager>();
|
||||||
await saveFileManager.WriteToFile(OptionsMenu.OptionsData, _optionsSavePath);
|
await saveFileManager.WriteToFile(OptionsMenu.OptionsData, _optionsSavePath);
|
||||||
MainMenu.Show();
|
var controllerOutput = InputHelper.SerializeInputsForActions();
|
||||||
|
await saveFileManager.WriteToFile(controllerOutput, _controllerSavePath);
|
||||||
OptionsMenu.Hide();
|
OptionsMenu.Hide();
|
||||||
|
MainMenu.OptionsButton.GrabFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGameLoaded(string sceneName)
|
private void OnGameLoaded(string sceneName)
|
||||||
@@ -141,7 +150,6 @@ public partial class App : Node, IApp
|
|||||||
});
|
});
|
||||||
|
|
||||||
AppLogic.Start();
|
AppLogic.Start();
|
||||||
MainMenu.Show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
@@ -170,7 +178,7 @@ public partial class App : Node, IApp
|
|||||||
private async void OnOptions()
|
private async void OnOptions()
|
||||||
{
|
{
|
||||||
OptionsMenu.Show();
|
OptionsMenu.Show();
|
||||||
MainMenu.Hide();
|
OptionsMenu.MasterVolumeSlider.GrabFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnQuit() => AppLogic.Input(new AppLogic.Input.QuitGame());
|
public void OnQuit() => AppLogic.Input(new AppLogic.Input.QuitGame());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://rfvnddfqufho"]
|
[gd_scene load_steps=3 format=3 uid="uid://rfvnddfqufho"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://14b7o2c6cgry" path="res://src/menu/MainMenu.cs" id="1_y6722"]
|
[ext_resource type="Script" uid="uid://14b7o2c6cgry" path="res://src/menu/MainMenu.cs" id="1_y6722"]
|
||||||
|
[ext_resource type="Shortcut" uid="uid://dumkrjur22k2a" path="res://src/ui/ButtonShortcut.tres" id="2_7fwjx"]
|
||||||
|
|
||||||
[node name="MainMenu" type="Control"]
|
[node name="MainMenu" type="Control"]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
@@ -27,7 +28,6 @@ anchor_right = 1.0
|
|||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
mouse_filter = 0
|
|
||||||
theme_override_constants/margin_left = 100
|
theme_override_constants/margin_left = 100
|
||||||
theme_override_constants/margin_top = 100
|
theme_override_constants/margin_top = 100
|
||||||
theme_override_constants/margin_right = 100
|
theme_override_constants/margin_right = 100
|
||||||
@@ -37,41 +37,56 @@ theme_override_constants/margin_bottom = 100
|
|||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 0
|
size_flags_horizontal = 0
|
||||||
size_flags_vertical = 0
|
size_flags_vertical = 0
|
||||||
mouse_filter = 0
|
|
||||||
|
|
||||||
[node name="StartGameButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
[node name="StartGameButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
focus_neighbor_bottom = NodePath("../EnemyViewerButton")
|
||||||
|
focus_next = NodePath("../EnemyViewerButton")
|
||||||
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
||||||
|
shortcut = ExtResource("2_7fwjx")
|
||||||
text = "Start Game"
|
text = "Start Game"
|
||||||
|
|
||||||
[node name="EnemyViewerButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
[node name="EnemyViewerButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_neighbor_bottom = NodePath("../GalleryButton")
|
focus_neighbor_bottom = NodePath("../GalleryButton")
|
||||||
|
focus_next = NodePath("../GalleryButton")
|
||||||
|
focus_previous = NodePath("../StartGameButton")
|
||||||
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
||||||
|
shortcut = ExtResource("2_7fwjx")
|
||||||
text = "Enemy Viewer"
|
text = "Enemy Viewer"
|
||||||
|
|
||||||
[node name="GalleryButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
[node name="GalleryButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_neighbor_top = NodePath("../EnemyViewerButton")
|
focus_neighbor_top = NodePath("../EnemyViewerButton")
|
||||||
focus_neighbor_bottom = NodePath("../QuitButton")
|
focus_neighbor_bottom = NodePath("../OptionsButton")
|
||||||
|
focus_next = NodePath("../OptionsButton")
|
||||||
|
focus_previous = NodePath("../EnemyViewerButton")
|
||||||
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
||||||
|
shortcut = ExtResource("2_7fwjx")
|
||||||
text = "Gallery"
|
text = "Gallery"
|
||||||
|
|
||||||
[node name="OptionsButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
[node name="OptionsButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_neighbor_top = NodePath("../EnemyViewerButton")
|
focus_neighbor_top = NodePath("../GalleryButton")
|
||||||
focus_neighbor_bottom = NodePath("../QuitButton")
|
focus_neighbor_bottom = NodePath("../QuitButton")
|
||||||
|
focus_next = NodePath("../QuitButton")
|
||||||
|
focus_previous = NodePath("../GalleryButton")
|
||||||
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
||||||
|
shortcut = ExtResource("2_7fwjx")
|
||||||
text = "Options"
|
text = "Options"
|
||||||
|
|
||||||
[node name="QuitButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
[node name="QuitButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_neighbor_top = NodePath("../GalleryButton")
|
focus_neighbor_top = NodePath("../OptionsButton")
|
||||||
|
focus_neighbor_bottom = NodePath(".")
|
||||||
|
focus_next = NodePath(".")
|
||||||
|
focus_previous = NodePath("../OptionsButton")
|
||||||
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
theme_override_colors/font_focus_color = Color(0.976471, 0.827451, 0, 1)
|
||||||
|
shortcut = ExtResource("2_7fwjx")
|
||||||
text = "Quit
|
text = "Quit
|
||||||
"
|
"
|
||||||
|
|||||||
19
Zennysoft.Game.Ma/src/options/InputMapButton.cs
Normal file
19
Zennysoft.Game.Ma/src/options/InputMapButton.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
public abstract partial class InputMapButton : Button
|
||||||
|
{
|
||||||
|
[Signal] public delegate void RemapEventHandler(InputMapButton buttonBeingRemapped);
|
||||||
|
|
||||||
|
public string Action { get; set; }
|
||||||
|
|
||||||
|
public InputEvent InputEvent { get; set; }
|
||||||
|
|
||||||
|
public InputMapButton()
|
||||||
|
{
|
||||||
|
Pressed += RemapButton_Pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemapButton_Pressed() => EmitSignal(SignalName.Remap, this);
|
||||||
|
}
|
||||||
1
Zennysoft.Game.Ma/src/options/InputMapButton.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/options/InputMapButton.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bhfrdlnv7xyf6
|
||||||
191
Zennysoft.Game.Ma/src/options/InputMapper.cs
Normal file
191
Zennysoft.Game.Ma/src/options/InputMapper.cs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
using Chickensoft.AutoInject;
|
||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Godot;
|
||||||
|
using NathanHoad;
|
||||||
|
using SimpleInjector.Lifestyles;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Abstractions;
|
||||||
|
using System.Linq;
|
||||||
|
using Zennysoft.Game.Abstractions;
|
||||||
|
using Zennysoft.Game.Implementation;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
[Meta(typeof(IAutoNode))]
|
||||||
|
public partial class InputMapper : PanelContainer
|
||||||
|
{
|
||||||
|
public override void _Notification(int what) => this.Notify(what);
|
||||||
|
|
||||||
|
[Node] public VBoxContainer ActionList { get; set; }
|
||||||
|
|
||||||
|
[Node] public KeyboardRemapButton MoveForwardKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton MoveForwardController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton MoveLeftKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton MoveLeftController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton MoveRightKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton MoveRightController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton MoveBackwardKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton MoveBackwardController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton StrafeLeftKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton StrafeLeftController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton StrafeRightKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton StrafeRightController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton AttackKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton AttackController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton InteractKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton InteractController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton InventoryKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton InventoryController { get; set; }
|
||||||
|
[Node] public KeyboardRemapButton SortKeyboard { get; set; }
|
||||||
|
[Node] public JoypadRemapButton SortController { get; set; }
|
||||||
|
|
||||||
|
private Button _remappingButton = null;
|
||||||
|
private InputEvent _remappingAction = null;
|
||||||
|
|
||||||
|
private List<JoypadRemapButton> _actionJoyMap = [];
|
||||||
|
private List<KeyboardRemapButton> _actionKeyMap = [];
|
||||||
|
|
||||||
|
private SimpleInjector.Container _container;
|
||||||
|
private ISaveFileManager _saveFileManager;
|
||||||
|
|
||||||
|
[Signal] public delegate void SaveControllerInputEventHandler();
|
||||||
|
|
||||||
|
public void OnReady()
|
||||||
|
{
|
||||||
|
_container = new SimpleInjector.Container();
|
||||||
|
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
|
||||||
|
_container.RegisterSingleton<IFileSystem, FileSystem>();
|
||||||
|
_container.RegisterSingleton<ISaveFileManager, SaveFileManager>();
|
||||||
|
_saveFileManager = _container.GetInstance<ISaveFileManager>();
|
||||||
|
|
||||||
|
MoveForwardController.Action = GameInputs.MoveUp;
|
||||||
|
MoveForwardKeyboard.Action = GameInputs.MoveUp;
|
||||||
|
MoveLeftController.Action = GameInputs.MoveLeft;
|
||||||
|
MoveLeftKeyboard.Action = GameInputs.MoveLeft;
|
||||||
|
MoveRightController.Action = GameInputs.MoveRight;
|
||||||
|
MoveRightKeyboard.Action = GameInputs.MoveRight;
|
||||||
|
MoveBackwardController.Action = GameInputs.MoveDown;
|
||||||
|
MoveBackwardKeyboard.Action = GameInputs.MoveDown;
|
||||||
|
StrafeLeftController.Action = GameInputs.StrafeLeft;
|
||||||
|
StrafeLeftKeyboard.Action = GameInputs.StrafeLeft;
|
||||||
|
StrafeRightController.Action = GameInputs.StrafeRight;
|
||||||
|
StrafeRightKeyboard.Action = GameInputs.StrafeRight;
|
||||||
|
AttackController.Action = GameInputs.Attack;
|
||||||
|
AttackKeyboard.Action = GameInputs.Attack;
|
||||||
|
InteractController.Action = GameInputs.Interact;
|
||||||
|
InteractKeyboard.Action = GameInputs.Interact;
|
||||||
|
InventoryController.Action = GameInputs.Inventory;
|
||||||
|
InventoryKeyboard.Action = GameInputs.Inventory;
|
||||||
|
SortController.Action = GameInputs.InventorySort;
|
||||||
|
SortKeyboard.Action = GameInputs.InventorySort;
|
||||||
|
|
||||||
|
_actionJoyMap.Add(MoveForwardController);
|
||||||
|
_actionJoyMap.Add(MoveLeftController);
|
||||||
|
_actionJoyMap.Add(MoveRightController);
|
||||||
|
_actionJoyMap.Add(MoveBackwardController);
|
||||||
|
_actionJoyMap.Add(StrafeLeftController);
|
||||||
|
_actionJoyMap.Add(StrafeRightController);
|
||||||
|
_actionJoyMap.Add(AttackController);
|
||||||
|
_actionJoyMap.Add(InteractController);
|
||||||
|
_actionJoyMap.Add(InventoryController);
|
||||||
|
_actionJoyMap.Add(SortController);
|
||||||
|
|
||||||
|
_actionKeyMap.Add(MoveForwardKeyboard);
|
||||||
|
_actionKeyMap.Add(MoveLeftKeyboard);
|
||||||
|
_actionKeyMap.Add(MoveRightKeyboard);
|
||||||
|
_actionKeyMap.Add(MoveBackwardKeyboard);
|
||||||
|
_actionKeyMap.Add(StrafeLeftKeyboard);
|
||||||
|
_actionKeyMap.Add(StrafeRightKeyboard);
|
||||||
|
_actionKeyMap.Add(AttackKeyboard);
|
||||||
|
_actionKeyMap.Add(InteractKeyboard);
|
||||||
|
_actionKeyMap.Add(InventoryKeyboard);
|
||||||
|
_actionKeyMap.Add(SortKeyboard);
|
||||||
|
|
||||||
|
MoveForwardKeyboard.Remap += OnRemap;
|
||||||
|
MoveForwardController.Remap += OnRemap;
|
||||||
|
MoveLeftKeyboard.Remap += OnRemap;
|
||||||
|
MoveLeftController.Remap += OnRemap;
|
||||||
|
MoveRightKeyboard.Remap += OnRemap;
|
||||||
|
MoveRightController.Remap += OnRemap;
|
||||||
|
MoveBackwardKeyboard.Remap += OnRemap;
|
||||||
|
MoveBackwardController.Remap += OnRemap;
|
||||||
|
StrafeLeftKeyboard.Remap += OnRemap;
|
||||||
|
StrafeLeftController.Remap += OnRemap;
|
||||||
|
StrafeRightKeyboard.Remap += OnRemap;
|
||||||
|
StrafeRightController.Remap += OnRemap;
|
||||||
|
AttackKeyboard.Remap += OnRemap;
|
||||||
|
AttackController.Remap += OnRemap;
|
||||||
|
InteractKeyboard.Remap += OnRemap;
|
||||||
|
InteractController.Remap += OnRemap;
|
||||||
|
InventoryKeyboard.Remap += OnRemap;
|
||||||
|
InventoryController.Remap += OnRemap;
|
||||||
|
SortKeyboard.Remap += OnRemap;
|
||||||
|
SortController.Remap += OnRemap;
|
||||||
|
|
||||||
|
InputHelper.JoypadInputChanged += (string action, InputEvent input) =>
|
||||||
|
{
|
||||||
|
var buttonChanged = _actionJoyMap.SingleOrDefault(x => x.Action == action);
|
||||||
|
if (buttonChanged != null)
|
||||||
|
{
|
||||||
|
buttonChanged.SetProcessInput(false);
|
||||||
|
buttonChanged.Text = InputHelper.GetLabelForInput(input);
|
||||||
|
}
|
||||||
|
var allButtons = _actionKeyMap.Concat<InputMapButton>(_actionJoyMap);
|
||||||
|
foreach (var button in allButtons)
|
||||||
|
button.Disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
InputHelper.KeyboardInputChanged += (string action, InputEvent input) =>
|
||||||
|
{
|
||||||
|
var buttonChanged = _actionKeyMap.SingleOrDefault(x => x.Action == action);
|
||||||
|
if (buttonChanged != null)
|
||||||
|
{
|
||||||
|
buttonChanged.SetProcessInput(false);
|
||||||
|
buttonChanged.Text = InputHelper.GetLabelForInput(input);
|
||||||
|
}
|
||||||
|
var allButtons = _actionKeyMap.Concat<InputMapButton>(_actionJoyMap);
|
||||||
|
foreach (var button in allButtons)
|
||||||
|
button.Disabled = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadControllerInput(string jsonData)
|
||||||
|
{
|
||||||
|
InputHelper.DeserializeInputsForActions(jsonData);
|
||||||
|
InitializeButtonText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitializeButtonText()
|
||||||
|
{
|
||||||
|
MoveForwardKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.MoveUp));
|
||||||
|
MoveForwardController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.MoveUp));
|
||||||
|
MoveLeftKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.MoveLeft));
|
||||||
|
MoveLeftController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.MoveLeft));
|
||||||
|
MoveRightKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.MoveRight));
|
||||||
|
MoveRightController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.MoveRight));
|
||||||
|
MoveBackwardKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.MoveDown));
|
||||||
|
MoveBackwardController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.MoveDown));
|
||||||
|
StrafeLeftKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.StrafeLeft));
|
||||||
|
StrafeLeftController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.StrafeLeft));
|
||||||
|
StrafeRightKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.StrafeRight));
|
||||||
|
StrafeRightController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.StrafeRight));
|
||||||
|
AttackKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.Attack));
|
||||||
|
AttackController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.Attack));
|
||||||
|
InteractKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.Interact));
|
||||||
|
InteractController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.Interact));
|
||||||
|
InventoryKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.Inventory));
|
||||||
|
InventoryController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.Inventory));
|
||||||
|
SortKeyboard.Text = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.InventorySort));
|
||||||
|
SortController.Text = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.InventorySort));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRemap(InputMapButton inputButton)
|
||||||
|
{
|
||||||
|
inputButton.Text = "...";
|
||||||
|
inputButton.SetProcessInput(true);
|
||||||
|
var allButtons = _actionKeyMap.Concat<InputMapButton>(_actionJoyMap);
|
||||||
|
foreach (var button in allButtons)
|
||||||
|
button.Disabled = true;
|
||||||
|
ReleaseFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Zennysoft.Game.Ma/src/options/InputMapper.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/options/InputMapper.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c6lw5yp8p0wb5
|
||||||
361
Zennysoft.Game.Ma/src/options/InputMapper.tscn
Normal file
361
Zennysoft.Game.Ma/src/options/InputMapper.tscn
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dk5esf6mm6kte"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://c6lw5yp8p0wb5" path="res://src/options/InputMapper.cs" id="1_rwvs3"]
|
||||||
|
[ext_resource type="Script" uid="uid://b70br20xue678" path="res://src/options/KeyboardRemapButton.cs" id="2_fmxfy"]
|
||||||
|
[ext_resource type="Script" uid="uid://bo7vk56h1lr07" path="res://src/options/JoypadRemapButton.cs" id="3_yis0i"]
|
||||||
|
|
||||||
|
[node name="InputMapper" type="PanelContainer"]
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -451.0
|
||||||
|
offset_top = -451.0
|
||||||
|
offset_right = 449.0
|
||||||
|
offset_bottom = 449.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_rwvs3")
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 0
|
||||||
|
theme_override_constants/margin_left = 25
|
||||||
|
theme_override_constants/margin_top = 25
|
||||||
|
theme_override_constants/margin_right = 25
|
||||||
|
theme_override_constants/margin_bottom = 25
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 3
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="ActionList" type="VBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
|
[node name="Header" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Header"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Actions"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Header"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Header"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Keyboard"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Header"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="Label3" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Header"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Controller"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="Move Forward" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Forward"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Move Forward"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Forward"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveForwardKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Forward"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Forward"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveForwardController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Forward"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Move Left" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Left"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Move Left"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Left"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveLeftKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Left"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Left"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveLeftController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Left"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Move Right" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Right"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Move Right"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Right"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveRightKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Right"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Right"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveRightController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Right"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Move Backward" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Backward"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Move Backward"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Backward"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveBackwardKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Backward"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Backward"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="MoveBackwardController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Move Backward"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Strafe Left" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Left"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Strafe Left"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Left"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="StrafeLeftKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Left"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Left"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="StrafeLeftController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Left"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Strafe Right" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Right"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Strafe Right"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Right"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="StrafeRightKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Right"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Right"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="StrafeRightController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Strafe Right"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Attack" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Attack"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Attack"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Attack"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="AttackKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Attack"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Attack"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="AttackController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Attack"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Interact" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Interact"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Interact"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Interact"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="InteractKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Interact"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Interact"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="InteractController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Interact"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Open Inventory" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Open Inventory"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Open Inventory"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Open Inventory"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="InventoryKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Open Inventory"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Open Inventory"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="InventoryController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Open Inventory"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
|
|
||||||
|
[node name="Sort Inventory" type="HBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Sort Inventory"]
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Sort Inventory"
|
||||||
|
horizontal_alignment = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Sort Inventory"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="SortKeyboard" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Sort Inventory"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 35)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("2_fmxfy")
|
||||||
|
|
||||||
|
[node name="Control2" type="Control" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Sort Inventory"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="SortController" type="Button" parent="MarginContainer/VBoxContainer/ScrollContainer/ActionList/Sort Inventory"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(200, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
script = ExtResource("3_yis0i")
|
||||||
1
Zennysoft.Game.Ma/src/options/InputToString.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/options/InputToString.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bwd066xv65pbi
|
||||||
41
Zennysoft.Game.Ma/src/options/JoypadRemapButton.cs
Normal file
41
Zennysoft.Game.Ma/src/options/JoypadRemapButton.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Godot;
|
||||||
|
using NathanHoad;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
public partial class JoypadRemapButton : InputMapButton
|
||||||
|
{
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
SetProcessInput(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
if (@event.IsActionType() && InputHelper.GetDeviceFromEvent(@event) != "keyboard")
|
||||||
|
{
|
||||||
|
if (InputHelper.GetJoypadInputForAction(GameInputs.Pause).IsMatch(@event))
|
||||||
|
{
|
||||||
|
InputHelper.SetJoypadInputForAction(Action, InputEvent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(Action, InputEvent, @event, true);
|
||||||
|
if (Action == GameInputs.MoveUp)
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(GameInputs.UiUp, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.MoveLeft)
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(GameInputs.UiLeft, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.MoveRight)
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(GameInputs.UiRight, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.MoveDown)
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(GameInputs.UiDown, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.Attack)
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(GameInputs.UiAccept, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.Interact)
|
||||||
|
InputHelper.ReplaceJoypadInputForAction(GameInputs.UiCancel, InputEvent, @event, true);
|
||||||
|
InputEvent = @event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AcceptEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Zennysoft.Game.Ma/src/options/JoypadRemapButton.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/options/JoypadRemapButton.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bo7vk56h1lr07
|
||||||
42
Zennysoft.Game.Ma/src/options/KeyboardRemapButton.cs
Normal file
42
Zennysoft.Game.Ma/src/options/KeyboardRemapButton.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using Godot;
|
||||||
|
using NathanHoad;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
public partial class KeyboardRemapButton : InputMapButton
|
||||||
|
{
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
SetProcessInput(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
AcceptEvent();
|
||||||
|
if (@event.IsActionType() && InputHelper.GetDeviceFromEvent(@event) == "keyboard")
|
||||||
|
{
|
||||||
|
if (InputHelper.GetKeyboardInputForAction(GameInputs.Pause).IsMatch(@event))
|
||||||
|
{
|
||||||
|
InputHelper.SetKeyboardInputForAction(Action, InputEvent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(Action, InputEvent, @event, true);
|
||||||
|
if (Action == GameInputs.MoveUp)
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(GameInputs.UiUp, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.MoveLeft)
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(GameInputs.UiLeft, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.MoveRight)
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(GameInputs.UiRight, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.MoveDown)
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(GameInputs.UiDown, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.Attack)
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(GameInputs.UiAccept, InputEvent, @event, true);
|
||||||
|
else if (Action == GameInputs.Interact)
|
||||||
|
InputHelper.ReplaceKeyboardInputForAction(GameInputs.UiCancel, InputEvent, @event, true);
|
||||||
|
InputEvent = @event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1
Zennysoft.Game.Ma/src/options/KeyboardRemapButton.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/options/KeyboardRemapButton.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b70br20xue678
|
||||||
21
Zennysoft.Game.Ma/src/options/OptionsData.cs
Normal file
21
Zennysoft.Game.Ma/src/options/OptionsData.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Chickensoft.Introspection;
|
||||||
|
using Chickensoft.Serialization;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
|
[Meta, Id("options_data")]
|
||||||
|
public partial class OptionsData : Node
|
||||||
|
{
|
||||||
|
[Save("MasterVolume")]
|
||||||
|
public required double MasterVolumeLevel { get; set; }
|
||||||
|
|
||||||
|
[Save("MusicVolume")]
|
||||||
|
public required double MusicVolumeLevel { get; set; }
|
||||||
|
|
||||||
|
[Save("SFXVolume")]
|
||||||
|
public required double SFXVolumeLevel { get; set; }
|
||||||
|
|
||||||
|
[Save("ScreenResolution")]
|
||||||
|
public required int ScreenResolution { get; set; }
|
||||||
|
}
|
||||||
1
Zennysoft.Game.Ma/src/options/OptionsData.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/options/OptionsData.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://jrl2hyudv6jn
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.Serialization;
|
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using NathanHoad;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
|
|
||||||
@@ -15,7 +16,12 @@ public partial class OptionsMenu : Control
|
|||||||
[Node] public HSlider MasterVolumeSlider { get; set; }
|
[Node] public HSlider MasterVolumeSlider { get; set; }
|
||||||
[Node] public HSlider MusicVolumeSlider { get; set; }
|
[Node] public HSlider MusicVolumeSlider { get; set; }
|
||||||
[Node] public HSlider SFXVolumeSlider { get; set; }
|
[Node] public HSlider SFXVolumeSlider { get; set; }
|
||||||
[Node] public Button SaveAndExitButton { get; set; }
|
|
||||||
|
[Node] public InputMapper Controller { get; set; }
|
||||||
|
[Node] public TabContainer TabContainer { get; set; }
|
||||||
|
[Node] public Label PressToGoBackLabel { get; set; }
|
||||||
|
|
||||||
|
[Node] public CanvasLayer CanvasLayer { get; set; }
|
||||||
|
|
||||||
public OptionsData OptionsData;
|
public OptionsData OptionsData;
|
||||||
|
|
||||||
@@ -48,11 +54,65 @@ public partial class OptionsMenu : Control
|
|||||||
|
|
||||||
ResolutionOptions.ItemSelected += ResolutionOptions_ItemSelected;
|
ResolutionOptions.ItemSelected += ResolutionOptions_ItemSelected;
|
||||||
|
|
||||||
SaveAndExitButton.ButtonUp += SaveAndExitButton_ButtonUp;
|
TabContainer.TabChanged += TabContainer_TabChanged;
|
||||||
|
|
||||||
_masterBusIndex = AudioServer.GetBusIndex("Master");
|
_masterBusIndex = AudioServer.GetBusIndex("Master");
|
||||||
_musicBusIndex = AudioServer.GetBusIndex("MUSIC");
|
_musicBusIndex = AudioServer.GetBusIndex("MUSIC");
|
||||||
_sfxBusIndex = AudioServer.GetBusIndex("SFX");
|
_sfxBusIndex = AudioServer.GetBusIndex("SFX");
|
||||||
|
|
||||||
|
VisibilityChanged += OptionsMenu_VisibilityChanged;
|
||||||
|
|
||||||
|
InputHelper.JoypadInputChanged += (string action, InputEvent input) =>
|
||||||
|
{
|
||||||
|
if (GameInputs.Interact == action)
|
||||||
|
{
|
||||||
|
var interactInputs = InputHelper.GetLabelForInput(InputHelper.GetJoypadInputForAction(GameInputs.Interact));
|
||||||
|
PressToGoBackLabel.Text = $"Press {interactInputs} to save and exit.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
InputHelper.KeyboardInputChanged += (string action, InputEvent input) =>
|
||||||
|
{
|
||||||
|
if (GameInputs.Interact == action)
|
||||||
|
{
|
||||||
|
var interactInputs = InputHelper.GetLabelForInput(InputHelper.GetKeyboardInputForAction(GameInputs.Interact));
|
||||||
|
PressToGoBackLabel.Text = $"Press {interactInputs} to save and exit.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TabContainer_TabChanged(long tab)
|
||||||
|
{
|
||||||
|
if (tab == 0)
|
||||||
|
MasterVolumeSlider.GrabFocus();
|
||||||
|
if (tab == 1)
|
||||||
|
Controller.MoveForwardKeyboard.GrabFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OptionsMenu_VisibilityChanged() => CanvasLayer.Visible = !CanvasLayer.Visible;
|
||||||
|
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
var interactInputs = InputHelper.GetKeyboardOrJoypadInputsForAction(GameInputs.Interact);
|
||||||
|
if (interactInputs.Any(x => x.IsMatch(@event)))
|
||||||
|
{
|
||||||
|
AcceptEvent();
|
||||||
|
SaveAndExitMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftTab = InputHelper.GetKeyboardOrJoypadInputsForAction(GameInputs.StrafeLeft);
|
||||||
|
if (leftTab.Any(x => x.IsMatch(@event)))
|
||||||
|
{
|
||||||
|
AcceptEvent();
|
||||||
|
TabContainer.CurrentTab = Mathf.Max(0, TabContainer.CurrentTab - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var rightTab = InputHelper.GetKeyboardOrJoypadInputsForAction(GameInputs.StrafeRight);
|
||||||
|
if (rightTab.Any(x => x.IsMatch(@event)))
|
||||||
|
{
|
||||||
|
AcceptEvent();
|
||||||
|
TabContainer.CurrentTab = Mathf.Min(TabContainer.GetTabCount() - 1, TabContainer.CurrentTab + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResolutionOptions_ItemSelected(long index)
|
private void ResolutionOptions_ItemSelected(long index)
|
||||||
@@ -71,7 +131,7 @@ public partial class OptionsMenu : Control
|
|||||||
DisplayServer.WindowSetMode(_windowModes[optionsData.ScreenResolution]);
|
DisplayServer.WindowSetMode(_windowModes[optionsData.ScreenResolution]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveAndExitButton_ButtonUp() => EmitSignal(SignalName.OptionsMenuExited);
|
private void SaveAndExitMenu() => EmitSignal(SignalName.OptionsMenuExited);
|
||||||
|
|
||||||
private void MasterVolumeSlider_Changed(double valueChanged)
|
private void MasterVolumeSlider_Changed(double valueChanged)
|
||||||
{
|
{
|
||||||
@@ -91,19 +151,3 @@ public partial class OptionsMenu : Control
|
|||||||
AudioServer.SetBusVolumeDb(_sfxBusIndex, Mathf.LinearToDb((float)valueChanged));
|
AudioServer.SetBusVolumeDb(_sfxBusIndex, Mathf.LinearToDb((float)valueChanged));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Meta, Id("options_data")]
|
|
||||||
public partial class OptionsData : Node
|
|
||||||
{
|
|
||||||
[Save("MasterVolume")]
|
|
||||||
public required double MasterVolumeLevel { get; set; }
|
|
||||||
|
|
||||||
[Save("MusicVolume")]
|
|
||||||
public required double MusicVolumeLevel { get; set; }
|
|
||||||
|
|
||||||
[Save("SFXVolume")]
|
|
||||||
public required double SFXVolumeLevel { get; set; }
|
|
||||||
|
|
||||||
[Save("ScreenResolution")]
|
|
||||||
public required int ScreenResolution { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
[gd_scene load_steps=5 format=3 uid="uid://drkl3btdy6uxj"]
|
[gd_scene load_steps=7 format=3 uid="uid://drkl3btdy6uxj"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://cjxmdvhixcj6e" path="res://src/options/OptionsMenu.cs" id="1_jli36"]
|
[ext_resource type="Script" uid="uid://cjxmdvhixcj6e" path="res://src/options/OptionsMenu.cs" id="1_jli36"]
|
||||||
|
[ext_resource type="Shortcut" uid="uid://dumkrjur22k2a" path="res://src/ui/ButtonShortcut.tres" id="2_1egkf"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dk5esf6mm6kte" path="res://src/options/InputMapper.tscn" id="2_utd4g"]
|
||||||
|
|
||||||
[sub_resource type="StyleBoxLine" id="StyleBoxLine_jli36"]
|
[sub_resource type="StyleBoxLine" id="StyleBoxLine_jli36"]
|
||||||
|
|
||||||
@@ -18,43 +20,50 @@ grow_horizontal = 2
|
|||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
script = ExtResource("1_jli36")
|
script = ExtResource("1_jli36")
|
||||||
|
|
||||||
[node name="ColorRect" type="ColorRect" parent="."]
|
[node name="CanvasLayer" type="CanvasLayer" parent="."]
|
||||||
layout_mode = 1
|
unique_name_in_owner = true
|
||||||
anchors_preset = 15
|
visible = false
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
color = Color(0.137255, 0.121569, 0.12549, 1)
|
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
[node name="CenterContainer" type="AspectRatioContainer" parent="CanvasLayer"]
|
||||||
layout_mode = 1
|
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
mouse_filter = 0
|
mouse_filter = 0
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TabContainer" type="TabContainer" parent="CanvasLayer/CenterContainer/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(1280, 960)
|
||||||
|
layout_mode = 2
|
||||||
|
current_tab = 0
|
||||||
|
|
||||||
|
[node name="Audio" type="MarginContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer"]
|
||||||
|
layout_mode = 2
|
||||||
theme_override_constants/margin_left = 100
|
theme_override_constants/margin_left = 100
|
||||||
theme_override_constants/margin_top = 100
|
theme_override_constants/margin_top = 100
|
||||||
theme_override_constants/margin_right = 100
|
theme_override_constants/margin_right = 100
|
||||||
theme_override_constants/margin_bottom = 100
|
theme_override_constants/margin_bottom = 100
|
||||||
|
metadata/_tab_index = 0
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 0
|
size_flags_horizontal = 0
|
||||||
mouse_filter = 0
|
mouse_filter = 0
|
||||||
|
|
||||||
[node name="MasterVolume" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
[node name="MasterVolume" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="VolumeLabel" type="Label" parent="MarginContainer/VBoxContainer/MasterVolume"]
|
[node name="VolumeLabel" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/MasterVolume"]
|
||||||
custom_minimum_size = Vector2(125, 0)
|
custom_minimum_size = Vector2(125, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Master Volume"
|
text = "Master Volume"
|
||||||
horizontal_alignment = 2
|
horizontal_alignment = 2
|
||||||
|
|
||||||
[node name="MasterVolumeSlider" type="HSlider" parent="MarginContainer/VBoxContainer/MasterVolume"]
|
[node name="MasterVolumeSlider" type="HSlider" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/MasterVolume"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(300, 0)
|
custom_minimum_size = Vector2(300, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -66,16 +75,16 @@ max_value = 1.0
|
|||||||
step = 0.001
|
step = 0.001
|
||||||
value = 1.0
|
value = 1.0
|
||||||
|
|
||||||
[node name="MusicVolume" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
[node name="MusicVolume" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="VolumeLabel" type="Label" parent="MarginContainer/VBoxContainer/MusicVolume"]
|
[node name="VolumeLabel" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/MusicVolume"]
|
||||||
custom_minimum_size = Vector2(125, 0)
|
custom_minimum_size = Vector2(125, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Music Volume"
|
text = "Music Volume"
|
||||||
horizontal_alignment = 2
|
horizontal_alignment = 2
|
||||||
|
|
||||||
[node name="MusicVolumeSlider" type="HSlider" parent="MarginContainer/VBoxContainer/MusicVolume"]
|
[node name="MusicVolumeSlider" type="HSlider" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/MusicVolume"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(300, 0)
|
custom_minimum_size = Vector2(300, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -87,16 +96,16 @@ max_value = 1.0
|
|||||||
step = 0.001
|
step = 0.001
|
||||||
value = 1.0
|
value = 1.0
|
||||||
|
|
||||||
[node name="SFXVolume" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
[node name="SFXVolume" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="VolumeLabel" type="Label" parent="MarginContainer/VBoxContainer/SFXVolume"]
|
[node name="VolumeLabel" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/SFXVolume"]
|
||||||
custom_minimum_size = Vector2(125, 0)
|
custom_minimum_size = Vector2(125, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "SFX Volume"
|
text = "SFX Volume"
|
||||||
horizontal_alignment = 2
|
horizontal_alignment = 2
|
||||||
|
|
||||||
[node name="SFXVolumeSlider" type="HSlider" parent="MarginContainer/VBoxContainer/SFXVolume"]
|
[node name="SFXVolumeSlider" type="HSlider" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/SFXVolume"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(300, 0)
|
custom_minimum_size = Vector2(300, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -108,27 +117,33 @@ max_value = 1.0
|
|||||||
step = 0.001
|
step = 0.001
|
||||||
value = 1.0
|
value = 1.0
|
||||||
|
|
||||||
[node name="Resolution" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
[node name="Resolution" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="ResolutionLabel" type="Label" parent="MarginContainer/VBoxContainer/Resolution"]
|
[node name="ResolutionLabel" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/Resolution"]
|
||||||
custom_minimum_size = Vector2(125, 0)
|
custom_minimum_size = Vector2(125, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Resolution: "
|
text = "Resolution: "
|
||||||
horizontal_alignment = 2
|
horizontal_alignment = 2
|
||||||
|
|
||||||
[node name="ResolutionOptions" type="OptionButton" parent="MarginContainer/VBoxContainer/Resolution"]
|
[node name="ResolutionOptions" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer/Resolution"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(200, 0)
|
custom_minimum_size = Vector2(200, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
shortcut = ExtResource("2_1egkf")
|
||||||
flat = true
|
flat = true
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer/Audio/VBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 10
|
size_flags_vertical = 10
|
||||||
|
|
||||||
[node name="SaveAndExitButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
[node name="Controller" parent="CanvasLayer/CenterContainer/VBoxContainer/TabContainer" instance=ExtResource("2_utd4g")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(150, 75)
|
visible = false
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Save and Exit"
|
metadata/_tab_index = 1
|
||||||
|
|
||||||
|
[node name="PressToGoBackLabel" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Press "
|
||||||
|
|||||||
3
Zennysoft.Game.Ma/src/ui/ButtonShortcut.tres
Normal file
3
Zennysoft.Game.Ma/src/ui/ButtonShortcut.tres
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[gd_resource type="Shortcut" format=3 uid="uid://dumkrjur22k2a"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
@@ -5,8 +5,8 @@ using Godot.Collections;
|
|||||||
namespace Zennysoft.Game.Ma;
|
namespace Zennysoft.Game.Ma;
|
||||||
public partial class DialogueBalloon : CanvasLayer
|
public partial class DialogueBalloon : CanvasLayer
|
||||||
{
|
{
|
||||||
[Export] public string NextAction = "ui_accept";
|
[Export] public string NextAction = GameInputs.Interact;
|
||||||
[Export] public string SkipAction = "ui_cancel";
|
[Export] public string SkipAction = GameInputs.Attack;
|
||||||
|
|
||||||
|
|
||||||
Control balloon;
|
Control balloon;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public partial class InGameUI : Control, IInGameUI
|
|||||||
|
|
||||||
public override void _UnhandledInput(InputEvent @event)
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
{
|
{
|
||||||
if (@event.IsActionPressed(GameInputs.Inventory))
|
if (@event.IsActionPressed(GameInputs.Inventory) && !InventoryMenu.Visible)
|
||||||
{
|
{
|
||||||
GD.Print("Inventory button pressed");
|
GD.Print("Inventory button pressed");
|
||||||
InGameUILogic.Input(new InGameUILogic.Input.ShowInventory());
|
InGameUILogic.Input(new InGameUILogic.Input.ShowInventory());
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||||
public override void _Input(InputEvent @event)
|
public override void _Input(InputEvent @event)
|
||||||
{
|
{
|
||||||
if (Visible && @event.IsActionPressed(GameInputs.UiCancel))
|
if (Visible && @event.IsActionPressed(GameInputs.Inventory))
|
||||||
{
|
{
|
||||||
if (UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus())
|
if (UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus())
|
||||||
{
|
{
|
||||||
@@ -134,6 +134,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
AcceptEvent();
|
||||||
Autoload.AudioManager.Play(SoundEffect.Cancel);
|
Autoload.AudioManager.Play(SoundEffect.Cancel);
|
||||||
_gameRepo.CloseInventory();
|
_gameRepo.CloseInventory();
|
||||||
}
|
}
|
||||||
@@ -142,17 +143,17 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
if (ItemSlots.Length == 0 || UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus())
|
if (ItemSlots.Length == 0 || UseButton.HasFocus() || DropButton.HasFocus() || ThrowButton.HasFocus())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (@event.IsActionPressed(GameInputs.UiRight) && _currentPageNumber == InventoryPageNumber.FirstPage)
|
if (@event.IsActionPressed(GameInputs.MoveRight) && _currentPageNumber == InventoryPageNumber.FirstPage)
|
||||||
{
|
{
|
||||||
var inventory = Player.Inventory;
|
var inventory = Player.Inventory;
|
||||||
if (inventory.Items.Count > _itemsPerPage)
|
if (inventory.Items.Count > _itemsPerPage)
|
||||||
ChangeInventoryPage(InventoryPageNumber.SecondPage);
|
ChangeInventoryPage(InventoryPageNumber.SecondPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@event.IsActionPressed(GameInputs.UiLeft) && _currentPageNumber == InventoryPageNumber.SecondPage)
|
if (@event.IsActionPressed(GameInputs.MoveLeft) && _currentPageNumber == InventoryPageNumber.SecondPage)
|
||||||
ChangeInventoryPage(InventoryPageNumber.FirstPage);
|
ChangeInventoryPage(InventoryPageNumber.FirstPage);
|
||||||
|
|
||||||
if (@event.IsActionPressed(GameInputs.UiDown))
|
if (@event.IsActionPressed(GameInputs.MoveDown))
|
||||||
{
|
{
|
||||||
var oldIndex = _currentIndex;
|
var oldIndex = _currentIndex;
|
||||||
var newIndex = new[] { _currentIndex + 1, _itemsPerPage - 1, ItemSlots.Length - 1 }.Min();
|
var newIndex = new[] { _currentIndex + 1, _itemsPerPage - 1, ItemSlots.Length - 1 }.Min();
|
||||||
@@ -165,7 +166,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
_currentIndex = newIndex;
|
_currentIndex = newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@event.IsActionPressed(GameInputs.UiUp))
|
if (@event.IsActionPressed(GameInputs.MoveUp))
|
||||||
{
|
{
|
||||||
var oldIndex = _currentIndex;
|
var oldIndex = _currentIndex;
|
||||||
var newIndex = new[] { _currentIndex - 1, 0 }.Max();
|
var newIndex = new[] { _currentIndex - 1, 0 }.Max();
|
||||||
@@ -179,7 +180,7 @@ public partial class InventoryMenu : Control, IInventoryMenu
|
|||||||
_currentIndex = newIndex;
|
_currentIndex = newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@event.IsActionPressed(GameInputs.UiAccept))
|
if (@event.IsActionPressed(GameInputs.Attack))
|
||||||
{
|
{
|
||||||
DisplayUserActionPrompt();
|
DisplayUserActionPrompt();
|
||||||
Autoload.AudioManager.Play(SoundEffect.Select);
|
Autoload.AudioManager.Play(SoundEffect.Select);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=29 format=3 uid="uid://dlj8qdg1c5048"]
|
[gd_scene load_steps=30 format=3 uid="uid://dlj8qdg1c5048"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://cmtet15hi5oiy" path="res://src/ui/inventory_menu/InventoryMenu.cs" id="1_l64wl"]
|
[ext_resource type="Script" uid="uid://cmtet15hi5oiy" path="res://src/ui/inventory_menu/InventoryMenu.cs" id="1_l64wl"]
|
||||||
[ext_resource type="Shader" uid="uid://cnphwvmr05hp1" path="res://src/ui/inventory_menu/InventoryMenu.gdshader" id="2_0fvsh"]
|
[ext_resource type="Shader" uid="uid://cnphwvmr05hp1" path="res://src/ui/inventory_menu/InventoryMenu.gdshader" id="2_0fvsh"]
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
[ext_resource type="LabelSettings" uid="uid://ca1q6yu8blwxf" path="res://src/ui/label_settings/InventoryMainTextBold.tres" id="6_tmdno"]
|
[ext_resource type="LabelSettings" uid="uid://ca1q6yu8blwxf" path="res://src/ui/label_settings/InventoryMainTextBold.tres" id="6_tmdno"]
|
||||||
[ext_resource type="LabelSettings" uid="uid://cuuo43x72xcsc" path="res://src/ui/label_settings/MainTextBold.tres" id="7_vyrxm"]
|
[ext_resource type="LabelSettings" uid="uid://cuuo43x72xcsc" path="res://src/ui/label_settings/MainTextBold.tres" id="7_vyrxm"]
|
||||||
[ext_resource type="Theme" uid="uid://daxuhpmyxwxck" path="res://src/ui/inventory_menu/InventoryDialogueSelectionStyle.tres" id="8_khyvo"]
|
[ext_resource type="Theme" uid="uid://daxuhpmyxwxck" path="res://src/ui/inventory_menu/InventoryDialogueSelectionStyle.tres" id="8_khyvo"]
|
||||||
|
[ext_resource type="Shortcut" uid="uid://dumkrjur22k2a" path="res://src/ui/ButtonShortcut.tres" id="9_b6rkr"]
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_i55tv"]
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_i55tv"]
|
||||||
shader = ExtResource("2_0fvsh")
|
shader = ExtResource("2_0fvsh")
|
||||||
@@ -381,6 +382,7 @@ theme_override_styles/disabled = SubResource("StyleBoxEmpty_fu7o2")
|
|||||||
theme_override_styles/pressed = SubResource("StyleBoxEmpty_nkvce")
|
theme_override_styles/pressed = SubResource("StyleBoxEmpty_nkvce")
|
||||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
|
||||||
button_mask = 0
|
button_mask = 0
|
||||||
|
shortcut = ExtResource("9_b6rkr")
|
||||||
text = "Use"
|
text = "Use"
|
||||||
alignment = 0
|
alignment = 0
|
||||||
|
|
||||||
@@ -405,6 +407,7 @@ theme_override_styles/disabled = SubResource("StyleBoxEmpty_ascpt")
|
|||||||
theme_override_styles/pressed = SubResource("StyleBoxEmpty_abpb1")
|
theme_override_styles/pressed = SubResource("StyleBoxEmpty_abpb1")
|
||||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_545ij")
|
||||||
button_mask = 0
|
button_mask = 0
|
||||||
|
shortcut = ExtResource("9_b6rkr")
|
||||||
text = "Throw"
|
text = "Throw"
|
||||||
alignment = 0
|
alignment = 0
|
||||||
|
|
||||||
@@ -429,6 +432,7 @@ theme_override_styles/disabled = SubResource("StyleBoxEmpty_uerb4")
|
|||||||
theme_override_styles/pressed = SubResource("StyleBoxEmpty_lvcf8")
|
theme_override_styles/pressed = SubResource("StyleBoxEmpty_lvcf8")
|
||||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_ct6ql")
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_ct6ql")
|
||||||
button_mask = 0
|
button_mask = 0
|
||||||
|
shortcut = ExtResource("9_b6rkr")
|
||||||
text = "Drop"
|
text = "Drop"
|
||||||
alignment = 0
|
alignment = 0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user