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 is null ) return false; 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 ) { if ( Internal is null ) { return; } Internal.SetTimelineTooltip( description, timeOffsetSeconds ); } /// /// Clears the previous set game state in the timeline. /// public static void ClearTimelineTooltip( float timeOffsetSeconds ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return default; } 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 ) { if ( Internal is null ) { return default; } 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 ) { if ( Internal is null ) { return default; } 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 ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return; } Internal.EndRangeTimelineEvent( handle, endOffsetSeconds ); } /// /// Use this to remove a Timeline event that was previously added. /// public static void RemoveTimelineEvent( TimelineEventHandle handle ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return false; } 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() { if ( Internal is null ) { return; } Internal.StartGamePhase(); } /// /// Use this to end a game phase that was started with . /// public static void EndGamePhase() { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return null; } 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 ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return; } Internal.SetTimelineGameMode( gameMode ); } /// /// Opens the Steam overlay to the section of the timeline represented by the game phase. /// public static void OpenOverlayToGamePhase( string phaseId ) { if ( Internal is null ) { return; } 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 ) { if ( Internal is null ) { return; } Internal.OpenOverlayToTimelineEvent( handle ); } }