Add steam screenshot api.

This commit is contained in:
Nemirtingas 2020-10-09 13:48:09 +02:00
parent ef35271a38
commit c8e9a162ea
5 changed files with 177 additions and 6 deletions

View File

@ -17,6 +17,16 @@
#include "local_storage.h"
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_STATIC
#define STBI_ONLY_PNG
#define STBI_ONLY_JPEG
#include "../stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define STB_IMAGE_WRITE_STATIC
#include "../stb/stb_image_write.h"
struct File_Data {
std::string name;
};
@ -143,6 +153,16 @@ std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
return std::vector<std::string>();
}
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path)
{
return std::vector<image_pixel_t>();
}
bool Local_Storage::save_screenshot(std::string const& image_path, uint8_t* img_ptr, int32_t width, int32_t height, int32_t channels)
{
return false;
}
#else
#if defined(__WINDOWS__)
@ -737,4 +757,32 @@ bool Local_Storage::write_json_file(std::string folder, std::string const&file,
return false;
}
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path)
{
std::vector<image_pixel_t> res;
FILE* hFile = fopen(image_path.c_str(), "r");
if (hFile != nullptr)
{
int width, height;
image_pixel_t* img = (image_pixel_t*)stbi_load_from_file(hFile, &width, &height, nullptr, 4);
if (img != nullptr)
{
res.resize(width*height);
std::copy(img, img + width * height, res.begin());
stbi_image_free(img);
}
fclose(hFile);
}
return res;
}
bool Local_Storage::save_screenshot(std::string const& image_path, uint8_t* img_ptr, int32_t width, int32_t height, int32_t channels)
{
std::string screenshot_path = std::move(save_directory + appid + screenshots_folder + PATH_SEPARATOR);
create_directory(screenshot_path);
screenshot_path += image_path;
return stbi_write_png(screenshot_path.c_str(), width, height, channels, img_ptr, 0) == 1;
}
#endif

View File

@ -22,6 +22,25 @@
#define MAX_FILENAME_LENGTH 300
union image_pixel_t
{
uint32_t pixel;
struct pixel_channels_t
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} channels;
};
struct image_t
{
size_t width;
size_t height;
std::vector<image_pixel_t> pix_map;
};
class Local_Storage {
public:
static constexpr auto inventory_storage_folder = "inventory";
@ -29,6 +48,7 @@ public:
static constexpr auto remote_storage_folder = "remote";
static constexpr auto stats_storage_folder = "stats";
static constexpr auto user_data_storage = "local";
static constexpr auto screenshots_folder = "screenshots";
static constexpr auto game_settings_folder = "steam_settings";
private:
@ -62,6 +82,9 @@ public:
bool load_json(std::string full_path, nlohmann::json& json);
bool load_json_file(std::string folder, std::string const& file, nlohmann::json& json);
bool write_json_file(std::string folder, std::string const& file, nlohmann::json const& json);
std::vector<image_pixel_t> load_image(std::string const& image_path);
bool save_screenshot(std::string const& image_path, uint8_t* img_ptr, int32_t width, int32_t height, int32_t channels);
};
#endif

View File

@ -72,7 +72,7 @@ Steam_Client::Steam_Client()
steam_apps = new Steam_Apps(settings_client, callback_results_client);
steam_networking = new Steam_Networking(settings_client, network, callbacks_client, run_every_runcb);
steam_remote_storage = new Steam_Remote_Storage(settings_client, local_storage, callback_results_client);
steam_screenshots = new Steam_Screenshots();
steam_screenshots = new Steam_Screenshots(local_storage, callbacks_client);
steam_http = new Steam_HTTP(settings_client, network, callback_results_client, callbacks_client);
steam_controller = new Steam_Controller(settings_client, callback_results_client, callbacks_client, run_every_runcb);
steam_ugc = new Steam_UGC(settings_client, callback_results_client, callbacks_client);

View File

@ -17,12 +17,40 @@
#include "steam_screenshots.h"
Steam_Screenshots::Steam_Screenshots(class Local_Storage* local_storage, class SteamCallBacks* callbacks) :
local_storage(local_storage),
callbacks(callbacks)
{
}
ScreenshotHandle Steam_Screenshots::create_screenshot_handle()
{
static ScreenshotHandle handle = 100;
return handle++;
}
// Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB format.
// The return value is a handle that is valid for the duration of the game process and can be used to apply tags.
ScreenshotHandle Steam_Screenshots::WriteScreenshot( void *pubRGB, uint32 cubRGB, int nWidth, int nHeight )
{
PRINT_DEBUG("WriteScreenshot\n");
return INVALID_SCREENSHOT_HANDLE;
char buff[128];
auto now = std::chrono::system_clock::now();
time_t now_time;
now_time = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
strftime(buff, 128, "%a_%b_%d_%H_%M_%S_%Y", localtime(&now_time));
std::string screenshot_name = buff;
screenshot_name += ".png";
if (!local_storage->save_screenshot( screenshot_name, (uint8_t*)pubRGB, nWidth, nHeight, 3))
return INVALID_SCREENSHOT_HANDLE;
auto handle = create_screenshot_handle();
auto& infos = _screenshots[handle];
infos.screenshot_name = buff;
return handle;
}
@ -33,7 +61,30 @@ ScreenshotHandle Steam_Screenshots::WriteScreenshot( void *pubRGB, uint32 cubRGB
ScreenshotHandle Steam_Screenshots::AddScreenshotToLibrary( const char *pchFilename, const char *pchThumbnailFilename, int nWidth, int nHeight )
{
PRINT_DEBUG("AddScreenshotToLibrary\n");
return INVALID_SCREENSHOT_HANDLE;
if (pchFilename == nullptr)
return INVALID_SCREENSHOT_HANDLE;
std::vector<image_pixel_t> pixels(std::move(local_storage->load_image(pchFilename)));
if (pixels.size() != size_t(nWidth) * size_t(nHeight))
return INVALID_SCREENSHOT_HANDLE;
char buff[128];
auto now = std::chrono::system_clock::now();
time_t now_time;
now_time = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
strftime(buff, 128, "%a_%b_%d_%H_%M_%S_%Y", localtime(&now_time));
std::string screenshot_name = buff;
screenshot_name += ".png";
if (!local_storage->save_screenshot(screenshot_name, (uint8_t*)pixels.data(), nWidth, nHeight, 4))
return INVALID_SCREENSHOT_HANDLE;
auto handle = create_screenshot_handle();
auto& infos = _screenshots[handle];
infos.screenshot_name = buff;
return handle;
}
@ -41,6 +92,16 @@ ScreenshotHandle Steam_Screenshots::AddScreenshotToLibrary( const char *pchFilen
void Steam_Screenshots::TriggerScreenshot()
{
PRINT_DEBUG("TriggerScreenshot\n");
if (hooked)
{
ScreenshotRequested_t data;
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
else
{
PRINT_DEBUG("TODO: Make the overlay take a screenshot");
}
}
@ -58,7 +119,15 @@ void Steam_Screenshots::HookScreenshots( bool bHook )
bool Steam_Screenshots::SetLocation( ScreenshotHandle hScreenshot, const char *pchLocation )
{
PRINT_DEBUG("SetLocation\n");
return false;
auto it = _screenshots.find(hScreenshot);
if (it == _screenshots.end())
return false;
it->second.metadatas["locations"].push_back(pchLocation);
local_storage->write_json_file(Local_Storage::screenshots_folder, it->second.screenshot_name + ".json", it->second.metadatas);
return true;
}
@ -66,7 +135,15 @@ bool Steam_Screenshots::SetLocation( ScreenshotHandle hScreenshot, const char *p
bool Steam_Screenshots::TagUser( ScreenshotHandle hScreenshot, CSteamID steamID )
{
PRINT_DEBUG("TagUser\n");
return false;
auto it = _screenshots.find(hScreenshot);
if (it == _screenshots.end())
return false;
it->second.metadatas["users"].push_back(uint64_t(steamID.ConvertToUint64()));
local_storage->write_json_file(Local_Storage::screenshots_folder, it->second.screenshot_name + ".json", it->second.metadatas);
return true;
}
@ -74,7 +151,15 @@ bool Steam_Screenshots::TagUser( ScreenshotHandle hScreenshot, CSteamID steamID
bool Steam_Screenshots::TagPublishedFile( ScreenshotHandle hScreenshot, PublishedFileId_t unPublishedFileID )
{
PRINT_DEBUG("TagPublishedFile\n");
return false;
auto it = _screenshots.find(hScreenshot);
if (it == _screenshots.end())
return false;
it->second.metadatas["published_files"].push_back(uint64_t(unPublishedFileID));
local_storage->write_json_file(Local_Storage::screenshots_folder, it->second.screenshot_name + ".json", it->second.metadatas);
return true;
}

View File

@ -17,10 +17,25 @@
#include "base.h"
struct screenshot_infos_t
{
std::string screenshot_name;
nlohmann::json metadatas;
};
class Steam_Screenshots : public ISteamScreenshots
{
bool hooked = false;
std::map<ScreenshotHandle, screenshot_infos_t> _screenshots;
class Local_Storage* local_storage;
class SteamCallBacks* callbacks;
ScreenshotHandle create_screenshot_handle();
public:
Steam_Screenshots(class Local_Storage* local_storage, class SteamCallBacks* callbacks);
// Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB format.
// The return value is a handle that is valid for the duration of the game process and can be used to apply tags.
ScreenshotHandle WriteScreenshot( void *pubRGB, uint32 cubRGB, int nWidth, int nHeight );