Line 2: |
Line 2: |
| | | |
| The input API lets you check and suppress controller/keyboard/mouse state. | | The input API lets you check and suppress controller/keyboard/mouse state. |
− |
| |
− | ==Data structures==
| |
− | ===SButton===
| |
− | SMAPI's <tt>SButton</tt> constants unify the [https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb975202(v%3dxnagamestudio.40) <tt>Buttons</tt>], [https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb197781(v%3dxnagamestudio.40) <tt>Keys</tt>], [https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb198097(v%3dxnagamestudio.40) <tt>MouseState</tt>], and <tt>InputButton</tt> constants. SMAPI events use this to let you handle controller, keyboard, and mouse input without needing separate code for each. See [[Modding:Player Guide/Key Bindings]] for a list of values.
| |
− |
| |
− | SMAPI provides extensions to convert any of the other constants to <tt>SButton</tt>:
| |
− | <source lang="c#">
| |
− | SButton key = Keys.A.ToSButton(); // SButton.A
| |
− | SButton button = Buttons.A.ToSButton(); // SButton.ControllerA
| |
− | SButton input = new InputButton(true).ToSButton(); // SButton.MouseLeft
| |
− | </source>
| |
− |
| |
− | You can also convert <tt>SButton</tt> to the other constants. This uses a <tt>TryGet</tt> approach since <tt>SButton</tt> is a superset of the others (e.g. you can't convert <tt>SButton.ControllerA</tt> to a keyboard value):
| |
− | <source lang="c#">
| |
− | SButton value = SButton.A;
| |
− | if (value.TryGetKeyboard(out Keys key))
| |
− | ...;
| |
− | if (value.TryGetController(out Buttons button))
| |
− | ...;
| |
− | if (value.TryGetStardewInput(out InputButton input))
| |
− | ...;
| |
− | </source>
| |
− |
| |
− | Two last extensions let you check how the button is mapped in the game:
| |
− | <source lang="c#">
| |
− | SButton button = SButton.MouseLeft;
| |
− | if (button.IsUseToolButton())
| |
− | // use tool
| |
− | else if (button.IsActionButton())
| |
− | // perform action
| |
− | </source>
| |
− |
| |
− | You can use <tt>SButton</tt> values directly in your [[../Config|config model]], and they'll be represented by their names:
| |
− | {| class="wikitable"
| |
− | | <source lang="c#">
| |
− | internal class ModConfig
| |
− | {
| |
− | public SButton DoThingButton { get; set; } = SButton.LeftControl;
| |
− | }
| |
− | </source>
| |
− | | →
| |
− | | <source lang="json">
| |
− | {
| |
− | "DoThingButton": "LeftControl"
| |
− | }
| |
− | </source>
| |
− | |}
| |
− |
| |
− | ===ICursorPosition===
| |
− | SMAPI's <tt>ICursorPosition</tt> provides the cursor position in four coordinate systems:
| |
− | * <tt>AbsolutePixels</tt> is the pixel position relative to the top-left corner of the in-game map, adjusted for [[Modding:Modder Guide/Game Fundamentals#Zoom level|zoom]] but not [[Modding:Modder Guide/Game Fundamentals#UI scaling|UI scaling]].
| |
− | * <tt>ScreenPixels</tt> is the pixel position relative to the top-left corner of the visible screen, adjusted for [[Modding:Modder Guide/Game Fundamentals#Zoom level|zoom]] but not [[Modding:Modder Guide/Game Fundamentals#UI scaling|UI scaling]].
| |
− | * <tt>Tile</tt> is the [[Modding:Modder Guide/Game Fundamentals#Tiles|tile position]] under the cursor.
| |
− | * <tt>GrabTile</tt> is the tile position that the game considers under the cursor for the purposes of clicking actions. This automatically accounts for controller mode. This may be different than <tt>Tile</tt> if that's too far from the player.
| |
− |
| |
− | This is returned by the <tt>this.Helper.Input.GetCursorPosition()</tt> method and in the event args for some input events.
| |
− |
| |
− | '''The pixel positions are ''not'' adjusted for [[Modding:Modder Guide/Game Fundamentals#UI scaling|UI scaling]]''' (i.e. they're non-UI mode). Whether you need UI or non-UI positions depends how you're using them, so you can use <tt>cursorPos.GetScaledAbsolutePixels()</tt> or <tt>cursorPos.GetScaledScreenPixels()</tt> to adjust them automatically for the current mode or <tt>Utility.ModifyCoordinatesForUIScale</tt> to always get UI mode coordinates.
| |
| | | |
| ==APIs== | | ==APIs== |
Line 66: |
Line 8: |
| <dt><tt>IsDown</tt></dt> | | <dt><tt>IsDown</tt></dt> |
| <dd> | | <dd> |
− | You can check if any controller/keyboard/mouse button is currently pressed by calling the <tt>IsDown(button)</tt> method. For example: | + | You can check if any [[#SButton|controller/keyboard/mouse button]] is currently pressed by calling the <tt>IsDown(button)</tt> method. For example: |
| <source lang="c#"> | | <source lang="c#"> |
| bool isShiftPressed = this.Helper.Input.IsDown(SButton.LeftShift) || this.Helper.Input.IsDown(SButton.RightShift); | | bool isShiftPressed = this.Helper.Input.IsDown(SButton.LeftShift) || this.Helper.Input.IsDown(SButton.RightShift); |
Line 74: |
Line 16: |
| <dt><tt>GetState</tt></dt> | | <dt><tt>GetState</tt></dt> |
| <dd> | | <dd> |
− | For more finetuned control, you can check the button state relative to the previous game tick: | + | For more finetuned control, you can check the [[#SButton|button]] state relative to the previous game tick: |
| <source lang="c#"> | | <source lang="c#"> |
| SButtonState state = this.Helper.Input.GetState(SButton.LeftShift); | | SButtonState state = this.Helper.Input.GetState(SButton.LeftShift); |
Line 106: |
Line 48: |
| | | |
| ===Check cursor position=== | | ===Check cursor position=== |
− | The <tt>GetCursorPosition()</tt> method provides the cursor position in three coordinate systems; see [[#ICursorPosition|ICursorPosition]]. | + | The <tt>GetCursorPosition()</tt> method provides the [[#ICursorPosition|cursor position in three coordinate systems|ICursorPosition]]. |
| | | |
| For example: | | For example: |
Line 116: |
Line 58: |
| | | |
| ===Suppress input=== | | ===Suppress input=== |
− | You can prevent the game from handling any controller/keyboard/mouse button press (including clicks) by ''suppressing'' it. This suppression will remain in effect until the player releases the button. This won't prevent other mods from handling it. | + | You can prevent the game from handling any [[#SButton|controller/keyboard/mouse button press]] (including clicks) by ''suppressing'' it. This suppression will remain in effect until the player releases the button. This won't prevent other mods from handling it. |
| | | |
| For example: | | For example: |
Line 138: |
Line 80: |
| </source></li> | | </source></li> |
| </ul> | | </ul> |
| + | |
| + | ==Data structures== |
| + | ===SButton=== |
| + | SMAPI's <tt>SButton</tt> constants unify the [https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb975202(v%3dxnagamestudio.40) <tt>Buttons</tt>], [https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb197781(v%3dxnagamestudio.40) <tt>Keys</tt>], [https://docs.microsoft.com/en-us/previous-versions/windows/xna/bb198097(v%3dxnagamestudio.40) <tt>MouseState</tt>], and <tt>InputButton</tt> constants. SMAPI events use this to let you handle controller, keyboard, and mouse input without needing separate code for each. See [[Modding:Player Guide/Key Bindings]] for a list of values. |
| + | |
| + | SMAPI provides extensions to convert any of the other constants to <tt>SButton</tt>: |
| + | <source lang="c#"> |
| + | SButton key = Keys.A.ToSButton(); // SButton.A |
| + | SButton button = Buttons.A.ToSButton(); // SButton.ControllerA |
| + | SButton input = new InputButton(true).ToSButton(); // SButton.MouseLeft |
| + | </source> |
| + | |
| + | You can also convert <tt>SButton</tt> to the other constants. This uses a <tt>TryGet</tt> approach since <tt>SButton</tt> is a superset of the others (e.g. you can't convert <tt>SButton.ControllerA</tt> to a keyboard value): |
| + | <source lang="c#"> |
| + | SButton value = SButton.A; |
| + | if (value.TryGetKeyboard(out Keys key)) |
| + | ...; |
| + | if (value.TryGetController(out Buttons button)) |
| + | ...; |
| + | if (value.TryGetStardewInput(out InputButton input)) |
| + | ...; |
| + | </source> |
| + | |
| + | Two last extensions let you check how the button is mapped in the game: |
| + | <source lang="c#"> |
| + | SButton button = SButton.MouseLeft; |
| + | if (button.IsUseToolButton()) |
| + | // use tool |
| + | else if (button.IsActionButton()) |
| + | // perform action |
| + | </source> |
| + | |
| + | You can use <tt>SButton</tt> values directly in your [[../Config|config model]], and they'll be represented by their names: |
| + | {| class="wikitable" |
| + | | <source lang="c#"> |
| + | internal class ModConfig |
| + | { |
| + | public SButton DoThingButton { get; set; } = SButton.LeftControl; |
| + | } |
| + | </source> |
| + | | → |
| + | | <source lang="json"> |
| + | { |
| + | "DoThingButton": "LeftControl" |
| + | } |
| + | </source> |
| + | |} |
| + | |
| + | ===ICursorPosition=== |
| + | SMAPI's <tt>ICursorPosition</tt> provides the cursor position in four coordinate systems: |
| + | * <tt>AbsolutePixels</tt> is the pixel position relative to the top-left corner of the in-game map, adjusted for [[Modding:Modder Guide/Game Fundamentals#Zoom level|zoom]] but not [[Modding:Modder Guide/Game Fundamentals#UI scaling|UI scaling]]. |
| + | * <tt>ScreenPixels</tt> is the pixel position relative to the top-left corner of the visible screen, adjusted for [[Modding:Modder Guide/Game Fundamentals#Zoom level|zoom]] but not [[Modding:Modder Guide/Game Fundamentals#UI scaling|UI scaling]]. |
| + | * <tt>Tile</tt> is the [[Modding:Modder Guide/Game Fundamentals#Tiles|tile position]] under the cursor. |
| + | * <tt>GrabTile</tt> is the tile position that the game considers under the cursor for the purposes of clicking actions. This automatically accounts for controller mode. This may be different than <tt>Tile</tt> if that's too far from the player. |
| + | |
| + | This is returned by the <tt>this.Helper.Input.GetCursorPosition()</tt> method and in the event args for some input events. |
| + | |
| + | '''The pixel positions are ''not'' adjusted for [[Modding:Modder Guide/Game Fundamentals#UI scaling|UI scaling]]''' (i.e. they're non-UI mode). Whether you need UI or non-UI positions depends how you're using them, so you can use <tt>cursorPos.GetScaledAbsolutePixels()</tt> or <tt>cursorPos.GetScaledScreenPixels()</tt> to adjust them automatically for the current mode or <tt>Utility.ModifyCoordinatesForUIScale</tt> to always get UI mode coordinates. |
| | | |
| ==See also== | | ==See also== |
| * [[../Events#Input|Input events]] | | * [[../Events#Input|Input events]] |
| * [[Modding:Player Guide/Key Bindings]] for a list of valid <tt>SButton</tt> values | | * [[Modding:Player Guide/Key Bindings]] for a list of valid <tt>SButton</tt> values |