(3dc4135ce) v0.9.5.1

This commit is contained in:
Regalis
2019-11-21 18:22:25 +01:00
parent b39922a074
commit 5c95c53118
287 changed files with 12655 additions and 5048 deletions
@@ -36,10 +36,13 @@ namespace Facepunch.Steamworks
internal Client client;
private byte[] buffer = new byte[1024 * 128];
public Dictionary<ulong, Action> OnRichPresenceUpdateCallbacks;
internal Friends( Client c )
{
client = c;
client.RegisterCallback<FriendRichPresenceUpdate_t>(OnRichPresenceUpdate);
client.RegisterCallback<AvatarImageLoaded_t>( OnAvatarImageLoaded );
client.RegisterCallback<PersonaStateChange_t>( OnPersonaStateChange );
client.RegisterCallback<GameRichPresenceJoinRequested_t>( OnGameJoinRequested );
@@ -149,6 +152,33 @@ namespace Facepunch.Steamworks
}
}
public void SetRichPresenceUpdateCallback(ulong steamId, Action callback)
{
if (callback != null)
{
if (OnRichPresenceUpdateCallbacks == null)
{
OnRichPresenceUpdateCallbacks = new Dictionary<ulong, Action>();
}
if (!OnRichPresenceUpdateCallbacks.ContainsKey(steamId))
{
OnRichPresenceUpdateCallbacks.Add(steamId, callback);
}
else
{
OnRichPresenceUpdateCallbacks[steamId] = callback;
}
}
else
{
if (OnRichPresenceUpdateCallbacks == null) { return; }
if (OnRichPresenceUpdateCallbacks.ContainsKey(steamId))
{
OnRichPresenceUpdateCallbacks.Remove(steamId);
}
}
}
/// <summary>
/// Returns only friends
/// </summary>
@@ -392,5 +422,14 @@ namespace Facepunch.Steamworks
LoadAvatarForSteamId( data.SteamID );
}
private void OnRichPresenceUpdate( FriendRichPresenceUpdate_t data )
{
if (OnRichPresenceUpdateCallbacks == null) { return; }
if (OnRichPresenceUpdateCallbacks.ContainsKey(data.SteamIDFriend))
{
OnRichPresenceUpdateCallbacks[data.SteamIDFriend]?.Invoke();
}
}
}
}
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Text;
using SteamNative;
//TODO: this entire file is the main reason why we need to update this library
namespace Facepunch.Steamworks
{
public partial class LobbyList : IDisposable
@@ -12,6 +14,8 @@ namespace Facepunch.Steamworks
//The list of retrieved lobbies
public List<Lobby> Lobbies { get; private set; }
public Dictionary<ulong, Action<Lobby>> ManualLobbyDataCallbacks { get; private set; }
//True when all the possible lobbies have had their data updated
//if the number of lobbies is now equal to the initial request number, we've found all lobbies
public bool Finished { get; private set; }
@@ -21,9 +25,13 @@ namespace Facepunch.Steamworks
internal LobbyList(Client client)
{
client.RegisterCallback<SteamNative.LobbyDataUpdate_t>(OnLobbyDataUpdated);
this.client = client;
Lobbies = new List<Lobby>();
requests = new List<ulong>();
ManualLobbyDataCallbacks = new Dictionary<ulong, Action<Lobby>>();
}
/// <summary>
@@ -77,7 +85,6 @@ namespace Facepunch.Steamworks
}
bool registeredLobbyDataUpdated = false;
void OnLobbyList(LobbyMatchList_t callback, bool error)
{
if (error) return;
@@ -107,11 +114,6 @@ namespace Facepunch.Steamworks
{
//else we need to get the info for the missing lobby
client.native.matchmaking.RequestLobbyData(lobby);
if (!registeredLobbyDataUpdated)
{
client.RegisterCallback<SteamNative.LobbyDataUpdate_t>(OnLobbyDataUpdated);
registeredLobbyDataUpdated = true;
}
}
}
@@ -135,24 +137,72 @@ namespace Facepunch.Steamworks
{
if (callback.Success == 1) //1 if success, 0 if failure
{
if (ManualLobbyDataCallbacks.ContainsKey(callback.SteamIDLobby))
{
ManualLobbyDataCallbacks[callback.SteamIDLobby]?.Invoke(Lobby.FromSteam(client, callback.SteamIDLobby));
}
//find the lobby that has been updated
Lobby lobby = Lobbies.Find(x => x != null && x.LobbyID == callback.SteamIDLobby);
//if this lobby isn't yet in the list of lobbies, we know that we should add it
if (lobby == null)
{
lobby = Lobby.FromSteam(client, callback.SteamIDLobby);
Lobbies.Add(lobby);
checkFinished();
if (requests.Contains(callback.SteamIDLobby))
{
lobby = Lobby.FromSteam(client, callback.SteamIDLobby);
Lobbies.Add(lobby);
checkFinished();
}
}
//otherwise lobby data in general was updated and you should listen to see what changed
if (OnLobbiesUpdated != null) { OnLobbiesUpdated(); }
if (requests.Contains(callback.SteamIDLobby))
{
OnLobbiesUpdated?.Invoke();
}
}
}
public Action OnLobbiesUpdated;
public Lobby GetLobbyFromID(ulong lobbyId)
{
return Lobby.FromSteam(client, lobbyId);
}
public void RequestLobbyData(ulong lobby)
{
client.native.matchmaking.RequestLobbyData(lobby);
}
public void SetManualLobbyDataCallback(ulong steamId, Action<Lobby> callback)
{
if (callback != null)
{
if (ManualLobbyDataCallbacks == null)
{
ManualLobbyDataCallbacks = new Dictionary<ulong, Action<Lobby>>();
}
if (!ManualLobbyDataCallbacks.ContainsKey(steamId))
{
ManualLobbyDataCallbacks.Add(steamId, callback);
}
else
{
ManualLobbyDataCallbacks[steamId] = callback;
}
}
else
{
if (ManualLobbyDataCallbacks == null) { return; }
if (ManualLobbyDataCallbacks.ContainsKey(steamId))
{
ManualLobbyDataCallbacks.Remove(steamId);
}
}
}
public void Dispose()
{
client = null;
@@ -1,12 +1,349 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using SteamNative;
namespace Facepunch.Steamworks
{
//ISteamMatchmakingRulesResponse & ISteamMatchmakingPlayersResponse taken from:
// https://github.com/rlabrecque/Steamworks.NET/blob/master/Plugins/Steamworks.NET/ISteamMatchmakingResponses.cs
/**
The MIT License (MIT)
Copyright (c) 2013-2019 Riley Labrecque
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.
**/
public class ISteamMatchmakingPingResponse
{
// Server has responded successfully and has updated data
public delegate void ServerResponded(ServerList.Server server);
// Server failed to respond to the ping request
public delegate void ServerFailedToRespond();
private VTable m_VTable;
private IntPtr m_pVTable;
private GCHandle m_pGCHandle;
private ServerResponded m_ServerResponded;
private ServerFailedToRespond m_ServerFailedToRespond;
private Client client;
public ISteamMatchmakingPingResponse(Client c, ServerResponded onServerResponded, ServerFailedToRespond onServerFailedToRespond)
{
if (onServerResponded == null || onServerFailedToRespond == null)
{
throw new ArgumentNullException();
}
client = c;
m_ServerResponded = onServerResponded;
m_ServerFailedToRespond = onServerFailedToRespond;
m_VTable = new VTable()
{
m_VTServerResponded = InternalOnServerResponded,
m_VTServerFailedToRespond = InternalOnServerFailedToRespond,
};
m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));
Marshal.StructureToPtr(m_VTable, m_pVTable, false);
m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);
}
~ISteamMatchmakingPingResponse()
{
if (m_pVTable != IntPtr.Zero)
{
Marshal.FreeHGlobal(m_pVTable);
}
if (m_pGCHandle.IsAllocated)
{
m_pGCHandle.Free();
}
}
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void InternalServerResponded(IntPtr thisptr, gameserveritem_t server);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void InternalServerFailedToRespond(IntPtr thisptr);
private void InternalOnServerResponded(IntPtr thisptr, gameserveritem_t serverItem)
{
m_ServerResponded(ServerList.Server.FromSteam(client, serverItem));
}
private void InternalOnServerFailedToRespond(IntPtr thisptr)
{
m_ServerFailedToRespond();
}
[StructLayout(LayoutKind.Sequential)]
private class VTable
{
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalServerResponded m_VTServerResponded;
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalServerFailedToRespond m_VTServerFailedToRespond;
}
public static explicit operator System.IntPtr(ISteamMatchmakingPingResponse that)
{
return that.m_pGCHandle.AddrOfPinnedObject();
}
};
public class ISteamMatchmakingRulesResponse
{
// Got data on a rule on the server -- you'll get one of these per rule defined on
// the server you are querying
public delegate void RulesResponded(string pchRule, string pchValue);
// The server failed to respond to the request for rule details
public delegate void RulesFailedToRespond();
// The server has finished responding to the rule details request
// (ie, you won't get anymore RulesResponded callbacks)
public delegate void RulesRefreshComplete();
private VTable m_VTable;
private IntPtr m_pVTable;
private GCHandle m_pGCHandle;
private RulesResponded m_RulesResponded;
private RulesFailedToRespond m_RulesFailedToRespond;
private RulesRefreshComplete m_RulesRefreshComplete;
public ISteamMatchmakingRulesResponse(RulesResponded onRulesResponded, RulesFailedToRespond onRulesFailedToRespond, RulesRefreshComplete onRulesRefreshComplete)
{
if (onRulesResponded == null || onRulesFailedToRespond == null || onRulesRefreshComplete == null)
{
throw new ArgumentNullException();
}
m_RulesResponded = onRulesResponded;
m_RulesFailedToRespond = onRulesFailedToRespond;
m_RulesRefreshComplete = onRulesRefreshComplete;
m_VTable = new VTable()
{
m_VTRulesResponded = InternalOnRulesResponded,
m_VTRulesFailedToRespond = InternalOnRulesFailedToRespond,
m_VTRulesRefreshComplete = InternalOnRulesRefreshComplete
};
m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));
Marshal.StructureToPtr(m_VTable, m_pVTable, false);
m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);
}
~ISteamMatchmakingRulesResponse()
{
if (m_pVTable != IntPtr.Zero)
{
Marshal.FreeHGlobal(m_pVTable);
}
if (m_pGCHandle.IsAllocated)
{
m_pGCHandle.Free();
}
}
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void InternalRulesResponded(IntPtr thisptr, IntPtr pchRule, IntPtr pchValue);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void InternalRulesFailedToRespond(IntPtr thisptr);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void InternalRulesRefreshComplete(IntPtr thisptr);
private void InternalOnRulesResponded(IntPtr thisptr, IntPtr pchRule, IntPtr pchValue)
{
List<byte> bytes = new List<byte>();
IntPtr seekPointer = pchRule;
byte b = Marshal.ReadByte(seekPointer);
while (b != 0)
{
bytes.Add(b);
seekPointer = (IntPtr)(seekPointer.ToInt64() + sizeof(byte));
b = Marshal.ReadByte(seekPointer);
}
string pchRuleDecoded = Encoding.UTF8.GetString(bytes.ToArray());
bytes.Clear();
seekPointer = pchValue;
b = Marshal.ReadByte(seekPointer);
while (b != 0)
{
bytes.Add(b);
seekPointer = (IntPtr)(seekPointer.ToInt64() + sizeof(byte));
b = Marshal.ReadByte(seekPointer);
}
string pchValueDecoded = Encoding.UTF8.GetString(bytes.ToArray());
m_RulesResponded(pchRuleDecoded, pchValueDecoded);
}
private void InternalOnRulesFailedToRespond(IntPtr thisptr)
{
m_RulesFailedToRespond();
}
private void InternalOnRulesRefreshComplete(IntPtr thisptr)
{
m_RulesRefreshComplete();
}
[StructLayout(LayoutKind.Sequential)]
private class VTable
{
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalRulesResponded m_VTRulesResponded;
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
}
public static explicit operator System.IntPtr(ISteamMatchmakingRulesResponse that)
{
return that.m_pGCHandle.AddrOfPinnedObject();
}
};
public class ISteamMatchmakingPlayersResponse
{
// Got data on a new player on the server -- you'll get this callback once per player
// on the server which you have requested player data on.
public delegate void AddPlayerToList(string pchName, int nScore, float flTimePlayed);
// The server failed to respond to the request for player details
public delegate void PlayersFailedToRespond();
// The server has finished responding to the player details request
// (ie, you won't get anymore AddPlayerToList callbacks)
public delegate void PlayersRefreshComplete();
private VTable m_VTable;
private IntPtr m_pVTable;
private GCHandle m_pGCHandle;
private AddPlayerToList m_AddPlayerToList;
private PlayersFailedToRespond m_PlayersFailedToRespond;
private PlayersRefreshComplete m_PlayersRefreshComplete;
public ISteamMatchmakingPlayersResponse(AddPlayerToList onAddPlayerToList, PlayersFailedToRespond onPlayersFailedToRespond, PlayersRefreshComplete onPlayersRefreshComplete)
{
if (onAddPlayerToList == null || onPlayersFailedToRespond == null || onPlayersRefreshComplete == null)
{
throw new ArgumentNullException();
}
m_AddPlayerToList = onAddPlayerToList;
m_PlayersFailedToRespond = onPlayersFailedToRespond;
m_PlayersRefreshComplete = onPlayersRefreshComplete;
m_VTable = new VTable()
{
m_VTAddPlayerToList = InternalOnAddPlayerToList,
m_VTPlayersFailedToRespond = InternalOnPlayersFailedToRespond,
m_VTPlayersRefreshComplete = InternalOnPlayersRefreshComplete
};
m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VTable)));
Marshal.StructureToPtr(m_VTable, m_pVTable, false);
m_pGCHandle = GCHandle.Alloc(m_pVTable, GCHandleType.Pinned);
}
~ISteamMatchmakingPlayersResponse()
{
if (m_pVTable != IntPtr.Zero)
{
Marshal.FreeHGlobal(m_pVTable);
}
if (m_pGCHandle.IsAllocated)
{
m_pGCHandle.Free();
}
}
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void InternalAddPlayerToList(IntPtr thisptr, IntPtr pchName, int nScore, float flTimePlayed);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void InternalPlayersFailedToRespond(IntPtr thisptr);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate void InternalPlayersRefreshComplete(IntPtr thisptr);
private void InternalOnAddPlayerToList(IntPtr thisptr, IntPtr pchName, int nScore, float flTimePlayed)
{
List<byte> bytes = new List<byte>();
IntPtr seekPointer = pchName;
byte b = Marshal.ReadByte(seekPointer);
while (b != 0)
{
bytes.Add(b);
seekPointer = (IntPtr)(seekPointer.ToInt64() + sizeof(byte));
b = Marshal.ReadByte(seekPointer);
}
string pchNameDecoded = Encoding.UTF8.GetString(bytes.ToArray());
m_AddPlayerToList(pchNameDecoded, nScore, flTimePlayed);
}
private void InternalOnPlayersFailedToRespond(IntPtr thisptr)
{
m_PlayersFailedToRespond();
}
private void InternalOnPlayersRefreshComplete(IntPtr thisptr)
{
m_PlayersRefreshComplete();
}
[StructLayout(LayoutKind.Sequential)]
private class VTable
{
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalAddPlayerToList m_VTAddPlayerToList;
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalPlayersFailedToRespond m_VTPlayersFailedToRespond;
[NonSerialized]
[MarshalAs(UnmanagedType.FunctionPtr)]
public InternalPlayersRefreshComplete m_VTPlayersRefreshComplete;
}
public static explicit operator System.IntPtr(ISteamMatchmakingPlayersResponse that)
{
return that.m_pGCHandle.AddrOfPinnedObject();
}
};
public partial class ServerList : IDisposable
{
internal Client client;
@@ -124,7 +461,20 @@ namespace Facepunch.Steamworks
public string value;
}
public void CancelHQuery(int query)
{
client.native.servers.CancelServerQuery((HServerQuery)query);
}
public int HQueryPing(ISteamMatchmakingPingResponse response, IPAddress ip, int port)
{
return client.native.servers.PingServer(ip.IpToInt32(), (ushort)port, (IntPtr)response).Value;
}
public int HQueryServerRules(ISteamMatchmakingRulesResponse response, IPAddress ip, int queryPort)
{
return client.native.servers.ServerRules(ip.IpToInt32(), (ushort)queryPort, (IntPtr)response).Value;
}
public Request Internet( Filter filter = null )
{
@@ -85,21 +85,30 @@ namespace Facepunch.Steamworks
unsafe void RunInternal()
{
string queryType = "";
if ( FileId.Count != 0 )
{
var fileArray = FileId.Select( x => (SteamNative.PublishedFileId_t)x ).ToArray();
_resultsRemain = fileArray.Length;
Handle = workshop.ugc.CreateQueryUGCDetailsRequest( fileArray );
queryType = "DetailsRequest";
}
else if ( UserId.HasValue )
{
uint accountId = (uint)( UserId.Value & 0xFFFFFFFFul );
Handle = workshop.ugc.CreateQueryUserUGCRequest( accountId, (SteamNative.UserUGCList)( int)UserQueryType, (SteamNative.UGCMatchingUGCType)( int)QueryType, SteamNative.UserUGCListSortOrder.LastUpdatedDesc, UploaderAppId, AppId, (uint)_resultPage + 1 );
queryType = "UserRequest";
}
else
{
Handle = workshop.ugc.CreateQueryAllUGCRequest( (SteamNative.UGCQuery)(int)Order, (SteamNative.UGCMatchingUGCType)(int)QueryType, UploaderAppId, AppId, (uint)_resultPage + 1 );
queryType = "AllRequest";
}
if (Handle == 0xfffffffffffffffful)
{
throw new Exception("Steam UGC "+queryType+" Query Handle invalid!");
}
if ( !string.IsNullOrEmpty( SearchText ) )
@@ -246,7 +255,7 @@ namespace Facepunch.Steamworks
public void Dispose()
{
// ReleaseQueryUGCRequest
workshop.ugc.ReleaseQueryUGCRequest(Handle);
}
}
@@ -520,8 +520,9 @@ namespace Microsoft.Xna.Framework.Graphics
if (_d3dContext != null)
_d3dContext.Dispose();
// Windows requires BGRA support out of DX.
var creationFlags = SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport;
// Windows requires BGRA support out of DX. (...what)
// Barotrauma doesn't tho
var creationFlags = SharpDX.Direct3D11.DeviceCreationFlags.None;//.BgraSupport;
if (GraphicsAdapter.UseDebugLayers)
{
@@ -545,14 +546,14 @@ namespace Microsoft.Xna.Framework.Graphics
{
featureLevels = new[]
{
// For the Reach profile, first try use the highest supported 9_X feature level
FeatureLevel.Level_9_3,
FeatureLevel.Level_9_2,
FeatureLevel.Level_9_1,
// If level 9 is not supported, then just use the highest supported level
// Try using the highest supported level
FeatureLevel.Level_11_0,
FeatureLevel.Level_10_1,
FeatureLevel.Level_10_0,
// Then try using the highest supported 9_X feature level
FeatureLevel.Level_9_3,
FeatureLevel.Level_9_2,
FeatureLevel.Level_9_1,
};
}
@@ -583,7 +584,7 @@ namespace Microsoft.Xna.Framework.Graphics
_d3dDevice = defaultDevice.QueryInterface<SharpDX.Direct3D11.Device>();
}
// Get Direct3D 11.1 context
// Get Direct3D 11 context
_d3dContext = _d3dDevice.ImmediateContext.QueryInterface<SharpDX.Direct3D11.DeviceContext>();
// Create a new instance of GraphicsDebug because we support it on Windows platforms.
@@ -600,24 +601,6 @@ namespace Microsoft.Xna.Framework.Graphics
_swapChain.SetFullscreenState(false, null);
}
internal void ResizeTargets()
{
var format = SharpDXHelper.ToFormat(PresentationParameters.BackBufferFormat);
var descr = new ModeDescription
{
Format = format,
#if WINRT
Scaling = DisplayModeScaling.Stretched,
#else
Scaling = DisplayModeScaling.Unspecified,
#endif
Width = PresentationParameters.BackBufferWidth,
Height = PresentationParameters.BackBufferHeight,
};
_swapChain.ResizeTarget(ref descr);
}
internal void GetModeSwitchedSize(out int width, out int height)
{
Output output = null;
@@ -717,76 +700,59 @@ namespace Microsoft.Xna.Framework.Graphics
format,
PresentationParameters.MultiSampleCount);
// If the swap chain already exists... update it.
if (false && _swapChain != null
// check if multisampling hasn't changed
&& _swapChain.Description.SampleDescription.Count == multisampleDesc.Count
&& _swapChain.Description.SampleDescription.Quality == multisampleDesc.Quality)
// Create a new swap chain.
var wasFullScreen = false;
// Dispose of old swap chain if exists
if (_swapChain != null)
{
_swapChain.ResizeBuffers(2,
PresentationParameters.BackBufferWidth,
PresentationParameters.BackBufferHeight,
format,
SwapChainFlags.AllowModeSwitch);
wasFullScreen = _swapChain.IsFullScreen;
// Before releasing a swap chain, first switch to windowed mode
_swapChain.SetFullscreenState(false, null);
_swapChain.Dispose();
}
// Otherwise, create a new swap chain.
else
// SwapChain description
var desc = new SharpDX.DXGI.SwapChainDescription()
{
var wasFullScreen = false;
// Dispose of old swap chain if exists
if (_swapChain != null)
ModeDescription =
{
wasFullScreen = _swapChain.IsFullScreen;
// Before releasing a swap chain, first switch to windowed mode
_swapChain.SetFullscreenState(false, null);
_swapChain.Dispose();
}
// SwapChain description
var desc = new SharpDX.DXGI.SwapChainDescription()
{
ModeDescription =
{
Format = format,
Format = format,
#if WINDOWS_UAP
Scaling = DisplayModeScaling.Stretched,
Scaling = DisplayModeScaling.Stretched,
#else
Scaling = DisplayModeScaling.Unspecified,
Scaling = DisplayModeScaling.Unspecified,
#endif
Width = PresentationParameters.BackBufferWidth,
Height = PresentationParameters.BackBufferHeight,
},
Width = PresentationParameters.BackBufferWidth,
Height = PresentationParameters.BackBufferHeight,
},
OutputHandle = PresentationParameters.DeviceWindowHandle,
SampleDescription = multisampleDesc,
Usage = SharpDX.DXGI.Usage.RenderTargetOutput,
BufferCount = 2,
SwapEffect = SharpDXHelper.ToSwapEffect(PresentationParameters.PresentationInterval),
IsWindowed = true,
Flags = SwapChainFlags.AllowModeSwitch
};
OutputHandle = PresentationParameters.DeviceWindowHandle,
SampleDescription = multisampleDesc,
Usage = SharpDX.DXGI.Usage.RenderTargetOutput,
BufferCount = 2,
SwapEffect = SharpDXHelper.ToSwapEffect(PresentationParameters.PresentationInterval),
IsWindowed = true
};
// Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
// Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
// First, retrieve the underlying DXGI Device from the D3D Device.
// Creates the swap chain
using (var dxgiDevice = _d3dDevice.QueryInterface<SharpDX.DXGI.Device1>())
using (var dxgiAdapter = dxgiDevice.Adapter)
using (var dxgiFactory = dxgiAdapter.GetParent<SharpDX.DXGI.Factory1>())
{
_swapChain = new SwapChain(dxgiFactory, dxgiDevice, desc);
RefreshAdapter();
dxgiFactory.MakeWindowAssociation(PresentationParameters.DeviceWindowHandle, WindowAssociationFlags.IgnoreAll);
// To reduce latency, ensure that DXGI does not queue more than one frame at a time.
// Docs: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471334(v=vs.85).aspx
dxgiDevice.MaximumFrameLatency = 1;
}
// Preserve full screen state, after swap chain is re-created
if (PresentationParameters.HardwareModeSwitch
&& wasFullScreen)
SetHardwareFullscreen();
// First, retrieve the underlying DXGI Device from the D3D Device.
// Creates the swap chain
using (var dxgiDevice = _d3dDevice.QueryInterface<SharpDX.DXGI.Device1>())
using (var dxgiAdapter = dxgiDevice.Adapter)
using (var dxgiFactory = dxgiAdapter.GetParent<SharpDX.DXGI.Factory1>())
{
_swapChain = new SwapChain(dxgiFactory, dxgiDevice, desc);
RefreshAdapter();
dxgiFactory.MakeWindowAssociation(PresentationParameters.DeviceWindowHandle, WindowAssociationFlags.IgnoreAll);
// To reduce latency, ensure that DXGI does not queue more than one frame at a time.
// Docs: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471334(v=vs.85).aspx
dxgiDevice.MaximumFrameLatency = 1;
}
// Preserve full screen state, after swap chain is re-created
if (PresentationParameters.HardwareModeSwitch
&& wasFullScreen)
SetHardwareFullscreen();
// Obtain the backbuffer for this window which will be the final 3D rendertarget.
Point targetSize;
@@ -72,7 +72,10 @@ namespace Microsoft.Xna.Framework.Graphics
var subresourceIndex = CalculateSubresourceIndex(0, level);
var d3dContext = GraphicsDevice._d3dContext;
lock (d3dContext)
{
d3dContext.UpdateSubresource(GetTexture(), subresourceIndex, region, dataPtr, GetPitch(w), 0);
d3dContext.GenerateMips(GetShaderResourceView());
}
}
finally
{
@@ -390,6 +393,12 @@ namespace Microsoft.Xna.Framework.Graphics
if (_shared)
desc.OptionFlags |= ResourceOptionFlags.Shared;
if (_mipmap)
{
desc.OptionFlags |= ResourceOptionFlags.GenerateMipMaps;
desc.BindFlags |= BindFlags.RenderTarget;
}
return desc;
}
internal override Resource CreateTexture()
@@ -403,6 +412,30 @@ namespace Microsoft.Xna.Framework.Graphics
return new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc);
}
protected override ShaderResourceView CreateShaderResourceView()
{
var texDesc = GetTexture2DDescription();
if (_mipmap)
{
ShaderResourceViewDescription resViewDesc = new ShaderResourceViewDescription()
{
Format = texDesc.Format,
Dimension = SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D,
Texture2D = new ShaderResourceViewDescription.Texture2DResource()
{
MostDetailedMip = 0,
MipLevels = texDesc.MipLevels
}
};
return new SharpDX.Direct3D11.ShaderResourceView(GraphicsDevice._d3dDevice, GetTexture(), resViewDesc);
}
else
{
return base.CreateShaderResourceView();
}
}
protected internal virtual SampleDescription CreateSampleDescription()
{
return new SampleDescription(1, 0);
@@ -118,6 +118,12 @@ namespace Microsoft.Xna.Framework.Graphics
}
GraphicsExtensions.CheckGLError();
if (CurrentPlatform.OS != OS.MacOSX)
{
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GraphicsExtensions.CheckGLError();
}
#if !ANDROID
// Required to make sure that any texture uploads on a thread are completed
// before the main thread tries to use the texture.
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Xna.Framework
{
public static class MessageBox
{
[Flags]
public enum Flags : uint
{
Error = 0x00000010,
Warning = 0x00000020,
Information = 0x00000040
}
public static void Show(Flags flags, string title, string message, GameWindow window = null)
{
Sdl.ShowSimpleMessageBox((uint)flags, title, message, window?.Handle ?? IntPtr.Zero);
}
public static void ShowWrapped(Flags flags, string title, string message, int charsPerLine = 60, GameWindow window = null)
{
string[] split = message.Split(' ');
if (split.Length > 0)
{
message = split[0];
string currLine = message;
for (int i = 1; i < split.Length; i++)
{
currLine += " " + split[i];
if (currLine.Length > charsPerLine)
{
currLine = split[i];
message += "\n" + split[i];
}
else
{
message += " " + split[i];
}
}
}
Show(flags, title, message, window);
}
}
}
@@ -30,7 +30,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<DebugType>none</DebugType>
<DebugType>pdbonly</DebugType>
<OutputPath>..\..\DesktopGL\</OutputPath>
<IntermediateOutputPath>obj\Linux\AnyCPU\Release</IntermediateOutputPath>
<DocumentationFile>..\..\DesktopGL\MonoGame.Framework.xml</DocumentationFile>
@@ -38,6 +38,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -45,6 +46,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Clipboard.cs" />
<Compile Include="MessageBox.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\AssemblyInfo.DesktopGL.cs">
<Platforms>WindowsGL,Linux</Platforms>
@@ -81,6 +81,7 @@
<Compile Include="Input\KeyboardUtil.SDL.cs" />
<Compile Include="Input\Mouse.SDL.cs" />
<Compile Include="Input\MouseCursor.SDL.cs" />
<Compile Include="MessageBox.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\AssemblyInfo.Windows.cs">
<Platforms>Windows</Platforms>
@@ -255,12 +255,26 @@ internal static class Sdl
public static void SetClipboardText(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
byte[] bytes = Encoding.UTF8.GetBytes(text+"\0");
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
GetError(SDL_SetClipboardText(handle.AddrOfPinnedObject()));
handle.Free();
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int d_sdl_showsimplemessagebox(uint flags, IntPtr title, IntPtr msg, IntPtr window);
public static d_sdl_showsimplemessagebox SDL_ShowSimpleMessageBox = FuncLoader.LoadFunction<d_sdl_showsimplemessagebox>(NativeLibrary, "SDL_ShowSimpleMessageBox");
public static void ShowSimpleMessageBox(uint flags, string title, string message, IntPtr window)
{
byte[] bytesTitle = Encoding.UTF8.GetBytes(title + "\0");
GCHandle handleTitle = GCHandle.Alloc(bytesTitle, GCHandleType.Pinned);
byte[] bytesMessage = Encoding.UTF8.GetBytes(message + "\0");
GCHandle handleMessage = GCHandle.Alloc(bytesMessage, GCHandleType.Pinned);
GetError(SDL_ShowSimpleMessageBox(flags, handleTitle.AddrOfPinnedObject(), handleMessage.AddrOfPinnedObject(), window));
handleTitle.Free();
handleMessage.Free();
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr d_sdl_gethint(string name);
public static d_sdl_gethint SDL_GetHint = FuncLoader.LoadFunction<d_sdl_gethint>(NativeLibrary, "SDL_GetHint");