← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/animation_scaling into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/animation_scaling into lp:widelands.

Commit message:
Implemented scaling for animations. Bigger idle textures for Barbarian warehouse and shipyard.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/animation_scaling/+merge/310718

This implements scaling for animations, so it will look nice when zoomed in.

I am having problems with the roof textures in the Blender models, but the warehouse and shipyard look good enough for testing.

We will need spritemaps before we convert the whole lot, otherwise our file size will explode - but that's for another branch.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/animation_scaling into lp:widelands.
=== modified file 'data/tribes/buildings/productionsites/barbarians/shipyard/idle_00.png'
Binary files data/tribes/buildings/productionsites/barbarians/shipyard/idle_00.png	2014-12-13 20:54:34 +0000 and data/tribes/buildings/productionsites/barbarians/shipyard/idle_00.png	2016-11-13 16:57:34 +0000 differ
=== modified file 'data/tribes/buildings/productionsites/barbarians/shipyard/idle_00_pc.png'
Binary files data/tribes/buildings/productionsites/barbarians/shipyard/idle_00_pc.png	2014-12-13 20:54:34 +0000 and data/tribes/buildings/productionsites/barbarians/shipyard/idle_00_pc.png	2016-11-13 16:57:34 +0000 differ
=== modified file 'data/tribes/buildings/productionsites/barbarians/shipyard/init.lua'
--- data/tribes/buildings/productionsites/barbarians/shipyard/init.lua	2016-09-03 14:59:10 +0000
+++ data/tribes/buildings/productionsites/barbarians/shipyard/init.lua	2016-11-13 16:57:34 +0000
@@ -7,6 +7,7 @@
    descname = pgettext("barbarians_building", "Shipyard"),
    helptext_script = dirname .. "helptexts.lua",
    icon = dirname .. "menu.png",
+   representative_image = dirname .. "representative_image.png",
    size = "medium",
    needs_seafaring = true,
 
@@ -26,6 +27,7 @@
       idle = {
          pictures = path.list_files(dirname .. "idle_??.png"),
          hotspot = { 62, 48 },
+         scale = 3.26
       },
       build = {
          pictures = path.list_files(dirname .. "build_??.png"),

=== added file 'data/tribes/buildings/productionsites/barbarians/shipyard/representative_image.png'
Binary files data/tribes/buildings/productionsites/barbarians/shipyard/representative_image.png	1970-01-01 00:00:00 +0000 and data/tribes/buildings/productionsites/barbarians/shipyard/representative_image.png	2016-11-13 16:57:34 +0000 differ
=== modified file 'data/tribes/buildings/warehouses/barbarians/warehouse/idle_00.png'
Binary files data/tribes/buildings/warehouses/barbarians/warehouse/idle_00.png	2015-02-05 17:05:45 +0000 and data/tribes/buildings/warehouses/barbarians/warehouse/idle_00.png	2016-11-13 16:57:34 +0000 differ
=== modified file 'data/tribes/buildings/warehouses/barbarians/warehouse/idle_00_pc.png'
Binary files data/tribes/buildings/warehouses/barbarians/warehouse/idle_00_pc.png	2015-02-05 17:05:45 +0000 and data/tribes/buildings/warehouses/barbarians/warehouse/idle_00_pc.png	2016-11-13 16:57:34 +0000 differ
=== modified file 'data/tribes/buildings/warehouses/barbarians/warehouse/init.lua'
--- data/tribes/buildings/warehouses/barbarians/warehouse/init.lua	2015-12-28 21:53:11 +0000
+++ data/tribes/buildings/warehouses/barbarians/warehouse/init.lua	2016-11-13 16:57:34 +0000
@@ -7,6 +7,7 @@
    descname = pgettext("barbarians_building", "Warehouse"),
    helptext_script = dirname .. "helptexts.lua",
    icon = dirname .. "menu.png",
+   representative_image = dirname .. "representative_image.png",
    size = "medium",
 
    buildcost = {
@@ -26,7 +27,8 @@
    animations = {
       idle = {
          pictures = path.list_files(dirname .. "idle_??.png"),
-         hotspot = { 60, 78 }
+         hotspot = { 60, 78 },
+         scale = 3.62
       },
       build = {
          pictures = path.list_files(dirname .. "build_??.png"),

=== added file 'data/tribes/buildings/warehouses/barbarians/warehouse/representative_image.png'
Binary files data/tribes/buildings/warehouses/barbarians/warehouse/representative_image.png	1970-01-01 00:00:00 +0000 and data/tribes/buildings/warehouses/barbarians/warehouse/representative_image.png	2016-11-13 16:57:34 +0000 differ
=== modified file 'doc/sphinx/source/animations.rst'
--- doc/sphinx/source/animations.rst	2016-10-14 07:02:10 +0000
+++ doc/sphinx/source/animations.rst	2016-11-13 16:57:34 +0000
@@ -7,6 +7,7 @@
       idle = {
          pictures = path.list_files(path.dirname(__file__) .. "idle_??.png"),
          hotspot = { 5, 7 },
+         scale = 2.5,
          fps = 4,
          sound_effect = {
             directory = "sound/foo",
@@ -30,5 +31,9 @@
 fps
    *Optional*. The frames per second for this animation if you want to deviate from the default fps. Do not specify this value if you have only 1 animation frame.
 
+scale
+   *Optional*. 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.

=== modified file 'doc/sphinx/source/lua_tribes_buildings.rst.org'
--- doc/sphinx/source/lua_tribes_buildings.rst.org	2016-10-18 07:54:45 +0000
+++ doc/sphinx/source/lua_tribes_buildings.rst.org	2016-11-13 16:57:34 +0000
@@ -44,6 +44,10 @@
 **icon**
     *Mandatory*. The full path to the menu icon for this building.
 
+**representative_image**
+    *Optional*. The full path to a representative image for this building.
+    This is needed if the building has a scaled "idle" animation.
+
 **size**
     *Mandatory*. The size of this building: ``"small"``, ``"medium"``, or ``"big"``.
 

=== modified file 'src/graphic/animation.cc'
--- src/graphic/animation.cc	2016-10-26 10:56:02 +0000
+++ src/graphic/animation.cc	2016-11-13 16:57:34 +0000
@@ -70,7 +70,7 @@
 	uint16_t nr_frames() const override;
 	uint32_t frametime() const override;
 	const Vector2i& hotspot() const override;
-	Image* representative_image(const RGBColor* clr) const override;
+	const Image* representative_image(const RGBColor* clr) const override;
 	const std::string& representative_image_filename() const override;
 	virtual void blit(uint32_t time,
 	                  const Rectf& dstrc,
@@ -78,6 +78,9 @@
 	                  const RGBColor* clr,
 	                  Surface*) const override;
 	void trigger_sound(uint32_t framenumber, uint32_t stereo_position) const override;
+	float scale() const override {
+		return scale_;
+	}
 
 private:
 	// Loads the graphics if they are not yet loaded.
@@ -93,6 +96,7 @@
 	bool hasplrclrs_;
 	std::vector<std::string> image_files_;
 	std::vector<std::string> pc_mask_image_files_;
+	float scale_;
 
 	vector<const Image*> frames_;
 	vector<const Image*> pcmasks_;
@@ -105,7 +109,7 @@
 };
 
 NonPackedAnimation::NonPackedAnimation(const LuaTable& table)
-   : frametime_(FRAME_LENGTH), hasplrclrs_(false), play_once_(false) {
+   : frametime_(FRAME_LENGTH), hasplrclrs_(false), scale_(1), play_once_(false) {
 	try {
 		get_point(*table.get_table("hotspot"), &hotspot_);
 
@@ -144,9 +148,19 @@
 				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 %f needs to be > 0.0f. First image of this animation is %s", 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);
 	} catch (const LuaError& e) {
 		throw wexception("Error in animation table: %s", e.what());
 	}
@@ -194,12 +208,12 @@
 
 uint16_t NonPackedAnimation::width() const {
 	ensure_graphics_are_loaded();
-	return frames_[0]->width();
+	return frames_[0]->width() / scale_;
 }
 
 uint16_t NonPackedAnimation::height() const {
 	ensure_graphics_are_loaded();
-	return frames_[0]->height();
+	return frames_[0]->height() / scale_;
 }
 
 uint16_t NonPackedAnimation::nr_frames() const {
@@ -215,20 +229,17 @@
 	return hotspot_;
 }
 
-Image* NonPackedAnimation::representative_image(const RGBColor* clr) const {
+const Image* NonPackedAnimation::representative_image(const RGBColor* clr) const {
 	assert(!image_files_.empty());
 	const Image* image = g_gr->images().get(image_files_[0]);
-
-	if (!hasplrclrs_ || clr == nullptr) {
-		// No player color means we simply want an exact copy of the original image.
-		const int w = image->width();
-		const int h = image->height();
-		Texture* rv = new Texture(w, h);
-		rv->blit(Rectf(0, 0, w, h), *image, Rectf(0, 0, w, h), 1., BlendMode::Copy);
-		return rv;
-	} else {
-		return playercolor_image(clr, image, g_gr->images().get(pc_mask_image_files_[0]));
+	if (hasplrclrs_ && clr) {
+		image = playercolor_image(clr, image, g_gr->images().get(pc_mask_image_files_[0]));
 	}
+	const int w = image->width();
+	const int h = image->height();
+	Texture* rv = new Texture(w / scale_, h / scale_);
+	rv->blit(Rectf(0, 0, w / scale_, h / scale_), *image, Rectf(0, 0, w, h), 1., BlendMode::Copy);
+	return rv;
 }
 
 const std::string& NonPackedAnimation::representative_image_filename() const {
@@ -266,6 +277,7 @@
 	const uint32_t idx = current_frame(time);
 	assert(idx < nr_frames());
 
+	// Scale is set from the outside in order to deal with the edge of the screen.
 	if (!hasplrclrs_ || clr == nullptr) {
 		target->blit(dstrc, *frames_.at(idx), srcrc, 1., BlendMode::UseAlpha);
 	} else {
@@ -315,9 +327,9 @@
 
 const Image* AnimationManager::get_representative_image(uint32_t id, const RGBColor* clr) {
 	if (representative_images_.count(id) != 1) {
-		representative_images_.insert(std::make_pair(
-		   id,
-		   std::unique_ptr<Image>(g_gr->animations().get_animation(id).representative_image(clr))));
+		representative_images_.insert(
+		   std::make_pair(id, std::unique_ptr<const Image>(
+		                         g_gr->animations().get_animation(id).representative_image(clr))));
 	}
 	return representative_images_.at(id).get();
 }

=== modified file 'src/graphic/animation.h'
--- src/graphic/animation.h	2016-10-25 08:14:28 +0000
+++ src/graphic/animation.h	2016-11-13 16:57:34 +0000
@@ -73,7 +73,7 @@
 	/// An image of the first frame, blended with the given player color.
 	/// The 'clr' is the player color used for blending - the parameter can be
 	/// 'nullptr', in which case the neutral image will be returned.
-	virtual Image* representative_image(const RGBColor* clr) const = 0;
+	virtual const Image* representative_image(const RGBColor* clr) const = 0;
 	/// The filename of the image used for the first frame, without player color.
 	virtual const std::string& representative_image_filename() const = 0;
 
@@ -91,6 +91,7 @@
 
 	/// Play the sound effect associated with this animation at the given time.
 	virtual void trigger_sound(uint32_t time, uint32_t stereo_position) const = 0;
+	virtual float scale() const = 0;
 
 private:
 	DISALLOW_COPY_AND_ASSIGN(Animation);
@@ -121,7 +122,7 @@
 
 private:
 	std::vector<std::unique_ptr<Animation>> animations_;
-	std::map<uint32_t, std::unique_ptr<Image>> representative_images_;
+	std::map<uint32_t, std::unique_ptr<const Image>> representative_images_;
 };
 
 #endif  // end of include guard: WL_GRAPHIC_ANIMATION_H

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2016-10-24 20:07:22 +0000
+++ src/graphic/rendertarget.cc	2016-11-13 16:57:34 +0000
@@ -326,6 +326,8 @@
 	Rectf destination_rect(dst.x - (animation.hotspot().x - source_rect.x) * scale,
 	                       dst.y - (animation.hotspot().y - source_rect.y) * scale,
 	                       source_rect.w * scale, source_rect.h * scale);
+	source_rect.w *= animation.scale();
+	source_rect.h *= animation.scale();
 	if (to_surface_geometry(&destination_rect, &source_rect)) {
 		animation.blit(time, destination_rect, source_rect, player_color, surface_);
 	}

=== modified file 'src/logic/map_objects/map_object.cc'
--- src/logic/map_objects/map_object.cc	2016-10-26 19:43:40 +0000
+++ src/logic/map_objects/map_object.cc	2016-11-13 16:57:34 +0000
@@ -243,6 +243,11 @@
 			throw GameDataError("Map object %s has a menu icon, but it is empty", init_name.c_str());
 		}
 	}
+	// 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");
+	}
 }
 MapObjectDescr::~MapObjectDescr() {
 	anims_.clear();


Follow ups