Add steam screenshot api.
parent
ef35271a38
commit
c8e9a162ea
|
@ -17,6 +17,16 @@
|
||||||
|
|
||||||
#include "local_storage.h"
|
#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 {
|
struct File_Data {
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
@ -143,6 +153,16 @@ std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
|
||||||
return std::vector<std::string>();
|
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
|
#else
|
||||||
#if defined(__WINDOWS__)
|
#if defined(__WINDOWS__)
|
||||||
|
|
||||||
|
@ -737,4 +757,32 @@ bool Local_Storage::write_json_file(std::string folder, std::string const&file,
|
||||||
return false;
|
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
|
#endif
|
||||||
|
|
|
@ -22,6 +22,25 @@
|
||||||
|
|
||||||
#define MAX_FILENAME_LENGTH 300
|
#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 {
|
class Local_Storage {
|
||||||
public:
|
public:
|
||||||
static constexpr auto inventory_storage_folder = "inventory";
|
static constexpr auto inventory_storage_folder = "inventory";
|
||||||
|
@ -29,6 +48,7 @@ public:
|
||||||
static constexpr auto remote_storage_folder = "remote";
|
static constexpr auto remote_storage_folder = "remote";
|
||||||
static constexpr auto stats_storage_folder = "stats";
|
static constexpr auto stats_storage_folder = "stats";
|
||||||
static constexpr auto user_data_storage = "local";
|
static constexpr auto user_data_storage = "local";
|
||||||
|
static constexpr auto screenshots_folder = "screenshots";
|
||||||
static constexpr auto game_settings_folder = "steam_settings";
|
static constexpr auto game_settings_folder = "steam_settings";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -62,6 +82,9 @@ public:
|
||||||
bool load_json(std::string full_path, nlohmann::json& json);
|
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 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);
|
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
|
#endif
|
||||||
|
|
|
@ -72,7 +72,7 @@ Steam_Client::Steam_Client()
|
||||||
steam_apps = new Steam_Apps(settings_client, callback_results_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_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_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_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_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);
|
steam_ugc = new Steam_UGC(settings_client, callback_results_client, callbacks_client);
|
||||||
|
|
|
@ -17,12 +17,40 @@
|
||||||
|
|
||||||
#include "steam_screenshots.h"
|
#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.
|
// 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.
|
// 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 )
|
ScreenshotHandle Steam_Screenshots::WriteScreenshot( void *pubRGB, uint32 cubRGB, int nWidth, int nHeight )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("WriteScreenshot\n");
|
PRINT_DEBUG("WriteScreenshot\n");
|
||||||
|
|
||||||
|
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;
|
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 )
|
ScreenshotHandle Steam_Screenshots::AddScreenshotToLibrary( const char *pchFilename, const char *pchThumbnailFilename, int nWidth, int nHeight )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("AddScreenshotToLibrary\n");
|
PRINT_DEBUG("AddScreenshotToLibrary\n");
|
||||||
|
|
||||||
|
if (pchFilename == nullptr)
|
||||||
return INVALID_SCREENSHOT_HANDLE;
|
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()
|
void Steam_Screenshots::TriggerScreenshot()
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("TriggerScreenshot\n");
|
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 )
|
bool Steam_Screenshots::SetLocation( ScreenshotHandle hScreenshot, const char *pchLocation )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("SetLocation\n");
|
PRINT_DEBUG("SetLocation\n");
|
||||||
|
|
||||||
|
auto it = _screenshots.find(hScreenshot);
|
||||||
|
if (it == _screenshots.end())
|
||||||
return false;
|
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 )
|
bool Steam_Screenshots::TagUser( ScreenshotHandle hScreenshot, CSteamID steamID )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("TagUser\n");
|
PRINT_DEBUG("TagUser\n");
|
||||||
|
|
||||||
|
auto it = _screenshots.find(hScreenshot);
|
||||||
|
if (it == _screenshots.end())
|
||||||
return false;
|
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 )
|
bool Steam_Screenshots::TagPublishedFile( ScreenshotHandle hScreenshot, PublishedFileId_t unPublishedFileID )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("TagPublishedFile\n");
|
PRINT_DEBUG("TagPublishedFile\n");
|
||||||
|
|
||||||
|
auto it = _screenshots.find(hScreenshot);
|
||||||
|
if (it == _screenshots.end())
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,25 @@
|
||||||
|
|
||||||
#include "base.h"
|
#include "base.h"
|
||||||
|
|
||||||
|
struct screenshot_infos_t
|
||||||
|
{
|
||||||
|
std::string screenshot_name;
|
||||||
|
nlohmann::json metadatas;
|
||||||
|
};
|
||||||
|
|
||||||
class Steam_Screenshots : public ISteamScreenshots
|
class Steam_Screenshots : public ISteamScreenshots
|
||||||
{
|
{
|
||||||
bool hooked = false;
|
bool hooked = false;
|
||||||
|
std::map<ScreenshotHandle, screenshot_infos_t> _screenshots;
|
||||||
|
|
||||||
|
class Local_Storage* local_storage;
|
||||||
|
class SteamCallBacks* callbacks;
|
||||||
|
|
||||||
|
ScreenshotHandle create_screenshot_handle();
|
||||||
|
|
||||||
public:
|
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.
|
// 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.
|
// 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 );
|
ScreenshotHandle WriteScreenshot( void *pubRGB, uint32 cubRGB, int nWidth, int nHeight );
|
||||||
|
|
Loading…
Reference in New Issue