From e4455258ace59c1e8f165cbaabb286fc0a8dc5c0 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Mon, 16 Dec 2024 11:49:31 -0500 Subject: [PATCH] Add SteamTimeline --- .../Generated/Interfaces/ISteamTimeline.cs | 32 +-- Facepunch.Steamworks/Generated/SteamEnums.cs | 4 +- Facepunch.Steamworks/Generated/SteamTypes.cs | 16 +- Facepunch.Steamworks/SteamClient.cs | 9 +- Facepunch.Steamworks/SteamTimeline.cs | 202 ++++++++++++++++++ .../Structs/GamePhaseRecordingInfo.cs | 10 + Generator/Cleanup.cs | 4 + 7 files changed, 248 insertions(+), 29 deletions(-) create mode 100644 Facepunch.Steamworks/SteamTimeline.cs create mode 100644 Facepunch.Steamworks/Structs/GamePhaseRecordingInfo.cs diff --git a/Facepunch.Steamworks/Generated/Interfaces/ISteamTimeline.cs b/Facepunch.Steamworks/Generated/Interfaces/ISteamTimeline.cs index a3835b9..16bc516 100644 --- a/Facepunch.Steamworks/Generated/Interfaces/ISteamTimeline.cs +++ b/Facepunch.Steamworks/Generated/Interfaces/ISteamTimeline.cs @@ -53,10 +53,10 @@ internal void SetTimelineGameMode( TimelineGameMode eMode ) #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_AddInstantaneousTimelineEvent", CallingConvention = Platform.CC)] - private static extern TimelineEventHandle_t _AddInstantaneousTimelineEvent( IntPtr self, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ); + private static extern TimelineEventHandle _AddInstantaneousTimelineEvent( IntPtr self, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ); #endregion - internal TimelineEventHandle_t AddInstantaneousTimelineEvent( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ) + internal TimelineEventHandle AddInstantaneousTimelineEvent( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ) { var returnValue = _AddInstantaneousTimelineEvent( Self, pchTitle, pchDescription, pchIcon, unIconPriority, flStartOffsetSeconds, ePossibleClip ); return returnValue; @@ -64,10 +64,10 @@ internal TimelineEventHandle_t AddInstantaneousTimelineEvent( [MarshalAs( Unmana #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_AddRangeTimelineEvent", CallingConvention = Platform.CC)] - private static extern TimelineEventHandle_t _AddRangeTimelineEvent( IntPtr self, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, float flDuration, TimelineEventClipPriority ePossibleClip ); + private static extern TimelineEventHandle _AddRangeTimelineEvent( IntPtr self, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, float flDuration, TimelineEventClipPriority ePossibleClip ); #endregion - internal TimelineEventHandle_t AddRangeTimelineEvent( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, float flDuration, TimelineEventClipPriority ePossibleClip ) + internal TimelineEventHandle AddRangeTimelineEvent( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unIconPriority, float flStartOffsetSeconds, float flDuration, TimelineEventClipPriority ePossibleClip ) { var returnValue = _AddRangeTimelineEvent( Self, pchTitle, pchDescription, pchIcon, unIconPriority, flStartOffsetSeconds, flDuration, ePossibleClip ); return returnValue; @@ -75,10 +75,10 @@ internal TimelineEventHandle_t AddRangeTimelineEvent( [MarshalAs( UnmanagedType. #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_StartRangeTimelineEvent", CallingConvention = Platform.CC)] - private static extern TimelineEventHandle_t _StartRangeTimelineEvent( IntPtr self, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ); + private static extern TimelineEventHandle _StartRangeTimelineEvent( IntPtr self, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ); #endregion - internal TimelineEventHandle_t StartRangeTimelineEvent( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ) + internal TimelineEventHandle StartRangeTimelineEvent( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, float flStartOffsetSeconds, TimelineEventClipPriority ePossibleClip ) { var returnValue = _StartRangeTimelineEvent( Self, pchTitle, pchDescription, pchIcon, unPriority, flStartOffsetSeconds, ePossibleClip ); return returnValue; @@ -86,40 +86,40 @@ internal TimelineEventHandle_t StartRangeTimelineEvent( [MarshalAs( UnmanagedTyp #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_UpdateRangeTimelineEvent", CallingConvention = Platform.CC)] - private static extern void _UpdateRangeTimelineEvent( IntPtr self, TimelineEventHandle_t ulEvent, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, TimelineEventClipPriority ePossibleClip ); + private static extern void _UpdateRangeTimelineEvent( IntPtr self, TimelineEventHandle ulEvent, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, TimelineEventClipPriority ePossibleClip ); #endregion - internal void UpdateRangeTimelineEvent( TimelineEventHandle_t ulEvent, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, TimelineEventClipPriority ePossibleClip ) + internal void UpdateRangeTimelineEvent( TimelineEventHandle ulEvent, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchTitle, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchDescription, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchIcon, uint unPriority, TimelineEventClipPriority ePossibleClip ) { _UpdateRangeTimelineEvent( Self, ulEvent, pchTitle, pchDescription, pchIcon, unPriority, ePossibleClip ); } #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_EndRangeTimelineEvent", CallingConvention = Platform.CC)] - private static extern void _EndRangeTimelineEvent( IntPtr self, TimelineEventHandle_t ulEvent, float flEndOffsetSeconds ); + private static extern void _EndRangeTimelineEvent( IntPtr self, TimelineEventHandle ulEvent, float flEndOffsetSeconds ); #endregion - internal void EndRangeTimelineEvent( TimelineEventHandle_t ulEvent, float flEndOffsetSeconds ) + internal void EndRangeTimelineEvent( TimelineEventHandle ulEvent, float flEndOffsetSeconds ) { _EndRangeTimelineEvent( Self, ulEvent, flEndOffsetSeconds ); } #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_RemoveTimelineEvent", CallingConvention = Platform.CC)] - private static extern void _RemoveTimelineEvent( IntPtr self, TimelineEventHandle_t ulEvent ); + private static extern void _RemoveTimelineEvent( IntPtr self, TimelineEventHandle ulEvent ); #endregion - internal void RemoveTimelineEvent( TimelineEventHandle_t ulEvent ) + internal void RemoveTimelineEvent( TimelineEventHandle ulEvent ) { _RemoveTimelineEvent( Self, ulEvent ); } #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_DoesEventRecordingExist", CallingConvention = Platform.CC)] - private static extern SteamAPICall_t _DoesEventRecordingExist( IntPtr self, TimelineEventHandle_t ulEvent ); + private static extern SteamAPICall_t _DoesEventRecordingExist( IntPtr self, TimelineEventHandle ulEvent ); #endregion - internal CallResult DoesEventRecordingExist( TimelineEventHandle_t ulEvent ) + internal CallResult DoesEventRecordingExist( TimelineEventHandle ulEvent ) { var returnValue = _DoesEventRecordingExist( Self, ulEvent ); return new CallResult( returnValue, IsServer ); @@ -198,10 +198,10 @@ internal void OpenOverlayToGamePhase( [MarshalAs( UnmanagedType.CustomMarshaler, #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamTimeline_OpenOverlayToTimelineEvent", CallingConvention = Platform.CC)] - private static extern void _OpenOverlayToTimelineEvent( IntPtr self, TimelineEventHandle_t ulEvent ); + private static extern void _OpenOverlayToTimelineEvent( IntPtr self, TimelineEventHandle ulEvent ); #endregion - internal void OpenOverlayToTimelineEvent( TimelineEventHandle_t ulEvent ) + internal void OpenOverlayToTimelineEvent( TimelineEventHandle ulEvent ) { _OpenOverlayToTimelineEvent( Self, ulEvent ); } diff --git a/Facepunch.Steamworks/Generated/SteamEnums.cs b/Facepunch.Steamworks/Generated/SteamEnums.cs index 2d6cc26..8e7b934 100644 --- a/Facepunch.Steamworks/Generated/SteamEnums.cs +++ b/Facepunch.Steamworks/Generated/SteamEnums.cs @@ -2196,7 +2196,7 @@ internal enum SteamItemFlags : int // // ETimelineGameMode // - internal enum TimelineGameMode : int + public enum TimelineGameMode : int { Invalid = 0, Playing = 1, @@ -2209,7 +2209,7 @@ internal enum TimelineGameMode : int // // ETimelineEventClipPriority // - internal enum TimelineEventClipPriority : int + public enum TimelineEventClipPriority : int { Invalid = 0, None = 1, diff --git a/Facepunch.Steamworks/Generated/SteamTypes.cs b/Facepunch.Steamworks/Generated/SteamTypes.cs index ed6dfea..9aaaa64 100644 --- a/Facepunch.Steamworks/Generated/SteamTypes.cs +++ b/Facepunch.Steamworks/Generated/SteamTypes.cs @@ -598,20 +598,20 @@ internal struct SteamInventoryUpdateHandle_t : IEquatable Value.CompareTo( other.Value ); } - internal struct TimelineEventHandle_t : IEquatable, IComparable + public struct TimelineEventHandle : IEquatable, IComparable { // Name: TimelineEventHandle_t, Type: unsigned long long public ulong Value; - public static implicit operator TimelineEventHandle_t( ulong value ) => new TimelineEventHandle_t(){ Value = value }; - public static implicit operator ulong( TimelineEventHandle_t value ) => value.Value; + public static implicit operator TimelineEventHandle( ulong value ) => new TimelineEventHandle(){ Value = value }; + public static implicit operator ulong( TimelineEventHandle value ) => value.Value; public override string ToString() => Value.ToString(); public override int GetHashCode() => Value.GetHashCode(); - public override bool Equals( object p ) => this.Equals( (TimelineEventHandle_t) p ); - public bool Equals( TimelineEventHandle_t p ) => p.Value == Value; - public static bool operator ==( TimelineEventHandle_t a, TimelineEventHandle_t b ) => a.Equals( b ); - public static bool operator !=( TimelineEventHandle_t a, TimelineEventHandle_t b ) => !a.Equals( b ); - public int CompareTo( TimelineEventHandle_t other ) => Value.CompareTo( other.Value ); + public override bool Equals( object p ) => this.Equals( (TimelineEventHandle) p ); + public bool Equals( TimelineEventHandle p ) => p.Value == Value; + public static bool operator ==( TimelineEventHandle a, TimelineEventHandle b ) => a.Equals( b ); + public static bool operator !=( TimelineEventHandle a, TimelineEventHandle b ) => !a.Equals( b ); + public int CompareTo( TimelineEventHandle other ) => Value.CompareTo( other.Value ); } internal struct RemotePlaySessionID_t : IEquatable, IComparable diff --git a/Facepunch.Steamworks/SteamClient.cs b/Facepunch.Steamworks/SteamClient.cs index 32d2eac..fd29e2f 100644 --- a/Facepunch.Steamworks/SteamClient.cs +++ b/Facepunch.Steamworks/SteamClient.cs @@ -43,7 +43,8 @@ public static void Init( uint appid, bool asyncCallbacks = true ) ISteamUserStats.Version, ISteamUtils.Version, ISteamVideo.Version, - ISteamRemotePlay.Version ); + ISteamRemotePlay.Version, + ISteamTimeline.Version ); var result = SteamAPI.Init( interfaceVersions, out var error ); if ( result != SteamAPIInitResult.OK ) { @@ -55,12 +56,12 @@ public static void Init( uint appid, bool asyncCallbacks = true ) initialized = true; // - // Dispatch is responsible for pumping the - // event loop. + // Dispatch is responsible for pumping the event loop. // Dispatch.Init(); Dispatch.ClientPipe = SteamAPI.GetHSteamPipe(); + // Note: don't forget to add the interface version to SteamAPI.Init above!!! AddInterface(); AddInterface(); AddInterface(); @@ -81,6 +82,8 @@ public static void Init( uint appid, bool asyncCallbacks = true ) AddInterface(); AddInterface(); AddInterface(); + AddInterface(); + // Note: don't forget to add the interface version to SteamAPI.Init above!!! initialized = openInterfaces.Count > 0; diff --git a/Facepunch.Steamworks/SteamTimeline.cs b/Facepunch.Steamworks/SteamTimeline.cs new file mode 100644 index 0000000..f3d44be --- /dev/null +++ b/Facepunch.Steamworks/SteamTimeline.cs @@ -0,0 +1,202 @@ +using System; +using System.Threading.Tasks; +using Steamworks.Data; + +namespace Steamworks; + +public class SteamTimeline : SteamClientClass +{ + internal static ISteamTimeline Internal => Interface as ISteamTimeline; + + internal override bool InitializeInterface( bool server ) + { + SetInterface( server, new ISteamTimeline( server ) ); + if ( Interface.Self == IntPtr.Zero ) return false; + + InstallEvents(); + return true; + } + + internal static void InstallEvents() + { + } + + /// + /// Sets a description for the current game state in the timeline. These help the user to find specific moments in the timeline when saving clips. Setting a + /// new state description replaces any previous description. + /// + public static void SetTimelineTooltip( string description, float timeOffsetSeconds ) + { + Internal.SetTimelineTooltip( description, timeOffsetSeconds ); + } + + /// + /// Clears the previous set game state in the timeline. + /// + public static void ClearTimelineTooltip( float timeOffsetSeconds ) + { + Internal.ClearTimelineTooltip( timeOffsetSeconds ); + } + + /// + /// Use this to mark an event on the Timeline. This event will be instantaneous. (See to add events that happened over time.) + /// + public static TimelineEventHandle AddInstantaneousTimelineEvent( string title, string description, string icon, + uint priority, float startOffsetSeconds, TimelineEventClipPriority possibleClip ) + { + return Internal.AddInstantaneousTimelineEvent( title, description, icon, priority, startOffsetSeconds, + possibleClip ); + } + + /// + /// Use this to mark an event on the Timeline that takes some amount of time to complete. + /// + public static TimelineEventHandle AddRangeTimelineEvent( string title, string description, string icon, + uint priority, float startOffsetSeconds, float durationSeconds, TimelineEventClipPriority possibleClip ) + { + return Internal.AddRangeTimelineEvent( title, description, icon, priority, startOffsetSeconds, durationSeconds, + possibleClip ); + } + + /// + /// Use this to mark the start of an event on the Timeline that takes some amount of time to complete. The duration of the event is determined by a matching call + /// to . If the game wants to cancel an event in progress, they can do that with a call to . + /// + public static TimelineEventHandle StartRangeTimelineEvent( string title, string description, string icon, + uint priority, + float startOffsetSeconds, TimelineEventClipPriority possibleClip ) + { + return Internal.StartRangeTimelineEvent( title, description, icon, priority, startOffsetSeconds, possibleClip ); + } + + /// + /// Use this to update the details of an event that was started with . + /// + public static void UpdateRangeTimelineEvent( TimelineEventHandle handle, string title, string description, + string icon, uint priority, TimelineEventClipPriority possibleClip ) + { + Internal.UpdateRangeTimelineEvent( handle, title, description, icon, priority, possibleClip ); + } + + /// + /// Use this to identify the end of an event that was started with . + /// + public static void EndRangeTimelineEvent( TimelineEventHandle handle, float endOffsetSeconds ) + { + Internal.EndRangeTimelineEvent( handle, endOffsetSeconds ); + } + + /// + /// Use this to remove a Timeline event that was previously added. + /// + public static void RemoveTimelineEvent( TimelineEventHandle handle ) + { + Internal.RemoveTimelineEvent( handle ); + } + + /// + /// Use this to determine if video recordings exist for the specified event. This can be useful when the game needs to decide whether or not to show a control + /// that will call . + /// + public static async Task DoesEventRecordingExist( TimelineEventHandle handle ) + { + var result = await Internal.DoesEventRecordingExist( handle ); + return result?.RecordingExists ?? false; + } + + /// + /// Use this to start a game phase. Game phases allow the user to navigate their background recordings and clips. Exactly what a game phase means will vary game + /// to game, but the game phase should be a section of gameplay that is usually between 10 minutes and a few hours in length, and should be the main way a user + /// would think to divide up the game. These are presented to the user in a UI that shows the date the game was played, with one row per game slice. Game phases + /// should be used to mark sections of gameplay that the user might be interested in watching. + /// + public static void StartGamePhase() + { + Internal.StartGamePhase(); + } + + /// + /// Use this to end a game phase that was started with . + /// + public static void EndGamePhase() + { + Internal.EndGamePhase(); + } + + /// + /// The phase ID is used to let the game identify which phase it is referring to in calls to or + /// . It may also be used to associated multiple phases with each other. + /// + /// A game-provided persistent ID for a game phase. This could be a the match ID in a multiplayer game, a chapter name in a single player game, the ID of a character, etc. + public static void SetGamePhaseId( string phaseId ) + { + Internal.SetGamePhaseID( phaseId ); + } + + /// + /// Use this to determine if video recordings exist for the specified game phase. This can be useful when the game needs to decide whether or not to show a control that will call . + /// + public static async Task DoesGamePhaseRecordingExist( string phaseId ) + { + var result = await Internal.DoesGamePhaseRecordingExist( phaseId ); + if ( !result.HasValue ) + { + return null; + } + + var info = result.Value; + return new GamePhaseRecordingInfo + { + PhaseId = info.PhaseIDUTF8(), + RecordingMs = info.RecordingMS, + LongestClipMs = info.LongestClipMS, + ClipCount = info.ClipCount, + ScreenshotCount = info.ScreenshotCount, + }; + } + + /// + /// Use this to add a game phase tag. Phase tags represent data with a well defined set of options, which could be data such as match resolution, hero played, game mode, etc. Tags can have an icon + /// in addition to a text name. Multiple tags within the same group may be added per phase and all will be remembered. For example, this may be called multiple times for a "Bosses Defeated" group, + /// with different names and icons for each boss defeated during the phase, all of which will be shown to the user. + /// + public static void AddGamePhaseTag( string tagName, string icon, string tagGroup, uint priority ) + { + Internal.AddGamePhaseTag( tagName, icon, tagGroup, priority ); + } + + /// + /// Use this to add a game phase attribute. Phase attributes represent generic text fields that can be updated throughout the duration of the phase. They are meant to be used for phase metadata + /// that is not part of a well defined set of options. For example, a KDA attribute that starts with the value "0/0/0" and updates as the phase progresses, or something like a played-entered character + /// name. Attributes can be set as many times as the game likes with SetGamePhaseAttribute, and only the last value will be shown to the user. + /// + public static void SetGamePhaseAttribute( string attributeGroup, string attributeValue, uint priority ) + { + Internal.SetGamePhaseAttribute( attributeGroup, attributeValue, priority ); + } + + /// + /// Changes the color of the timeline bar. See for how to use each value. + /// + public static void SetTimelineGameMode( TimelineGameMode gameMode ) + { + Internal.SetTimelineGameMode( gameMode ); + } + + /// + /// Opens the Steam overlay to the section of the timeline represented by the game phase. + /// + public static void OpenOverlayToGamePhase( string phaseId ) + { + Internal.OpenOverlayToGamePhase( phaseId ); + } + + /// + /// Opens the Steam overlay to the section of the timeline represented by the timeline event. This event must be in the current game session, since values are not + /// valid for future runs of the game. + /// + public static void OpenOverlayToTimelineEvent( TimelineEventHandle handle ) + { + Internal.OpenOverlayToTimelineEvent( handle ); + } +} diff --git a/Facepunch.Steamworks/Structs/GamePhaseRecordingInfo.cs b/Facepunch.Steamworks/Structs/GamePhaseRecordingInfo.cs new file mode 100644 index 0000000..e44a14b --- /dev/null +++ b/Facepunch.Steamworks/Structs/GamePhaseRecordingInfo.cs @@ -0,0 +1,10 @@ +namespace Steamworks; + +public struct GamePhaseRecordingInfo +{ + public string PhaseId; + public ulong RecordingMs; + public ulong LongestClipMs; + public uint ClipCount; + public uint ScreenshotCount; +} diff --git a/Generator/Cleanup.cs b/Generator/Cleanup.cs index 3414c58..2bb7da2 100644 --- a/Generator/Cleanup.cs +++ b/Generator/Cleanup.cs @@ -64,6 +64,7 @@ public static string ConvertType( string type ) type = type.Replace( "SteamNetConnectionRealTimeLaneStatus_t", "ConnectionLaneStatus" ); type = type.Replace( "SteamInputGlyphSize", "GlyphSize" ); type = type.Replace( "FloatingGamepadTextInputMode", "TextInputMode" ); + type = type.Replace( "TimelineEventHandle_t", "TimelineEventHandle" ); type = type.Replace( "::", "." ); @@ -152,6 +153,9 @@ internal static string Expose( string name ) if ( name == "TextFilteringContext" ) return "public"; if ( name == "GlyphSize" ) return "public"; if ( name == "TextInputMode" ) return "public"; + if ( name == "TimelineGameMode" ) return "public"; + if ( name == "TimelineEventClipPriority" ) return "public"; + if ( name == "TimelineEventHandle" ) return "public"; return "internal"; }