Diff comments:

> === modified file 'data/scripting/mapobjects.lua'
> --- data/scripting/mapobjects.lua     2017-02-08 18:48:32 +0000
> +++ data/scripting/mapobjects.lua     2019-03-02 13:59:45 +0000
> @@ -20,32 +22,114 @@
>  end
>  
>  
> --- RST
> --- .. function:: add_walking_animations(table, animationname, dirname, 
> basename, hotspot, fps)
> ---
> ---    Adds 6 walk or sail animations - one for each walking direction - to 
> 'table'.
> ---
> ---    :arg table: A table that the animation data is added to. It may 
> already contain some animations.
> +-- Helper function for finding animation files with varying numbering length
> +function get_animation_files(prefix)
> +   local animation_files = path.list_files(prefix .. "_??.png")
> +   if #animation_files < 1 then
> +      animation_files = path.list_files(prefix .. "_???.png")
> +   end
> +   if #animation_files < 1 then
> +      animation_files = path.list_files(prefix .. "_?.png")
> +   end
> +   return animation_files
> +end
> +
> +
> +-- The mipmap scales supported by the engine.
> +-- Ensure that this always matches kSupportedScales in animations.cc
> +local supported_scales = { 0.5, 1, 2, 4 }
> +
> +
> +-- RST
> +-- .. function:: add_animation(animationtable, animationname, dirname, 
> basename, hotspot [, fps])
> +--
> +--    Convenience function for adding an animation to `animationtable`.
> +--    Supports both simple animations and mipmaps.
> +--    See :ref:`animations` for more documentation and code examples.
> +--
> +--    :arg animationtable: The table that the animation data will be added 
> to.
> +--       It may already contain some animations.
> +--    :type animationtable: :class:`table`
> +--    :arg animationname: The name of the animation to be added, e.g. 
> ``idle``.
> +--    :type animationname: :class:`string`
> +--    :arg dirname: The name of the directory where the animation image 
> files are located.
> +--    :type dirname: :class:`string`
> +--    :arg basename: The basename of the animation files. The filenames of 
> the
> +--       animation files need to have the format ``<basename>_\d{2,3}.png`` 
> for simple
> +--       file animations, and  ``<basename>_<scale>_\d{2,3}.png`` for 
> mipmaps.
> +--       Supported scales are ``0.5``, ``1``, ``2`` and ``4``.
> +--    :type basename: :class:`string`
> +--    :arg hotspot: The hotspot coordinates for blitting, e.g. ``{2, 20}``.
> +--    :type hotspot: :class:`table`

Thanks, done.

> +--    :arg fps: Frames per second. Only use this if the animation has more 
> than
> +--       1 frame, and if you need to deviate from the default frame rate.
> +--    :type fps: :class:`integer`
> +function add_animation(animationtable, animationname, dirname, basename, 
> hotspot, fps)
> +   mipmap = {}
> +   for scale_idx, current_scale in ipairs(supported_scales) do
> +      local listed_files = get_animation_files(dirname .. basename .. "_" .. 
> current_scale)
> +      if #listed_files > 0 then
> +         table.insert(
> +            mipmap,
> +            {
> +               scale = current_scale,
> +               files = listed_files,
> +            }
> +         )
> +      end
> +   end
> +   if #mipmap < 1 then
> +      table.insert(
> +      mipmap,
> +         {
> +            scale = 1,
> +            files = get_animation_files(dirname .. basename),
> +         }
> +      )
> +   end
> +   animationtable[animationname] = {
> +      mipmap = mipmap,
> +      hotspot = hotspot,
> +   }
> +   if (fps ~= nil) then

I think we should keep the error, because the FPS should not be specified at 
all in init.lua if thee is only 1 frame.

> +      animationtable[animationname]["fps"] = fps
> +   end
> +end
> +
> +
> +
> +-- RST
> +-- .. function:: add_walking_animations(animationtable, animationname, 
> dirname, basename, hotspot [, fps])
> +--
> +--    Adds 6 walk or sail animations - one for each walking direction - to 
> `animationtable`.
> +--    Supports both simple animations and mipmaps.
> +--    See :ref:`animations` for more documentation and code examples.
> +--
> +--    :arg animationtable: The table that the animation data will be added 
> to.
> +--       It may already contain some animations.
> +--    :type animationtable: :class:`table`
>  --    :arg animationname: The name of the animation to be added, e.g. 
> ``walkload``.
> +--    :type animationname: :class:`string`
>  --    :arg dirname: The name of the directory where the animation image 
> files are located.
> ---    :arg basename: The basename of the animation files. The filenames of 
> the animation files need to have the format 
> ``<basename>_(e|ne|se|sw|w|nw)_\d+.png``
> ---    :arg hotspot: The hotspot coordinates for blitting, e.g. ``{ 2, 20 }``.
> ---    :arg fps: Frames per second. Only use this if the animation has more 
> than 1 frame, and if you need to deviate from the default frame rate.
> -function add_walking_animations(table, animationname, dirname, basename, 
> hotspot, fps)
> -   if (fps ~= nil) then
> -      for idx, dir in ipairs{ "ne", "e", "se", "sw", "w", "nw" } do
> -         table[animationname .. "_" .. dir] = {
> -            pictures = path.list_files(dirname .. basename .. "_" .. dir ..  
> "_??.png"),
> -            hotspot = hotspot,
> -            fps = fps,
> -         }
> -      end
> -   else
> -      for idx, dir in ipairs{ "ne", "e", "se", "sw", "w", "nw" } do
> -         table[animationname .. "_" .. dir] = {
> -            pictures = path.list_files(dirname .. basename .. "_" .. dir ..  
> "_??.png"),
> -            hotspot = hotspot,
> -         }
> +--    :type dirname: :class:`table`
> +--    :arg basename: The basename of the animation files. The filenames of 
> the
> +--       animation files need to have the format
> +--       ``<basename>_(e|ne|se|sw|w|nw)_\d{2,3}.png`` for simple animations, 
> and
> +--       ``<basename>_(e|ne|se|sw|w|nw)_<scale>_\d{2,3}.png`` for mipmaps.
> +--       Supported scales are ``0.5``, ``1``, ``2`` and ``4``.
> +--    :type basename: :class:`string`
> +--    :arg hotspot: The hotspot coordinates for blitting, e.g. ``{2, 20}``.
> +--    :type hotspot: :class:`table`
> +--    :arg fps: Frames per second. Only use this if the animation has more 
> than
> +--       1 frame, and if you need to deviate from the default frame rate.
> +--    :type fps: :class:`integer`
> +function add_walking_animations(animationtable, animationname, dirname, 
> basename, hotspot, fps)
> +   for idx, dir in ipairs{ "ne", "e", "se", "sw", "w", "nw" } do
> +      if fps ~= nil then
> +         add_animation(animationtable, animationname .. "_" .. dir, dirname, 
> basename .. "_" .. dir, hotspot, fps)
> +      else
> +         add_animation(animationtable, animationname .. "_" .. dir, dirname, 
> basename .. "_" .. dir, hotspot)
>        end
>     end
>  end
> +
> 
> === modified file 'doc/sphinx/source/animations.rst'
> --- doc/sphinx/source/animations.rst  2018-04-09 08:01:28 +0000
> +++ doc/sphinx/source/animations.rst  2019-03-02 13:59:45 +0000
> @@ -24,8 +35,11 @@
>  **idle**
>     *Mandatory*. This is the name of the animation. The animation can then be 
> referenced by this name e.g. if you want to trigger it in a production 
> program.
>  
> +**files**
> +   *Mandatory*. A template for the image names. Our example will pick up any 
> image from ``idle_00.png`` through ``idle_99.png`` in the specified directory 
> path -- the current path in our example. These images can optionally have 
> corresponding player color mask images called ``idle_00_pc.png`` through 
> ``idle_99_pc.png``. Make sure to include leading 0's in the file names and to 
> have consistent length -- we support either 2 digit or 3 digit numbers in an 
> animation.

OK. I have updated the documentation here too.

> +
>  **pictures**
> -   *Mandatory*. A template for the image names. Our example will pick up any 
> image from ``idle_00.png`` through ``idle_99.png`` in the specified directory 
> path – the current path in our example. These images can optionally have 
> corresponding player color mask images called ``idle_00_pc.png`` through 
> ``idle_99_pc.png``. Make sure to include leading 0's in the file names.
> +   *DEPRECATED*. The same as ``files``.
>  
>  **hotspot**
>     *Mandatory*. Hotspots define a place on a graphic image through its *x* 
> and *y* coordinates that can be used as a handle or reference point to 
> provide control over positioning the image on the map. For example, hotspots 
> help carriers stay on the road, and control the positioning of the wares they 
> carry. Increase ``x`` to shift the animation to the left and ``y`` to shift 
> it upwards.
> @@ -33,22 +47,141 @@
>  **fps**
>     *Optional*. The frames per second for this animation if you want to 
> deviate from the default fps. This will control the playback speed of the 
> animation. Do not specify this value if you have only 1 animation frame.
>  
> -**scale**
> -   **DEPRECATED**. If the animation should be blitted at any other scale 
> than 1:1,
> -   specify the float value here. For example, if the animation images are 
> 2.5 times the size of what should be blitted at default zoom, use ``scale = 
> 2.5``.
> -
>  **sound_effect**
>     *Optional*. Our example will look for the sound files ``bar_00.ogg`` 
> through ``bar_99.ogg`` in the directory ``data/sound/foo`` and play them in 
> sequence.
>  
>  
> +Mipmaps
> +-------
> +
> +We support mipmaps for animations. They allow us to provide the same image 
> in different
> +resolutions for optimum rendering quality. Let's look at an example with a 
> mipmap ``idle`` animation and a normal ``build`` animation:
> +
> +.. code-block:: lua
> +
> +   animations = {
> +      idle = {
> +         mipmap = {
> +            {
> +               scale = 0.5,
> +               files = path.list_files(dirname .. "idle_0.5_??.png"),
> +            },
> +            {
> +               scale = 1,
> +               files = path.list_files(dirname .. "idle_1_??.png"),
> +            },
> +            {
> +               scale = 2,
> +               files = path.list_files(dirname .. "idle_2_??.png"),
> +            },
> +            {
> +               scale = 4,
> +               files = path.list_files(dirname .. "idle_4_??.png"),
> +            }
> +         },
> +         hotspot = { 5, 7 },
> +         fps = 4,
> +         sound_effect = {
> +            directory = "sound/foo",
> +            name = "bar",
> +         },
> +      },
> +      build = {
> +         files = path.list_files(dirname .. "build_??.png"),
> +         hotspot = { 5, 7 },
> +      }
> +   },
> +
> +The scale of ``1`` is mandatory, and other supported scales are ``0.5``, 
> ``2``
> +and ``4``.
> +The base table should no longer contain the ``files`` entry
> +when you're using a mipmap.
> +Each mimap entry must define the ``files`` and the ``scale``.
> +See also :ref:`animations_converting_formats`.
> +
> +
>  Directional Animations
>  ----------------------
>  
>  For objects that move around the map, like carriers, ships or animals, there 
> need to be 6 animations for the walking directions northeast ``"ne"``, east 
> ``"e"``, southeast ``"se"``, southwest ``"sw"``, west ``"w"``, and northwest 
> ``"nw"``. So, a "walk" animation would consist of 6 animations called 
> ``"walk_ne"``, ``"walk_e"``, ``"walk_se"``, ``"walk_sw"``, ``"walk_w"``, and 
> ``"walk_nw"``.
>  
> -Each of these 6 animations will then be defined like the animation above, so 
> we would end up with pictures called ``walk_ne_00.png``, ``walk_ne_01.png`` 
> ... ``walk_nw_00.png``,  ``walk_nw_01.png`` ..., and for player color: 
> ``walk_ne_00_pc.png``, ``walk_ne_01_pc.png`` ... ``walk_nw_00_pc.png``,  
> ``walk_nw_01_pc.png``, ...
> -
> -In order to cut down on the manual coding needed, we have a convenience 
> function :any:`add_walking_animations` to define the animation tables for 
> walking animations. The corresponding ``.lua`` script file is included 
> centrally when the tribe or world loading is started, so you won't need to 
> include it again.
> +Each of these 6 animations will then be defined like the animation above, so 
> we would end up with files called ``walk_ne_00.png``, ``walk_ne_01.png`` ... 
> ``walk_nw_00.png``,  ``walk_nw_01.png`` ..., and for player color: 
> ``walk_ne_00_pc.png``, ``walk_ne_01_pc.png`` ... ``walk_nw_00_pc.png``,  
> ``walk_nw_01_pc.png``, ...
> +
> +We also support mipmaps here -- name the files ``walk_ne_0.5_00.png``,
> +``walk_ne_0.5_01.png`` etc. for scale `0.5`, ``walk_ne_1_00.png``,
> +``walk_ne_1_01.png`` etc. for scale `1` and so on.
> +
> +
> +
> +.. _animations_convenience_functions:
> +
> +Convenience Functions
> +---------------------
> +
> +In order to cut down on the manual coding needed, we provide the convenience 
> functions
> +:any:`add_animation` for static animations and :any:`add_walking_animations` 
> for walking
> +animations, both of which will also detect mipmaps automatically.
> +The corresponding ``.lua`` script file is included centrally when the tribe 
> or world
> +loading is started, so you won't need to include it again. Example:
> +
> +.. code-block:: lua
> +
> +   dirname = path.dirname(__file__)
> +
> +   -- This table will contain the animations
> +   animations = {}
> +
> +   -- Add an idle animation with hotspot = {16, 30} and fps = 5
> +   add_animation(animations, "idle", dirname, "idle", {16, 30}, 5)
> +
> +   -- Add animations for the 6 directions with hotspot = {16, 30} and fps = 
> 10
> +   add_walking_animations(animations, "walk", dirname, "walk", {16, 30}, 10)
> +
> +   -- Add a "walkload" animation. The animation hasn't been created yet in 
> this example, so we reuse the files for the "walk" animation.
> +   add_walking_animations(animations, "walkload", dirname, "walk", {16, 30}, 
> 10)
> +
> +
> +   tribes:new_worker_type {
> +      msgctxt = "fancytribe_worker",
> +      name = "fancytribe_diligentworker",
> +      ...
> +
> +      animations = animations, -- Include the animations table in your map 
> object
> +      ...
> +   }
> +
> +The convenience functions don't support sound effects directly, so you'll 
> have to
> +add them manually, like this:
> +
> +.. code-block:: lua
> +
> +   animations = {}
> +   add_animation(animations, "work", dirname, "work", {11, 26}, 10)
> +   animations["work"]["sound_effect"] = {
> +      name = "bar",
> +      directory = "sound/foo"
> +   }
> +
> +
> +.. _animations_converting_formats:
> +
> +Converting Animation Formats
> +----------------------------
> +
> +When converting a simple file animation to a mipmap animation, follow these 
> steps:
> +
> +* Use `utils/rename_animation.py` to rename the previous animation, to make 
> sure
> +  that our version control system will not lose its history, e.g.::
> +
> +   utils/rename_animation.py 
> data/tribes/workers/fancytribe/diligentworker/walk_ne 
> data/tribes/workers/fancytribe/diligentworker/walk_ne_1
> +   utils/rename_animation.py 
> data/tribes/workers/fancytribe/diligentworker/walk_nw 
> data/tribes/workers/fancytribe/diligentworker/walk_nw_1
> +   ...
> +
> +* Export the new animations from Blender, preferably at all supported scales.
> +  Only export the higher resolution scales if the textures have sufficient 
> resolution.

Excellent! Can you document its usage here?

> +
> +
> +.. _animations_map_object_types:
>  
>  Map Object Types
>  ----------------
> 
> === modified file 'src/graphic/animation.cc'
> --- src/graphic/animation.cc  2019-02-23 11:00:49 +0000
> +++ src/graphic/animation.cc  2019-03-02 13:59:45 +0000
> @@ -42,19 +44,34 @@
>  #include "sound/sound_handler.h"
>  
>  namespace {
> +// The mipmap scales supported by the engine.
> +// Ensure that this always matches supported_scales in 
> data/scription/mapobjects.lua.

Fixed.

> +const std::set<float> kSupportedScales { 0.5, 1, 2, 4};
> +
>  /**
>   * Implements the Animation interface for an animation that is unpacked on 
> disk, that
>   * is every frame and every pc color frame is an singular file on disk.
>   */
>  class NonPackedAnimation : public Animation {
>  public:
> +     struct MipMapEntry {
> +             explicit MipMapEntry(float scale, const LuaTable& table);
> +
> +             bool hasplrclrs;

Done.

> +             std::vector<std::string> image_files;
> +             std::vector<std::string> pc_mask_image_files;
> +
> +             std::vector<const Image*> frames;
> +             std::vector<const Image*> pcmasks;

Done. I also added some comments.

> +     };
> +
>       ~NonPackedAnimation() override {
>       }
>       explicit NonPackedAnimation(const LuaTable& table);
>  
>       // Implements Animation.
>       float height() const override;
> -     Rectf source_rectangle(int percent_from_bottom) const override;
> +     Rectf source_rectangle(int percent_from_bottom, float scale) const 
> override;
>       Rectf destination_rectangle(const Vector2f& position,
>                                   const Rectf& source_rect,
>                                   float scale) const override;
> @@ -111,98 +156,128 @@
>                       g_sound_handler.load_fx_if_needed(directory, name, 
> sound_effect_);
>               }
>  
> +             // Repetition
>               if (table.has_key("play_once")) {
>                       play_once_ = table.get_bool("play_once");
>               }
>  
> -             image_files_ = 
> table.get_table("pictures")->array_entries<std::string>();
> +             if (table.has_key("mipmap")) {
> +                     std::unique_ptr<LuaTable> mipmaps_table = 
> table.get_table("mipmap");
> +                     for (const int key : mipmaps_table->keys<int>()) {
> +                             std::unique_ptr<LuaTable> current_scale_table = 
> mipmaps_table->get_table(key);
> +                             const float current_scale = 
> current_scale_table->get_double("scale");
> +                             if (kSupportedScales.count(current_scale) != 1) 
> {
> +                                     std::string supported_scales = "";
> +                                     for (const float supported_scale : 
> kSupportedScales) {
> +                                             supported_scales = 
> (boost::format("%s %.1f") % supported_scales % supported_scale).str();
> +                                     }
> +                                     throw wexception(
> +                                             "Animation has unsupported 
> scale '%.1f' in mipmap - supported scales are:%s", current_scale, 
> supported_scales.c_str());
> +                             }
> +                             mipmaps_.insert(std::make_pair(current_scale, 
> std::unique_ptr<MipMapEntry>(new MipMapEntry(current_scale, 
> *current_scale_table))));
> +                     }
> +             } else {
> +                     mipmaps_.insert(std::make_pair(1.0f, 
> std::unique_ptr<MipMapEntry>(new MipMapEntry(1.0f, table))));
> +             }
>  
> -             if (image_files_.empty()) {
> -                     throw wexception("Animation without pictures. The 
> template should look similar to this:"
> -                                      " 'directory/idle_??.png' for 
> 'directory/idle_00.png' etc.");
> -             } else if (table.has_key("fps")) {
> -                     if (image_files_.size() == 1) {
> +             // Frames
> +             if (table.has_key("fps")) {
> +                     if (nr_frames_ == 1) {
>                               throw wexception(
> -                                "Animation with one picture %s must not have 
> 'fps'", image_files_[0].c_str());
> +                                     "Animation with one picture %s must not 
> have 'fps'", mipmaps_.begin()->second->image_files[0].c_str());
>                       }
>                       frametime_ = 1000 / get_positive_int(table, "fps");
>               }
> -
> -             for (std::string image_file : image_files_) {
> -                     boost::replace_last(image_file, ".png", "_pc.png");
> -                     if (g_fs->file_exists(image_file)) {
> -                             hasplrclrs_ = true;
> -                             pc_mask_image_files_.push_back(image_file);
> -                     } else if (hasplrclrs_) {
> -                             throw wexception("Animation is missing player 
> color file: %s", image_file.c_str());
> -                     }
> -             }
> -
> -             if (table.has_key("scale")) {
> -                     scale_ = table.get_double("scale");
> -                     if (scale_ <= 0.0f) {
> -                             throw wexception("Animation scale needs to be > 
> 0.0f, but it is %f. The first image of "
> -                                              "this animation is %s",
> -                                              static_cast<double>(scale_), 
> image_files_[0].c_str());
> -                     }
> -             }
> -
> -             assert(!image_files_.empty());
> -             assert(pc_mask_image_files_.size() == image_files_.size() || 
> pc_mask_image_files_.empty());
> -             assert(scale_ > 0);
> +             nr_frames_ = mipmaps_.begin()->second->image_files.size();
> +
> +             // Perform some checks to make sure that the data is complete 
> and consistent
> +             const bool should_have_playercolor = 
> mipmaps_.begin()->second->hasplrclrs;
> +             for (const auto& mipmap : mipmaps_) {
> +                     if (mipmap.second->image_files.size() != nr_frames_) {
> +                             throw wexception("Mismatched number of images 
> for different scales in animation table: %" PRIuS " vs. %u at scale %.2f",
> +                                                                       
> mipmap.second->image_files.size(),
> +                                                                       
> nr_frames_,
> +                                                                       
> mipmap.first);
> +                     }
> +                     if (mipmap.second->hasplrclrs != 
> should_have_playercolor) {
> +                             throw wexception("Mismatched existence of 
> player colors in animation table for scales %.2f and %.2f",
> +                                                                       
> mipmaps_.begin()->first,
> +                                                                       
> mipmap.first);
> +                     }
> +             }
> +             if (mipmaps_.count(1.0f) != 1) {
> +                     throw wexception("All animations must provide images 
> for the neutral scale (1.0)");

If they are all <1, we will have crap quality.

I might be convinced to drop the requirement if there are higher-resolution 
images if it should become a problem. I'd rather have 
https://code.launchpad.net/~widelands-dev/widelands/representative_image_in_font_renderer
 merged first though so we won't start cluttering the files with extra images 
for scale 1.

> +             }
>       } catch (const LuaError& e) {
>               throw wexception("Error in animation table: %s", e.what());
>       }
>  }
>  
> +float NonPackedAnimation::find_best_scale(float scale) const {
> +     assert(!mipmaps_.empty());
> +     float result = mipmaps_.begin()->first;
> +     for (const auto& mipmap : mipmaps_) {
> +             // The map is reverse sorted, so we can break as soon as we are 
> lower than the wanted scale
> +             if (mipmap.first < scale) {
> +                     break;
> +             }
> +             result = mipmap.first;
> +     }
> +     return result;
> +}
> +
>  void NonPackedAnimation::ensure_graphics_are_loaded() const {
> -     if (frames_.empty()) {
> +     if (mipmaps_.begin()->second->frames.empty()) {
>               const_cast<NonPackedAnimation*>(this)->load_graphics();
>       }
>  }
>  
>  void NonPackedAnimation::load_graphics() {
> -     if (image_files_.empty())
> -             throw wexception("animation without pictures.");
> -
> -     if (pc_mask_image_files_.size() && pc_mask_image_files_.size() != 
> image_files_.size())
> -             throw wexception("animation has %" PRIuS " frames but 
> playercolor mask has %" PRIuS " frames",
> -                              image_files_.size(), 
> pc_mask_image_files_.size());
> -
> -     for (const std::string& filename : image_files_) {
> -             const Image* image = g_gr->images().get(filename);
> -             if (frames_.size() &&
> -                 (frames_[0]->width() != image->width() || 
> frames_[0]->height() != image->height())) {
> -                     throw wexception("wrong size: (%u, %u), should be (%u, 
> %u) like the first frame",
> -                                      image->width(), image->height(), 
> frames_[0]->width(),
> -                                      frames_[0]->height());
> -             }
> -             frames_.push_back(image);
> -     }
> -
> -     for (const std::string& filename : pc_mask_image_files_) {
> -             // TODO(unknown): Do not load playercolor mask as opengl 
> texture or use it as
> -             //     opengl texture.
> -             const Image* pc_image = g_gr->images().get(filename);
> -             if (frames_[0]->width() != pc_image->width() || 
> frames_[0]->height() != pc_image->height()) {
> -                     // TODO(unknown): see bug #1324642
> -                     throw wexception("playercolor mask has wrong size: (%u, 
> %u), should "
> -                                      "be (%u, %u) like the animation frame",
> -                                      pc_image->width(), pc_image->height(), 
> frames_[0]->width(),
> -                                      frames_[0]->height());
> -             }
> -             pcmasks_.push_back(pc_image);
> +     for (const auto& entry : mipmaps_) {
> +             MipMapEntry* mipmap = entry.second.get();
> +
> +             if (mipmap->image_files.empty()) {
> +                     throw wexception("animation without image files at 
> promised scale %.2f.", entry.first);
> +             }
> +             if (mipmap->pc_mask_image_files.size() && 
> mipmap->pc_mask_image_files.size() != mipmap->image_files.size()) {
> +                     throw wexception("animation has %" PRIuS " frames but 
> playercolor mask has %" PRIuS " frames for scale %.2f",
> +                                                               
> mipmap->image_files.size(), mipmap->pc_mask_image_files.size(), entry.first);
> +             }
> +
> +             for (const std::string& filename : mipmap->image_files) {
> +                     const Image* image = g_gr->images().get(filename);
> +                     if (mipmap->frames.size() &&
> +                              (mipmap->frames[0]->width() != image->width() 
> || mipmap->frames[0]->height() != image->height())) {
> +                             throw wexception("wrong size: (%u, %u), should 
> be (%u, %u) like the first frame",
> +                                                                       
> image->width(), image->height(), mipmap->frames[0]->width(),
> +                                                                       
> mipmap->frames[0]->height());
> +                     }
> +                     mipmap->frames.push_back(image);
> +             }
> +
> +             for (const std::string& filename : mipmap->pc_mask_image_files) 
> {
> +                     // TODO(unknown): Do not load playercolor mask as 
> opengl texture or use it as
> +                     //     opengl texture.
> +                     const Image* pc_image = g_gr->images().get(filename);
> +                     if (mipmap->frames[0]->width() != pc_image->width() || 
> mipmap->frames[0]->height() != pc_image->height()) {
> +                             // TODO(unknown): see bug #1324642
> +                             throw wexception("playercolor mask has wrong 
> size: (%u, %u), should "
> +                                                                       "be 
> (%u, %u) like the animation frame",
> +                                                                       
> pc_image->width(), pc_image->height(), mipmap->frames[0]->width(),
> +                                                                       
> mipmap->frames[0]->height());
> +                     }
> +                     mipmap->pcmasks.push_back(pc_image);
> +             }
>       }
>  }
>  
>  float NonPackedAnimation::height() const {
>       ensure_graphics_are_loaded();
> -     return frames_[0]->height() / scale_;
> +     return mipmaps_.at(1.0f)->frames.at(0)->height();
>  }
>  
>  uint16_t NonPackedAnimation::nr_frames() const {
> -     ensure_graphics_are_loaded();
> -     return frames_.size();
> +     return nr_frames_;
>  }
>  
>  uint32_t NonPackedAnimation::frametime() const {
> 
> === modified file 'src/logic/map_objects/map_object.cc'
> --- src/logic/map_objects/map_object.cc       2019-02-27 17:19:00 +0000
> +++ src/logic/map_objects/map_object.cc       2019-03-02 13:59:45 +0000
> @@ -255,11 +255,6 @@
>                       throw GameDataError("Map object %s has a menu icon, but 
> it is empty", init_name.c_str());
>               }
>       }
> -     // TODO(GunChleoc): We can't scale down images in the font renderer 
> yet, so we need an extra
> -     // representative image if the animation has high resolution.
> -     if (table.has_key("representative_image")) {
> -             representative_image_filename_ = 
> table.get_string("representative_image");

This fill be fixed in 
https://code.launchpad.net/~widelands-dev/widelands/representative_image_in_font_renderer/+merge/363781
 with the "representative_frame" parameter.

> -     }
>       check_representative_image();
>  }
>  MapObjectDescr::~MapObjectDescr() {


-- 
https://code.launchpad.net/~widelands-dev/widelands/mipmaps/+merge/363780
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/mipmaps into lp:widelands.

_______________________________________________
Mailing list: https://launchpad.net/~widelands-dev
Post to     : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to