Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ISteamTimeline supports #201

Merged
merged 2 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub use crate::networking::*;
pub use crate::remote_play::*;
pub use crate::remote_storage::*;
pub use crate::server::*;
pub use crate::timeline::*;
pub use crate::ugc::*;
pub use crate::user::*;
pub use crate::user_stats::*;
Expand All @@ -55,6 +56,7 @@ mod remote_play;
mod remote_storage;
pub mod screenshots;
mod server;
pub mod timeline;
mod ugc;
mod user;
mod user_stats;
Expand Down Expand Up @@ -426,6 +428,19 @@ where
}
}

/// Returns an accessor to the steam timeline interface
pub fn timeline(&self) -> Timeline<Manager> {
unsafe {
let timeline = sys::SteamAPI_SteamTimeline_v001();

Timeline {
timeline,
disabled: timeline.is_null(),
_inner: self.inner.clone(),
}
}
}

pub fn networking_messages(&self) -> networking_messages::NetworkingMessages<Manager> {
unsafe {
let net = sys::SteamAPI_SteamNetworkingMessages_SteamAPI_v002();
Expand Down
141 changes: 141 additions & 0 deletions src/timeline.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use super::*;
use std::time::Duration;

pub struct Timeline<Manager> {
pub(crate) timeline: *mut sys::ISteamTimeline,
/// Whether the client's steam API is not recent enough.
pub(crate) disabled: bool,
pub(crate) _inner: Arc<Inner<Manager>>,
}

pub enum TimelineGameMode {
/// The player is fully loaded into the game and playing.
Playing,
/// The player is in a multiplayer lobby.
Staging,
/// The player is in the game's main menu or a pause menu.
Menus,
/// The player is waiting for a loading screen.
LoadingScreen,
}

impl From<TimelineGameMode> for sys::ETimelineGameMode {
fn from(mode: TimelineGameMode) -> Self {
match mode {
TimelineGameMode::Playing => sys::ETimelineGameMode::k_ETimelineGameMode_Playing,
TimelineGameMode::Staging => sys::ETimelineGameMode::k_ETimelineGameMode_Staging,
TimelineGameMode::Menus => sys::ETimelineGameMode::k_ETimelineGameMode_Menus,
TimelineGameMode::LoadingScreen => {
sys::ETimelineGameMode::k_ETimelineGameMode_LoadingScreen
}
}
}
}

pub enum TimelineEventClipPriority {
/// This event is not appropriate as a clip.
None,
/// The user may want to make a clip around this event.
Standard,
/// The player will be likely to want a clip around event,
/// and those clips should be promoted more prominently than clips with the [TimelineEventClipPriority::Standard] priority.
Featured,
}

impl From<TimelineEventClipPriority> for sys::ETimelineEventClipPriority {
fn from(priority: TimelineEventClipPriority) -> Self {
match priority {
TimelineEventClipPriority::None => {
sys::ETimelineEventClipPriority::k_ETimelineEventClipPriority_None
}
TimelineEventClipPriority::Standard => {
sys::ETimelineEventClipPriority::k_ETimelineEventClipPriority_Standard
}
TimelineEventClipPriority::Featured => {
sys::ETimelineEventClipPriority::k_ETimelineEventClipPriority_Featured
}
}
}
}

impl<Manager> Timeline<Manager> {
/// Changes the color of the timeline bar.
pub fn set_timeline_game_mode(&self, mode: TimelineGameMode) {
if self.disabled {
return;
}

unsafe {
sys::SteamAPI_ISteamTimeline_SetTimelineGameMode(self.timeline, mode.into());
}
}

/// 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.
pub fn set_timeline_state_description(&self, description: &str, duration: Duration) {
if self.disabled {
return;
}

let description = CString::new(description).unwrap();

unsafe {
sys::SteamAPI_ISteamTimeline_SetTimelineStateDescription(
self.timeline,
description.as_ptr(),
duration.as_secs_f32(),
)
}
}

/// Clears the previous set game state in the timeline.
pub fn clear_timeline_state_description(&self, duration: Duration) {
if self.disabled {
return;
}

unsafe {
sys::SteamAPI_ISteamTimeline_ClearTimelineStateDescription(
self.timeline,
duration.as_secs_f32(),
)
}
}

/// Use this to mark an event on the Timeline.
/// The event can be instantaneous or take some amount of time to complete,
/// depending on the value passed in `duration`.
pub fn add_timeline_event(
&self,
icon: &str,
title: &str,
description: &str,
priority: u32,
start_offset_seconds: f32,
duration: Duration,
clip_priority: TimelineEventClipPriority,
) {
if self.disabled {
return;
}

let icon = CString::new(icon).unwrap();
let title = CString::new(title).unwrap();
let description = CString::new(description).unwrap();
let duration = duration.as_secs_f32();

unsafe {
sys::SteamAPI_ISteamTimeline_AddTimelineEvent(
self.timeline,
icon.as_ptr(),
title.as_ptr(),
description.as_ptr(),
priority,
start_offset_seconds,
duration,
clip_priority.into(),
)
}
}
}
Loading