diff --git a/data/gui.xml b/data/gui.xml
index fbc1a44b9..29ff8d768 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -21,7 +21,6 @@
-
@@ -510,6 +509,9 @@
+
+
+
diff --git a/data/strings/en.ini b/data/strings/en.ini
index 8959434fb..d03409ae1 100644
--- a/data/strings/en.ini
+++ b/data/strings/en.ini
@@ -400,6 +400,7 @@ SavePalette = Save Palette
Screenshot = Screenshot
Screenshot_Open = Take & Open Screenshot
Screenshot_Save = Take & Save Screenshot
+Screenshot_Steam = Take & Add Screenshot to Steam
Screenshot_sRGB = (sRGB Color Profile)
Screenshot_DisplayCS = (Display Color Profile)
Scroll = Scroll {0}
diff --git a/src/app/commands/screenshot.cpp b/src/app/commands/screenshot.cpp
index 84f09f9e7..2af92ce97 100644
--- a/src/app/commands/screenshot.cpp
+++ b/src/app/commands/screenshot.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2019 Igara Studio S.A.
+// Copyright (C) 2019-2020 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -17,15 +17,23 @@
#include "app/file/file.h"
#include "app/i18n/strings.h"
#include "app/resource_finder.h"
+#include "base/buffer.h"
#include "base/fs.h"
#include "doc/cel.h"
#include "doc/color.h"
+#include "doc/image_impl.h"
#include "doc/layer.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "os/display.h"
#include "os/surface.h"
+#include "ui/alert.h"
#include "ui/manager.h"
+#include "ui/scale.h"
+
+#ifdef ENABLE_STEAM
+ #include "steam/steam.h"
+#endif
namespace app {
@@ -34,6 +42,9 @@ using namespace ui;
struct ScreenshotParams : public NewParams {
Param save { this, false, "save" };
Param srgb { this, true, "srgb" };
+#ifdef ENABLE_STEAM
+ Param steam { this, false, "steam" };
+#endif
};
class ScreenshotCommand : public CommandWithNewParams {
@@ -85,9 +96,11 @@ void ScreenshotCommand::onExecute(Context* ctx)
doc::Cel* cel = spr->firstLayer()->cel(0);
doc::Image* img = cel->image();
+ const int w = img->width();
+ const int h = img->height();
- for (int y=0; yheight(); ++y) {
- for (int x=0; xwidth(); ++x) {
+ for (int y=0; ygetPixel(x, y);
img->putPixel(x, y, doc::rgba(gfx::getr(c),
@@ -103,6 +116,34 @@ void ScreenshotCommand::onExecute(Context* ctx)
if (params().srgb())
cmd::convert_color_profile(spr, gfx::ColorSpace::MakeSRGB());
+ if (params().steam()) {
+#ifdef ENABLE_STEAM
+ if (auto steamAPI = steam::SteamAPI::instance()) {
+ // Get image again (cmd::convert_color_profile() might have changed it)
+ img = cel->image();
+
+ const int scale = display->scale();
+ base::buffer rgbBuffer(3*w*h*scale*scale);
+ int c = 0;
+ doc::LockImageBits bits(img);
+ for (int y=0; y(img, x, y);
+ for (int j=0; jwriteScreenshot(&rgbBuffer[0], rgbBuffer.size(), w*scale, h*scale))
+ return;
+ }
+#endif
+ }
+
if (params().save()) {
save_document(ctx, doc.get());
}
@@ -115,7 +156,9 @@ void ScreenshotCommand::onExecute(Context* ctx)
std::string ScreenshotCommand::onGetFriendlyName() const
{
std::string name;
- if (params().save())
+ if (params().steam())
+ name = Strings::commands_Screenshot_Steam();
+ else if (params().save())
name = Strings::commands_Screenshot_Save();
else
name = Strings::commands_Screenshot_Open();
diff --git a/src/steam/LICENSE.txt b/src/steam/LICENSE.txt
index 9a182c0f3..aed3f772b 100644
--- a/src/steam/LICENSE.txt
+++ b/src/steam/LICENSE.txt
@@ -1,3 +1,4 @@
+Copyright (c) 2020 Igara Studio S.A.
Copyright (c) 2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining
diff --git a/src/steam/steam.cpp b/src/steam/steam.cpp
index 3b9e2b5ce..0ecd0e94c 100644
--- a/src/steam/steam.cpp
+++ b/src/steam/steam.cpp
@@ -1,4 +1,5 @@
// Aseprite Steam Wrapper
+// Copyright (c) 2020 Igara Studio S.A.
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
@@ -12,13 +13,22 @@
#include "base/dll.h"
#include "base/fs.h"
+#include "base/ints.h"
#include "base/log.h"
#include "base/string.h"
namespace steam {
-typedef bool (*SteamAPI_Init_Func)();
-typedef void (*SteamAPI_Shutdown_Func)();
+typedef uint32_t ScreenshotHandle;
+typedef void* ISteamScreenshots;
+
+// Steam main API
+typedef bool __cdecl (*SteamAPI_Init_Func)();
+typedef void __cdecl (*SteamAPI_Shutdown_Func)();
+
+// ISteamScreenshots
+typedef ISteamScreenshots* __cdecl (*SteamAPI_SteamScreenshots_v003_Func)();
+typedef ScreenshotHandle __cdecl (*SteamAPI_ISteamScreenshots_WriteScreenshot_Func)(ISteamScreenshots*, void*, uint32_t, int, int);
#ifdef _WIN32
#ifdef _WIN64
@@ -32,9 +42,11 @@ typedef void (*SteamAPI_Shutdown_Func)();
#define STEAM_API_DLL_FILENAME "libsteam_api.so"
#endif
+#define GETPROC(name) base::get_dll_proc(m_steamLib, #name)
+
class SteamAPI::Impl {
public:
- Impl() : m_initialized(false) {
+ Impl() {
m_steamLib = base::load_dll(
base::join_path(base::get_file_path(base::get_app_path()),
STEAM_API_DLL_FILENAME));
@@ -43,18 +55,19 @@ public:
return;
}
- auto SteamAPI_Init = base::get_dll_proc(m_steamLib, "SteamAPI_Init");
+ auto SteamAPI_Init = GETPROC(SteamAPI_Init);
if (!SteamAPI_Init) {
LOG("STEAM: SteamAPI_Init not found...\n");
return;
}
+ // Call SteamAPI_Init() to connect to Steam
if (!SteamAPI_Init()) {
LOG("STEAM: Steam is not initialized...\n");
return;
}
- LOG("STEAM: Steam initialized...\n");
+ LOG("STEAM: Steam initialized\n");
m_initialized = true;
}
@@ -62,7 +75,7 @@ public:
if (!m_steamLib)
return;
- auto SteamAPI_Shutdown = base::get_dll_proc(m_steamLib, "SteamAPI_Shutdown");
+ auto SteamAPI_Shutdown = GETPROC(SteamAPI_Shutdown);
if (SteamAPI_Shutdown) {
LOG("STEAM: Steam shutdown...\n");
SteamAPI_Shutdown();
@@ -75,19 +88,55 @@ public:
return m_initialized;
}
+ bool writeScreenshot(void* rgbBuffer,
+ uint32_t sizeInBytes,
+ int width, int height) {
+ if (!m_initialized)
+ return false;
+
+ auto SteamScreenshots = GETPROC(SteamAPI_SteamScreenshots_v003);
+ auto WriteScreenshot = GETPROC(SteamAPI_ISteamScreenshots_WriteScreenshot);
+ if (!SteamScreenshots || !WriteScreenshot) {
+ LOG("STEAM: Error getting Steam Screenshot API functions\n");
+ return false;
+ }
+
+ auto screenshots = SteamScreenshots();
+ if (!screenshots) {
+ LOG("STEAM: Error getting Steam Screenshot API instance\n");
+ return false;
+ }
+
+ WriteScreenshot(screenshots, rgbBuffer, sizeInBytes, width, height);
+ return true;
+ }
+
private:
- base::dll m_steamLib;
- bool m_initialized;
+ bool m_initialized = false;
+ base::dll m_steamLib = nullptr;
};
+SteamAPI* g_instance = nullptr;
+
+// static
+SteamAPI* SteamAPI::instance()
+{
+ return g_instance;
+}
+
SteamAPI::SteamAPI()
: m_impl(new Impl)
{
+ ASSERT(g_instance == nullptr);
+ g_instance = this;
}
SteamAPI::~SteamAPI()
{
delete m_impl;
+
+ ASSERT(g_instance == this);
+ g_instance = nullptr;
}
bool SteamAPI::initialized() const
@@ -95,4 +144,11 @@ bool SteamAPI::initialized() const
return m_impl->initialized();
}
+bool SteamAPI::writeScreenshot(void* rgbBuffer,
+ uint32_t sizeInBytes,
+ int width, int height)
+{
+ return m_impl->writeScreenshot(rgbBuffer, sizeInBytes, width, height);
+}
+
} // namespace steam
diff --git a/src/steam/steam.h b/src/steam/steam.h
index 236682c5a..664e211f1 100644
--- a/src/steam/steam.h
+++ b/src/steam/steam.h
@@ -1,4 +1,5 @@
// Aseprite Steam Wrapper
+// Copyright (c) 2020 Igara Studio S.A.
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
@@ -12,11 +13,17 @@ namespace steam {
class SteamAPI {
public:
+ static SteamAPI* instance();
+
SteamAPI();
~SteamAPI();
bool initialized() const;
+ bool writeScreenshot(void* rgbBuffer,
+ uint32_t sizeInBytes,
+ int width, int height);
+
private:
class Impl;
Impl* m_impl;