Show screenshot window before saving the screenshot
In particular, this allows the player to choose the filename before saving, including the extension. If support for target format is present, Wesnoth honors the extension and saves the screenshot in that format. I also changed the default screenshot format back to PNG due to quality issues JPEG has with pixel art. See discussion in pull request #2655. This commit doesn't introduce any string changes. I used existing strings for everything (sometimes having to take them from another textdomain).
This commit is contained in:
parent
f6428edabd
commit
267510ea07
8 changed files with 121 additions and 99 deletions
|
@ -81,6 +81,8 @@
|
|||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
#textdomain wesnoth
|
||||
|
||||
grow_factor = 1
|
||||
|
||||
border = "all"
|
||||
|
@ -91,7 +93,7 @@
|
|||
id = "title"
|
||||
definition = "title"
|
||||
|
||||
label = _ "Screenshot Saved"
|
||||
label = _ "Screenshot"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
@ -147,6 +149,7 @@
|
|||
horizontal_alignment = "left"
|
||||
|
||||
[label]
|
||||
label = ""
|
||||
id = "filesize"
|
||||
wrap = true
|
||||
[/label]
|
||||
|
@ -188,6 +191,19 @@
|
|||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "right"
|
||||
|
||||
[button]
|
||||
id = "save"
|
||||
definition = "default"
|
||||
|
||||
label = _ "Save"
|
||||
[/button]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
@ -197,7 +213,7 @@
|
|||
id = "ok"
|
||||
definition = "default"
|
||||
|
||||
label = _ "OK"
|
||||
label = _ "Close"
|
||||
[/button]
|
||||
|
||||
[/column]
|
||||
|
|
|
@ -768,26 +768,15 @@ map_location display::minimap_location_on(int x, int y)
|
|||
return loc;
|
||||
}
|
||||
|
||||
bool display::screenshot(const std::string& filename, bool map_screenshot)
|
||||
surface display::screenshot(bool map_screenshot)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if (!map_screenshot) {
|
||||
surface& screenshot_surf = screen_.getSurface();
|
||||
|
||||
res = image::save_image(screenshot_surf, filename);
|
||||
#if 0
|
||||
// FIXME: the SDL_SavePNG path results in oblique errors that don't
|
||||
// make sense to anyone who's not familiarized with it, so
|
||||
// we can't use this.
|
||||
if (!res) {
|
||||
ERR_DP << "Screenshot failed: " << SDL_GetError() << '\n';
|
||||
}
|
||||
#endif
|
||||
// Use make_neutral_surface() to copy surface content
|
||||
return make_neutral_surface(screen_.getSurface());
|
||||
} else {
|
||||
if (get_map().empty()) {
|
||||
ERR_DP << "No map loaded, cannot create a map screenshot.\n";
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_Rect area = max_map_area();
|
||||
|
@ -796,7 +785,7 @@ bool display::screenshot(const std::string& filename, bool map_screenshot)
|
|||
if (map_screenshot_surf_ == nullptr) {
|
||||
// Memory problem ?
|
||||
ERR_DP << "Could not create screenshot surface, try zooming out.\n";
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// back up the current map view position and move to top-left
|
||||
|
@ -806,39 +795,20 @@ bool display::screenshot(const std::string& filename, bool map_screenshot)
|
|||
ypos_ = 0;
|
||||
|
||||
// we reroute render output to the screenshot surface and invalidate all
|
||||
map_screenshot_= true ;
|
||||
map_screenshot_= true;
|
||||
invalidateAll_ = true;
|
||||
DBG_DP << "draw() with map_screenshot\n";
|
||||
draw(true,true);
|
||||
|
||||
// finally save the image on disk
|
||||
res = image::save_image(map_screenshot_surf_,filename);
|
||||
|
||||
#if 0
|
||||
// FIXME: the SDL_SavePNG path results in oblique errors that don't
|
||||
// make sense to anyone who's not familiarized with it, so
|
||||
// we can't use this.
|
||||
if (!res) {
|
||||
// Need to do this ASAP or spurious messages result due to
|
||||
// redraw_everything calling SDL too (e.g. "SDL_UpperBlit: passed
|
||||
// a nullptr surface")
|
||||
ERR_DP << "Map screenshot failed: " << SDL_GetError() << '\n';
|
||||
}
|
||||
#endif
|
||||
|
||||
//NOTE: need to be sure that we free this huge surface (is it enough?)
|
||||
map_screenshot_surf_ = nullptr;
|
||||
|
||||
// restore normal rendering
|
||||
map_screenshot_= false;
|
||||
xpos_ = old_xpos;
|
||||
ypos_ = old_ypos;
|
||||
// some drawing functions are confused by the temporary change
|
||||
// of the map_area and thus affect the UI outside of the map
|
||||
redraw_everything();
|
||||
}
|
||||
|
||||
return res;
|
||||
// Clear map_screenshot_surf_ and return a new surface that contains the same data
|
||||
surface surf(std::move(map_screenshot_surf_));
|
||||
return surf;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<gui::button> display::find_action_button(const std::string& id)
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace wb {
|
|||
#include "key.hpp"
|
||||
#include "time_of_day.hpp"
|
||||
#include "sdl/rect.hpp"
|
||||
#include "sdl/surface.hpp"
|
||||
#include "theme.hpp"
|
||||
#include "video.hpp"
|
||||
#include "widgets/button.hpp"
|
||||
|
@ -359,8 +360,8 @@ public:
|
|||
/** Setter for the terrain code debug overlay on tiles */
|
||||
void set_draw_num_of_bitmaps(bool value) { draw_num_of_bitmaps_ = value; }
|
||||
|
||||
/** Save a (map-)screenshot and return whether the operation succeeded. */
|
||||
bool screenshot(const std::string& filename, bool map_screenshot = false);
|
||||
/** Capture a (map-)screenshot into a surface. */
|
||||
surface screenshot(bool map_screenshot = false);
|
||||
|
||||
/** Invalidates entire screen, including all tiles and sidebar. Calls redraw observers. */
|
||||
void redraw_everything();
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "game_board.hpp"
|
||||
#include "preferences/game.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "image.hpp"
|
||||
#include "preferences/display.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "units/unit.hpp"
|
||||
|
@ -187,7 +188,8 @@ void editor_controller::status_table() {
|
|||
void editor_controller::do_screenshot(const std::string& screenshot_filename /* = "map_screenshot.bmp" */)
|
||||
{
|
||||
try {
|
||||
if (!gui().screenshot(screenshot_filename,true)) {
|
||||
surface screenshot = gui().screenshot(true);
|
||||
if(screenshot.null() || !image::save_image(screenshot, screenshot_filename)) {
|
||||
ERR_ED << "Screenshot creation failed!\n";
|
||||
}
|
||||
} catch (wml_exception& e) {
|
||||
|
|
|
@ -18,17 +18,24 @@
|
|||
|
||||
#include "desktop/clipboard.hpp"
|
||||
#include "desktop/open.hpp"
|
||||
#include "display.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
#include "gui/core/event/dispatcher.hpp"
|
||||
#include "gui/dialogs/message.hpp"
|
||||
#include "gui/widgets/button.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "image.hpp"
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
#include "gettext.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
namespace dialogs
|
||||
|
@ -65,46 +72,89 @@ namespace dialogs
|
|||
|
||||
REGISTER_DIALOG(screenshot_notification)
|
||||
|
||||
screenshot_notification::screenshot_notification(const std::string& path)
|
||||
: path_(path), screenshots_dir_path_(filesystem::get_screenshot_dir())
|
||||
screenshot_notification::screenshot_notification(const std::string& path, surface screenshot)
|
||||
: path_(path)
|
||||
, screenshots_dir_path_(filesystem::get_screenshot_dir())
|
||||
, screenshot_(screenshot)
|
||||
{
|
||||
const int filesize = filesystem::file_size(path);
|
||||
|
||||
const std::string sizetext
|
||||
= filesize >= 0
|
||||
? utils::si_string(filesize, true, _("unit_byte^B"))
|
||||
: _("file_size^Unknown");
|
||||
|
||||
register_label("filesize",
|
||||
false,
|
||||
sizetext,
|
||||
false);
|
||||
}
|
||||
|
||||
void screenshot_notification::pre_show(window& window)
|
||||
{
|
||||
window.set_enter_disabled(true);
|
||||
|
||||
text_box& path_box = find_widget<text_box>(&window, "path", false);
|
||||
path_box.set_value(filesystem::base_name(path_));
|
||||
path_box.set_active(false);
|
||||
window.keyboard_capture(&path_box);
|
||||
connect_signal_pre_key_press(path_box, std::bind(&screenshot_notification::keypress_callback, this,
|
||||
std::placeholders::_3, std::placeholders::_5));
|
||||
|
||||
button& copy_b = find_widget<button>(&window, "copy", false);
|
||||
connect_signal_mouse_left_click(
|
||||
copy_b, std::bind(&desktop::clipboard::copy_to_clipboard, std::ref(path_), false));
|
||||
copy_b, std::bind(&desktop::clipboard::copy_to_clipboard, std::ref(path_), false));
|
||||
copy_b.set_active(false);
|
||||
|
||||
if (!desktop::clipboard::available()) {
|
||||
copy_b.set_active(false);
|
||||
copy_b.set_tooltip(_("Clipboard support not found, contact your packager"));
|
||||
}
|
||||
|
||||
button& open_b = find_widget<button>(&window, "open", false);
|
||||
connect_signal_mouse_left_click(
|
||||
open_b, bind_void(&desktop::open_object, std::ref(path_)));
|
||||
open_b, bind_void(&desktop::open_object, std::ref(path_)));
|
||||
open_b.set_active(false);
|
||||
|
||||
button& bdir_b = find_widget<button>(&window, "browse_dir", false);
|
||||
connect_signal_mouse_left_click(
|
||||
bdir_b,
|
||||
bind_void(&desktop::open_object,
|
||||
std::ref(screenshots_dir_path_)));
|
||||
bdir_b,
|
||||
bind_void(&desktop::open_object,
|
||||
std::ref(screenshots_dir_path_)));
|
||||
|
||||
button& save_b = find_widget<button>(&window, "save", false);
|
||||
connect_signal_mouse_left_click(save_b, std::bind(&screenshot_notification::save_screenshot, this));
|
||||
|
||||
if(screenshot_.null()) {
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
void screenshot_notification::save_screenshot()
|
||||
{
|
||||
window& window = *get_window();
|
||||
text_box& path_box = find_widget<text_box>(&window, "path", false);
|
||||
std::string filename = path_box.get_value();
|
||||
boost::filesystem::path path(screenshots_dir_path_);
|
||||
path /= filename;
|
||||
|
||||
const bool res = image::save_image(screenshot_, path.string());
|
||||
if(!res) {
|
||||
gui2::show_error_message(
|
||||
translation::dsgettext("wesnoth", "Screenshot creation failed.\n\n"
|
||||
"Make sure there is enough space on the drive holding Wesnoth’s player resource files and that file permissions are set up correctly."));
|
||||
} else {
|
||||
path_box.set_active(false);
|
||||
find_widget<button>(&window, "open", false).set_active(true);
|
||||
find_widget<button>(&window, "save", false).set_active(false);
|
||||
|
||||
if(desktop::clipboard::available()) {
|
||||
find_widget<button>(&window, "copy", false).set_active(true);
|
||||
}
|
||||
|
||||
const int filesize = filesystem::file_size(path.string());
|
||||
const std::string sizetext = utils::si_string(filesize, true, _("unit_byte^B"));
|
||||
find_widget<label>(&window, "filesize", false).set_label(sizetext);
|
||||
|
||||
window.invalidate_layout();
|
||||
}
|
||||
}
|
||||
|
||||
void screenshot_notification::keypress_callback(bool& handled, SDL_Keycode key)
|
||||
{
|
||||
if(key == SDLK_RETURN || key == SDLK_KP_ENTER) {
|
||||
save_screenshot();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "gui/dialogs/modal_dialog.hpp"
|
||||
#include "sdl/surface.hpp"
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
@ -27,11 +28,10 @@ public:
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param path Path to the screenshot file created. The caller should
|
||||
* ensure the file exists, otherwise it will be displayed
|
||||
* with size 0.
|
||||
* @param path Path to the screenshot file to create.
|
||||
* @param screenshot Screenshot to save.
|
||||
*/
|
||||
screenshot_notification(const std::string& path);
|
||||
screenshot_notification(const std::string& path, surface screenshot);
|
||||
|
||||
/**
|
||||
* The display function.
|
||||
|
@ -43,6 +43,10 @@ public:
|
|||
private:
|
||||
const std::string path_;
|
||||
const std::string screenshots_dir_path_;
|
||||
surface screenshot_;
|
||||
|
||||
void save_screenshot();
|
||||
void keypress_callback(bool& handled, const SDL_Keycode key);
|
||||
|
||||
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
|
||||
virtual const std::string& window_id() const override;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "game_end_exceptions.hpp"
|
||||
#include "display.hpp"
|
||||
#include "quit_confirmation.hpp"
|
||||
#include "sdl/surface.hpp"
|
||||
#include "show_dialog.hpp"
|
||||
#include "../resources.hpp"
|
||||
#include "../playmp_controller.hpp"
|
||||
|
@ -50,33 +51,13 @@ static lg::log_domain log_hotkey("hotkey");
|
|||
|
||||
namespace {
|
||||
|
||||
bool screenshot(const std::string& filename)
|
||||
void make_screenshot(const std::string& name, bool map_screenshot)
|
||||
{
|
||||
return image::save_image(CVideo::get_singleton().getSurface(), filename);
|
||||
}
|
||||
|
||||
template<typename TFunc>
|
||||
void make_screenshot(const std::string& name, const TFunc& func)
|
||||
{
|
||||
std::string filename = filesystem::get_screenshot_dir() + "/" + name + "_";
|
||||
|
||||
// TODO: there should be a way to configure which of these is used by default.
|
||||
#ifdef SDL_IMAGE_VERSION_ATLEAST
|
||||
#if SDL_IMAGE_VERSION_ATLEAST(2, 0, 2)
|
||||
const std::string ext = ".jpg";
|
||||
#endif
|
||||
#else
|
||||
const std::string ext = ".png";
|
||||
#endif
|
||||
|
||||
filename = filesystem::get_next_filename(filename, ext);
|
||||
const bool res = func(filename);
|
||||
if (res) {
|
||||
gui2::dialogs::screenshot_notification::display(filename);
|
||||
} else {
|
||||
gui2::show_error_message(
|
||||
_("Screenshot creation failed.\n\n"
|
||||
"Make sure there is enough space on the drive holding Wesnoth’s player resource files and that file permissions are set up correctly."));
|
||||
surface screenshot = display::get_singleton()->screenshot(map_screenshot);
|
||||
if(!screenshot.null()) {
|
||||
std::string filename = filesystem::get_screenshot_dir() + "/" + name + "_";
|
||||
filename = filesystem::get_next_filename(filename, ".png");
|
||||
gui2::dialogs::screenshot_notification::display(filename, screenshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -615,7 +596,7 @@ void command_executor::execute_command(const SDL_Event& event, int index)
|
|||
CVideo::get_singleton().toggle_fullscreen();
|
||||
break;
|
||||
case HOTKEY_SCREENSHOT:
|
||||
make_screenshot(_("Screenshot"), &::screenshot);
|
||||
make_screenshot(_("Screenshot"), false);
|
||||
break;
|
||||
case HOTKEY_ANIMATE_MAP:
|
||||
preferences::set_animate_map(!preferences::animate_map());
|
||||
|
@ -758,8 +739,6 @@ void command_executor_default::zoom_default()
|
|||
|
||||
void command_executor_default::map_screenshot()
|
||||
{
|
||||
make_screenshot(_("Map-Screenshot"), [this](const std::string& filename) {
|
||||
return get_display().screenshot(filename, true);
|
||||
});
|
||||
make_screenshot(_("Map-Screenshot"), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1304,7 +1304,7 @@ bool save_image(const surface& surf, const std::string& filename)
|
|||
|
||||
#ifdef SDL_IMAGE_VERSION_ATLEAST
|
||||
#if SDL_IMAGE_VERSION_ATLEAST(2, 0, 2)
|
||||
if(filesystem::ends_with(filename, ".jpg")) {
|
||||
if(filesystem::ends_with(filename, ".jpeg") || filesystem::ends_with(filename, ".jpg") || filesystem::ends_with(filename, ".jpe")) {
|
||||
LOG_DP << "Writing a JPG image to " << filename << std::endl;
|
||||
|
||||
const int err = IMG_SaveJPG_RW(surf, filesystem::make_write_RWops(filename).release(), true, 75); // SDL takes ownership of the RWops
|
||||
|
|
Loading…
Add table
Reference in a new issue