Skip to content

Commit

Permalink
Cursor support.
Browse files Browse the repository at this point in the history
  • Loading branch information
tomspilman committed Sep 2, 2024
1 parent 28ac36c commit 871a61f
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 9 deletions.
5 changes: 3 additions & 2 deletions MonoGame.Framework/Platform/Native/Mouse.Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ private static unsafe void PlatformSetPosition(int x, int y)

public static unsafe void PlatformSetCursor(MouseCursor cursor)
{
// TODO: Multiple window support.
// TODO: Multiple window support?

//Sdl.Mouse.SetCursor(cursor.Handle);
var window = PrimaryWindow as NativeGameWindow;
MGP.Window_SetCursor(window._handle, (MGP_Cursor*)cursor.Handle);
}
}
34 changes: 30 additions & 4 deletions MonoGame.Framework/Platform/Native/MouseCursor.Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,49 @@

using System;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Interop;

namespace Microsoft.Xna.Framework.Input;

public partial class MouseCursor
{
private static void PlatformInitalize()
private unsafe MouseCursor(SystemCursor cursor)
{
Handle = (nint)MGP.Cursor_Create(cursor);
}

private static void PlatformInitalize()
{
Arrow = new MouseCursor(SystemCursor.Arrow);
IBeam = new MouseCursor(SystemCursor.IBeam);
Wait = new MouseCursor(SystemCursor.Wait);
Crosshair = new MouseCursor(SystemCursor.Crosshair);
WaitArrow = new MouseCursor(SystemCursor.WaitArrow);
SizeNWSE = new MouseCursor(SystemCursor.SizeNWSE);
SizeNESW = new MouseCursor(SystemCursor.SizeNESW);
SizeWE = new MouseCursor(SystemCursor.SizeWE);
SizeNS = new MouseCursor(SystemCursor.SizeNS);
SizeAll = new MouseCursor(SystemCursor.SizeAll);
No = new MouseCursor(SystemCursor.No);
Hand = new MouseCursor(SystemCursor.Hand);
}

private static MouseCursor PlatformFromTexture2D(Texture2D texture, int originx, int originy)
private unsafe static MouseCursor PlatformFromTexture2D(Texture2D texture, int originx, int originy)
{
return new MouseCursor(IntPtr.Zero);
var bytes = new byte[texture.Width * texture.Height * 4];
texture.GetData(bytes);

var handle = MGP.Cursor_CreateCustom(bytes, texture.Width, texture.Height, originx, originy);

return new MouseCursor((nint)handle);
}

private void PlatformDispose()
private unsafe void PlatformDispose()
{
if (Handle == IntPtr.Zero)
return;

MGP.Cursor_Destroy((MGP_Cursor*)Handle);
Handle = IntPtr.Zero;
}
}
35 changes: 34 additions & 1 deletion MonoGame.Framework/Platform/Native/Platform.Interop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,25 @@ internal struct MGP_MouseWheelEvent
public int ScrollH;
}

internal enum SystemCursor : int
{
Arrow,
IBeam,
Wait,
Crosshair,
WaitArrow,
SizeNWSE,
SizeNESW,
SizeWE,
SizeNS,
SizeAll,
No,
Hand
}

[MGHandle]
internal readonly struct MGP_Cursor { }

internal enum ControllerInput : int
{
INVALID = -1,
Expand Down Expand Up @@ -268,6 +287,9 @@ internal static unsafe partial class MGP
[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Window_SetPosition", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Window_SetPosition(MGP_Window* window, int x, int y);

[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Window_SetCursor", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Window_SetCursor(MGP_Window* window, MGP_Cursor* cursor);

[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Window_ShowMessageBox", StringMarshalling = StringMarshalling.Utf8)]
public static partial int Window_ShowMessageBox(
MGP_Window* window,
Expand All @@ -286,8 +308,19 @@ public static partial int Window_ShowMessageBox(
[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Mouse_WarpPosition", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Mouse_WarpPosition(MGP_Window* window, int x, int y);

[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Cursor_Create", StringMarshalling = StringMarshalling.Utf8)]
public static partial MGP_Cursor* Cursor_Create(SystemCursor cursor);

[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Cursor_CreateCustom", StringMarshalling = StringMarshalling.Utf8)]
public static partial MGP_Cursor* Cursor_CreateCustom(byte[] rgba, int width, int height, int originx, int originy);

[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_Cursor_Destroy", StringMarshalling = StringMarshalling.Utf8)]
public static partial void Cursor_Destroy(MGP_Cursor* cursor);

#endregion


[LibraryImport(MonoGameNativeDLL, EntryPoint = "MGP_GamePad_GetMaxSupported", StringMarshalling = StringMarshalling.Utf8)]
public static partial int GamePad_GetMaxSupported();

#endregion
}
2 changes: 2 additions & 0 deletions src/monogame/common/MGM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.

struct MGG_Texture;

#include "csharp_MGM.h"

#include "stl_common.h"
Expand Down
3 changes: 1 addition & 2 deletions src/monogame/include/csharp_MGM.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

struct MGM_Song;
struct MGM_Video;
struct MGG_Texture;

MG_EXPORT MGM_Song* MGM_Song_Create(const char* mediaFilePath);
MG_EXPORT void MGM_Song_Destroy(MGM_Song* song);
MG_EXPORT mgulong MGM_Song_GetDuration(MGM_Song* song);
MG_EXPORT mgulong MGM_Song_GetPosition(MGM_Song* song);
MG_EXPORT mgfloat MGM_Song_GetVolume(MGM_Song* song);
Expand All @@ -27,7 +27,6 @@ MG_EXPORT void MGM_Song_Play(MGM_Song* song, mgulong startPositionMs, void (*cal
MG_EXPORT void MGM_Song_Pause(MGM_Song* song);
MG_EXPORT void MGM_Song_Resume(MGM_Song* song);
MG_EXPORT void MGM_Song_Stop(MGM_Song* song);
MG_EXPORT void MGM_Song_Destroy(MGM_Song* song);
MG_EXPORT MGM_Video* MGM_Video_Create(const char* mediaFilePath, mgint cachedFrameNum, mgint& width, mgint& height, mgfloat& fps, mgulong& duration);
MG_EXPORT void MGM_Video_Destroy(MGM_Video* video);
MG_EXPORT MGMediaState MGM_Video_GetState(MGM_Video* video);
Expand Down
5 changes: 5 additions & 0 deletions src/monogame/include/csharp_MGP.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

struct MGP_Platform;
struct MGP_Window;
struct MGP_Cursor;

MG_EXPORT MGP_Platform* MGP_Platform_Create(MGGameRunBehavior& behavior);
MG_EXPORT void MGP_Platform_Destroy(MGP_Platform* platform);
Expand All @@ -38,7 +39,11 @@ MG_EXPORT void MGP_Window_SetTitle(MGP_Window* window, const char* title);
MG_EXPORT void MGP_Window_Show(MGP_Window* window, mgbool show);
MG_EXPORT void MGP_Window_GetPosition(MGP_Window* window, mgint& x, mgint& y);
MG_EXPORT void MGP_Window_SetPosition(MGP_Window* window, mgint x, mgint y);
MG_EXPORT void MGP_Window_SetCursor(MGP_Window* window, MGP_Cursor* cursor);
MG_EXPORT mgint MGP_Window_ShowMessageBox(MGP_Window* window, const char* title, const char* description, const char** buttons, mgint count);
MG_EXPORT void MGP_Mouse_SetVisible(MGP_Platform* platform, mgbool visible);
MG_EXPORT void MGP_Mouse_WarpPosition(MGP_Window* window, mgint x, mgint y);
MG_EXPORT MGP_Cursor* MGP_Cursor_Create(MGSystemCursor cursor);
MG_EXPORT MGP_Cursor* MGP_Cursor_CreateCustom(mgbyte* rgba, mgint width, mgint height, mgint originx, mgint originy);
MG_EXPORT void MGP_Cursor_Destroy(MGP_Cursor* cursor);
MG_EXPORT mgint MGP_GamePad_GetMaxSupported();
16 changes: 16 additions & 0 deletions src/monogame/include/csharp_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,3 +469,19 @@ enum class MGControllerInput : mgint
INVALID = -1,
};

enum class MGSystemCursor : mgint
{
Arrow = 0,
IBeam = 1,
Wait = 2,
Crosshair = 3,
WaitArrow = 4,
SizeNWSE = 5,
SizeNESW = 6,
SizeWE = 7,
SizeNS = 8,
SizeAll = 9,
No = 10,
Hand = 11,
};

40 changes: 40 additions & 0 deletions src/monogame/sdl/MGP_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ struct MGP_Window
SDL_Window* window = nullptr;
};

struct MGP_Cursor
{
SDL_Cursor* cursor;
};


MGP_Platform* MGP_Platform_Create(MGGameRunBehavior& behavior)
{
SDL_Init(
Expand Down Expand Up @@ -723,6 +729,14 @@ void MGP_Window_SetPosition(MGP_Window* window, mgint x, mgint y)
SDL_SetWindowPosition(window->window, x, y);
}

void MGP_Window_SetCursor(MGP_Window* window, MGP_Cursor* cursor)
{
assert(window != nullptr);
assert(cursor != nullptr);

SDL_SetCursor(cursor->cursor);
}

void MGP_Mouse_SetVisible(MGP_Platform* platform, mgbool visible)
{
assert(platform != nullptr);
Expand All @@ -735,6 +749,32 @@ void MGP_Mouse_WarpPosition(MGP_Window* window, mgint x, mgint y)
SDL_WarpMouseInWindow(window->window, x, y);
}

MGP_Cursor* MGP_Cursor_Create(MGSystemCursor cursor_)
{
auto cursor = new MGP_Cursor();
cursor->cursor = SDL_CreateSystemCursor((SDL_SystemCursor)cursor_);
return cursor;
}

MGP_Cursor* MGP_Cursor_CreateCustom(mgbyte* rgba, mgint width, mgint height, mgint originx, mgint originy)
{
assert(rgba != nullptr);

auto cursor = new MGP_Cursor();

auto surface = SDL_CreateRGBSurfaceFrom(rgba, width, height, 32, width * 4, 0x000000ff, 0x0000FF00, 0x00FF0000, 0xFF000000);
cursor->cursor = SDL_CreateColorCursor(surface, originx, originy);

return cursor;
}

void MGP_Cursor_Destroy(MGP_Cursor* cursor)
{
assert(cursor != nullptr);
SDL_FreeCursor(cursor->cursor);
delete cursor;
}

mgint MGP_GamePad_GetMaxSupported()
{
return 16;
Expand Down

0 comments on commit 871a61f

Please sign in to comment.