1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use std::path::Path;
pub use sys::ScreenshotHandle;
use super::*;
/// Access to the steam screenshots interface
pub struct Screenshots {
pub(crate) screenshots: *mut sys::ISteamScreenshots,
pub(crate) _inner: Arc<Inner>,
}
impl Screenshots {
/// Toggles whether the overlay handles screenshots when the user presses the screenshot hotkey, or if the game handles them.
///
/// Hooking is disabled by default, and only ever enabled if you do so with this function.
///
/// If the hooking is enabled, then the [`ScreenshotRequested`] callback will be sent if the user presses the hotkey or when [`Self::trigger_screenshot`] is called,
/// and then the game is expected to call `WriteScreenshot` or [`Self::add_screenshot_to_library`] in response.
///
/// You can check if hooking is enabled with [`Self::is_screenshots_hooked`].
pub fn hook_screenshots(&self, hook: bool) {
unsafe {
sys::SteamAPI_ISteamScreenshots_HookScreenshots(self.screenshots, hook);
}
}
/// Checks if the app is hooking screenshots, or if the Steam Overlay is handling them.
///
/// This can be toggled with [`Self::hook_screenshots`].
///
/// Returns
/// - `true` if the game is hooking screenshots and is expected to handle them; otherwise, `false`.
pub fn is_screenshots_hooked(&self) -> bool {
unsafe { sys::SteamAPI_ISteamScreenshots_IsScreenshotsHooked(self.screenshots) }
}
/// Either causes the Steam Overlay to take a screenshot, or tells your screenshot manager that a screenshot needs to be taken.
/// Depending on the value of [`Self::is_screenshots_hooked`].
///
/// - Triggers a [`ScreenshotRequested`] callback.
/// - Triggers a [`ScreenshotReady`] callback.
/// - Only causes [`ScreenshotRequested`] if hooking has been enabled with [`Self::hook_screenshots`].
/// - Otherwise [`ScreenshotReady`] will be called when the screenshot has been saved and added to the library.
pub fn trigger_screenshot(&self) {
unsafe {
sys::SteamAPI_ISteamScreenshots_TriggerScreenshot(self.screenshots);
}
}
/// Adds a screenshot to the user's Steam screenshot library from disk.
///
/// Triggers a [`ScreenshotReady`] callback.
/// The handle to this screenshot that is valid for the duration of the game process and can be used to apply tags.
///
/// This call is asynchronous, a [`ScreenshotReady`] callback will be sent when the screenshot has finished writing to disk.
pub fn add_screenshot_to_library(
&self,
filename: &Path,
thumbnail_filename: Option<&Path>,
width: i32,
height: i32,
) -> Result<ScreenshotHandle, ScreenshotLibraryAddError> {
let filename =
path_to_absolute_cstring(filename).ok_or(ScreenshotLibraryAddError::InvalidPath)?;
let thumbnail_filename = if let Some(thumbnail_filename) = thumbnail_filename {
Some(
path_to_absolute_cstring(thumbnail_filename)
.ok_or(ScreenshotLibraryAddError::InvalidPath)?,
)
} else {
None
};
unsafe {
let handle = sys::SteamAPI_ISteamScreenshots_AddScreenshotToLibrary(
self.screenshots,
filename.as_ptr(),
thumbnail_filename.map_or(std::ptr::null(), |s| s.as_ptr()),
width,
height,
);
if handle != sys::INVALID_SCREENSHOT_HANDLE {
Ok(handle)
} else {
Err(ScreenshotLibraryAddError::SavingFailed)
}
}
}
}
#[derive(Debug, Error)]
pub enum ScreenshotLibraryAddError {
/// Steam failed to save the file for an unspecified reason.
#[error("The screenshot file could not be saved")]
SavingFailed,
/// One of the paths provided was invalid.
#[error("Invalid path")]
InvalidPath,
}
/// A screenshot has been requested by the user from the Steam screenshot hotkey.
/// This will only be called if [`Screenshots::hook_screenshots`] has been enabled, in which case Steam will not take the screenshot itself.
#[derive(Clone, Debug)]
pub struct ScreenshotRequested;
impl_callback!(_cb: ScreenshotRequested_t => ScreenshotRequested {
Self
});
#[derive(Clone, Debug, Error)]
pub enum ScreenshotReadyError {
/// The screenshot could not be loaded or parsed.
#[error("The screenshot could not be loaded or parsed")]
Fail,
/// The screenshot could not be saved to the disk.
#[error("The screenshot could not be saved to the disk")]
IoFailure,
}
/// A screenshot successfully written or otherwise added to the library and can now be tagged.
#[derive(Clone, Debug)]
pub struct ScreenshotReady {
/// The screenshot handle that has been written.
pub local_handle: Result<ScreenshotHandle, ScreenshotReadyError>,
}
impl_callback!(cb: ScreenshotReady_t => ScreenshotReady {
let local_handle = match cb.m_eResult {
sys::EResult::k_EResultOK => Ok(cb.m_hLocal),
sys::EResult::k_EResultIOFailure => Err(ScreenshotReadyError::Fail),
_ => Err(ScreenshotReadyError::Fail),
};
Self { local_handle }
});
fn path_to_absolute_cstring(filename: &Path) -> Option<CString> {
let filename = filename.canonicalize().ok()?;
Some(CString::new(filename.to_str()?).unwrap())
}