Merge remote-tracking branch 'upstream/dev' into develop

This commit is contained in:
EvilFactory
2022-12-09 17:33:44 -03:00
416 changed files with 12674 additions and 5862 deletions

View File

@@ -69,77 +69,71 @@ namespace Steamworks
/// <param name="fileId">The ID of the file you want to download</param>
/// <param name="progress">An optional callback</param>
/// <param name="ct">Allows you to send a message to cancel the download anywhere during the process</param>
/// <param name="milisecondsUpdateDelay">How often to call the progress function</param>
/// <param name="millisecondsUpdateDelay">How often to call the progress function</param>
/// <returns>true if downloaded and installed correctly</returns>
public static async Task<bool> DownloadAsync( PublishedFileId fileId, Action<float> progress = null, int milisecondsUpdateDelay = 60, CancellationToken ct = default )
public static async Task<bool> DownloadAsync(
PublishedFileId fileId,
Action<float> progress = null,
int millisecondsUpdateDelay = 60,
CancellationToken? ct = null)
{
var item = new Steamworks.Ugc.Item( fileId );
if ( ct == default )
ct = new CancellationTokenSource( TimeSpan.FromSeconds( 60 ) ).Token;
var cancellationToken = ct ?? new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token;
async Task waitOrCancel()
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(millisecondsUpdateDelay);
}
progress?.Invoke( 0.0f );
if ( Download( fileId, highPriority: true ) == false )
return item.IsInstalled;
Result downloadStartResult = Result.None;
// Steam docs about Download:
// If the return value is true then register and wait
// for the Callback DownloadItemResult_t before calling
// GetItemInstallInfo or accessing the workshop item on disk.
// Wait for DownloadItemResult_t
void onDownloadFinished(Result r, ulong id)
{
Action<Result, ulong> onDownloadStarted = null;
if (id != item.Id) { return; }
downloadStartResult = r;
}
OnDownloadItemResult += onDownloadFinished;
try
if (!Download(fileId, highPriority: true)) { return item.IsInstalled; }
await Task.Delay(500);
try
{
while (true)
{
var downloadStarted = false;
onDownloadStarted = (r, id) => downloadStarted = true;
OnDownloadItemResult += onDownloadStarted;
cancellationToken.ThrowIfCancellationRequested();
int iters = 0;
while ( downloadStarted == false )
progress?.Invoke(item.DownloadAmount);
if (downloadStartResult != Result.None)
{
ct.ThrowIfCancellationRequested();
iters++;
if (iters >= 1000 / milisecondsUpdateDelay)
{
if (!item.IsDownloading && !item.IsInstalled)
{
//force download to start if it's not started
if ( Download( fileId, highPriority: true ) == false )
return item.IsInstalled;
}
iters = 0;
}
await Task.Delay( milisecondsUpdateDelay );
if (downloadStartResult != Result.OK) { return false; }
break;
}
}
finally
{
OnDownloadItemResult -= onDownloadStarted;
if (!item.IsDownloadPending && !item.IsDownloading)
{
if (item.IsInstalled)
{
break;
}
if (!Download(fileId, highPriority: true))
{
return item.IsInstalled;
}
}
await Task.Delay( millisecondsUpdateDelay );
}
}
progress?.Invoke( 0.2f );
await Task.Delay( milisecondsUpdateDelay );
//Wait for downloading completion
finally
{
while ( true )
{
ct.ThrowIfCancellationRequested();
progress?.Invoke( 0.2f + item.DownloadAmount * 0.8f );
if ( !item.IsDownloading && item.IsInstalled )
break;
await Task.Delay( milisecondsUpdateDelay );
}
OnDownloadItemResult -= onDownloadFinished;
}
progress?.Invoke( 1.0f );

View File

@@ -224,7 +224,7 @@ namespace Steamworks.Ugc
}
}
private ItemState State => (ItemState) SteamUGC.Internal.GetItemState( Id );
private ItemState State => (ItemState)(SteamUGC.Internal?.GetItemState( Id ) ?? 0);
public static async Task<Item?> GetAsync( PublishedFileId id, int maxageseconds = 60 * 30 )
{

View File

@@ -106,6 +106,16 @@ namespace Microsoft.Xna.Framework {
/// This event is only supported on the Windows DirectX, Windows OpenGL and Linux platforms.
/// </remarks>
public event EventHandler<TextInputEventArgs> TextInput;
/// <summary>
/// Used for displaying uncommitted IME text.
/// </summary>
public event EventHandler<TextEditingEventArgs> TextEditing;
/// <summary>
/// Used for when a key is pressed, including modifiers.
/// </summary>
public event EventHandler<TextInputEventArgs> KeyDown;
#endif
#endregion Events
@@ -152,6 +162,16 @@ namespace Microsoft.Xna.Framework {
{
EventHelpers.Raise(this, TextInput, e);
}
protected void OnKeyDown(object sender, TextInputEventArgs e)
{
EventHelpers.Raise(this, KeyDown, e);
}
protected void OnTextEditing(object sender, TextEditingEventArgs e)
{
EventHelpers.Raise(this, TextEditing, e);
}
#endif
protected internal abstract void SetSupportedOrientations (DisplayOrientation orientations);

View File

@@ -71,6 +71,8 @@
<Compile Include="PlayerIndex.cs" />
<Compile Include="PreparingDeviceSettingsEventArgs.cs" />
<Compile Include="ReusableItemList.cs" />
<Compile Include="TextEditingEventArgs.cs" />
<Compile Include="TextInput.cs" />
<Compile Include="TextInputEventArgs.cs">
<Platforms>Angle,Linux,MacOS,Windows,WindowsGL,WindowsUniversal</Platforms>
</Compile>

View File

@@ -71,6 +71,8 @@
<Compile Include="PlayerIndex.cs" />
<Compile Include="PreparingDeviceSettingsEventArgs.cs" />
<Compile Include="ReusableItemList.cs" />
<Compile Include="TextEditingEventArgs.cs" />
<Compile Include="TextInput.cs" />
<Compile Include="TextInputEventArgs.cs">
<Platforms>Angle,Linux,MacOS,Windows,WindowsGL,WindowsUniversal</Platforms>
</Compile>

View File

@@ -84,6 +84,8 @@
<Compile Include="SDL\SDL2.cs" />
<Compile Include="SDL\SDLGamePlatform.cs" />
<Compile Include="SDL\SDLGameWindow.cs" />
<Compile Include="TextEditingEventArgs.cs" />
<Compile Include="TextInput.cs" />
<Compile Include="TextInputEventArgs.cs">
<Platforms>Angle,Linux,MacOS,Windows,WindowsGL,WindowsUniversal</Platforms>
</Compile>

View File

@@ -75,6 +75,8 @@ internal static class Sdl
TextEditing = 0x302,
TextInput = 0x303,
TextEditingExt = 0x305,
MouseMotion = 0x400,
MouseButtonDown = 0x401,
MouseButtonup = 0x402,
@@ -139,6 +141,8 @@ internal static class Sdl
[FieldOffset(0)]
public Keyboard.TextEditingEvent Edit;
[FieldOffset(0)]
public Keyboard.TextEditingExtEvent EditExt;
[FieldOffset(0)]
public Keyboard.TextInputEvent Text;
[FieldOffset(0)]
public Mouse.WheelEvent Wheel;
@@ -240,6 +244,22 @@ internal static class Sdl
return pointer;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool d_sdl_istextinputshown();
public static d_sdl_istextinputshown SDL_IsTextInputShown = FuncLoader.LoadFunction<d_sdl_istextinputshown>(NativeLibrary, "SDL_IsTextInputShown");
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void d_sdl_starttextinput();
public static d_sdl_starttextinput SDL_StartTextInput = FuncLoader.LoadFunction<d_sdl_starttextinput>(NativeLibrary, "SDL_StartTextInput");
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void d_sdl_stoptextinput();
public static d_sdl_stoptextinput SDL_StopTextInput = FuncLoader.LoadFunction<d_sdl_stoptextinput>(NativeLibrary, "SDL_StopTextInput");
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void d_sdl_settextinputrect(ref Rectangle rect);
public static d_sdl_settextinputrect SDL_SetTextInputRect = FuncLoader.LoadFunction<d_sdl_settextinputrect>(NativeLibrary, "SDL_SetTextInputRect");
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void d_sdl_clearerror();
public static d_sdl_clearerror ClearError = FuncLoader.LoadFunction<d_sdl_clearerror>(NativeLibrary, "SDL_ClearError");
@@ -825,6 +845,17 @@ internal static class Sdl
public int Length;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct TextEditingExtEvent
{
public EventType Type;
public uint Timestamp;
public uint WindowId;
public byte* Text;
public int Start;
public int Length;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct TextInputEvent
{

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
@@ -136,8 +137,7 @@ namespace Microsoft.Xna.Framework
{
var key = KeyboardUtil.ToXna(ev.Key.Keysym.Sym);
if (!_keys.Contains(key))
_keys.Add(key);
if (!_keys.Contains(key)) _keys.Add(key);
//TODO: rethink all of this
char character = (char)KeyboardUtil.ApplyModifiers(ev.Key.Keysym.Sym, ev.Key.Keysym.Mod);
@@ -147,38 +147,44 @@ namespace Microsoft.Xna.Framework
character = '\0';
}
if (char.IsControl(character) ||
key == Keys.Left ||
key == Keys.Right ||
key == Keys.Up ||
key == Keys.Down)
{
_view.CallTextInput(character, key);
}
_view.CallKeyDown(character, key);
}
else if (ev.Type == Sdl.EventType.KeyUp)
{
var key = KeyboardUtil.ToXna(ev.Key.Keysym.Sym);
_keys.Remove(key);
}
else if (ev.Type == Sdl.EventType.TextInput)
else if (ev.Type == Sdl.EventType.TextEditing)
{
int len = 0;
string text = String.Empty;
string text;
unsafe
{
while (Marshal.ReadByte ((IntPtr)ev.Text.Text, len) != 0) {
len++;
}
var buffer = new byte [len];
Marshal.Copy ((IntPtr)ev.Text.Text, buffer, 0, len);
text = System.Text.Encoding.UTF8.GetString (buffer);
text = ReadString(ev.Edit.Text);
}
if (text.Length == 0)
continue;
foreach (var c in text)
_view.CallTextEditing(text, ev.Edit.Start, ev.Edit.Length);
}
else if (ev.Type == Sdl.EventType.TextEditingExt)
{
string text;
unsafe
{
var key = KeyboardUtil.ToXna((int)c);
text = ReadString(ev.EditExt.Text);
Sdl.Free((IntPtr)ev.EditExt.Text);
}
_view.CallTextEditing(text, ev.EditExt.Start, ev.EditExt.Length);
}
else if (ev.Type == Sdl.EventType.TextInput)
{
string text;
unsafe { text = ReadString(ev.Text.Text); }
if (text.Length is 0) { continue; }
foreach (char c in text)
{
var key = KeyboardUtil.ToXna(c);
_view.CallTextInput(c, key);
}
}
@@ -194,11 +200,22 @@ namespace Microsoft.Xna.Framework
IsActive = false;
else if (ev.Window.EventID == Sdl.Window.EventId.Moved)
_view.Moved();
else if (ev.Window.EventID == Sdl.Window.EventId.Close)
_isExiting++;
else if (ev.Window.EventID == Sdl.Window.EventId.Close) _isExiting++;
}
}
}
static unsafe string ReadString(byte* ptr)
{
int len = 0;
while (Marshal.ReadByte((IntPtr)ptr, len) != 0)
{
len++;
}
var buffer = new byte [len];
Marshal.Copy((IntPtr)ptr, buffer, 0, len);
return Encoding.UTF8.GetString(buffer);
}
}
public override void StartRunLoop()

View File

@@ -113,6 +113,13 @@ namespace Microsoft.Xna.Framework
Sdl.SetHint("SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS", "0");
Sdl.SetHint("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", "1");
/*
* By default SDL2 will hide IME popups since it probably assumes the game will implement their own suggestions box.
* We don't want that, so this hint will allow the system native IME popups to show up when typing in the game.
*/
Sdl.SetHint("SDL_IME_SHOW_UI", "1");
Sdl.SetHint("SDL_IME_SUPPORT_EXTENDED_TEXT", "1");
// when running NUnit tests entry assembly can be null
if (Assembly.GetEntryAssembly() != null)
{
@@ -333,6 +340,16 @@ namespace Microsoft.Xna.Framework
OnTextInput(this, new TextInputEventArgs(c, key));
}
public void CallKeyDown(char c, Keys key = Keys.None)
{
OnKeyDown(this, new TextInputEventArgs(c, key));
}
public void CallTextEditing(string text, int start, int length)
{
OnTextEditing(this, new TextEditingEventArgs(text, start, length));
}
public void DropFile(string filePath)
{
OnFileDropped(new FileDropEventArgs(filePath));

View File

@@ -0,0 +1,17 @@
using System;
namespace Microsoft.Xna.Framework
{
public sealed class TextEditingEventArgs : EventArgs
{
public readonly string Text;
public readonly int Start;
public readonly int Length;
public TextEditingEventArgs(string text, int start, int length)
{
Text = text;
Start = start;
Length = length;
}
}
}

View File

@@ -0,0 +1,34 @@
#nullable enable
namespace Microsoft.Xna.Framework
{
public static class TextInput
{
public static bool IsTextInputShown()
{
return Sdl.SDL_IsTextInputShown();
}
public static void StartTextInput()
{
Sdl.SDL_StartTextInput();
}
public static void StopTextInput()
{
Sdl.SDL_StopTextInput();
}
public static void SetTextInputRect(Rectangle rectangle)
{
Sdl.Rectangle r = new Sdl.Rectangle
{
X = rectangle.X,
Y = rectangle.Y,
Width = rectangle.Width,
Height = rectangle.Height
};
Sdl.SDL_SetTextInputRect(ref r);
}
}
}

Binary file not shown.

Binary file not shown.