IntroWML code cleanup and fix/rename of [image]resize_with_background=

Prior to this commit, the scaled= attribute was undocumented and had what I
assume was a bug - when enabled the image was scaled up to the width and height
of the background - not to the same ratio as the background, but to the full
size. So if you had a 1000 pixel wide background in an 800 pixel wide window,
then scaled=yes meant each journey-marker was an 800 pixel-wide blob.

However, if anyone was using it with background-size images as overlays then
this commit will break that usage - that use case is still supported by having
multiple [background_layer]s.

Closes #5223, which was a question about whether to fix or simply remove the
scaled attribute. Given that [background_layer]scale= and [image]scaled= have
different meanings (the background_layer one should and does cause it to be
full-window), I've kept the 'd' on the end of 'scaled' too.

Use a loop instead of recursion. This cleanup is prompted by #5041 (drawing
map labels in IntroWML), which will add more items to be drawn in this loop.
The old implementation would not have triggered tail-recursion optimisations,
as the recursion site wasn't the final code in the function.

Correct documentation in the .hpp file about when the delay takes effect (this
isn't a behavior change, just a documentation correction).

Review the schema, and remove attributes that aren't supported by the code.
Many of these attributes are supported for `background_layer` but not `image`.
This commit is contained in:
Steve Cotton 2020-10-22 04:45:27 +02:00 committed by Steve Cotton
parent f39bd33899
commit 1cdc4ef530
5 changed files with 72 additions and 106 deletions

View file

@ -20,6 +20,9 @@
### WML Engine
### Miscellaneous and Bug Fixes
* Fixed a rare issue on Windows that could result in wesnoth.exe sticking around waiting for console input after encountering an error despite not being launched with the `--wconsole` option.
* Fixed a potential crash when drawing many images on the story screens.
* Fixed the schema's list of attributes supported by IntroWML.
* Fixed and renamed IntroWML's `[image]resize_with_background=yes` to keep images proportional to the background.
* Fixed precise log timestamps missing a space between the timestamp and the log severity label.
* Improve the in-game help's topic about orbs, add crowns and ellipses.
* Removed documentation for network proxy-related command line options previously removed in version 1.13.1 along with libana.

View file

@ -329,24 +329,6 @@
max=infinite
{SIMPLE_KEY title string}
{INSERT_TAG}
# TODO: Is this really recognized at story toplevel? Wiki claims it is.
[tag]
name="image"
max=infinite
{INSERT_TAG}
{SIMPLE_KEY x int}
{SIMPLE_KEY y int}
{SIMPLE_KEY centered bool}
{SIMPLE_KEY file string}
{SIMPLE_KEY delay int}
# These keys possibly not documented?
{SIMPLE_KEY scale_vertically bool}
{SIMPLE_KEY scale_horizontally bool}
{SIMPLE_KEY scale bool}
{SIMPLE_KEY tile_vertically bool}
{SIMPLE_KEY tile_horizontally bool}
{SIMPLE_KEY tile bool}
[/tag]
[tag]
name="part"
max=infinite
@ -360,7 +342,6 @@
{SIMPLE_KEY sound string_list}
{DEFAULT_KEY text_layout string bottom}
{DEFAULT_KEY title_alignment text_alignment left}
{SIMPLE_KEY delay int} # Not documented?
[tag]
name="background_layer"
max=infinite
@ -375,6 +356,17 @@
{SIMPLE_KEY tile bool}
{SIMPLE_KEY base_layer bool}
[/tag]
[tag]
name="image"
max=infinite
{INSERT_TAG}
{SIMPLE_KEY x int}
{SIMPLE_KEY y int}
{SIMPLE_KEY centered bool}
{SIMPLE_KEY file string}
{SIMPLE_KEY delay int}
{SIMPLE_KEY resize_with_background bool}
[/tag]
[tag]
name="if"
max=infinite
@ -404,7 +396,6 @@
super="scenario/story/part"
[/tag]
[/tag]
{LINK_TAG "scenario/story/image"}
{LINK_TAG "$action_wml/deprecated_message"}
{LINK_TAG "$action_wml/wml_message"}
[/tag]

View file

@ -319,63 +319,58 @@ void story_viewer::display_part(window& window)
void story_viewer::draw_floating_image(window& window, floating_image_list::const_iterator image_iter, int this_part_index)
{
const auto& images = current_part_->get_floating_images();
// If the current part has changed or we're out of images to draw, exit the draw loop.
if((this_part_index != part_index_) || (image_iter == images.end())) {
timer_id_ = 0;
return;
}
const auto& floating_image = *image_iter;
std::ostringstream x_ss;
std::ostringstream y_ss;
// Floating images are scaled by the same factor as the background.
x_ss << "(trunc(fi_ref_x * base_scale_x) + base_origin.x";
y_ss << "(trunc(fi_ref_y * base_scale_y) + base_origin.y";
if(floating_image.centered()) {
x_ss << " - (image_original_width / 2)";
y_ss << " - (image_original_height / 2)";
}
x_ss << " where fi_ref_x = " << floating_image.ref_x() << ")";
y_ss << " where fi_ref_y = " << floating_image.ref_y() << ")";
config cfg, image;
image["x"] = x_ss.str();
image["y"] = y_ss.str();
image["w"] = floating_image.autoscale() ? "(width)" : "(image_width)";
image["h"] = floating_image.autoscale() ? "(height)" : "(image_height)";
image["name"] = floating_image.file();
// TODO: implement handling of the tiling options.
//image["resize_mode"] = "tile_centered"
cfg.add_child("image", std::move(image));
canvas& window_canvas = window.get_canvas(0);
// Needed to make the background redraw correctly.
window_canvas.append_cfg(cfg);
window_canvas.set_is_dirty(true);
// If the current part has changed or we're out of images to draw, exit the draw loop.
while((this_part_index == part_index_) && (image_iter != images.end())) {
const auto& floating_image = *image_iter;
++image_iter;
window.set_is_dirty(true);
std::ostringstream x_ss;
std::ostringstream y_ss;
++image_iter;
// Floating images' locations are scaled by the same factor as the background.
x_ss << "(trunc(" << floating_image.ref_x() << " * base_scale_x) + base_origin.x";
y_ss << "(trunc(" << floating_image.ref_y() << " * base_scale_y) + base_origin.y";
// If a delay is specified, schedule the next image draw. This *must* be a non-repeating timer!
// Else draw the next image immediately.
const unsigned int draw_delay = floating_image.display_delay();
if(floating_image.centered()) {
x_ss << " - (image_width / 2)";
y_ss << " - (image_height / 2)";
}
if(draw_delay != 0) {
timer_id_ = add_timer(draw_delay,
std::bind(&story_viewer::draw_floating_image, this, std::ref(window), image_iter, this_part_index), false);
} else {
draw_floating_image(window, image_iter, this_part_index);
x_ss << ")";
y_ss << ")";
config image;
image["x"] = x_ss.str();
image["y"] = y_ss.str();
// Width and height don't need to be set unless the image needs to be scaled.
if(floating_image.resize_with_background()) {
image["w"] = "(image_original_width * base_scale_x)";
image["h"] = "(image_original_height * base_scale_y)";
}
image["name"] = floating_image.file();
config cfg{"image", std::move(image)};
cfg.add_child("image", std::move(image));
window_canvas.append_cfg(std::move(cfg));
// Needed to make the background redraw correctly.
window_canvas.set_is_dirty(true);
window.set_is_dirty(true);
// If a delay is specified, schedule the next image draw and break out of the loop.
const unsigned int draw_delay = floating_image.display_delay();
if(draw_delay != 0) {
// This must be a non-repeating timer
timer_id_ = add_timer(draw_delay, std::bind(&story_viewer::draw_floating_image, this, std::ref(window), image_iter, this_part_index), false);
return;
}
}
timer_id_ = 0;
}
void story_viewer::nav_button_callback(window& window, NAV_DIRECTION direction)

View file

@ -24,41 +24,16 @@
namespace storyscreen
{
floating_image::floating_image(const floating_image& fi)
: file_()
, x_(0)
, y_(0)
, delay_(0)
, autoscaled_(false)
, centered_(false)
{
this->assign(fi);
}
floating_image::floating_image(const config& cfg)
: file_(cfg["file"])
, x_(cfg["x"])
, y_(cfg["y"])
, delay_(cfg["delay"])
, autoscaled_(cfg["scaled"].to_bool())
, resize_with_background_(cfg["resize_with_background"].to_bool())
, centered_(cfg["centered"].to_bool())
{
}
void floating_image::assign(const floating_image& fi)
{
if(&fi == this) {
return;
}
file_ = fi.file_;
x_ = fi.x_;
y_ = fi.y_;
delay_ = fi.delay_;
autoscaled_ = fi.autoscaled_;
centered_ = fi.centered_;
}
background_layer::background_layer()
: scale_horizontally_(true)
, scale_vertically_(true)

View file

@ -44,10 +44,8 @@ public:
*/
floating_image(const config& cfg);
/**
* Copy constructor.
*/
floating_image(const floating_image& fi);
floating_image(const floating_image& fi) = default;
floating_image(floating_image&& fi) = default;
floating_image& operator=(const floating_image& fi)
{
@ -79,12 +77,13 @@ public:
}
/**
* Whether the image should be automatically scaled as much as
* the storyscreen background is.
* If true, the size of the image is changed in the same way that the ref_x
* and ref_y are mapped to use the base layer's pixels as the coordinate
* system.
*/
bool autoscale() const
bool resize_with_background() const
{
return autoscaled_;
return resize_with_background_;
}
/**
@ -96,7 +95,10 @@ public:
return centered_;
}
/** Delay before displaying, in milliseconds. */
/**
* Delay after displaying this image and before displaying the next image,
* in milliseconds.
*/
int display_delay() const
{
return delay_;
@ -106,7 +108,7 @@ private:
std::string file_;
int x_, y_; // referential (non corrected) x,y
int delay_;
bool autoscaled_;
bool resize_with_background_;
bool centered_;
/** Copy constructor and operator=() implementation details. */