Merge lp:~widelands-dev/widelands/zoom into lp:widelands

Proposed by SirVer on 2016-10-22
Status: Merged
Merged at revision: 8148
Proposed branch: lp:~widelands-dev/widelands/zoom
Merge into: lp:widelands
Diff against target: 10816 lines (+2707/-2303)
183 files modified
src/base/CMakeLists.txt (+10/-3)
src/base/math.cc (+20/-0)
src/base/math.h (+43/-0)
src/base/point.h (+0/-79)
src/base/rect.h (+25/-15)
src/base/vector.cc (+10/-4)
src/base/vector.h (+81/-16)
src/economy/flag.h (+6/-1)
src/economy/portdock.cc (+1/-1)
src/economy/portdock.h (+5/-1)
src/economy/road.h (+5/-1)
src/editor/editorinteractive.cc (+4/-2)
src/editor/tools/set_origin_tool.cc (+2/-5)
src/editor/tools/set_starting_pos_tool.cc (+1/-1)
src/editor/ui_menus/main_menu_load_or_save_map.cc (+1/-1)
src/editor/ui_menus/main_menu_map_options.cc (+1/-1)
src/editor/ui_menus/main_menu_random_map.cc (+1/-1)
src/editor/ui_menus/main_menu_save_map.h (+1/-1)
src/editor/ui_menus/player_menu.cc (+3/-3)
src/editor/ui_menus/tool_change_resources_options_menu.cc (+1/-1)
src/editor/ui_menus/tool_menu.cc (+2/-2)
src/editor/ui_menus/tool_place_bob_options_menu.cc (+2/-2)
src/editor/ui_menus/tool_place_immovable_options_menu.cc (+1/-1)
src/editor/ui_menus/tool_set_terrain_options_menu.cc (+6/-6)
src/game_io/CMakeLists.txt (+2/-0)
src/game_io/game_interactive_player_packet.cc (+42/-12)
src/game_io/game_preload_packet.cc (+8/-3)
src/graphic/CMakeLists.txt (+1/-1)
src/graphic/align.cc (+6/-1)
src/graphic/align.h (+2/-2)
src/graphic/animation.cc (+20/-16)
src/graphic/animation.h (+7/-4)
src/graphic/font_handler.cc (+10/-9)
src/graphic/font_handler.h (+3/-3)
src/graphic/font_handler1.h (+1/-1)
src/graphic/game_renderer.cc (+303/-269)
src/graphic/game_renderer.h (+23/-34)
src/graphic/gl/blit_data.h (+1/-1)
src/graphic/gl/blit_program.cc (+5/-5)
src/graphic/gl/blit_program.h (+3/-3)
src/graphic/gl/coordinate_conversion.h (+6/-6)
src/graphic/gl/dither_program.cc (+35/-36)
src/graphic/gl/dither_program.h (+2/-2)
src/graphic/gl/draw_line_program.h (+1/-1)
src/graphic/gl/fields_to_draw.h (+48/-12)
src/graphic/gl/fill_rect_program.cc (+1/-1)
src/graphic/gl/fill_rect_program.h (+2/-2)
src/graphic/gl/road_program.cc (+29/-29)
src/graphic/gl/road_program.h (+2/-0)
src/graphic/gl/terrain_program.cc (+21/-21)
src/graphic/gl/terrain_program.h (+2/-2)
src/graphic/minimap_renderer.cc (+132/-131)
src/graphic/minimap_renderer.h (+29/-21)
src/graphic/render_queue.cc (+6/-5)
src/graphic/render_queue.h (+4/-3)
src/graphic/rendertarget.cc (+80/-87)
src/graphic/rendertarget.h (+37/-34)
src/graphic/richtext.cc (+15/-15)
src/graphic/richtext.h (+2/-2)
src/graphic/screen.cc (+4/-4)
src/graphic/screen.h (+4/-4)
src/graphic/surface.cc (+43/-43)
src/graphic/surface.h (+12/-12)
src/graphic/text/rt_render.cc (+20/-21)
src/graphic/texture.cc (+8/-10)
src/graphic/texture.h (+5/-5)
src/graphic/texture_atlas.cc (+13/-13)
src/graphic/texture_atlas.h (+2/-2)
src/graphic/wordwrap.cc (+4/-4)
src/graphic/wordwrap.h (+2/-2)
src/io/streamread.cc (+10/-0)
src/io/streamread.h (+1/-0)
src/io/streamwrite.cc (+1/-0)
src/io/streamwrite.h (+6/-0)
src/logic/CMakeLists.txt (+8/-6)
src/logic/game.cc (+1/-1)
src/logic/game_controller.h (+0/-3)
src/logic/map_objects/bob.cc (+47/-39)
src/logic/map_objects/bob.h (+13/-7)
src/logic/map_objects/draw_text.h (+34/-0)
src/logic/map_objects/immovable.cc (+24/-21)
src/logic/map_objects/immovable.h (+24/-11)
src/logic/map_objects/map_object.cc (+33/-20)
src/logic/map_objects/map_object.h (+10/-4)
src/logic/map_objects/tribes/building.cc (+20/-35)
src/logic/map_objects/tribes/building.h (+7/-3)
src/logic/map_objects/tribes/constructionsite.cc (+19/-22)
src/logic/map_objects/tribes/constructionsite.h (+5/-1)
src/logic/map_objects/tribes/dismantlesite.cc (+9/-12)
src/logic/map_objects/tribes/dismantlesite.h (+5/-1)
src/logic/map_objects/tribes/road_textures.cc (+4/-4)
src/logic/map_objects/tribes/road_textures.h (+5/-4)
src/logic/map_objects/tribes/ship.cc (+9/-7)
src/logic/map_objects/tribes/ship.h (+5/-1)
src/logic/map_objects/tribes/soldier.cc (+91/-71)
src/logic/map_objects/tribes/soldier.h (+16/-3)
src/logic/map_objects/tribes/worker.cc (+20/-8)
src/logic/map_objects/tribes/worker.h (+9/-2)
src/logic/map_objects/tribes/worker_descr.cc (+3/-3)
src/logic/map_objects/tribes/worker_descr.h (+2/-2)
src/logic/widelands_geometry.h (+1/-0)
src/map_io/map_saver.cc (+4/-3)
src/profile/profile.cc (+4/-4)
src/profile/profile.h (+3/-3)
src/scripting/lua_game.cc (+1/-1)
src/scripting/lua_map.cc (+6/-6)
src/scripting/lua_ui.cc (+14/-14)
src/sound/CMakeLists.txt (+1/-0)
src/sound/sound_handler.cc (+5/-6)
src/ui_basic/box.cc (+3/-3)
src/ui_basic/button.cc (+39/-41)
src/ui_basic/checkbox.cc (+9/-9)
src/ui_basic/checkbox.h (+4/-4)
src/ui_basic/editbox.cc (+16/-16)
src/ui_basic/icon.cc (+9/-10)
src/ui_basic/listselect.cc (+8/-8)
src/ui_basic/multilineeditbox.cc (+9/-9)
src/ui_basic/multilinetextarea.cc (+7/-7)
src/ui_basic/panel.cc (+22/-22)
src/ui_basic/panel.h (+8/-8)
src/ui_basic/progressbar.cc (+11/-12)
src/ui_basic/progresswindow.cc (+9/-9)
src/ui_basic/progresswindow.h (+6/-3)
src/ui_basic/radiobutton.cc (+2/-2)
src/ui_basic/radiobutton.h (+3/-3)
src/ui_basic/scrollbar.cc (+40/-40)
src/ui_basic/scrollbar.h (+2/-2)
src/ui_basic/slider.cc (+28/-29)
src/ui_basic/table.cc (+15/-15)
src/ui_basic/tabpanel.cc (+27/-28)
src/ui_basic/textarea.cc (+9/-9)
src/ui_basic/unique_window.cc (+1/-1)
src/ui_basic/window.cc (+34/-31)
src/ui_basic/window.h (+2/-2)
src/ui_fsmenu/about.cc (+1/-1)
src/ui_fsmenu/base.cc (+1/-1)
src/ui_fsmenu/helpwindow.cc (+1/-1)
src/ui_fsmenu/launch_mpg.cc (+1/-1)
src/ui_fsmenu/loadgame.cc (+1/-1)
src/ui_fsmenu/mapselect.cc (+2/-2)
src/ui_fsmenu/options.cc (+14/-14)
src/website/map_info.cc (+2/-2)
src/wlapplication.cc (+4/-4)
src/wlapplication.h (+6/-6)
src/wui/CMakeLists.txt (+32/-6)
src/wui/building_statistics_menu.cc (+2/-2)
src/wui/building_ui.cc (+2/-2)
src/wui/buildingwindow.cc (+5/-4)
src/wui/chatoverlay.cc (+3/-5)
src/wui/field_overlay_manager.cc (+5/-5)
src/wui/field_overlay_manager.h (+7/-7)
src/wui/fieldaction.cc (+1/-1)
src/wui/game_message_menu.cc (+1/-1)
src/wui/game_options_sound_menu.cc (+4/-3)
src/wui/game_tips.cc (+4/-5)
src/wui/general_statistics_menu.cc (+13/-12)
src/wui/interactive_base.cc (+22/-93)
src/wui/interactive_base.h (+6/-8)
src/wui/interactive_gamebase.cc (+1/-1)
src/wui/interactive_player.cc (+1/-1)
src/wui/itemwaresdisplay.cc (+4/-3)
src/wui/login_box.cc (+3/-3)
src/wui/mapdetails.cc (+1/-1)
src/wui/mapview.cc (+159/-53)
src/wui/mapview.h (+29/-25)
src/wui/mapviewpixelconstants.h (+5/-1)
src/wui/mapviewpixelfunctions.cc (+30/-31)
src/wui/mapviewpixelfunctions.h (+26/-16)
src/wui/minimap.cc (+27/-45)
src/wui/minimap.h (+17/-16)
src/wui/playerdescrgroup.cc (+1/-1)
src/wui/plot_area.cc (+28/-25)
src/wui/quicknavigation.cc (+23/-24)
src/wui/quicknavigation.h (+19/-25)
src/wui/shipwindow.cc (+2/-2)
src/wui/soldierlist.cc (+22/-18)
src/wui/story_message_box.cc (+2/-2)
src/wui/transport_draw.cc (+19/-12)
src/wui/warehousewindow.cc (+1/-1)
src/wui/waresdisplay.cc (+10/-11)
src/wui/waresdisplay.h (+1/-1)
src/wui/waresqueuedisplay.cc (+6/-6)
src/wui/watchwindow.cc (+87/-99)
To merge this branch: bzr merge lp:~widelands-dev/widelands/zoom
Reviewer Review Type Date Requested Status
GunChleoc 2016-10-22 Approve on 2016-10-24
Review via email: mp+309086@code.launchpad.net

Commit message

- Adds mouse wheel zoom to the MapView and adapt code for these changes.
  - Overlays (text & soldier icons) are drawn at integer scale only and not at all once scale is < 0.5.
  - This required to change all blitting to be sub-pixel - i.e. float - for the 'destination'.
- Adapted and simplified minimap rendering. It gained a feature too: Minimaps can be drawn using two modes :
    - the map scrolls and the view window stands still (the old one, stil used for in-game)
    - the view window scrolls and the map always looks like the minimap preview. This is now used in the editor.
- Renames Vector -> Vector3f, Point -> Vector2i, Pointf -> Vector2f, Rect -> Recti, FloatRect -> Rectf.
- Refactored object drawing to be simpler and slightly faster:
    - Never pass the field to be drawn to the draw routine.
    - Do not calculate if statics or census should be shown inside the draw routines of the objects, but outside.
    - Move 'owner' field to MapObject - it was duplicated on Bob, Immovable and PlayerImmovable.

Known issues that I will not fix in this branch:
Lua is not aware of zoom and uses zoomless calculations for its moving functions of the view. That means that if the player has zoomed in a scenario and the code wants to move to a certain field, the movement will be wrong. My plan is to remove the Lua functions and add a Animator class to the MapView that will do smooth animations over time in the next branch.

Description of the change

Jaaai - a journey of some 3 years starting with OpenGL finally enabling zoom!

Apologies for the huge diff. If it is unreviewable, I can pull out some of the
changes, like the renames and changing to floating point in rendering and
changing the minimap to two modes - but it would be a hassle and I'd prefer to
get it in as is after b19.

To post a comment you must log in.
lp:~widelands-dev/widelands/zoom updated on 2016-10-22
8167. By SirVer on 2016-10-22

Finished saving/loading and small cleanups. All done.

GunChleoc (gunchleoc) wrote :

This branch creates a problem with the new font renderer - see

https://bugs.launchpad.net/widelands/+bug/536461/comments/14

lp:~widelands-dev/widelands/zoom updated on 2016-10-23
8168. By SirVer on 2016-10-23

Align text rendering to pixels to avoid sub-sampling.

SirVer (sirver) wrote :

should be fixed now. ptal.

GunChleoc (gunchleoc) wrote :

I have given it a quick spin, zooming works fine. I still think it would be good to have some keyboard navigation for it, something like:

bool MapView::handle_key(bool down, SDL_Keysym code) {
 if (down)
  switch (code.sym) {
  case SDLK_PLUS:
   if (code.mod & KMOD_CTRL) {
    <decrease zoom>;
    return true;
   }
   break;
  case SDLK_MINUS:
   if (code.mod & KMOD_CTRL) {
    <increase zoom>;
    return true;
   }
   break;
  case SDLK_0:
   if (code.mod & KMOD_CTRL) {
    <reset zoom>;
    return true;
   }
   break;
  default:
   break;
  }
 return false;
}

lp:~widelands-dev/widelands/zoom updated on 2016-10-23
8169. By SirVer on 2016-10-23

Fixed progress text in progresswindow.

SirVer (sirver) wrote :

I agree, let's do that in the next branch though. this one is so big.

bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

Running 'bzr pull --overwrite' failed. Output:

Warning: Permanently added 'bazaar.launchpad.net,91.189.95.84' (RSA) to the list of known hosts.
Permission denied (publickey).
ConnectionReset reading response for 'BzrDir.open_2.1', retrying
Permission denied (publickey).
bzr: ERROR: Connection closed: Unexpected end of message. Please check connectivity and permissions, and report a bug if problems persist.
Using saved parent location: bzr+ssh://bazaar.launchpad.net/~widelands-dev/widelands/zoom/

bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

Running 'bzr pull --overwrite' failed. Output:

Permission denied (publickey).
ConnectionReset reading response for 'BzrDir.open_2.1', retrying
Permission denied (publickey).
bzr: ERROR: Connection closed: Unexpected end of message. Please check connectivity and permissions, and report a bug if problems persist.
Using saved parent location: bzr+ssh://bazaar.launchpad.net/~widelands-dev/widelands/zoom/

lp:~widelands-dev/widelands/zoom updated on 2016-10-24
8170. By GunChleoc on 2016-10-24

Code review.

GunChleoc (gunchleoc) wrote :

Code review done in last commit. Just some few minor nits + refactoring ideas for the future. And I found some more float coordinates for text that I fixed.

I still have a list of things that I want to test, but looking very good overall :)

lp:~widelands-dev/widelands/zoom updated on 2016-10-24
8171. By GunChleoc on 2016-10-24

Merged trunk.

8172. By GunChleoc on 2016-10-24

Fixed codecheck.

GunChleoc (gunchleoc) wrote :

Testing done - this can go in whenever you're happy.

review: Approve
bunnybot (widelandsofficial) wrote :

Bunnybot encountered an error while working on this merge proposal:

Running 'git fetch bzr_origin' failed. Output:

Traceback (most recent call last):
  File "/usr/local/bin/git-remote-bzr", line 1022, in <module>
    sys.exit(main(sys.argv))
  File "/usr/local/bin/git-remote-bzr", line 994, in main
    repo = get_repo(url, alias)
  File "/usr/local/bin/git-remote-bzr", line 870, in get_repo
    origin = bzrlib.bzrdir.BzrDir.open(url, possible_transports=transports)
  File "/usr/lib/python2.7/dist-packages/bzrlib/controldir.py", line 689, in open
    _unsupported=_unsupported)
  File "/usr/lib/python2.7/dist-packages/bzrlib/controldir.py", line 718, in open_from_transport
    find_format, transport, redirected)
  File "/usr/lib/python2.7/dist-packages/bzrlib/transport/__init__.py", line 1719, in do_catching_redirections
    return action(transport)
  File "/usr/lib/python2.7/dist-packages/bzrlib/controldir.py", line 706, in find_format
    probers=probers)
  File "/usr/lib/python2.7/dist-packages/bzrlib/controldir.py", line 1155, in find_format
    raise errors.NotBranchError(path=transport.base)
bzrlib.errors.NotBranchError: Not a branch: "/home/bunnybot/bunnybot/data/bzr_repo/".

lp:~widelands-dev/widelands/zoom updated on 2016-10-24
8173. By SirVer on 2016-10-24

Addressed code review comments.

SirVer (sirver) wrote :

Excellent code review - thanks for that! I applied everything except for one thing:

> move set_owner to superclass as well, where get_owner() is now.

I considered this - but set_owner has different implementations in different classes and makes no sense for some MapObjects (that can never be owned). So I left it in the classes where it was defined.

Bunnybot should be all ready for action again too - and it should now deal fine with many branches.

SirVer (sirver) wrote :

@bunnybot merge

Lets see if that works again.

GunChleoc (gunchleoc) wrote :

Thanks for a great feature :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/base/CMakeLists.txt'
2--- src/base/CMakeLists.txt 2016-08-15 10:43:23 +0000
3+++ src/base/CMakeLists.txt 2016-10-24 20:07:47 +0000
4@@ -37,9 +37,9 @@
5
6 wl_library(base_geometry
7 SRCS
8- point.h
9- point.cc
10 rect.h
11+ vector.h
12+ vector.cc
13 )
14
15 wl_library(base_md5
16@@ -50,7 +50,6 @@
17 base_macros
18 )
19
20-
21 wl_library(base_scoped_timer
22 SRCS
23 scoped_timer.h
24@@ -68,3 +67,11 @@
25 DEPENDS
26 base_i18n
27 )
28+
29+wl_library(base_math
30+ SRCS
31+ math.h
32+ math.cc
33+ DEPENDS
34+ base_macros
35+)
36
37=== added file 'src/base/math.cc'
38--- src/base/math.cc 1970-01-01 00:00:00 +0000
39+++ src/base/math.cc 2016-10-24 20:07:47 +0000
40@@ -0,0 +1,20 @@
41+/*
42+ * Copyright (C) 2006-2016 by the Widelands Development Team
43+ *
44+ * This program is free software; you can redistribute it and/or
45+ * modify it under the terms of the GNU General Public License
46+ * as published by the Free Software Foundation; either version 2
47+ * of the License, or (at your option) any later version.
48+ *
49+ * This program is distributed in the hope that it will be useful,
50+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52+ * GNU General Public License for more details.
53+ *
54+ * You should have received a copy of the GNU General Public License
55+ * along with this program; if not, write to the Free Software
56+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
57+ *
58+ */
59+
60+// Dummy file as cmake cannot handle header only libraries :(.
61
62=== added file 'src/base/math.h'
63--- src/base/math.h 1970-01-01 00:00:00 +0000
64+++ src/base/math.h 2016-10-24 20:07:47 +0000
65@@ -0,0 +1,43 @@
66+/*
67+ * Copyright (C) 2006-2016 by the Widelands Development Team
68+ *
69+ * This program is free software; you can redistribute it and/or
70+ * modify it under the terms of the GNU General Public License
71+ * as published by the Free Software Foundation; either version 2
72+ * of the License, or (at your option) any later version.
73+ *
74+ * This program is distributed in the hope that it will be useful,
75+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
76+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77+ * GNU General Public License for more details.
78+ *
79+ * You should have received a copy of the GNU General Public License
80+ * along with this program; if not, write to the Free Software
81+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
82+ *
83+ */
84+
85+#ifndef WL_BASE_MATH_H
86+#define WL_BASE_MATH_H
87+
88+#include "base/macros.h"
89+
90+namespace math {
91+
92+// Returns 1 for positive and -1 for negative numbers.
93+template <typename T>
94+T sign(const T& val) {
95+ return val < T(0.) ? T(-1.) : T(1.);
96+}
97+
98+// Clamps 'val' to 'min' and 'max'.
99+template <typename T>
100+T clamp(const T& val, const T& low, const T& high) {
101+ if (val < low) { return low; }
102+ if (val > high) { return high; }
103+ return val;
104+}
105+
106+} // namespace math
107+
108+#endif // end of include guard: WL_BASE_MATH_H
109
110=== removed file 'src/base/point.h'
111--- src/base/point.h 2016-08-04 15:49:05 +0000
112+++ src/base/point.h 1970-01-01 00:00:00 +0000
113@@ -1,79 +0,0 @@
114-/*
115- * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
116- *
117- * This program is free software; you can redistribute it and/or
118- * modify it under the terms of the GNU General Public License
119- * as published by the Free Software Foundation; either version 2
120- * of the License, or (at your option) any later version.
121- *
122- * This program is distributed in the hope that it will be useful,
123- * but WITHOUT ANY WARRANTY; without even the implied warranty of
124- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
125- * GNU General Public License for more details.
126- *
127- * You should have received a copy of the GNU General Public License
128- * along with this program; if not, write to the Free Software
129- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
130- *
131- */
132-
133-#ifndef WL_BASE_POINT_H
134-#define WL_BASE_POINT_H
135-
136-#include <limits>
137-
138-#include <stdint.h>
139-
140-template <typename T> struct GenericPoint {
141- GenericPoint(const T& px, const T& py) : x(px), y(py) {
142- }
143- GenericPoint() : GenericPoint(T(0), T(0)) {
144- }
145-
146- // Returns an invalid point.
147- static GenericPoint invalid() {
148- return GenericPoint(std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
149- }
150-
151- bool operator==(const GenericPoint& other) const {
152- return x == other.x && y == other.y;
153- }
154- bool operator!=(const GenericPoint& other) const {
155- return !(*this == other);
156- }
157-
158- GenericPoint operator+(const GenericPoint& other) const {
159- return GenericPoint(x + other.x, y + other.y);
160- }
161-
162- GenericPoint operator-() const {
163- return GenericPoint(-x, -y);
164- }
165-
166- GenericPoint operator-(const GenericPoint& other) const {
167- return GenericPoint(x - other.x, y - other.y);
168- }
169-
170- GenericPoint& operator+=(const GenericPoint& other) {
171- x += other.x;
172- y += other.y;
173- return *this;
174- }
175-
176- GenericPoint& operator-=(const GenericPoint& other) {
177- x -= other.x;
178- y -= other.y;
179- return *this;
180- }
181-
182- T x, y;
183-};
184-
185-using Point = GenericPoint<int>;
186-using FloatPoint = GenericPoint<float>;
187-
188-/// Returns the point in the middle between a and b (rounded to integer
189-/// values).
190-Point middle(const Point& a, const Point& b);
191-
192-#endif // end of include guard: WL_BASE_POINT_H
193
194=== modified file 'src/base/rect.h'
195--- src/base/rect.h 2016-08-04 15:49:05 +0000
196+++ src/base/rect.h 2016-10-24 20:07:47 +0000
197@@ -20,41 +20,51 @@
198 #ifndef WL_BASE_RECT_H
199 #define WL_BASE_RECT_H
200
201-#include "base/point.h"
202+#include "base/vector.h"
203
204-template <typename T> struct GenericRect {
205- /// Generates a degenerate Rect at (0, 0) with no height or width.
206- GenericRect() : GenericRect(T(0), T(0), T(0), T(0)) {
207+template <typename T> struct Rect {
208+ /// Generates a degenerate Recti at (0, 0) with no height or width.
209+ Rect() : Rect(T(0), T(0), T(0), T(0)) {
210 }
211
212- GenericRect(const T& gx, const T& gy, const T& W, const T& H) : x(gx), y(gy), w(W), h(H) {
213+ Rect(const T& gx, const T& gy, const T& W, const T& H) : x(gx), y(gy), w(W), h(H) {
214 }
215
216 template <typename PointType>
217- GenericRect(const GenericPoint<PointType>& p, const T& width, const T& height)
218- : GenericRect(T(p.x), T(p.y), width, height) {
219+ Rect(const Vector2<PointType>& p, const T& width, const T& height)
220+ : Rect(T(p.x), T(p.y), width, height) {
221 }
222
223- /// The Point (x, y).
224- GenericPoint<T> origin() const {
225- return GenericPoint<T>(x, y);
226+ /// The Vector2i (x, y).
227+ Vector2<T> origin() const {
228+ return Vector2<T>(x, y);
229 }
230
231 /// The point (x + w, y + h).
232- GenericPoint<T> opposite_of_origin() const {
233- return GenericPoint<T>(x + w, y + h);
234+ Vector2<T> opposite_of_origin() const {
235+ return Vector2<T>(x + w, y + h);
236 }
237
238 /// Returns true if this rectangle contains the given point.
239 /// The bottom and right borders of the rectangle are considered to be excluded.
240- template <typename PointType> bool contains(const GenericPoint<PointType>& pt) const {
241+ template <typename PointType> bool contains(const Vector2<PointType>& pt) const {
242 return T(pt.x) >= x && T(pt.x) < x + w && T(pt.y) >= y && T(pt.y) < y + h;
243 }
244
245+ // The center point of 'r'.
246+ Vector2f center() const {
247+ return Vector2f(x + w / 2.f, y + h / 2.f);
248+ }
249+
250+ template<typename Type>
251+ Rect<Type> cast() const {
252+ return Rect<Type>(Type(x), Type(y), Type(w), Type(h));
253+ }
254+
255 T x, y, w, h;
256 };
257
258-using Rect = GenericRect<int>;
259-using FloatRect = GenericRect<float>;
260+using Recti = Rect<int>;
261+using Rectf = Rect<float>;
262
263 #endif // end of include guard: WL_BASE_RECT_H
264
265=== renamed file 'src/base/point.cc' => 'src/base/vector.cc'
266--- src/base/point.cc 2015-03-01 09:21:20 +0000
267+++ src/base/vector.cc 2016-10-24 20:07:47 +0000
268@@ -17,8 +17,14 @@
269 *
270 */
271
272-#include "base/point.h"
273-
274-Point middle(const Point& a, const Point& b) {
275- return Point((a.x + b.x) / 2, (a.y + b.y) / 2);
276+#include "base/vector.h"
277+
278+#include <cmath>
279+
280+Vector2f middle(const Vector2f& a, const Vector2f& b) {
281+ return Vector2f((a.x + b.x) / 2.f, (a.y + b.y) / 2.f);
282+}
283+
284+Vector2i round(const Vector2f& a) {
285+ return Vector2i(std::lround(a.x), std::lround(a.y));
286 }
287
288=== renamed file 'src/wui/vector.h' => 'src/base/vector.h'
289--- src/wui/vector.h 2016-08-04 15:49:05 +0000
290+++ src/base/vector.h 2016-10-24 20:07:47 +0000
291@@ -17,23 +17,88 @@
292 *
293 */
294
295-#ifndef WL_WUI_VECTOR_H
296-#define WL_WUI_VECTOR_H
297+#ifndef WL_BASE_VECTOR_H
298+#define WL_BASE_VECTOR_H
299
300 #include <cmath>
301-
302-// hm, floats...
303-// tried to be faster with fixed point arithmetics
304-// it was, but i'll try to find other opts first
305-struct Vector {
306- Vector() : x(0), y(0), z(0) {
307- }
308- Vector(const float X, const float Y, const float Z) : x(X), y(Y), z(Z) {
309+#include <limits>
310+
311+#include <stdint.h>
312+
313+template <typename T> struct Vector2 {
314+ Vector2(const T& px, const T& py) : x(px), y(py) {
315+ }
316+ Vector2() : Vector2(T(0), T(0)) {
317+ }
318+
319+ // Returns an invalid point.
320+ static Vector2 invalid() {
321+ return Vector2(std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
322+ }
323+
324+ bool operator==(const Vector2& other) const {
325+ return x == other.x && y == other.y;
326+ }
327+ bool operator!=(const Vector2& other) const {
328+ return !(*this == other);
329+ }
330+
331+ Vector2 operator+(const Vector2& other) const {
332+ return Vector2(x + other.x, y + other.y);
333+ }
334+
335+ Vector2 operator*(const float a) const {
336+ return Vector2(a * x, a * y);
337+ }
338+
339+ Vector2 operator/(const float a) const {
340+ return Vector2(x / a, y / a);
341+ }
342+
343+ Vector2 operator-() const {
344+ return Vector2(-x, -y);
345+ }
346+
347+ Vector2 operator-(const Vector2& other) const {
348+ return Vector2(x - other.x, y - other.y);
349+ }
350+
351+ Vector2& operator+=(const Vector2& other) {
352+ x += other.x;
353+ y += other.y;
354+ return *this;
355+ }
356+
357+ Vector2& operator-=(const Vector2& other) {
358+ x -= other.x;
359+ y -= other.y;
360+ return *this;
361+ }
362+
363+ template<typename Type>
364+ Vector2<Type> cast() const {
365+ return Vector2<Type>(Type(x), Type(y));
366+ }
367+
368+ T x, y;
369+};
370+
371+using Vector2i = Vector2<int>;
372+using Vector2f = Vector2<float>;
373+
374+/// Returns the point in the middle between a and b.
375+Vector2f middle(const Vector2f& a, const Vector2f& b);
376+
377+// Returns an point rounded to the closest integer.
378+Vector2i round(const Vector2f& a);
379+
380+struct Vector3f {
381+ Vector3f(const float X, const float Y, const float Z) : x(X), y(Y), z(Z) {
382 }
383
384 void normalize() {
385- const float f = static_cast<float>(sqrt(x * x + y * y + z * z));
386- if (fabs(f) < 0.00001) // check for ==0
387+ const float f = static_cast<float>(std::sqrt(x * x + y * y + z * z));
388+ if (std::fabs(f) < 0.00001f) // check for ==0
389 return;
390 x /= f;
391 y /= f;
392@@ -41,16 +106,16 @@
393 }
394
395 // vector addition
396- Vector operator+(const Vector& other) const {
397- return Vector(x + other.x, y + other.y, z + other.z);
398+ Vector3f operator+(const Vector3f& other) const {
399+ return Vector3f(x + other.x, y + other.y, z + other.z);
400 }
401
402 // inner product
403- float operator*(const Vector& other) const {
404+ float dot(const Vector3f& other) const {
405 return x * other.x + y * other.y + z * other.z;
406 }
407
408 float x, y, z;
409 };
410
411-#endif // end of include guard: WL_WUI_VECTOR_H
412+#endif // end of include guard: WL_BASE_VECTOR_H
413
414=== modified file 'src/economy/flag.h'
415--- src/economy/flag.h 2016-08-04 15:49:05 +0000
416+++ src/economy/flag.h 2016-10-24 20:07:47 +0000
417@@ -25,6 +25,7 @@
418
419 #include "base/macros.h"
420 #include "economy/routing_node.h"
421+#include "logic/map_objects/draw_text.h"
422 #include "logic/map_objects/immovable.h"
423
424 namespace Widelands {
425@@ -144,7 +145,11 @@
426 void init(EditorGameBase&) override;
427 void cleanup(EditorGameBase&) override;
428
429- void draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) override;
430+ void draw(uint32_t gametime,
431+ DrawText draw_text,
432+ const Vector2f& point_on_dst,
433+ float scale,
434+ RenderTarget* dst) override;
435
436 void wake_up_capacity_queue(Game&);
437
438
439=== modified file 'src/economy/portdock.cc'
440--- src/economy/portdock.cc 2016-09-30 07:34:06 +0000
441+++ src/economy/portdock.cc 2016-10-24 20:07:47 +0000
442@@ -141,7 +141,7 @@
443 expedition_bootstrap_->set_economy(e);
444 }
445
446-void PortDock::draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) {
447+void PortDock::draw(uint32_t, const DrawText, const Vector2f&, float, RenderTarget*) {
448 // do nothing
449 }
450
451
452=== modified file 'src/economy/portdock.h'
453--- src/economy/portdock.h 2016-08-04 15:49:05 +0000
454+++ src/economy/portdock.h 2016-10-24 20:07:47 +0000
455@@ -96,7 +96,11 @@
456
457 Flag& base_flag() override;
458 PositionList get_positions(const EditorGameBase&) const override;
459- void draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) override;
460+ void draw(uint32_t gametime,
461+ DrawText draw_text,
462+ const Vector2f& point_on_dst,
463+ float scale,
464+ RenderTarget* dst) override;
465
466 void init(EditorGameBase&) override;
467 void cleanup(EditorGameBase&) override;
468
469=== modified file 'src/economy/road.h'
470--- src/economy/road.h 2016-08-04 15:49:05 +0000
471+++ src/economy/road.h 2016-10-24 20:07:47 +0000
472@@ -118,7 +118,11 @@
473 void init(EditorGameBase&) override;
474 void cleanup(EditorGameBase&) override;
475
476- void draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) override;
477+ void draw(uint32_t gametime,
478+ DrawText draw_text,
479+ const Vector2f& point_on_dst,
480+ float scale,
481+ RenderTarget* dst) override;
482
483 private:
484 void set_path(EditorGameBase&, const Path&);
485
486=== modified file 'src/editor/editorinteractive.cc'
487--- src/editor/editorinteractive.cc 2016-09-25 18:46:29 +0000
488+++ src/editor/editorinteractive.cc 2016-10-24 20:07:47 +0000
489@@ -160,6 +160,8 @@
490 [this](const Widelands::NoteFieldResourceChanged& note) {
491 update_resource_overlay(note, egbase().world(), mutable_field_overlay_manager());
492 });
493+
494+ minimap_registry().minimap_type = MiniMapType::kStaticMap;
495 }
496
497 void EditorInteractive::register_overlays() {
498@@ -173,7 +175,7 @@
499 const Image* player_image = g_gr->images().get(player_pictures[p - 1]);
500 assert(player_image);
501 mutable_field_overlay_manager()->register_overlay(
502- sp, player_image, 8, Point(player_image->width() / 2, STARTING_POS_HOTSPOT_Y));
503+ sp, player_image, 8, Vector2i(player_image->width() / 2, STARTING_POS_HOTSPOT_Y));
504 }
505 }
506
507@@ -669,7 +671,7 @@
508 }
509
510 // Make sure that we will start at coordinates (0,0).
511- set_viewpoint(Point(0, 0), true);
512+ set_viewpoint(Vector2f(0, 0), true);
513 set_sel_pos(Widelands::NodeAndTriangle<>(
514 Widelands::Coords(0, 0),
515 Widelands::TCoords<>(Widelands::Coords(0, 0), Widelands::TCoords<>::D)));
516
517=== modified file 'src/editor/tools/set_origin_tool.cc'
518--- src/editor/tools/set_origin_tool.cc 2016-08-04 15:49:05 +0000
519+++ src/editor/tools/set_origin_tool.cc 2016-10-24 20:07:47 +0000
520@@ -30,9 +30,7 @@
521 Widelands::Map* map) {
522 map->set_origin(center.node);
523 eia.map_changed(EditorInteractive::MapWas::kGloballyMutated);
524- eia.set_rel_viewpoint(Point(-(center.node.x * 2 + (center.node.y & 1)) * (kTriangleWidth / 2),
525- -center.node.y * kTriangleHeight),
526- true);
527+ eia.center_view_on_coords(Widelands::Coords(0, 0));
528 return 0;
529 }
530
531@@ -46,8 +44,7 @@
532 map->get_width() - 1 - center.node.x, map->get_height() - 1 - center.node.y);
533 map->set_origin(nc);
534 eia.map_changed(EditorInteractive::MapWas::kGloballyMutated);
535- eia.set_rel_viewpoint(
536- Point(-(nc.x * 2 + (nc.y & 1)) * (kTriangleWidth / 2), -nc.y * kTriangleHeight), true);
537+ eia.center_view_on_coords(Widelands::Coords(0, 0));
538 return 0;
539 }
540
541
542=== modified file 'src/editor/tools/set_starting_pos_tool.cc'
543--- src/editor/tools/set_starting_pos_tool.cc 2016-08-04 15:49:05 +0000
544+++ src/editor/tools/set_starting_pos_tool.cc 2016-10-24 20:07:47 +0000
545@@ -113,7 +113,7 @@
546
547 // add new overlay
548 overlay_manager->register_overlay(
549- center.node, player_image, 4, Point(player_image->width() / 2, STARTING_POS_HOTSPOT_Y));
550+ center.node, player_image, 4, Vector2i(player_image->width() / 2, STARTING_POS_HOTSPOT_Y));
551
552 // set new player pos
553 map->set_starting_pos(current_player_, center.node);
554
555=== modified file 'src/editor/ui_menus/main_menu_load_or_save_map.cc'
556--- src/editor/ui_menus/main_menu_load_or_save_map.cc 2016-08-04 18:09:55 +0000
557+++ src/editor/ui_menus/main_menu_load_or_save_map.cc 2016-10-24 20:07:47 +0000
558@@ -89,7 +89,7 @@
559 vbox->add(show_mapnames_, UI::Align::kLeft, true);
560
561 /** TRANSLATORS: Checkbox title. If this checkbox is enabled, map names aren't translated. */
562- cb_dont_localize_mapnames_ = new UI::Checkbox(vbox, Point(0, 0), _("Show original map names"));
563+ cb_dont_localize_mapnames_ = new UI::Checkbox(vbox, Vector2i(0, 0), _("Show original map names"));
564 cb_dont_localize_mapnames_->set_state(false);
565 vbox->add_space(2 * padding_);
566 vbox->add(cb_dont_localize_mapnames_, UI::Align::kLeft, true);
567
568=== modified file 'src/editor/ui_menus/main_menu_map_options.cc'
569--- src/editor/ui_menus/main_menu_map_options.cc 2016-08-07 10:10:18 +0000
570+++ src/editor/ui_menus/main_menu_map_options.cc 2016-10-24 20:07:47 +0000
571@@ -227,7 +227,7 @@
572 std::string tag,
573 std::string displ_name) {
574 UI::Box* box = new UI::Box(parent, 0, 0, UI::Box::Horizontal, max_w_, checkbox_space_, 0);
575- UI::Checkbox* cb = new UI::Checkbox(box, Point(0, 0), displ_name);
576+ UI::Checkbox* cb = new UI::Checkbox(box, Vector2i(0, 0), displ_name);
577 box->add(cb, UI::Align::kLeft, true);
578 box->add_space(checkbox_space_);
579 parent->add(box, UI::Align::kLeft);
580
581=== modified file 'src/editor/ui_menus/main_menu_random_map.cc'
582--- src/editor/ui_menus/main_menu_random_map.cc 2016-08-04 15:49:05 +0000
583+++ src/editor/ui_menus/main_menu_random_map.cc 2016-10-24 20:07:47 +0000
584@@ -184,7 +184,7 @@
585 resources_label_.get_h(),
586 (boost::format(_("%i %%")) % mountainsval_).str(),
587 UI::Align::kHCenter),
588- island_mode_(&box_, Point(0, 0), _("Island mode")),
589+ island_mode_(&box_, Vector2i(0, 0), _("Island mode")),
590 // Geeky stuff
591 map_number_box_(&box_, 0, 0, UI::Box::Horizontal, 0, 0, margin_),
592 map_number_label_(&map_number_box_, 0, 0, _("Random Number:")),
593
594=== modified file 'src/editor/ui_menus/main_menu_save_map.h'
595--- src/editor/ui_menus/main_menu_save_map.h 2016-08-04 15:49:05 +0000
596+++ src/editor/ui_menus/main_menu_save_map.h 2016-10-24 20:07:47 +0000
597@@ -40,7 +40,7 @@
598
599 private:
600 EditorInteractive& eia();
601- void clicked_ok();
602+ void clicked_ok() override;
603 void clicked_make_directory();
604 void clicked_edit_options();
605 void clicked_item();
606
607=== modified file 'src/editor/ui_menus/player_menu.cc'
608--- src/editor/ui_menus/player_menu.cc 2016-09-25 11:24:10 +0000
609+++ src/editor/ui_menus/player_menu.cc 2016-10-24 20:07:47 +0000
610@@ -95,11 +95,11 @@
611 set_inner_size(375, 135);
612
613 UI::Textarea* ta = new UI::Textarea(this, 0, 0, _("Number of Players"));
614- ta->set_pos(Point((get_inner_w() - ta->get_w()) / 2, posy + 5));
615+ ta->set_pos(Vector2i((get_inner_w() - ta->get_w()) / 2, posy + 5));
616 posy += spacing + width;
617
618 nr_of_players_ta_ = new UI::Textarea(this, 0, 0, "5");
619- nr_of_players_ta_->set_pos(Point((get_inner_w() - nr_of_players_ta_->get_w()) / 2, posy + 5));
620+ nr_of_players_ta_->set_pos(Vector2i((get_inner_w() - nr_of_players_ta_->get_w()) / 2, posy + 5));
621
622 posy += width + spacing + spacing;
623
624@@ -292,7 +292,7 @@
625 // jump to the current node
626 Widelands::Map& map = menu.egbase().map();
627 if (Widelands::Coords const sp = map.get_starting_pos(n))
628- menu.move_view_to(sp);
629+ menu.center_view_on_coords(sp);
630
631 // select tool set mplayer
632 menu.select_tool(menu.tools()->set_starting_pos, EditorTool::First);
633
634=== modified file 'src/editor/ui_menus/tool_change_resources_options_menu.cc'
635--- src/editor/ui_menus/tool_change_resources_options_menu.cc 2016-08-04 15:49:05 +0000
636+++ src/editor/ui_menus/tool_change_resources_options_menu.cc 2016-10-24 20:07:47 +0000
637@@ -100,7 +100,7 @@
638
639 for (Widelands::DescriptionIndex i = 0; i < nr_resources; ++i) {
640 const Widelands::ResourceDescription& resource = *world.get_resource(i);
641- radiogroup_.add_button(&resources_box_, Point(0, 0),
642+ radiogroup_.add_button(&resources_box_, Vector2i(0, 0),
643 g_gr->images().get(resource.representative_image()),
644 resource.descname());
645 resources_box_.add(radiogroup_.get_first_button(), UI::Align::kLeft, false, true);
646
647=== modified file 'src/editor/ui_menus/tool_menu.cc'
648--- src/editor/ui_menus/tool_menu.cc 2016-08-04 15:49:05 +0000
649+++ src/editor/ui_menus/tool_menu.cc 2016-10-24 20:07:47 +0000
650@@ -45,8 +45,8 @@
651 : UI::UniqueWindow(&parent, "tool_menu", &registry, 350, 400, _("Tools")) {
652
653 #define spacing 5
654- Point const offs(spacing, spacing);
655- Point pos = offs;
656+ Vector2i const offs(spacing, spacing);
657+ Vector2i pos = offs;
658 int32_t const width = 34;
659 int32_t const height = 34;
660
661
662=== modified file 'src/editor/ui_menus/tool_place_bob_options_menu.cc'
663--- src/editor/ui_menus/tool_place_bob_options_menu.cc 2016-08-04 15:49:05 +0000
664+++ src/editor/ui_menus/tool_place_bob_options_menu.cc 2016-10-24 20:07:47 +0000
665@@ -64,14 +64,14 @@
666 }
667
668 const Image* tab_icon = g_gr->images().get("images/ui_basic/list_first_entry.png");
669- Point pos;
670+ Vector2i pos;
671 uint32_t cur_x = bobs_in_row;
672 int32_t i = 0;
673 UI::Box* box = nullptr;
674 while (i < nr_bobs) {
675 if (cur_x == bobs_in_row) {
676 cur_x = 0;
677- pos = Point(5, 15);
678+ pos = Vector2i(5, 15);
679 box = new UI::Box(&tabpanel_, 0, 0, UI::Box::Horizontal);
680 tabpanel_.add("icons", tab_icon, box);
681 }
682
683=== modified file 'src/editor/ui_menus/tool_place_immovable_options_menu.cc'
684--- src/editor/ui_menus/tool_place_immovable_options_menu.cc 2016-08-04 15:49:05 +0000
685+++ src/editor/ui_menus/tool_place_immovable_options_menu.cc 2016-10-24 20:07:47 +0000
686@@ -39,7 +39,7 @@
687
688 UI::Checkbox* create_immovable_checkbox(UI::Panel* parent, const ImmovableDescr& immovable_descr) {
689 const Image* pic = immovable_descr.representative_image();
690- UI::Checkbox* cb = new UI::Checkbox(parent, Point(0, 0), pic, immovable_descr.descname());
691+ UI::Checkbox* cb = new UI::Checkbox(parent, Vector2i(0, 0), pic, immovable_descr.descname());
692 const int kMinClickableArea = 24;
693 cb->set_desired_size(std::max<int>(pic->width(), kMinClickableArea),
694 std::max<int>(pic->height(), kMinClickableArea));
695
696=== modified file 'src/editor/ui_menus/tool_set_terrain_options_menu.cc'
697--- src/editor/ui_menus/tool_set_terrain_options_menu.cc 2016-08-04 15:49:05 +0000
698+++ src/editor/ui_menus/tool_set_terrain_options_menu.cc 2016-10-24 20:07:47 +0000
699@@ -53,10 +53,10 @@
700 // Blit the main terrain image
701 const Image& terrain_texture = terrain_descr.get_texture(0);
702 Texture* texture = new Texture(terrain_texture.width(), terrain_texture.height());
703- texture->blit(Rect(0, 0, terrain_texture.width(), terrain_texture.height()), terrain_texture,
704- Rect(0, 0, terrain_texture.width(), terrain_texture.height()), 1.,
705+ texture->blit(Rectf(0, 0, terrain_texture.width(), terrain_texture.height()), terrain_texture,
706+ Rectf(0, 0, terrain_texture.width(), terrain_texture.height()), 1.,
707 BlendMode::UseAlpha);
708- Point pt(1, terrain_texture.height() - kSmallPicSize - 1);
709+ Vector2i pt(1, terrain_texture.height() - kSmallPicSize - 1);
710
711 // Collect tooltips and blit small icons representing "is" values
712 for (const TerrainDescription::Type& terrain_type : terrain_descr.get_types()) {
713@@ -64,9 +64,9 @@
714 terrain_descr.custom_tooltips().end());
715 tooltips.push_back(terrain_type.descname);
716
717- texture->blit(Rect(pt.x, pt.y, terrain_type.icon->width(), terrain_type.icon->height()),
718+ texture->blit(Rectf(pt.x, pt.y, terrain_type.icon->width(), terrain_type.icon->height()),
719 *terrain_type.icon,
720- Rect(0, 0, terrain_type.icon->width(), terrain_type.icon->height()), 1.,
721+ Rectf(0, 0, terrain_type.icon->width(), terrain_type.icon->height()), 1.,
722 BlendMode::UseAlpha);
723 pt.x += kSmallPicSize + 1;
724 }
725@@ -79,7 +79,7 @@
726 .str();
727
728 std::unique_ptr<const Image>& image = offscreen_images->back();
729- UI::Checkbox* cb = new UI::Checkbox(parent, Point(0, 0), image.get(), tooltip);
730+ UI::Checkbox* cb = new UI::Checkbox(parent, Vector2i(0, 0), image.get(), tooltip);
731 cb->set_desired_size(image->width() + 1, image->height() + 1);
732 return cb;
733 }
734
735=== modified file 'src/game_io/CMakeLists.txt'
736--- src/game_io/CMakeLists.txt 2016-01-20 20:12:00 +0000
737+++ src/game_io/CMakeLists.txt 2016-10-24 20:07:47 +0000
738@@ -30,6 +30,7 @@
739 build_info
740 economy
741 graphic
742+ graphic_image_io
743 graphic_minimap_renderer
744 io_fileread
745 io_filesystem
746@@ -42,4 +43,5 @@
747 scripting_lua_table
748 wui
749 wui_mapview_pixelfunctions
750+ wui_mapview
751 )
752
753=== modified file 'src/game_io/game_interactive_player_packet.cc'
754--- src/game_io/game_interactive_player_packet.cc 2016-08-04 15:49:05 +0000
755+++ src/game_io/game_interactive_player_packet.cc 2016-10-24 20:07:47 +0000
756@@ -30,7 +30,22 @@
757
758 namespace Widelands {
759
760-constexpr uint16_t kCurrentPacketVersion = 3;
761+namespace {
762+
763+constexpr uint16_t kCurrentPacketVersion = 4;
764+
765+void load_landmarks_pre_zoom(FileRead* fr, InteractiveBase* ibase) {
766+ size_t no_of_landmarks = fr->unsigned_8();
767+ for (size_t i = 0; i < no_of_landmarks; ++i) {
768+ uint8_t set = fr->unsigned_8();
769+ QuickNavigation::View view = {Vector2f(fr->signed_32(), fr->signed_32()), 1.f};
770+ if (set > 0) {
771+ ibase->set_landmark(i, view);
772+ }
773+ }
774+}
775+
776+} // namespace
777
778 void GameInteractivePlayerPacket::read(FileSystem& fs, Game& game, MapObjectLoader*) {
779 try {
780@@ -55,12 +70,19 @@
781 if (player_number > max)
782 throw GameDataError("The game has no players!");
783 }
784- int32_t const x = fr.unsigned_16();
785- int32_t const y = fr.unsigned_16();
786+ float viewpoint_x, viewpoint_y;
787+ if (packet_version <= 3) {
788+ viewpoint_x = fr.unsigned_16();
789+ viewpoint_y = fr.unsigned_16();
790+ } else {
791+ viewpoint_x = fr.float_32();
792+ viewpoint_y = fr.float_32();
793+ }
794+
795 uint32_t const display_flags = fr.unsigned_32();
796
797 if (InteractiveBase* const ibase = game.get_ibase()) {
798- ibase->set_viewpoint(Point(x, y), true);
799+ ibase->set_viewpoint(Vector2f(viewpoint_x, viewpoint_y), true);
800
801 uint32_t const loaded_df =
802 InteractiveBase::dfShowCensus | InteractiveBase::dfShowStatistics;
803@@ -73,14 +95,19 @@
804 }
805
806 // Map landmarks
807- if (packet_version >= 3) {
808- if (InteractiveBase* const ibase = game.get_ibase()) {
809+ if (InteractiveBase* const ibase = game.get_ibase()) {
810+ if (packet_version == 3) {
811+ load_landmarks_pre_zoom(&fr, ibase);
812+ } else if (packet_version >= 4) {
813 size_t no_of_landmarks = fr.unsigned_8();
814 for (size_t i = 0; i < no_of_landmarks; ++i) {
815 uint8_t set = fr.unsigned_8();
816- Point landmark(fr.signed_32(), fr.signed_32());
817+ const float x = fr.float_32();
818+ const float y = fr.float_32();
819+ const float zoom = fr.float_32();
820+ QuickNavigation::View view = {Vector2f(x, y), zoom};
821 if (set > 0) {
822- ibase->set_landmark(i, landmark);
823+ ibase->set_landmark(i, view);
824 }
825 }
826 }
827@@ -109,12 +136,14 @@
828 fw.unsigned_8(iplayer ? iplayer->player_number() : 1);
829
830 // Map Position
831+#ifndef NDEBUG
832 if (ibase) {
833 assert(0 <= ibase->get_viewpoint().x);
834 assert(0 <= ibase->get_viewpoint().y);
835 }
836- fw.unsigned_16(ibase ? ibase->get_viewpoint().x : 0);
837- fw.unsigned_16(ibase ? ibase->get_viewpoint().y : 0);
838+#endif
839+ fw.float_32(ibase ? ibase->get_viewpoint().x : 0.f);
840+ fw.float_32(ibase ? ibase->get_viewpoint().y : 0.f);
841
842 // Display flags
843 fw.unsigned_32(ibase ? ibase->get_display_flags() : 0);
844@@ -124,8 +153,9 @@
845 fw.unsigned_8(landmarks.size());
846 for (const QuickNavigation::Landmark& landmark : landmarks) {
847 fw.unsigned_8(landmark.set ? 1 : 0);
848- fw.signed_32(landmark.point.x);
849- fw.signed_32(landmark.point.y);
850+ fw.float_32(landmark.view.viewpoint.x);
851+ fw.float_32(landmark.view.viewpoint.y);
852+ fw.float_32(landmark.view.zoom);
853 }
854
855 fw.write(fs, "binary/interactive_player");
856
857=== modified file 'src/game_io/game_preload_packet.cc'
858--- src/game_io/game_preload_packet.cc 2016-08-05 12:32:08 +0000
859+++ src/game_io/game_preload_packet.cc 2016-10-24 20:07:47 +0000
860@@ -27,6 +27,7 @@
861 #include "base/time_string.h"
862 #include "build_info.h"
863 #include "graphic/graphic.h"
864+#include "graphic/image_io.h"
865 #include "graphic/minimap_renderer.h"
866 #include "logic/game.h"
867 #include "logic/game_data_error.h"
868@@ -120,13 +121,17 @@
869
870 std::unique_ptr<::StreamWrite> sw(fs.open_stream_write(kMinimapFilename));
871 if (sw.get() != nullptr) {
872- const MiniMapLayer flags =
873+ const MiniMapLayer layers =
874 MiniMapLayer::Owner | MiniMapLayer::Building | MiniMapLayer::Terrain;
875+ std::unique_ptr<Texture> texture;
876 if (ipl != nullptr) { // Player
877- write_minimap_image(game, &ipl->player(), ipl->get_viewpoint(), flags, sw.get());
878+ texture = draw_minimap(
879+ game, &ipl->player(), ipl->get_view_area(), MiniMapType::kStaticViewWindow, layers);
880 } else { // Observer
881- write_minimap_image(game, nullptr, Point(0, 0), flags, sw.get());
882+ texture = draw_minimap(game, nullptr, Rectf(), MiniMapType::kStaticMap, layers);
883 }
884+ assert(texture != nullptr);
885+ save_to_png(texture.get(), sw.get(), ColorType::RGBA);
886 sw->flush();
887 }
888 }
889
890=== modified file 'src/graphic/CMakeLists.txt'
891--- src/graphic/CMakeLists.txt 2016-02-19 19:10:44 +0000
892+++ src/graphic/CMakeLists.txt 2016-10-24 20:07:47 +0000
893@@ -124,6 +124,7 @@
894 graphic_surface
895 io_filesystem
896 logic
897+ logic_widelands_geometry
898 )
899
900 wl_library(graphic_draw_programs
901@@ -209,7 +210,6 @@
902 base_macros
903 economy
904 graphic
905- graphic_image_io
906 graphic_surface
907 logic
908 wui_mapview_pixelfunctions
909
910=== modified file 'src/graphic/align.cc'
911--- src/graphic/align.cc 2016-08-04 15:49:05 +0000
912+++ src/graphic/align.cc 2016-10-24 20:07:47 +0000
913@@ -53,7 +53,12 @@
914 return alignment;
915 }
916
917-void correct_for_align(Align align, uint32_t w, uint32_t h, Point* pt) {
918+void correct_for_align(Align align, uint32_t w, uint32_t h, Vector2f* pt) {
919+ // When correcting for align, we never move from pixel boundaries to
920+ // sub-pixels, because this might lead from pixel-perfect rendering to
921+ // subsampled rendering - this can lead to blurry texts. That is why we
922+ // never do float divisions in this function.
923+
924 // Vertical Align
925 if (static_cast<int>(align & (Align::kVCenter | Align::kBottom))) {
926 if (static_cast<int>(align & Align::kVCenter))
927
928=== modified file 'src/graphic/align.h'
929--- src/graphic/align.h 2016-08-04 15:49:05 +0000
930+++ src/graphic/align.h 2016-10-24 20:07:47 +0000
931@@ -20,7 +20,7 @@
932 #ifndef WL_GRAPHIC_ALIGN_H
933 #define WL_GRAPHIC_ALIGN_H
934
935-#include "base/point.h"
936+#include "base/vector.h"
937
938 namespace UI {
939
940@@ -58,6 +58,6 @@
941 }
942
943 Align mirror_alignment(Align alignment);
944-void correct_for_align(Align, uint32_t w, uint32_t h, Point* pt);
945+void correct_for_align(Align, uint32_t w, uint32_t h, Vector2f* pt);
946 }
947 #endif // end of include guard: WL_GRAPHIC_ALIGN_H
948
949=== modified file 'src/graphic/animation.cc'
950--- src/graphic/animation.cc 2016-08-04 15:49:05 +0000
951+++ src/graphic/animation.cc 2016-10-24 20:07:47 +0000
952@@ -44,7 +44,7 @@
953
954 namespace {
955 // Parses an array { 12, 23 } into a point.
956-void get_point(const LuaTable& table, Point* p) {
957+void get_point(const LuaTable& table, Vector2i* p) {
958 std::vector<int> pts = table.array_entries<int>();
959 if (pts.size() != 2) {
960 throw wexception("Expected 2 entries, but got %" PRIuS ".", pts.size());
961@@ -68,11 +68,14 @@
962 uint16_t height() const override;
963 uint16_t nr_frames() const override;
964 uint32_t frametime() const override;
965- const Point& hotspot() const override;
966+ const Vector2i& hotspot() const override;
967 Image* representative_image(const RGBColor* clr) const override;
968 const std::string& representative_image_filename() const override;
969- virtual void blit(
970- uint32_t time, const Point&, const Rect& srcrc, const RGBColor* clr, Surface*) const override;
971+ virtual void blit(uint32_t time,
972+ const Rectf& dstrc,
973+ const Rectf& srcrc,
974+ const RGBColor* clr,
975+ Surface*) const override;
976 void trigger_sound(uint32_t framenumber, uint32_t stereo_position) const override;
977
978 private:
979@@ -85,7 +88,7 @@
980 uint32_t current_frame(uint32_t time) const;
981
982 uint32_t frametime_;
983- Point hotspot_;
984+ Vector2i hotspot_;
985 bool hasplrclrs_;
986 std::vector<std::string> image_files_;
987 std::vector<std::string> pc_mask_image_files_;
988@@ -207,7 +210,7 @@
989 return frametime_;
990 }
991
992-const Point& NonPackedAnimation::hotspot() const {
993+const Vector2i& NonPackedAnimation::hotspot() const {
994 return hotspot_;
995 }
996
997@@ -221,11 +224,11 @@
998 Texture* rv = new Texture(w, h);
999 if (!hasplrclrs_ || clr == nullptr) {
1000 // No player color means we simply want an exact copy of the original image.
1001- rv->blit(Rect(Point(0, 0), w, h), *image, Rect(Point(0, 0), w, h), 1., BlendMode::Copy);
1002+ rv->blit(Rectf(0, 0, w, h), *image, Rectf(0, 0, w, h), 1., BlendMode::Copy);
1003 } else {
1004- rv->fill_rect(Rect(Point(0, 0), w, h), RGBAColor(0, 0, 0, 0));
1005- rv->blit_blended(Rect(Point(0, 0), w, h), *image,
1006- *g_gr->images().get(pc_mask_image_files_[0]), Rect(Point(0, 0), w, h), *clr);
1007+ rv->fill_rect(Rectf(0, 0, w, h), RGBAColor(0, 0, 0, 0));
1008+ rv->blit_blended(Rectf(0, 0, w, h), *image, *g_gr->images().get(pc_mask_image_files_[0]),
1009+ Rectf(0, 0, w, h), *clr);
1010 }
1011 return rv;
1012 }
1013@@ -255,19 +258,20 @@
1014 }
1015 }
1016
1017-void NonPackedAnimation::blit(
1018- uint32_t time, const Point& dst, const Rect& srcrc, const RGBColor* clr, Surface* target) const {
1019+void NonPackedAnimation::blit(uint32_t time,
1020+ const Rectf& dstrc,
1021+ const Rectf& srcrc,
1022+ const RGBColor* clr,
1023+ Surface* target) const {
1024 assert(target);
1025
1026 const uint32_t idx = current_frame(time);
1027 assert(idx < nr_frames());
1028
1029 if (!hasplrclrs_ || clr == nullptr) {
1030- target->blit(
1031- Rect(dst.x, dst.y, srcrc.w, srcrc.h), *frames_.at(idx), srcrc, 1., BlendMode::UseAlpha);
1032+ target->blit(dstrc, *frames_.at(idx), srcrc, 1., BlendMode::UseAlpha);
1033 } else {
1034- target->blit_blended(
1035- Rect(dst.x, dst.y, srcrc.w, srcrc.h), *frames_.at(idx), *pcmasks_.at(idx), srcrc, *clr);
1036+ target->blit_blended(dstrc, *frames_.at(idx), *pcmasks_.at(idx), srcrc, *clr);
1037 }
1038 }
1039
1040
1041=== modified file 'src/graphic/animation.h'
1042--- src/graphic/animation.h 2016-08-04 15:49:05 +0000
1043+++ src/graphic/animation.h 2016-10-24 20:07:47 +0000
1044@@ -29,8 +29,8 @@
1045 #include <boost/utility.hpp>
1046
1047 #include "base/macros.h"
1048-#include "base/point.h"
1049 #include "base/rect.h"
1050+#include "base/vector.h"
1051
1052 class Image;
1053 class LuaTable;
1054@@ -68,7 +68,7 @@
1055
1056 /// The hotspot of this animation. Note that this is ignored when blitting,
1057 /// so the caller has to adjust for the hotspot himself.
1058- virtual const Point& hotspot() const = 0;
1059+ virtual const Vector2i& hotspot() const = 0;
1060
1061 /// An image of the first frame, blended with the given player color.
1062 /// The 'clr' is the player color used for blending - the parameter can be
1063@@ -83,8 +83,11 @@
1064 /// color used for blitting - the parameter can be 'nullptr', in which case the
1065 /// neutral image will be blitted. The Surface is the target for the blit
1066 /// operation and must be non-null.
1067- virtual void
1068- blit(uint32_t time, const Point&, const Rect& srcrc, const RGBColor* clr, Surface*) const = 0;
1069+ virtual void blit(uint32_t time,
1070+ const Rectf& dstrc,
1071+ const Rectf& srcrc,
1072+ const RGBColor* clr,
1073+ Surface*) const = 0;
1074
1075 /// Play the sound effect associated with this animation at the given time.
1076 virtual void trigger_sound(uint32_t time, uint32_t stereo_position) const = 0;
1077
1078=== modified file 'src/graphic/font_handler.cc'
1079--- src/graphic/font_handler.cc 2016-08-04 15:49:05 +0000
1080+++ src/graphic/font_handler.cc 2016-10-24 20:07:47 +0000
1081@@ -46,16 +46,15 @@
1082 */
1083 void draw_caret(RenderTarget& dst,
1084 const TextStyle& style,
1085- const Point& dstpoint,
1086+ const Vector2f& dstpoint,
1087 const std::string& text,
1088 uint32_t caret_offset) {
1089 int caret_x = style.calc_bare_width(text.substr(0, caret_offset));
1090
1091 const Image* caret_image = g_gr->images().get("images/ui_basic/caret.png");
1092- Point caretpt;
1093+ Vector2f caretpt;
1094 caretpt.x = dstpoint.x + caret_x + LINE_MARGIN - caret_image->width();
1095- caretpt.y = dstpoint.y + (style.font->height() - caret_image->height()) / 2;
1096-
1097+ caretpt.y = dstpoint.y + (style.font->height() - caret_image->height()) / 2.f;
1098 dst.blit(caretpt, caret_image);
1099 }
1100
1101@@ -202,7 +201,7 @@
1102 */
1103 void FontHandler::draw_text(RenderTarget& dst,
1104 const TextStyle& style,
1105- Point dstpoint,
1106+ Vector2i dstpoint_i,
1107 const std::string& text,
1108 Align align,
1109 uint32_t caret) {
1110@@ -212,10 +211,11 @@
1111 copytext = i18n::make_ligatures(copytext.c_str());
1112 const LineCacheEntry& lce = d->get_line(style, copytext);
1113
1114+ Vector2f dstpoint = dstpoint_i.cast<float>();
1115 UI::correct_for_align(align, lce.width + 2 * LINE_MARGIN, lce.height, &dstpoint);
1116
1117 if (lce.image)
1118- dst.blit(Point(dstpoint.x + LINE_MARGIN, dstpoint.y), lce.image.get());
1119+ dst.blit(Vector2f(dstpoint.x + LINE_MARGIN, dstpoint.y), lce.image.get());
1120
1121 if (caret <= copytext.size())
1122 draw_caret(dst, style, dstpoint, copytext, caret);
1123@@ -226,12 +226,13 @@
1124 */
1125 uint32_t FontHandler::draw_text_raw(RenderTarget& dst,
1126 const UI::TextStyle& style,
1127- Point dstpoint,
1128+ Vector2i dstpoint,
1129 const std::string& text) {
1130 const LineCacheEntry& lce = d->get_line(style, text);
1131
1132- if (lce.image)
1133- dst.blit(dstpoint, lce.image.get());
1134+ if (lce.image) {
1135+ dst.blit(dstpoint.cast<float>(), lce.image.get());
1136+ }
1137
1138 return lce.width;
1139 }
1140
1141=== modified file 'src/graphic/font_handler.h'
1142--- src/graphic/font_handler.h 2016-08-04 15:49:05 +0000
1143+++ src/graphic/font_handler.h 2016-10-24 20:07:47 +0000
1144@@ -24,7 +24,7 @@
1145 #include <memory>
1146 #include <string>
1147
1148-#include "base/point.h"
1149+#include "base/vector.h"
1150 #include "graphic/align.h"
1151
1152 class RenderTarget;
1153@@ -42,11 +42,11 @@
1154
1155 void draw_text(RenderTarget&,
1156 const TextStyle&,
1157- Point dstpoint,
1158+ Vector2i dstpoint,
1159 const std::string& text,
1160 Align align = UI::Align::kCenterLeft,
1161 uint32_t caret = std::numeric_limits<uint32_t>::max());
1162- uint32_t draw_text_raw(RenderTarget&, const TextStyle&, Point dstpoint, const std::string& text);
1163+ uint32_t draw_text_raw(RenderTarget&, const TextStyle&, Vector2i dstpoint, const std::string& text);
1164
1165 void get_size(const TextStyle&,
1166 const std::string& text,
1167
1168=== modified file 'src/graphic/font_handler1.h'
1169--- src/graphic/font_handler1.h 2016-08-04 15:49:05 +0000
1170+++ src/graphic/font_handler1.h 2016-10-24 20:07:47 +0000
1171@@ -25,7 +25,7 @@
1172 #include <string>
1173
1174 #include "base/macros.h"
1175-#include "base/point.h"
1176+#include "base/vector.h"
1177 #include "graphic/align.h"
1178 #include "graphic/text/font_set.h"
1179
1180
1181=== modified file 'src/graphic/game_renderer.cc'
1182--- src/graphic/game_renderer.cc 2016-08-04 15:49:05 +0000
1183+++ src/graphic/game_renderer.cc 2016-10-24 20:07:47 +0000
1184@@ -97,23 +97,214 @@
1185 return brightness / 255.;
1186 }
1187
1188-// Returns the road that should be rendered here. The format is like in field,
1189-// but this is not the physically present road, but the one that should be
1190-// drawn (i.e. taking into account if there is fog of war involved or road
1191-// building overlays enabled).
1192-uint8_t field_roads(const FCoords& coords,
1193- const Map& map,
1194- const EdgeOverlayManager& edge_overlay_manager,
1195- const Player* const player) {
1196- uint8_t roads;
1197- if (player && !player->see_all()) {
1198- const Player::Field& pf = player->fields()[Map::get_index(coords, map.get_width())];
1199- roads = pf.roads | edge_overlay_manager.get_overlay(coords);
1200- } else {
1201- roads = coords.field->get_roads();
1202- }
1203- roads |= edge_overlay_manager.get_overlay(coords);
1204- return roads;
1205+void draw_objects_for_visible_field(const EditorGameBase& egbase,
1206+ const FieldsToDraw::Field& field,
1207+ const float zoom,
1208+ const DrawText draw_text,
1209+ const Player* player,
1210+ RenderTarget* dst) {
1211+ BaseImmovable* const imm = field.fcoords.field->get_immovable();
1212+ if (imm != nullptr && imm->get_positions(egbase).front() == field.fcoords) {
1213+ DrawText draw_text_for_this_immovable = draw_text;
1214+ const Player* owner = imm->get_owner();
1215+ if (player != nullptr && owner != nullptr && !player->see_all() &&
1216+ player->is_hostile(*owner)) {
1217+ draw_text_for_this_immovable =
1218+ static_cast<DrawText>(draw_text_for_this_immovable & ~DrawText::kStatistics);
1219+ }
1220+
1221+ imm->draw(
1222+ egbase.get_gametime(), draw_text_for_this_immovable, field.rendertarget_pixel, zoom, dst);
1223+ }
1224+ for (Bob* bob = field.fcoords.field->get_first_bob(); bob; bob = bob->get_next_bob()) {
1225+ DrawText draw_text_for_this_bob = draw_text;
1226+ const Player* owner = bob->get_owner();
1227+ if (player != nullptr && owner != nullptr && !player->see_all() &&
1228+ player->is_hostile(*owner)) {
1229+ draw_text_for_this_bob =
1230+ static_cast<DrawText>(draw_text_for_this_bob & ~DrawText::kStatistics);
1231+ }
1232+ bob->draw(egbase, draw_text_for_this_bob, field.rendertarget_pixel, zoom, dst);
1233+ }
1234+}
1235+
1236+void draw_objets_for_formerly_visible_field(const FieldsToDraw::Field& field,
1237+ const Player::Field& player_field,
1238+ const float zoom,
1239+ RenderTarget* dst) {
1240+ if (const MapObjectDescr* const map_object_descr =
1241+ player_field.map_object_descr[TCoords<>::None]) {
1242+ if (player_field.constructionsite.becomes) {
1243+ assert(field.owner != nullptr);
1244+ const ConstructionsiteInformation& csinf = player_field.constructionsite;
1245+ // draw the partly finished constructionsite
1246+ uint32_t anim_idx;
1247+ try {
1248+ anim_idx = csinf.becomes->get_animation("build");
1249+ } catch (MapObjectDescr::AnimationNonexistent&) {
1250+ try {
1251+ anim_idx = csinf.becomes->get_animation("unoccupied");
1252+ } catch (MapObjectDescr::AnimationNonexistent) {
1253+ anim_idx = csinf.becomes->get_animation("idle");
1254+ }
1255+ }
1256+ const Animation& anim = g_gr->animations().get_animation(anim_idx);
1257+ const size_t nr_frames = anim.nr_frames();
1258+ uint32_t cur_frame =
1259+ csinf.totaltime ? csinf.completedtime * nr_frames / csinf.totaltime : 0;
1260+ uint32_t tanim = cur_frame * FRAME_LENGTH;
1261+
1262+ const uint16_t w = anim.width();
1263+ const uint16_t h = anim.height();
1264+ uint32_t lines = h * csinf.completedtime * nr_frames;
1265+ if (csinf.totaltime)
1266+ lines /= csinf.totaltime;
1267+ assert(h * cur_frame <= lines);
1268+ lines -= h * cur_frame;
1269+
1270+ if (cur_frame) { // not the first frame
1271+ // draw the prev frame from top to where next image will be drawing
1272+ dst->blit_animation(field.rendertarget_pixel, zoom, anim_idx, tanim - FRAME_LENGTH,
1273+ field.owner->get_playercolor(),
1274+ Recti(Vector2i(0, 0), w, h - lines));
1275+ } else if (csinf.was) {
1276+ // Is the first frame, but there was another building here before,
1277+ // get its last build picture and draw it instead.
1278+ uint32_t a;
1279+ try {
1280+ a = csinf.was->get_animation("unoccupied");
1281+ } catch (MapObjectDescr::AnimationNonexistent&) {
1282+ a = csinf.was->get_animation("idle");
1283+ }
1284+ dst->blit_animation(field.rendertarget_pixel, zoom, a, tanim - FRAME_LENGTH,
1285+ field.owner->get_playercolor(),
1286+ Recti(Vector2i(0, 0), w, h - lines));
1287+ }
1288+ assert(lines <= h);
1289+ dst->blit_animation(field.rendertarget_pixel, zoom, anim_idx, tanim,
1290+ field.owner->get_playercolor(),
1291+ Recti(Vector2i(0, h - lines), w, lines));
1292+ } else if (upcast(const BuildingDescr, building, map_object_descr)) {
1293+ assert(field.owner != nullptr);
1294+ // this is a building therefore we either draw unoccupied or idle animation
1295+ uint32_t pic;
1296+ try {
1297+ pic = building->get_animation("unoccupied");
1298+ } catch (MapObjectDescr::AnimationNonexistent&) {
1299+ pic = building->get_animation("idle");
1300+ }
1301+ dst->blit_animation(
1302+ field.rendertarget_pixel, zoom, pic, 0, field.owner->get_playercolor());
1303+ } else if (map_object_descr->type() == MapObjectType::FLAG) {
1304+ assert(field.owner != nullptr);
1305+ dst->blit_animation(field.rendertarget_pixel, zoom, field.owner->tribe().flag_animation(),
1306+ 0, field.owner->get_playercolor());
1307+ } else if (const uint32_t pic = map_object_descr->main_animation()) {
1308+ if (field.owner != nullptr) {
1309+ dst->blit_animation(
1310+ field.rendertarget_pixel, zoom, pic, 0, field.owner->get_playercolor());
1311+ } else {
1312+ dst->blit_animation(field.rendertarget_pixel, zoom, pic, 0);
1313+ }
1314+ }
1315+ }
1316+}
1317+
1318+// Draws the objects (animations & overlays).
1319+void draw_objects(const EditorGameBase& egbase,
1320+ const float zoom,
1321+ const FieldsToDraw& fields_to_draw,
1322+ const Player* player,
1323+ const DrawText draw_text,
1324+ RenderTarget* dst) {
1325+ std::vector<FieldOverlayManager::OverlayInfo> overlay_info;
1326+ for (size_t current_index = 0; current_index < fields_to_draw.size(); ++current_index) {
1327+ const FieldsToDraw::Field& field = fields_to_draw.at(current_index);
1328+ if (!field.all_neighbors_valid()) {
1329+ continue;
1330+ }
1331+
1332+ const FieldsToDraw::Field& rn = fields_to_draw.at(field.rn_index);
1333+ const FieldsToDraw::Field& bln = fields_to_draw.at(field.bln_index);
1334+ const FieldsToDraw::Field& brn = fields_to_draw.at(field.brn_index);
1335+
1336+ if (field.is_border) {
1337+ assert(field.owner != nullptr);
1338+ uint32_t const anim_idx = field.owner->tribe().frontier_animation();
1339+ if (field.vision) {
1340+ dst->blit_animation(
1341+ field.rendertarget_pixel, zoom, anim_idx, 0, field.owner->get_playercolor());
1342+ }
1343+ for (const auto& nf : {rn, bln, brn}) {
1344+ if ((field.vision || nf.vision) && nf.is_border &&
1345+ (field.owner == nf.owner || nf.owner == nullptr)) {
1346+ dst->blit_animation(middle(field.rendertarget_pixel, nf.rendertarget_pixel), zoom,
1347+ anim_idx, 0, field.owner->get_playercolor());
1348+ }
1349+ }
1350+ }
1351+
1352+ if (1 < field.vision) { // Render stuff that belongs to the node.
1353+ draw_objects_for_visible_field(egbase, field, zoom, draw_text, player, dst);
1354+ } else if (field.vision == 1) {
1355+ // We never show census or statistics for objects in the fog.
1356+ assert(player != nullptr);
1357+ const Map& map = egbase.map();
1358+ const Player::Field& player_field =
1359+ player->fields()[map.get_index(field.fcoords, map.get_width())];
1360+ draw_objets_for_formerly_visible_field(field, player_field, zoom, dst);
1361+ }
1362+
1363+ const FieldOverlayManager& overlay_manager = egbase.get_ibase()->field_overlay_manager();
1364+ {
1365+ overlay_info.clear();
1366+ overlay_manager.get_overlays(field.fcoords, &overlay_info);
1367+ for (const auto& overlay : overlay_info) {
1368+ dst->blitrect_scale(
1369+ Rectf(field.rendertarget_pixel - overlay.hotspot.cast<float>() * zoom,
1370+ overlay.pic->width() * zoom, overlay.pic->height() * zoom),
1371+ overlay.pic, Recti(0, 0, overlay.pic->width(), overlay.pic->height()), 1.f,
1372+ BlendMode::UseAlpha);
1373+ }
1374+ }
1375+
1376+ {
1377+ // Render overlays on the right triangle
1378+ overlay_info.clear();
1379+ overlay_manager.get_overlays(TCoords<>(field.fcoords, TCoords<>::R), &overlay_info);
1380+
1381+ Vector2f tripos(
1382+ (field.rendertarget_pixel.x + rn.rendertarget_pixel.x + brn.rendertarget_pixel.x) / 3.f,
1383+ (field.rendertarget_pixel.y + rn.rendertarget_pixel.y + brn.rendertarget_pixel.y) /
1384+ 3.f);
1385+ for (const auto& overlay : overlay_info) {
1386+ dst->blitrect_scale(Rectf(tripos - overlay.hotspot.cast<float>() * zoom,
1387+ overlay.pic->width() * zoom, overlay.pic->height() * zoom),
1388+ overlay.pic,
1389+ Recti(0, 0, overlay.pic->width(), overlay.pic->height()), 1.f,
1390+ BlendMode::UseAlpha);
1391+ }
1392+ }
1393+
1394+ {
1395+ // Render overlays on the D triangle
1396+ overlay_info.clear();
1397+ overlay_manager.get_overlays(TCoords<>(field.fcoords, TCoords<>::D), &overlay_info);
1398+
1399+ Vector2f tripos(
1400+ (field.rendertarget_pixel.x + bln.rendertarget_pixel.x + brn.rendertarget_pixel.x) /
1401+ 3.f,
1402+ (field.rendertarget_pixel.y + bln.rendertarget_pixel.y + brn.rendertarget_pixel.y) /
1403+ 3.f);
1404+ for (const auto& overlay : overlay_info) {
1405+ dst->blitrect_scale(Rectf(tripos - overlay.hotspot.cast<float>() * zoom,
1406+ overlay.pic->width() * zoom, overlay.pic->height() * zoom),
1407+ overlay.pic,
1408+ Recti(0, 0, overlay.pic->width(), overlay.pic->height()), 1.f,
1409+ BlendMode::UseAlpha);
1410+ }
1411+ }
1412+ }
1413 }
1414
1415 } // namespace
1416@@ -124,46 +315,60 @@
1417 GameRenderer::~GameRenderer() {
1418 }
1419
1420-void GameRenderer::rendermap(RenderTarget& dst,
1421- const Widelands::EditorGameBase& egbase,
1422- const Point& view_offset,
1423-
1424- const Widelands::Player& player) {
1425- draw(dst, egbase, view_offset, &player);
1426-}
1427-
1428-void GameRenderer::rendermap(RenderTarget& dst,
1429- const Widelands::EditorGameBase& egbase,
1430- const Point& view_offset) {
1431- draw(dst, egbase, view_offset, nullptr);
1432-}
1433-
1434-void GameRenderer::draw(RenderTarget& dst,
1435- const EditorGameBase& egbase,
1436- const Point& view_offset,
1437- const Player* player) {
1438- Point tl_map = dst.get_offset() + view_offset;
1439-
1440- assert(tl_map.x >= 0); // divisions involving negative numbers are bad
1441- assert(tl_map.y >= 0);
1442-
1443- int minfx = tl_map.x / kTriangleWidth - 1;
1444- int minfy = tl_map.y / kTriangleHeight - 1;
1445- int maxfx = (tl_map.x + dst.get_rect().w + (kTriangleWidth / 2)) / kTriangleWidth;
1446- int maxfy = (tl_map.y + dst.get_rect().h) / kTriangleHeight;
1447-
1448- // fudge for triangle boundary effects and for height differences
1449- minfx -= 1;
1450- minfy -= 1;
1451- maxfx += 1;
1452+void GameRenderer::rendermap(const Widelands::EditorGameBase& egbase,
1453+ const Vector2f& viewpoint,
1454+ const float zoom,
1455+ const Widelands::Player& player,
1456+ const DrawText draw_text,
1457+ RenderTarget* dst) {
1458+ draw(egbase, viewpoint, zoom, draw_text, &player, dst);
1459+}
1460+
1461+void GameRenderer::rendermap(const Widelands::EditorGameBase& egbase,
1462+ const Vector2f& viewpoint,
1463+ const float zoom,
1464+ const DrawText draw_text,
1465+ RenderTarget* dst) {
1466+ draw(egbase, viewpoint, zoom, draw_text, nullptr, dst);
1467+}
1468+
1469+void GameRenderer::draw(const EditorGameBase& egbase,
1470+ const Vector2f& viewpoint,
1471+ const float zoom,
1472+ const DrawText draw_text,
1473+ const Player* player,
1474+ RenderTarget* dst) {
1475+ assert(viewpoint.x >= 0); // divisions involving negative numbers are bad
1476+ assert(viewpoint.y >= 0);
1477+ assert(dst->get_offset().x <= 0);
1478+ assert(dst->get_offset().y <= 0);
1479+
1480+ int minfx = std::floor(viewpoint.x / kTriangleWidth);
1481+ int minfy = std::floor(viewpoint.y / kTriangleHeight);
1482+
1483+ // If a view window is partially moved outside of the display, its 'rect' is
1484+ // adjusted to be fully contained on the screen - i.e. x = 0 and width is
1485+ // made smaller. Its offset is made negative to account for this change.
1486+ // To figure out which fields we need to draw, we have to add the absolute
1487+ // value of 'offset' to the actual dimension of the 'rect' to get to desired
1488+ // dimension of the 'rect'
1489+ const Vector2f br_map = MapviewPixelFunctions::panel_to_map(
1490+ viewpoint, zoom, Vector2f(dst->get_rect().w + std::abs(dst->get_offset().x),
1491+ dst->get_rect().h + std::abs(dst->get_offset().y)));
1492+ int maxfx = std::ceil(br_map.x / kTriangleWidth);
1493+ int maxfy = std::ceil(br_map.y / kTriangleHeight);
1494+
1495+ // Adjust for triangle boundary effects and for height differences.
1496+ minfx -= 2;
1497+ maxfx += 2;
1498+ minfy -= 2;
1499 maxfy += 10;
1500
1501- Surface* surface = dst.get_surface();
1502+ Surface* surface = dst->get_surface();
1503 if (!surface)
1504 return;
1505
1506- const Rect& bounding_rect = dst.get_rect();
1507- const Point surface_offset = bounding_rect.origin() + dst.get_offset() - view_offset;
1508+ const Recti& bounding_rect = dst->get_rect();
1509 const int surface_width = surface->width();
1510 const int surface_height = surface->height();
1511
1512@@ -171,46 +376,60 @@
1513 const EdgeOverlayManager& edge_overlay_manager = egbase.get_ibase()->edge_overlay_manager();
1514 const uint32_t gametime = egbase.get_gametime();
1515
1516+ const float scale = 1.f / zoom;
1517 fields_to_draw_.reset(minfx, maxfx, minfy, maxfy);
1518 for (int32_t fy = minfy; fy <= maxfy; ++fy) {
1519 for (int32_t fx = minfx; fx <= maxfx; ++fx) {
1520 FieldsToDraw::Field& f =
1521 *fields_to_draw_.mutable_field(fields_to_draw_.calculate_index(fx, fy));
1522
1523- f.fx = fx;
1524- f.fy = fy;
1525-
1526- Coords coords(fx, fy);
1527- int x, y;
1528- MapviewPixelFunctions::get_basepix(coords, x, y);
1529-
1530- map.normalize_coords(coords);
1531- const FCoords& fcoords = map.get_fcoords(coords);
1532+ f.geometric_coords = Coords(fx, fy);
1533+
1534+ f.ln_index = fields_to_draw_.calculate_index(fx - 1, fy);
1535+ f.rn_index = fields_to_draw_.calculate_index(fx + 1, fy);
1536+ f.trn_index = fields_to_draw_.calculate_index(fx + (fy & 1), fy - 1);
1537+ f.bln_index = fields_to_draw_.calculate_index(fx + (fy & 1) - 1, fy + 1);
1538+ f.brn_index = fields_to_draw_.calculate_index(fx + (fy & 1), fy + 1);
1539
1540 // Texture coordinates for pseudo random tiling of terrain and road
1541 // graphics. Since screen space X increases top-to-bottom and OpenGL
1542 // increases bottom-to-top we flip the y coordinate to not have
1543 // terrains and road graphics vertically mirrorerd.
1544- f.texture_x = float(x) / kTextureSideLength;
1545- f.texture_y = -float(y) / kTextureSideLength;
1546-
1547- f.gl_x = f.pixel_x = x + surface_offset.x;
1548- f.gl_y = f.pixel_y = y + surface_offset.y - fcoords.field->get_height() * kHeightFactor;
1549- pixel_to_gl_renderbuffer(surface_width, surface_height, &f.gl_x, &f.gl_y);
1550-
1551- f.ter_d = fcoords.field->terrain_d();
1552- f.ter_r = fcoords.field->terrain_r();
1553-
1554- f.brightness = field_brightness(fcoords, gametime, map, player);
1555-
1556- PlayerNumber owner_number = fcoords.field->get_owned_by();
1557- if (owner_number > 0) {
1558- f.road_textures = &egbase.player(owner_number).tribe().road_textures();
1559- } else {
1560- f.road_textures = nullptr;
1561+ Vector2f map_pixel =
1562+ MapviewPixelFunctions::to_map_pixel_ignoring_height(f.geometric_coords);
1563+ f.texture_coords.x = map_pixel.x / kTextureSideLength;
1564+ f.texture_coords.y = -map_pixel.y / kTextureSideLength;
1565+
1566+ Coords normalized = f.geometric_coords;
1567+ map.normalize_coords(normalized);
1568+ f.fcoords = map.get_fcoords(normalized);
1569+
1570+ map_pixel.y -= f.fcoords.field->get_height() * kHeightFactor;
1571+
1572+ f.rendertarget_pixel = MapviewPixelFunctions::map_to_panel(viewpoint, zoom, map_pixel);
1573+ f.gl_position = f.surface_pixel = f.rendertarget_pixel +
1574+ dst->get_rect().origin().cast<float>() +
1575+ dst->get_offset().cast<float>();
1576+ pixel_to_gl_renderbuffer(
1577+ surface_width, surface_height, &f.gl_position.x, &f.gl_position.y);
1578+
1579+ f.brightness = field_brightness(f.fcoords, gametime, map, player);
1580+
1581+ PlayerNumber owned_by = f.fcoords.field->get_owned_by();
1582+ f.owner = owned_by != 0 ? &egbase.player(owned_by) : nullptr;
1583+ f.is_border = f.fcoords.field->is_border();
1584+ f.vision = 2;
1585+ f.roads = f.fcoords.field->get_roads();
1586+ if (player && !player->see_all()) {
1587+ const Player::Field& pf = player->fields()[map.get_index(f.fcoords, map.get_width())];
1588+ f.roads = pf.roads;
1589+ f.vision = pf.vision;
1590+ if (pf.vision == 1) {
1591+ f.owner = pf.owner != 0 ? &egbase.player(owned_by) : nullptr;
1592+ f.is_border = pf.border;
1593+ }
1594 }
1595-
1596- f.roads = field_roads(fcoords, map, edge_overlay_manager, player);
1597+ f.roads |= edge_overlay_manager.get_overlay(f.fcoords);
1598 }
1599 }
1600
1601@@ -219,13 +438,14 @@
1602 i.program_id = RenderQueue::Program::kTerrainBase;
1603 i.blend_mode = BlendMode::Copy;
1604 i.terrain_arguments.destination_rect =
1605- FloatRect(bounding_rect.x, surface_height - bounding_rect.y - bounding_rect.h,
1606- bounding_rect.w, bounding_rect.h);
1607+ Rectf(bounding_rect.x, surface_height - bounding_rect.y - bounding_rect.h, bounding_rect.w,
1608+ bounding_rect.h);
1609 i.terrain_arguments.gametime = gametime;
1610 i.terrain_arguments.renderbuffer_width = surface_width;
1611 i.terrain_arguments.renderbuffer_height = surface_height;
1612 i.terrain_arguments.terrains = &egbase.world().terrains();
1613 i.terrain_arguments.fields_to_draw = &fields_to_draw_;
1614+ i.terrain_arguments.scale = scale;
1615 RenderQueue::instance().enqueue(i);
1616
1617 // Enqueue the drawing of the dither layer.
1618@@ -237,191 +457,5 @@
1619 i.program_id = RenderQueue::Program::kTerrainRoad;
1620 RenderQueue::instance().enqueue(i);
1621
1622- draw_objects(dst, egbase, view_offset, player, minfx, maxfx, minfy, maxfy);
1623-}
1624-
1625-void GameRenderer::draw_objects(RenderTarget& dst,
1626- const EditorGameBase& egbase,
1627- const Point& view_offset,
1628- const Player* player,
1629- int minfx,
1630- int maxfx,
1631- int minfy,
1632- int maxfy) {
1633- // TODO(sirver): this should use FieldsToDraw. Would simplify this function a lot.
1634- static const uint32_t F = 0;
1635- static const uint32_t R = 1;
1636- static const uint32_t BL = 2;
1637- static const uint32_t BR = 3;
1638- const Map& map = egbase.map();
1639-
1640- std::vector<FieldOverlayManager::OverlayInfo> overlay_info;
1641- for (int32_t fy = minfy; fy <= maxfy; ++fy) {
1642- for (int32_t fx = minfx; fx <= maxfx; ++fx) {
1643- Coords ncoords(fx, fy);
1644- map.normalize_coords(ncoords);
1645- FCoords coords[4];
1646- coords[F] = map.get_fcoords(ncoords);
1647- coords[R] = map.r_n(coords[F]);
1648- coords[BL] = map.bl_n(coords[F]);
1649- coords[BR] = map.br_n(coords[F]);
1650- Point pos[4];
1651- MapviewPixelFunctions::get_basepix(Coords(fx, fy), pos[F].x, pos[F].y);
1652- MapviewPixelFunctions::get_basepix(Coords(fx + 1, fy), pos[R].x, pos[R].y);
1653- MapviewPixelFunctions::get_basepix(
1654- Coords(fx + (fy & 1) - 1, fy + 1), pos[BL].x, pos[BL].y);
1655- MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1), fy + 1), pos[BR].x, pos[BR].y);
1656- for (uint32_t d = 0; d < 4; ++d) {
1657- pos[d].y -= coords[d].field->get_height() * kHeightFactor;
1658- pos[d] -= view_offset;
1659- }
1660-
1661- PlayerNumber owner_number[4];
1662- bool isborder[4];
1663- Vision vision[4] = {2, 2, 2, 2};
1664- for (uint32_t d = 0; d < 4; ++d)
1665- owner_number[d] = coords[d].field->get_owned_by();
1666- for (uint32_t d = 0; d < 4; ++d)
1667- isborder[d] = coords[d].field->is_border();
1668-
1669- if (player && !player->see_all()) {
1670- for (uint32_t d = 0; d < 4; ++d) {
1671- const Player::Field& pf =
1672- player->fields()[map.get_index(coords[d], map.get_width())];
1673- vision[d] = pf.vision;
1674- if (pf.vision == 1) {
1675- owner_number[d] = pf.owner;
1676- isborder[d] = pf.border;
1677- }
1678- }
1679- }
1680-
1681- if (isborder[F]) {
1682- const Player& owner = egbase.player(owner_number[F]);
1683- uint32_t const anim_idx = owner.tribe().frontier_animation();
1684- if (vision[F])
1685- dst.blit_animation(pos[F], anim_idx, 0, owner.get_playercolor());
1686- for (uint32_t d = 1; d < 4; ++d) {
1687- if ((vision[F] || vision[d]) && isborder[d] &&
1688- (owner_number[d] == owner_number[F] || !owner_number[d])) {
1689- dst.blit_animation(middle(pos[F], pos[d]), anim_idx, 0, owner.get_playercolor());
1690- }
1691- }
1692- }
1693-
1694- if (1 < vision[F]) { // Render stuff that belongs to the node.
1695- if (BaseImmovable* const imm = coords[F].field->get_immovable())
1696- imm->draw(egbase, dst, coords[F], pos[F]);
1697- for (Bob* bob = coords[F].field->get_first_bob(); bob; bob = bob->get_next_bob())
1698- bob->draw(egbase, dst, pos[F]);
1699- } else if (vision[F] == 1) {
1700- const Player::Field& f_pl = player->fields()[map.get_index(coords[F], map.get_width())];
1701- const Player* owner = owner_number[F] ? egbase.get_player(owner_number[F]) : nullptr;
1702- if (const MapObjectDescr* const map_object_descr =
1703- f_pl.map_object_descr[TCoords<>::None]) {
1704- if (f_pl.constructionsite.becomes) {
1705- assert(owner != nullptr);
1706- const ConstructionsiteInformation& csinf = f_pl.constructionsite;
1707- // draw the partly finished constructionsite
1708- uint32_t anim_idx;
1709- try {
1710- anim_idx = csinf.becomes->get_animation("build");
1711- } catch (MapObjectDescr::AnimationNonexistent&) {
1712- try {
1713- anim_idx = csinf.becomes->get_animation("unoccupied");
1714- } catch (MapObjectDescr::AnimationNonexistent) {
1715- anim_idx = csinf.becomes->get_animation("idle");
1716- }
1717- }
1718- const Animation& anim = g_gr->animations().get_animation(anim_idx);
1719- const size_t nr_frames = anim.nr_frames();
1720- uint32_t cur_frame =
1721- csinf.totaltime ? csinf.completedtime * nr_frames / csinf.totaltime : 0;
1722- uint32_t tanim = cur_frame * FRAME_LENGTH;
1723-
1724- const uint16_t w = anim.width();
1725- const uint16_t h = anim.height();
1726- uint32_t lines = h * csinf.completedtime * nr_frames;
1727- if (csinf.totaltime)
1728- lines /= csinf.totaltime;
1729- assert(h * cur_frame <= lines);
1730- lines -= h * cur_frame;
1731-
1732- if (cur_frame) { // not the first frame
1733- // draw the prev frame from top to where next image will be drawing
1734- dst.blit_animation(pos[F], anim_idx, tanim - FRAME_LENGTH,
1735- owner->get_playercolor(), Rect(Point(0, 0), w, h - lines));
1736- } else if (csinf.was) {
1737- // Is the first frame, but there was another building here before,
1738- // get its last build picture and draw it instead.
1739- uint32_t a;
1740- try {
1741- a = csinf.was->get_animation("unoccupied");
1742- } catch (MapObjectDescr::AnimationNonexistent&) {
1743- a = csinf.was->get_animation("idle");
1744- }
1745- dst.blit_animation(pos[F], a, tanim - FRAME_LENGTH, owner->get_playercolor(),
1746- Rect(Point(0, 0), w, h - lines));
1747- }
1748- assert(lines <= h);
1749- dst.blit_animation(pos[F], anim_idx, tanim, owner->get_playercolor(),
1750- Rect(Point(0, h - lines), w, lines));
1751- } else if (upcast(const BuildingDescr, building, map_object_descr)) {
1752- assert(owner != nullptr);
1753- // this is a building therefore we either draw unoccupied or idle animation
1754- uint32_t pic;
1755- try {
1756- pic = building->get_animation("unoccupied");
1757- } catch (MapObjectDescr::AnimationNonexistent&) {
1758- pic = building->get_animation("idle");
1759- }
1760- dst.blit_animation(pos[F], pic, 0, owner->get_playercolor());
1761- } else if (map_object_descr->type() == MapObjectType::FLAG) {
1762- assert(owner != nullptr);
1763- dst.blit_animation(
1764- pos[F], owner->tribe().flag_animation(), 0, owner->get_playercolor());
1765- } else if (const uint32_t pic = map_object_descr->main_animation()) {
1766- if (owner != nullptr) {
1767- dst.blit_animation(pos[F], pic, 0, owner->get_playercolor());
1768- } else {
1769- dst.blit_animation(pos[F], pic, 0);
1770- }
1771- }
1772- }
1773- }
1774-
1775- const FieldOverlayManager& overlay_manager = egbase.get_ibase()->field_overlay_manager();
1776- {
1777- overlay_info.clear();
1778- overlay_manager.get_overlays(coords[F], &overlay_info);
1779- for (const auto& overlay : overlay_info) {
1780- dst.blit(pos[F] - overlay.hotspot, overlay.pic);
1781- }
1782- }
1783-
1784- {
1785- // Render overlays on the R triangle
1786- overlay_info.clear();
1787- overlay_manager.get_overlays(TCoords<>(coords[F], TCoords<>::R), &overlay_info);
1788-
1789- Point tripos(
1790- (pos[F].x + pos[R].x + pos[BR].x) / 3, (pos[F].y + pos[R].y + pos[BR].y) / 3);
1791- for (const auto& overlay : overlay_info) {
1792- dst.blit(tripos - overlay.hotspot, overlay.pic);
1793- }
1794- }
1795-
1796- {
1797- // Render overlays on the D triangle
1798- overlay_info.clear();
1799- overlay_manager.get_overlays(TCoords<>(coords[F], TCoords<>::D), &overlay_info);
1800-
1801- Point tripos(
1802- (pos[F].x + pos[BL].x + pos[BR].x) / 3, (pos[F].y + pos[BL].y + pos[BR].y) / 3);
1803- for (const auto& overlay : overlay_info) {
1804- dst.blit(tripos - overlay.hotspot, overlay.pic);
1805- }
1806- }
1807- }
1808- }
1809+ draw_objects(egbase, scale, fields_to_draw_, player, draw_text, dst);
1810 }
1811
1812=== modified file 'src/graphic/game_renderer.h'
1813--- src/graphic/game_renderer.h 2016-08-04 15:49:05 +0000
1814+++ src/graphic/game_renderer.h 2016-10-24 20:07:47 +0000
1815@@ -23,8 +23,9 @@
1816 #include <memory>
1817
1818 #include "base/macros.h"
1819-#include "base/point.h"
1820+#include "base/vector.h"
1821 #include "graphic/gl/fields_to_draw.h"
1822+#include "logic/map_objects/draw_text.h"
1823
1824 namespace Widelands {
1825 class Player;
1826@@ -33,51 +34,39 @@
1827
1828 class RenderTarget;
1829
1830-/**
1831- * This abstract base class renders the main game view into an
1832- * arbitrary @ref RenderTarget.
1833- *
1834- * Specializations exist for SDL software rendering and for OpenGL rendering.
1835- *
1836- * Users of this class should keep instances alive for as long as possible,
1837- * so that target-specific optimizations (such as caching data) can
1838- * be effective.
1839- */
1840+// Renders the MapView on screen.
1841 class GameRenderer {
1842 public:
1843 GameRenderer();
1844 ~GameRenderer();
1845
1846- // Renders the map from a player's point of view into the given
1847- // drawing window. 'view_offset' is the offset of the upper left
1848- // corner of the window into the map, in pixels.
1849- void rendermap(RenderTarget& dst,
1850- const Widelands::EditorGameBase& egbase,
1851- const Point& view_offset,
1852- const Widelands::Player& player);
1853+ // Renders the map from a player's point of view into the given drawing
1854+ // window. The 'viewpoint' is the top left screens pixel map pixel and
1855+ // 'scale' is the magnification of the view.
1856+ void rendermap(const Widelands::EditorGameBase& egbase,
1857+ const Vector2f& viewpoint,
1858+ float scale,
1859+ const Widelands::Player& player,
1860+ DrawText draw_text,
1861+ RenderTarget* dst);
1862
1863 // Renders the map from an omniscient perspective. This is used
1864 // for spectators, players that see all, and in the editor.
1865- void
1866- rendermap(RenderTarget& dst, const Widelands::EditorGameBase& egbase, const Point& view_offset);
1867+ void rendermap(const Widelands::EditorGameBase& egbase,
1868+ const Vector2f& viewpoint,
1869+ float scale,
1870+ DrawText draw_text,
1871+ RenderTarget* dst);
1872
1873 private:
1874 // Draw the map for the given parameters (see rendermap). 'player'
1875 // can be nullptr in which case the whole map is drawn.
1876- void draw(RenderTarget& dst,
1877- const Widelands::EditorGameBase& egbase,
1878- const Point& view_offset,
1879- const Widelands::Player* player);
1880-
1881- // Draws the objects (animations & overlays).
1882- void draw_objects(RenderTarget& dst,
1883- const Widelands::EditorGameBase& egbase,
1884- const Point& view_offset,
1885- const Widelands::Player* player,
1886- int minfx,
1887- int maxfx,
1888- int minfy,
1889- int maxfy);
1890+ void draw(const Widelands::EditorGameBase& egbase,
1891+ const Vector2f& viewpoint,
1892+ float scale,
1893+ DrawText draw_text,
1894+ const Widelands::Player* player,
1895+ RenderTarget* dst);
1896
1897 // This is owned and handled by us, but handed to the RenderQueue, so we
1898 // basically promise that this stays valid for one frame.
1899
1900=== modified file 'src/graphic/gl/blit_data.h'
1901--- src/graphic/gl/blit_data.h 2016-01-04 20:54:08 +0000
1902+++ src/graphic/gl/blit_data.h 2016-10-24 20:07:47 +0000
1903@@ -38,7 +38,7 @@
1904 int parent_height;
1905
1906 // The subrect in the parent texture.
1907- Rect rect;
1908+ Rectf rect;
1909 };
1910
1911 #endif // end of include guard: WL_GRAPHIC_GL_BLIT_DATA_H
1912
1913=== modified file 'src/graphic/gl/blit_program.cc'
1914--- src/graphic/gl/blit_program.cc 2016-08-04 15:49:05 +0000
1915+++ src/graphic/gl/blit_program.cc 2016-10-24 20:07:47 +0000
1916@@ -108,8 +108,8 @@
1917 const float blend_b = current_args.blend.b / 255.;
1918 const float blend_a = current_args.blend.a / 255.;
1919
1920- const FloatRect texture_rect = to_gl_texture(current_args.texture);
1921- const FloatRect mask_rect = to_gl_texture(current_args.mask);
1922+ const Rectf texture_rect = to_gl_texture(current_args.texture);
1923+ const Rectf mask_rect = to_gl_texture(current_args.mask);
1924 float program_flavor = 0;
1925 switch (current_args.blit_mode) {
1926 case BlitMode::kDirect:
1927@@ -176,7 +176,7 @@
1928 }
1929 }
1930
1931-void BlitProgram::draw(const FloatRect& gl_dest_rect,
1932+void BlitProgram::draw(const Rectf& gl_dest_rect,
1933 const float z_value,
1934 const BlitData& texture,
1935 const BlitData& mask,
1936@@ -186,11 +186,11 @@
1937 mask.texture_id != 0 ? BlitMode::kBlendedWithMask : BlitMode::kDirect}});
1938 }
1939
1940-void BlitProgram::draw_monochrome(const FloatRect& dest_rect,
1941+void BlitProgram::draw_monochrome(const Rectf& dest_rect,
1942 const float z_value,
1943 const BlitData& texture,
1944 const RGBAColor& blend) {
1945- draw({Arguments{dest_rect, z_value, texture, BlitData{0, 0, 0, Rect()}, blend,
1946+ draw({Arguments{dest_rect, z_value, texture, BlitData{0, 0, 0, Rectf()}, blend,
1947 BlendMode::UseAlpha, BlitMode::kMonochrome}});
1948 }
1949
1950
1951=== modified file 'src/graphic/gl/blit_program.h'
1952--- src/graphic/gl/blit_program.h 2016-08-04 15:49:05 +0000
1953+++ src/graphic/gl/blit_program.h 2016-10-24 20:07:47 +0000
1954@@ -36,7 +36,7 @@
1955 class BlitProgram {
1956 public:
1957 struct Arguments {
1958- FloatRect destination_rect;
1959+ Rectf destination_rect;
1960 float z_value;
1961 BlitData texture;
1962 BlitData mask;
1963@@ -53,7 +53,7 @@
1964 // 'gl_texture_image' to 'gl_dest_rect' in the currently bound framebuffer. All
1965 // coordinates are in the OpenGL frame. The 'texture_mask' is used to selectively apply
1966 // the 'blend'. This is used for blitting player colored images.
1967- void draw(const FloatRect& gl_dest_rect,
1968+ void draw(const Rectf& gl_dest_rect,
1969 const float z_value,
1970 const BlitData& texture,
1971 const BlitData& mask,
1972@@ -64,7 +64,7 @@
1973 // 'texture' to 'gl_dest_rect' in the currently bound framebuffer. All
1974 // coordinates are in the OpenGL frame. The image is first converted to
1975 // luminance, then all values are multiplied with blend.
1976- void draw_monochrome(const FloatRect& gl_dest_rect,
1977+ void draw_monochrome(const Rectf& gl_dest_rect,
1978 const float z_value,
1979 const BlitData& blit_source,
1980 const RGBAColor& blend);
1981
1982=== modified file 'src/graphic/gl/coordinate_conversion.h'
1983--- src/graphic/gl/coordinate_conversion.h 2016-08-04 15:49:05 +0000
1984+++ src/graphic/gl/coordinate_conversion.h 2016-10-24 20:07:47 +0000
1985@@ -38,34 +38,34 @@
1986 // Converts 'rect' given on a screen of 'width' x 'height' pixels into a rect
1987 // in opengl coordinates in a renderbuffer, i.e. in [-1, 1]. The returned
1988 // rectangle has positive width and height.
1989-inline FloatRect rect_to_gl_renderbuffer(const int width, const int height, const Rect& rect) {
1990+inline Rectf rect_to_gl_renderbuffer(const int width, const int height, const Rectf& rect) {
1991 float left = rect.x;
1992 float top = rect.y;
1993 float right = rect.x + rect.w;
1994 float bottom = rect.y + rect.h;
1995 pixel_to_gl_renderbuffer(width, height, &left, &top);
1996 pixel_to_gl_renderbuffer(width, height, &right, &bottom);
1997- return FloatRect(left, bottom, right - left, top - bottom);
1998+ return Rectf(left, bottom, right - left, top - bottom);
1999 }
2000
2001 // Converts 'rect' given on a texture of 'width' x 'height' pixels into a rect
2002 // in opengl coordinates in a texture, i.e. in [0, 1]. Texture pixels are sampled in their center.
2003 // The returned rectangle has positive width and height.
2004-inline FloatRect rect_to_gl_texture(const int width, const int height, const FloatRect& rect) {
2005+inline Rectf rect_to_gl_texture(const int width, const int height, const Rectf& rect) {
2006 float left = rect.x;
2007 float top = rect.y;
2008 float right = rect.x + rect.w;
2009 float bottom = rect.y + rect.h;
2010 pixel_to_gl_texture(width, height, &left, &top);
2011 pixel_to_gl_texture(width, height, &right, &bottom);
2012- return FloatRect(left, bottom, right - left, top - bottom);
2013+ return Rectf(left, bottom, right - left, top - bottom);
2014 }
2015
2016 // Convert 'blit_data' from pixel space into opengl space.
2017-inline FloatRect to_gl_texture(const BlitData& blit_data) {
2018+inline Rectf to_gl_texture(const BlitData& blit_data) {
2019 return rect_to_gl_texture(
2020 blit_data.parent_width, blit_data.parent_height,
2021- FloatRect(blit_data.rect.x, blit_data.rect.y, blit_data.rect.w, blit_data.rect.h));
2022+ Rectf(blit_data.rect.x, blit_data.rect.y, blit_data.rect.w, blit_data.rect.h));
2023 }
2024
2025 #endif // end of include guard: WL_GRAPHIC_GL_COORDINATE_CONVERSION_H
2026
2027=== modified file 'src/graphic/gl/dither_program.cc'
2028--- src/graphic/gl/dither_program.cc 2016-08-04 15:49:05 +0000
2029+++ src/graphic/gl/dither_program.cc 2016-10-24 20:07:47 +0000
2030@@ -56,14 +56,14 @@
2031
2032 void DitherProgram::add_vertex(const FieldsToDraw::Field& field,
2033 const TrianglePoint triangle_point,
2034- const FloatPoint& texture_offset) {
2035+ const Vector2f& texture_offset) {
2036 vertices_.emplace_back();
2037 PerVertexData& back = vertices_.back();
2038
2039- back.gl_x = field.gl_x;
2040- back.gl_y = field.gl_y;
2041- back.texture_x = field.texture_x;
2042- back.texture_y = field.texture_y;
2043+ back.gl_x = field.gl_position.x;
2044+ back.gl_y = field.gl_position.y;
2045+ back.texture_x = field.texture_coords.x;
2046+ back.texture_y = field.texture_coords.y;
2047 back.brightness = field.brightness;
2048 back.texture_offset_x = texture_offset.x;
2049 back.texture_offset_y = texture_offset.y;
2050@@ -98,7 +98,7 @@
2051 }
2052 const Widelands::TerrainDescription& other_terrain_description = terrains.get(other_terrain);
2053 if (terrains.get(my_terrain).dither_layer() < other_terrain_description.dither_layer()) {
2054- const FloatPoint texture_offset =
2055+ const Vector2f texture_offset =
2056 to_gl_texture(other_terrain_description.get_texture(gametime).blit_data()).origin();
2057 add_vertex(fields_to_draw.at(idx1), TrianglePoint::kTopRight, texture_offset);
2058 add_vertex(fields_to_draw.at(idx2), TrianglePoint::kTopLeft, texture_offset);
2059@@ -156,50 +156,49 @@
2060 // The bottom right neighbor fields_to_draw is needed for both triangles
2061 // associated with this field. If it is not in fields_to_draw, there is no need to
2062 // draw any triangles.
2063- const int brn_index = fields_to_draw.calculate_index(field.fx + (field.fy & 1), field.fy + 1);
2064- if (brn_index == -1) {
2065+ if (field.brn_index == FieldsToDraw::kInvalidIndex) {
2066 continue;
2067 }
2068
2069 // Dithering triangles for Down triangle.
2070- const int bln_index =
2071- fields_to_draw.calculate_index(field.fx + (field.fy & 1) - 1, field.fy + 1);
2072- if (bln_index != -1) {
2073- maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, brn_index, current_index,
2074- bln_index, field.ter_d, field.ter_r);
2075-
2076- const int terrain_dd = fields_to_draw.at(bln_index).ter_r;
2077- maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, bln_index, brn_index,
2078- current_index, field.ter_d, terrain_dd);
2079-
2080- const int ln_index = fields_to_draw.calculate_index(field.fx - 1, field.fy);
2081- if (ln_index != -1) {
2082- const int terrain_l = fields_to_draw.at(ln_index).ter_r;
2083+ if (field.bln_index != FieldsToDraw::kInvalidIndex) {
2084+ maybe_add_dithering_triangle(
2085+ gametime, terrains, fields_to_draw, field.brn_index, current_index, field.bln_index,
2086+ field.fcoords.field->terrain_d(), field.fcoords.field->terrain_r());
2087+
2088+ const int terrain_dd = fields_to_draw.at(field.bln_index).fcoords.field->terrain_r();
2089+ maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, field.bln_index,
2090+ field.brn_index, current_index,
2091+ field.fcoords.field->terrain_d(), terrain_dd);
2092+
2093+ if (field.ln_index != FieldsToDraw::kInvalidIndex) {
2094+ const int terrain_l = fields_to_draw.at(field.ln_index).fcoords.field->terrain_r();
2095 maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, current_index,
2096- bln_index, brn_index, field.ter_d, terrain_l);
2097+ field.bln_index, field.brn_index,
2098+ field.fcoords.field->terrain_d(), terrain_l);
2099 }
2100 }
2101
2102 // Dithering for right triangle.
2103- const int rn_index = fields_to_draw.calculate_index(field.fx + 1, field.fy);
2104- if (rn_index != -1) {
2105- maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, current_index, brn_index,
2106- rn_index, field.ter_r, field.ter_d);
2107- int terrain_rr = fields_to_draw.at(rn_index).ter_d;
2108- maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, brn_index, rn_index,
2109- current_index, field.ter_r, terrain_rr);
2110+ if (field.rn_index != FieldsToDraw::kInvalidIndex) {
2111+ maybe_add_dithering_triangle(
2112+ gametime, terrains, fields_to_draw, current_index, field.brn_index, field.rn_index,
2113+ field.fcoords.field->terrain_r(), field.fcoords.field->terrain_d());
2114+ int terrain_rr = fields_to_draw.at(field.rn_index).fcoords.field->terrain_d();
2115+ maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, field.brn_index,
2116+ field.rn_index, current_index,
2117+ field.fcoords.field->terrain_r(), terrain_rr);
2118
2119- const int trn_index =
2120- fields_to_draw.calculate_index(field.fx + (field.fy & 1), field.fy - 1);
2121- if (trn_index != -1) {
2122- const int terrain_u = fields_to_draw.at(trn_index).ter_d;
2123- maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, rn_index,
2124- current_index, brn_index, field.ter_r, terrain_u);
2125+ if (field.trn_index != FieldsToDraw::kInvalidIndex) {
2126+ const int terrain_u = fields_to_draw.at(field.trn_index).fcoords.field->terrain_d();
2127+ maybe_add_dithering_triangle(gametime, terrains, fields_to_draw, field.rn_index,
2128+ current_index, field.brn_index,
2129+ field.fcoords.field->terrain_r(), terrain_u);
2130 }
2131 }
2132 }
2133
2134 const BlitData& blit_data = terrains.get(0).get_texture(0).blit_data();
2135- const FloatRect texture_coordinates = to_gl_texture(blit_data);
2136+ const Rectf texture_coordinates = to_gl_texture(blit_data);
2137 gl_draw(blit_data.texture_id, texture_coordinates.w, texture_coordinates.h, z_value);
2138 }
2139
2140=== modified file 'src/graphic/gl/dither_program.h'
2141--- src/graphic/gl/dither_program.h 2016-01-08 21:00:39 +0000
2142+++ src/graphic/gl/dither_program.h 2016-10-24 20:07:47 +0000
2143@@ -22,7 +22,7 @@
2144
2145 #include <memory>
2146
2147-#include "base/point.h"
2148+#include "base/vector.h"
2149 #include "graphic/gl/fields_to_draw.h"
2150 #include "graphic/gl/utils.h"
2151 #include "logic/description_maintainer.h"
2152@@ -66,7 +66,7 @@
2153 // this vertex.
2154 void add_vertex(const FieldsToDraw::Field& field,
2155 TrianglePoint triangle_point,
2156- const FloatPoint& texture_offset);
2157+ const Vector2f& texture_offset);
2158
2159 struct PerVertexData {
2160 float gl_x;
2161
2162=== modified file 'src/graphic/gl/draw_line_program.h'
2163--- src/graphic/gl/draw_line_program.h 2016-02-02 09:02:53 +0000
2164+++ src/graphic/gl/draw_line_program.h 2016-10-24 20:07:47 +0000
2165@@ -22,8 +22,8 @@
2166
2167 #include <vector>
2168
2169-#include "base/point.h"
2170 #include "base/rect.h"
2171+#include "base/vector.h"
2172 #include "graphic/blend_mode.h"
2173 #include "graphic/color.h"
2174 #include "graphic/gl/utils.h"
2175
2176=== modified file 'src/graphic/gl/fields_to_draw.h'
2177--- src/graphic/gl/fields_to_draw.h 2016-08-04 15:49:05 +0000
2178+++ src/graphic/gl/fields_to_draw.h 2016-10-24 20:07:47 +0000
2179@@ -21,29 +21,64 @@
2180 #define WL_GRAPHIC_GL_FIELDS_TO_DRAW_H
2181
2182 #include <cstddef>
2183+#include <limits>
2184 #include <string>
2185 #include <vector>
2186
2187 #include <stdint.h>
2188
2189+#include "base/vector.h"
2190 #include "logic/map_objects/tribes/road_textures.h"
2191+#include "logic/player.h"
2192+#include "logic/widelands.h"
2193+#include "logic/widelands_geometry.h"
2194
2195 // Helper struct that contains the data needed for drawing all fields. All
2196 // methods are inlined for performance reasons.
2197 class FieldsToDraw {
2198 public:
2199+ static constexpr int kInvalidIndex = std::numeric_limits<int>::min();
2200+
2201 struct Field {
2202- int fx, fy; // geometric coordinates (i.e. map coordinates that can be out of bounds).
2203- float gl_x, gl_y; // GL Position of this field.
2204- float pixel_x, pixel_y; // Pixel position relative to top left.
2205- float texture_x, texture_y; // Texture coordinates.
2206- float brightness; // brightness of the pixel
2207- uint8_t ter_r, ter_d; // Texture index of the right and down triangle.
2208- uint8_t roads; // Bitmask of roads to render, see logic/roadtype.h.
2209- const RoadTextures* road_textures; // Road Textures to use for drawing.
2210+ Widelands::Coords geometric_coords; // geometric coordinates (i.e. map coordinates that can
2211+ // be out of bounds).
2212+ Widelands::FCoords fcoords; // The normalized coords and the field this is refering to.
2213+ Vector2f gl_position; // GL Position of this field.
2214+
2215+ // Surface pixel this will be plotted on.
2216+ Vector2f surface_pixel;
2217+
2218+ // Rendertarget pixel this will be plotted on. This is only different by
2219+ // the Rendertarget::get_rect().origin() of the view window.
2220+ Vector2f rendertarget_pixel;
2221+ Vector2f texture_coords; // Texture coordinates.
2222+ float brightness; // brightness of the pixel
2223+
2224+ // The next values are not necessarily the true data of this field, but
2225+ // what the player should see. For example in fog of war we always draw
2226+ // what we saw last.
2227+ uint8_t roads; // Bitmask of roads to render, see logic/roadtype.h.
2228+ bool is_border;
2229+ Widelands::Vision vision;
2230+ Widelands::Player* owner; // can be nullptr.
2231+
2232+ // Index of neighbors in this 'FieldsToDraw'. kInvalidIndex if this
2233+ // neighbor is not contained.
2234+ int ln_index;
2235+ int rn_index;
2236+ int trn_index;
2237+ int bln_index;
2238+ int brn_index;
2239+
2240+ inline bool all_neighbors_valid() const {
2241+ return ln_index != kInvalidIndex && rn_index != kInvalidIndex &&
2242+ trn_index != kInvalidIndex && bln_index != kInvalidIndex &&
2243+ brn_index != kInvalidIndex;
2244+ }
2245 };
2246
2247- FieldsToDraw() = default;
2248+ FieldsToDraw() {
2249+ }
2250
2251 // Resize this fields to draw for reuse.
2252 void reset(int minfx, int maxfx, int minfy, int maxfy) {
2253@@ -60,15 +95,16 @@
2254 }
2255
2256 // Calculates the index of the given field with ('fx', 'fy') being geometric
2257- // coordinates in the map. Returns -1 if this field is not in the fields_to_draw.
2258+ // coordinates in the map. Returns kInvalidIndex if this field is not in the
2259+ // fields_to_draw.
2260 inline int calculate_index(int fx, int fy) const {
2261 uint16_t xidx = fx - min_fx_;
2262 if (xidx >= w_) {
2263- return -1;
2264+ return kInvalidIndex;
2265 }
2266 uint16_t yidx = fy - min_fy_;
2267 if (yidx >= h_) {
2268- return -1;
2269+ return kInvalidIndex;
2270 }
2271 return yidx * w_ + xidx;
2272 }
2273
2274=== modified file 'src/graphic/gl/fill_rect_program.cc'
2275--- src/graphic/gl/fill_rect_program.cc 2016-08-04 15:49:05 +0000
2276+++ src/graphic/gl/fill_rect_program.cc 2016-10-24 20:07:47 +0000
2277@@ -37,7 +37,7 @@
2278 attr_color_ = glGetAttribLocation(gl_program_.object(), "attr_color");
2279 }
2280
2281-void FillRectProgram::draw(const FloatRect& destination_rect,
2282+void FillRectProgram::draw(const Rectf& destination_rect,
2283 const float z_value,
2284 const RGBAColor& color,
2285 const BlendMode blend_mode) {
2286
2287=== modified file 'src/graphic/gl/fill_rect_program.h'
2288--- src/graphic/gl/fill_rect_program.h 2016-08-04 15:49:05 +0000
2289+++ src/graphic/gl/fill_rect_program.h 2016-10-24 20:07:47 +0000
2290@@ -30,7 +30,7 @@
2291 class FillRectProgram {
2292 public:
2293 struct Arguments {
2294- FloatRect destination_rect;
2295+ Rectf destination_rect;
2296 float z_value;
2297 RGBAColor color;
2298 BlendMode blend_mode;
2299@@ -41,7 +41,7 @@
2300
2301 // Fills a solid rect in 'color'. If blend_mode is BlendMode::UseAlpha, this
2302 // will brighten the rect, if it is BlendMode::Subtract it darkens it.
2303- void draw(const FloatRect& destination_rect,
2304+ void draw(const Rectf& destination_rect,
2305 float z_value,
2306 const RGBAColor& color,
2307 BlendMode blend_mode);
2308
2309=== modified file 'src/graphic/gl/road_program.cc'
2310--- src/graphic/gl/road_program.cc 2016-08-04 15:49:05 +0000
2311+++ src/graphic/gl/road_program.cc 2016-10-24 20:07:47 +0000
2312@@ -50,6 +50,7 @@
2313 const int renderbuffer_height,
2314 const FieldsToDraw::Field& start,
2315 const FieldsToDraw::Field& end,
2316+ const float scale,
2317 const Widelands::RoadType road_type,
2318 const Direction direction,
2319 uint32_t* gl_texture) {
2320@@ -59,8 +60,8 @@
2321 // The overshot of the road in either direction in percent.
2322 static constexpr float kRoadElongationInPercent = .1;
2323
2324- const float delta_x = end.pixel_x - start.pixel_x;
2325- const float delta_y = end.pixel_y - start.pixel_y;
2326+ const float delta_x = end.surface_pixel.x - start.surface_pixel.x;
2327+ const float delta_y = end.surface_pixel.y - start.surface_pixel.y;
2328 const float vector_length = std::hypot(delta_x, delta_y);
2329
2330 const float road_overshoot_x = delta_x * kRoadElongationInPercent;
2331@@ -68,13 +69,15 @@
2332
2333 // Find the reciprocal unit vector, so that we can calculate start and end
2334 // points for the quad that will make the road.
2335- const float road_thickness_x = (-delta_y / vector_length) * kRoadThicknessInPixels;
2336- const float road_thickness_y = (delta_x / vector_length) * kRoadThicknessInPixels;
2337+ const float road_thickness_x = (-delta_y / vector_length) * kRoadThicknessInPixels * scale;
2338+ const float road_thickness_y = (delta_x / vector_length) * kRoadThicknessInPixels * scale;
2339
2340+ assert(start.owner != nullptr);
2341 const Image& texture =
2342 road_type == Widelands::RoadType::kNormal ?
2343- start.road_textures->get_normal_texture(start.fx, start.fy, direction) :
2344- start.road_textures->get_busy_texture(start.fx, start.fy, direction);
2345+ start.owner->tribe().road_textures().get_normal_texture(
2346+ start.geometric_coords, direction) :
2347+ start.owner->tribe().road_textures().get_busy_texture(start.geometric_coords, direction);
2348 if (*gl_texture == 0) {
2349 *gl_texture = texture.blit_data().texture_id;
2350 }
2351@@ -82,27 +85,27 @@
2352 // one texture atlas.
2353 assert(*gl_texture == texture.blit_data().texture_id);
2354
2355- const FloatRect texture_rect = to_gl_texture(texture.blit_data());
2356+ const Rectf texture_rect = to_gl_texture(texture.blit_data());
2357
2358 vertices_.emplace_back(PerVertexData{
2359- start.pixel_x - road_overshoot_x + road_thickness_x,
2360- start.pixel_y - road_overshoot_y + road_thickness_y, texture_rect.x, texture_rect.y,
2361+ start.surface_pixel.x - road_overshoot_x + road_thickness_x,
2362+ start.surface_pixel.y - road_overshoot_y + road_thickness_y, texture_rect.x, texture_rect.y,
2363 start.brightness,
2364 });
2365 pixel_to_gl_renderbuffer(
2366 renderbuffer_width, renderbuffer_height, &vertices_.back().gl_x, &vertices_.back().gl_y);
2367
2368 vertices_.emplace_back(PerVertexData{
2369- start.pixel_x - road_overshoot_x - road_thickness_x,
2370- start.pixel_y - road_overshoot_y - road_thickness_y, texture_rect.x,
2371+ start.surface_pixel.x - road_overshoot_x - road_thickness_x,
2372+ start.surface_pixel.y - road_overshoot_y - road_thickness_y, texture_rect.x,
2373 texture_rect.y + texture_rect.h, start.brightness,
2374 });
2375 pixel_to_gl_renderbuffer(
2376 renderbuffer_width, renderbuffer_height, &vertices_.back().gl_x, &vertices_.back().gl_y);
2377
2378 vertices_.emplace_back(PerVertexData{
2379- end.pixel_x + road_overshoot_x + road_thickness_x,
2380- end.pixel_y + road_overshoot_y + road_thickness_y, texture_rect.x + texture_rect.w,
2381+ end.surface_pixel.x + road_overshoot_x + road_thickness_x,
2382+ end.surface_pixel.y + road_overshoot_y + road_thickness_y, texture_rect.x + texture_rect.w,
2383 texture_rect.y, end.brightness,
2384 });
2385 pixel_to_gl_renderbuffer(
2386@@ -116,8 +119,8 @@
2387 vertices_.emplace_back(vertices_.at(vertices_.size() - 2));
2388
2389 vertices_.emplace_back(PerVertexData{
2390- end.pixel_x + road_overshoot_x - road_thickness_x,
2391- end.pixel_y + road_overshoot_y - road_thickness_y, texture_rect.x + texture_rect.w,
2392+ end.surface_pixel.x + road_overshoot_x - road_thickness_x,
2393+ end.surface_pixel.y + road_overshoot_y - road_thickness_y, texture_rect.x + texture_rect.w,
2394 texture_rect.y + texture_rect.h, end.brightness,
2395 });
2396 pixel_to_gl_renderbuffer(
2397@@ -127,7 +130,8 @@
2398 void RoadProgram::draw(const int renderbuffer_width,
2399 const int renderbuffer_height,
2400 const FieldsToDraw& fields_to_draw,
2401- float z_value) {
2402+ const float scale,
2403+ const float z_value) {
2404 vertices_.clear();
2405
2406 uint32_t gl_texture = 0;
2407@@ -135,36 +139,32 @@
2408 const FieldsToDraw::Field& field = fields_to_draw.at(current_index);
2409
2410 // Road to right neighbor.
2411- const int rn_index = fields_to_draw.calculate_index(field.fx + 1, field.fy);
2412- if (rn_index != -1) {
2413+ if (field.rn_index != FieldsToDraw::kInvalidIndex) {
2414 const Widelands::RoadType road =
2415 static_cast<Widelands::RoadType>(field.roads & Widelands::RoadType::kMask);
2416 if (road != Widelands::RoadType::kNone) {
2417- add_road(renderbuffer_width, renderbuffer_height, field, fields_to_draw.at(rn_index),
2418- road, kEast, &gl_texture);
2419+ add_road(renderbuffer_width, renderbuffer_height, field,
2420+ fields_to_draw.at(field.rn_index), scale, road, kEast, &gl_texture);
2421 }
2422 }
2423
2424 // Road to bottom right neighbor.
2425- const int brn_index = fields_to_draw.calculate_index(field.fx + (field.fy & 1), field.fy + 1);
2426- if (brn_index != -1) {
2427+ if (field.brn_index != FieldsToDraw::kInvalidIndex) {
2428 const Widelands::RoadType road =
2429 static_cast<Widelands::RoadType>((field.roads >> 2) & Widelands::RoadType::kMask);
2430 if (road != Widelands::RoadType::kNone) {
2431- add_road(renderbuffer_width, renderbuffer_height, field, fields_to_draw.at(brn_index),
2432- road, kSouthEast, &gl_texture);
2433+ add_road(renderbuffer_width, renderbuffer_height, field,
2434+ fields_to_draw.at(field.brn_index), scale, road, kSouthEast, &gl_texture);
2435 }
2436 }
2437
2438 // Road to bottom right neighbor.
2439- const int bln_index =
2440- fields_to_draw.calculate_index(field.fx + (field.fy & 1) - 1, field.fy + 1);
2441- if (bln_index != -1) {
2442+ if (field.bln_index != FieldsToDraw::kInvalidIndex) {
2443 const Widelands::RoadType road =
2444 static_cast<Widelands::RoadType>((field.roads >> 4) & Widelands::RoadType::kMask);
2445 if (road != Widelands::RoadType::kNone) {
2446- add_road(renderbuffer_width, renderbuffer_height, field, fields_to_draw.at(bln_index),
2447- road, kSouthWest, &gl_texture);
2448+ add_road(renderbuffer_width, renderbuffer_height, field,
2449+ fields_to_draw.at(field.bln_index), scale, road, kSouthWest, &gl_texture);
2450 }
2451 }
2452 }
2453
2454=== modified file 'src/graphic/gl/road_program.h'
2455--- src/graphic/gl/road_program.h 2016-08-04 15:49:05 +0000
2456+++ src/graphic/gl/road_program.h 2016-10-24 20:07:47 +0000
2457@@ -42,6 +42,7 @@
2458 void draw(int renderbuffer_width,
2459 int renderbuffer_height,
2460 const FieldsToDraw& fields_to_draw,
2461+ float scale,
2462 float z_value);
2463
2464 private:
2465@@ -61,6 +62,7 @@
2466 int renderbuffer_height,
2467 const FieldsToDraw::Field& start,
2468 const FieldsToDraw::Field& end,
2469+ float scale,
2470 const Widelands::RoadType road_type,
2471 const Direction direction,
2472 uint32_t* gl_texture);
2473
2474=== modified file 'src/graphic/gl/terrain_program.cc'
2475--- src/graphic/gl/terrain_program.cc 2016-08-04 15:49:05 +0000
2476+++ src/graphic/gl/terrain_program.cc 2016-10-24 20:07:47 +0000
2477@@ -71,15 +71,15 @@
2478 }
2479
2480 void TerrainProgram::add_vertex(const FieldsToDraw::Field& field,
2481- const FloatPoint& texture_offset) {
2482+ const Vector2f& texture_offset) {
2483 vertices_.emplace_back();
2484 PerVertexData& back = vertices_.back();
2485
2486- back.gl_x = field.gl_x;
2487- back.gl_y = field.gl_y;
2488+ back.gl_x = field.gl_position.x;
2489+ back.gl_y = field.gl_position.y;
2490 back.brightness = field.brightness;
2491- back.texture_x = field.texture_x;
2492- back.texture_y = field.texture_y;
2493+ back.texture_x = field.texture_coords.x;
2494+ back.texture_y = field.texture_coords.y;
2495 back.texture_offset_x = texture_offset.x;
2496 back.texture_offset_y = texture_offset.y;
2497 }
2498@@ -101,34 +101,34 @@
2499 // The bottom right neighbor fields_to_draw is needed for both triangles
2500 // associated with this field. If it is not in fields_to_draw, there is no need to
2501 // draw any triangles.
2502- const int brn_index = fields_to_draw.calculate_index(field.fx + (field.fy & 1), field.fy + 1);
2503- if (brn_index == -1) {
2504+ if (field.brn_index == FieldsToDraw::kInvalidIndex) {
2505 continue;
2506 }
2507
2508 // Down triangle.
2509- const int bln_index =
2510- fields_to_draw.calculate_index(field.fx + (field.fy & 1) - 1, field.fy + 1);
2511- if (bln_index != -1) {
2512- const FloatPoint texture_offset =
2513- to_gl_texture(terrains.get(field.ter_d).get_texture(gametime).blit_data()).origin();
2514+ if (field.bln_index != FieldsToDraw::kInvalidIndex) {
2515+ const Vector2f texture_offset =
2516+ to_gl_texture(
2517+ terrains.get(field.fcoords.field->terrain_d()).get_texture(gametime).blit_data())
2518+ .origin();
2519 add_vertex(fields_to_draw.at(current_index), texture_offset);
2520- add_vertex(fields_to_draw.at(bln_index), texture_offset);
2521- add_vertex(fields_to_draw.at(brn_index), texture_offset);
2522+ add_vertex(fields_to_draw.at(field.bln_index), texture_offset);
2523+ add_vertex(fields_to_draw.at(field.brn_index), texture_offset);
2524 }
2525
2526 // Right triangle.
2527- const int rn_index = fields_to_draw.calculate_index(field.fx + 1, field.fy);
2528- if (rn_index != -1) {
2529- const FloatPoint texture_offset =
2530- to_gl_texture(terrains.get(field.ter_r).get_texture(gametime).blit_data()).origin();
2531+ if (field.rn_index != FieldsToDraw::kInvalidIndex) {
2532+ const Vector2f texture_offset =
2533+ to_gl_texture(
2534+ terrains.get(field.fcoords.field->terrain_r()).get_texture(gametime).blit_data())
2535+ .origin();
2536 add_vertex(fields_to_draw.at(current_index), texture_offset);
2537- add_vertex(fields_to_draw.at(brn_index), texture_offset);
2538- add_vertex(fields_to_draw.at(rn_index), texture_offset);
2539+ add_vertex(fields_to_draw.at(field.brn_index), texture_offset);
2540+ add_vertex(fields_to_draw.at(field.rn_index), texture_offset);
2541 }
2542 }
2543
2544 const BlitData& blit_data = terrains.get(0).get_texture(0).blit_data();
2545- const FloatRect texture_coordinates = to_gl_texture(blit_data);
2546+ const Rectf texture_coordinates = to_gl_texture(blit_data);
2547 gl_draw(blit_data.texture_id, texture_coordinates.w, texture_coordinates.h, z_value);
2548 }
2549
2550=== modified file 'src/graphic/gl/terrain_program.h'
2551--- src/graphic/gl/terrain_program.h 2016-08-04 15:49:05 +0000
2552+++ src/graphic/gl/terrain_program.h 2016-10-24 20:07:47 +0000
2553@@ -22,7 +22,7 @@
2554
2555 #include <vector>
2556
2557-#include "base/point.h"
2558+#include "base/vector.h"
2559 #include "graphic/gl/fields_to_draw.h"
2560 #include "graphic/gl/utils.h"
2561 #include "logic/description_maintainer.h"
2562@@ -54,7 +54,7 @@
2563 void gl_draw(int gl_texture, float texture_w, float texture_h, float z_value);
2564
2565 // Adds a vertex to the end of vertices with data from 'field' and 'texture_coordinates'.
2566- void add_vertex(const FieldsToDraw::Field& field, const FloatPoint& texture_coordinates);
2567+ void add_vertex(const FieldsToDraw::Field& field, const Vector2f& texture_coordinates);
2568
2569 // The program used for drawing the terrain.
2570 Gl::Program gl_program_;
2571
2572=== modified file 'src/graphic/minimap_renderer.cc'
2573--- src/graphic/minimap_renderer.cc 2016-08-04 15:49:05 +0000
2574+++ src/graphic/minimap_renderer.cc 2016-10-24 20:07:47 +0000
2575@@ -25,13 +25,9 @@
2576 #include "economy/flag.h"
2577 #include "economy/road.h"
2578 #include "graphic/graphic.h"
2579-#include "graphic/image_io.h"
2580-#include "graphic/texture.h"
2581 #include "logic/field.h"
2582-#include "logic/map.h"
2583 #include "logic/map_objects/world/terrain_description.h"
2584 #include "logic/map_objects/world/world.h"
2585-#include "logic/player.h"
2586 #include "wui/mapviewpixelconstants.h"
2587 #include "wui/mapviewpixelfunctions.h"
2588
2589@@ -40,12 +36,17 @@
2590 namespace {
2591
2592 const RGBColor kWhite(255, 255, 255);
2593+const RGBColor kRed(255, 0, 0);
2594
2595 // Blend two colors.
2596 inline RGBColor blend_color(const RGBColor& c1, const RGBColor& c2) {
2597 return RGBColor((c1.r + c2.r) / 2, (c1.g + c2.g) / 2, (c1.b + c2.b) / 2);
2598 }
2599
2600+int round_up_to_nearest_even(int number) {
2601+ return number % 2 == 0 ? number : number + 1;
2602+}
2603+
2604 // Returns the color to be used in the minimap for the given field.
2605 inline RGBColor calc_minimap_color(const Widelands::EditorGameBase& egbase,
2606 const Widelands::FCoords& f,
2607@@ -85,83 +86,83 @@
2608 return color;
2609 }
2610
2611-// Draws the dotted frame border onto the minimap.
2612-bool is_minimap_frameborder(const Widelands::FCoords& f,
2613- const Point& ptopleft,
2614- const Point& pbottomright,
2615- int32_t mapwidth,
2616- int32_t mapheight,
2617- int32_t modx,
2618- int32_t mody) {
2619- bool isframepixel = false;
2620-
2621- if (ptopleft.x <= pbottomright.x) {
2622- if (f.x >= ptopleft.x && f.x <= pbottomright.x &&
2623- (f.y == ptopleft.y || f.y == pbottomright.y) && f.x % 2 == modx)
2624- isframepixel = true;
2625- } else {
2626- if (((f.x >= ptopleft.x && f.x <= mapwidth) || (f.x >= 0 && f.x <= pbottomright.x)) &&
2627- (f.y == ptopleft.y || f.y == pbottomright.y) && (f.x % 2) == modx)
2628- isframepixel = true;
2629- }
2630-
2631- if (ptopleft.y <= pbottomright.y) {
2632- if (f.y >= ptopleft.y && f.y <= pbottomright.y &&
2633- (f.x == ptopleft.x || f.x == pbottomright.x) && f.y % 2 == mody)
2634- isframepixel = true;
2635- } else {
2636- if (((f.y >= ptopleft.y && f.y <= mapheight) || (f.y >= 0 && f.y <= pbottomright.y)) &&
2637- (f.x == ptopleft.x || f.x == pbottomright.x) && f.y % 2 == mody)
2638- isframepixel = true;
2639- }
2640-
2641- return isframepixel;
2642+void draw_view_window(const Map& map,
2643+ const Rectf& view_area,
2644+ const MiniMapType minimap_type,
2645+ const bool zoom,
2646+ Texture* texture) {
2647+ const float divider = zoom ? 1.f : 2.f;
2648+ const int half_width =
2649+ round_up_to_nearest_even(std::ceil(view_area.w / kTriangleWidth / divider));
2650+ const int half_height =
2651+ round_up_to_nearest_even(std::ceil(view_area.h / kTriangleHeight / divider));
2652+
2653+ Vector2i center_pixel;
2654+ switch (minimap_type) {
2655+ case MiniMapType::kStaticViewWindow:
2656+ center_pixel = Vector2i(texture->width() / 2, texture->height() / 2);
2657+ break;
2658+
2659+ case MiniMapType::kStaticMap: {
2660+ Vector2f origin = view_area.center();
2661+ MapviewPixelFunctions::normalize_pix(map, &origin);
2662+ center_pixel =
2663+ Vector2i(origin.x / kTriangleWidth, origin.y / kTriangleHeight) * (zoom ? 2 : 1);
2664+ break;
2665+ }
2666+ }
2667+
2668+ const int width = zoom ? map.get_width() * 2 : map.get_width();
2669+ const int height = zoom ? map.get_height() * 2 : map.get_height();
2670+ const auto make_red = [width, height, &texture](int x, int y) {
2671+ if (x < 0) {
2672+ x += width;
2673+ }
2674+ if (x >= width) {
2675+ x -= width;
2676+ }
2677+ if (y < 0) {
2678+ y += height;
2679+ }
2680+ if (y >= height) {
2681+ y -= height;
2682+ }
2683+ texture->set_pixel(x, y, kRed);
2684+ };
2685+
2686+ bool draw = true;
2687+ for (int y = -half_height; y <= half_height; ++y) {
2688+ if (draw) {
2689+ make_red(-half_width + center_pixel.x, y + center_pixel.y);
2690+ make_red(half_width + center_pixel.x, y + center_pixel.y);
2691+ }
2692+ draw = !draw;
2693+ }
2694+
2695+ draw = true;
2696+ for (int x = -half_width; x <= half_width; ++x) {
2697+ if (draw) {
2698+ make_red(x + center_pixel.x, -half_height + center_pixel.y);
2699+ make_red(x + center_pixel.x, half_height + center_pixel.y);
2700+ }
2701+ draw = !draw;
2702+ }
2703 }
2704
2705 // Does the actual work of drawing the minimap.
2706-void draw_minimap_int(Texture* texture,
2707- const Widelands::EditorGameBase& egbase,
2708- const Widelands::Player* player,
2709- const Point& viewpoint,
2710- MiniMapLayer layers) {
2711+void do_draw_minimap(Texture* texture,
2712+ const Widelands::EditorGameBase& egbase,
2713+ const Widelands::Player* player,
2714+ const Vector2i& top_left,
2715+ MiniMapLayer layers) {
2716 const Widelands::Map& map = egbase.map();
2717-
2718 const uint16_t surface_h = texture->height();
2719 const uint16_t surface_w = texture->width();
2720-
2721- // size of the display frame
2722- int32_t xsize = g_gr->get_xres() / kTriangleWidth / 2;
2723- int32_t ysize = g_gr->get_yres() / kTriangleHeight / 2;
2724-
2725 const int32_t mapwidth = egbase.get_map().get_width();
2726- const int32_t mapheight = map.get_height();
2727-
2728- Point ptopleft; // top left point of the current display frame
2729- ptopleft.x = viewpoint.x + mapwidth / 2 - xsize;
2730- if (ptopleft.x < 0) {
2731- ptopleft.x += mapwidth;
2732- }
2733- ptopleft.y = viewpoint.y + mapheight / 2 - ysize;
2734- if (ptopleft.y < 0) {
2735- ptopleft.y += mapheight;
2736- }
2737-
2738- Point pbottomright; // bottom right point of the current display frame
2739- pbottomright.x = viewpoint.x + mapwidth / 2 + xsize;
2740- if (pbottomright.x >= mapwidth) {
2741- pbottomright.x -= mapwidth;
2742- }
2743- pbottomright.y = viewpoint.y + mapheight / 2 + ysize;
2744- if (pbottomright.y >= mapheight) {
2745- pbottomright.y -= mapheight;
2746- }
2747-
2748- uint32_t modx = pbottomright.x % 2;
2749- uint32_t mody = pbottomright.y % 2;
2750
2751 for (uint32_t y = 0; y < surface_h; ++y) {
2752 Widelands::FCoords f(
2753- Widelands::Coords(viewpoint.x, viewpoint.y + (layers & MiniMapLayer::Zoom2 ? y / 2 : y)));
2754+ Widelands::Coords(top_left.x, top_left.y + (layers & MiniMapLayer::Zoom2 ? y / 2 : y)));
2755 map.normalize_coords(f);
2756 f.field = &map[f];
2757 Widelands::MapIndex i = Widelands::Map::get_index(f, mapwidth);
2758@@ -170,30 +171,26 @@
2759 move_r(mapwidth, f, i);
2760 }
2761
2762- RGBColor pixel_color;
2763- if ((layers & MiniMapLayer::ViewWindow) &&
2764- is_minimap_frameborder(f, ptopleft, pbottomright, mapwidth, mapheight, modx, mody)) {
2765- pixel_color = RGBColor(255, 0, 0);
2766- } else {
2767- uint16_t vision =
2768- 0; // See Player::Field::Vision: 1 if seen once, > 1 if seen right now.
2769- Widelands::PlayerNumber owner = 0;
2770- if (player == nullptr || player->see_all()) {
2771- vision = 2; // Seen right now.
2772- owner = f.field->get_owned_by();
2773- } else if (player != nullptr) {
2774- const auto& field = player->fields()[i];
2775- vision = field.vision;
2776- owner = field.owner;
2777- }
2778-
2779- if (vision > 0) {
2780- pixel_color = calc_minimap_color(egbase, f, layers, owner, vision > 1);
2781- }
2782+ uint16_t vision = 0; // See Player::Field::Vision: 1 if seen once, > 1 if seen right now.
2783+ Widelands::PlayerNumber owner = 0;
2784+ if (player == nullptr || player->see_all()) {
2785+ // This player has omnivision - show the field like it is in reality.
2786+ vision = 2; // Seen right now.
2787+ owner = f.field->get_owned_by();
2788+ } else if (player != nullptr) {
2789+ // This player might be affected by fog of war - instead of the
2790+ // reality, we show her what she last saw on this field. If she has
2791+ // vision of this field, this will be the same as reality -
2792+ // otherwise this shows reality as it was the last time she had
2793+ // vision on the field.
2794+ // If she never had vision, field.vision will be 0.
2795+ const auto& field = player->fields()[i];
2796+ vision = field.vision;
2797+ owner = field.owner;
2798 }
2799
2800- if (pixel_color.r != 0 || pixel_color.g != 0 || pixel_color.b != 0) {
2801- texture->set_pixel(x, y, pixel_color);
2802+ if (vision > 0) {
2803+ texture->set_pixel(x, y, calc_minimap_color(egbase, f, layers, owner, vision > 1));
2804 }
2805 }
2806 }
2807@@ -201,12 +198,38 @@
2808
2809 } // namespace
2810
2811+Vector2f minimap_pixel_to_mappixel(const Widelands::Map& map,
2812+ const Vector2i& minimap_pixel,
2813+ const Rectf& view_area,
2814+ MiniMapType minimap_type,
2815+ const bool zoom) {
2816+ Vector2f top_left;
2817+ switch (minimap_type) {
2818+ case MiniMapType::kStaticViewWindow:
2819+ top_left =
2820+ view_area.center() -
2821+ Vector2f(map.get_width() * kTriangleWidth, map.get_height() * kTriangleHeight) / 2.f;
2822+ break;
2823+
2824+ case MiniMapType::kStaticMap:
2825+ top_left = Vector2f(0., 0.);
2826+ break;
2827+ }
2828+
2829+ const float multiplier = zoom ? 2.f : 1.f;
2830+ Vector2f map_pixel = top_left + Vector2f(minimap_pixel.x / multiplier * kTriangleWidth,
2831+ minimap_pixel.y / multiplier * kTriangleHeight);
2832+ MapviewPixelFunctions::normalize_pix(map, &map_pixel);
2833+ return map_pixel;
2834+}
2835+
2836 std::unique_ptr<Texture> draw_minimap(const EditorGameBase& egbase,
2837 const Player* player,
2838- const Point& viewpoint,
2839+ const Rectf& view_area,
2840+ const MiniMapType& minimap_type,
2841 MiniMapLayer layers) {
2842- // TODO(unknown): Currently the minimap is redrawn every frame. That is not really
2843- // necesary. The created texture could be cached and only redrawn two
2844+ // TODO(sirver): Currently the minimap is redrawn every frame. That is not really
2845+ // necessary. The created texture could be cached and only redrawn two
2846 // or three times per second
2847 const Map& map = egbase.map();
2848 const int16_t map_w = (layers & MiniMapLayer::Zoom2) ? map.get_width() * 2 : map.get_width();
2849@@ -214,44 +237,22 @@
2850
2851 std::unique_ptr<Texture> texture(new Texture(map_w, map_h));
2852
2853- texture->fill_rect(Rect(0, 0, texture->width(), texture->height()), RGBAColor(0, 0, 0, 255));
2854+ texture->fill_rect(Rectf(0, 0, texture->width(), texture->height()), RGBAColor(0, 0, 0, 255));
2855+
2856+ // Center the view on the middle of the 'view_area'.
2857+ const bool zoom = layers & MiniMapLayer::Zoom2;
2858+ Vector2f top_left =
2859+ minimap_pixel_to_mappixel(map, Vector2i(0, 0), view_area, minimap_type, zoom);
2860+ const Coords node =
2861+ MapviewPixelFunctions::calc_node_and_triangle(map, top_left.x, top_left.y).node;
2862
2863 texture->lock();
2864- draw_minimap_int(texture.get(), egbase, player, viewpoint, layers);
2865+ do_draw_minimap(texture.get(), egbase, player, Vector2i(node.x, node.y), layers);
2866+
2867+ if (layers & MiniMapLayer::ViewWindow) {
2868+ draw_view_window(map, view_area, minimap_type, zoom, texture.get());
2869+ }
2870 texture->unlock(Texture::Unlock_Update);
2871
2872 return texture;
2873 }
2874-
2875-void write_minimap_image(const EditorGameBase& egbase,
2876- const Player* player,
2877- const Point& gviewpoint,
2878- MiniMapLayer layers,
2879- ::StreamWrite* const streamwrite) {
2880- assert(streamwrite != nullptr);
2881-
2882- Point viewpoint(gviewpoint);
2883-
2884- // map dimension
2885- const int16_t map_w = egbase.get_map().get_width();
2886- const int16_t map_h = egbase.get_map().get_height();
2887- const int32_t maxx = MapviewPixelFunctions::get_map_end_screen_x(egbase.get_map());
2888- const int32_t maxy = MapviewPixelFunctions::get_map_end_screen_y(egbase.get_map());
2889- // adjust the viewpoint top topleft in map coords
2890- viewpoint.x += g_gr->get_xres() / 2;
2891- if (viewpoint.x >= maxx) {
2892- viewpoint.x -= maxx;
2893- }
2894- viewpoint.y += g_gr->get_yres() / 2;
2895- if (viewpoint.y >= maxy) {
2896- viewpoint.y -= maxy;
2897- }
2898- viewpoint.x /= kTriangleWidth;
2899- viewpoint.y /= kTriangleHeight;
2900- viewpoint.x -= map_w / 2;
2901- viewpoint.y -= map_h / 2;
2902-
2903- // Render minimap
2904- std::unique_ptr<Texture> texture(draw_minimap(egbase, player, viewpoint, layers));
2905- save_to_png(texture.get(), streamwrite, ColorType::RGBA);
2906-}
2907
2908=== modified file 'src/graphic/minimap_renderer.h'
2909--- src/graphic/minimap_renderer.h 2016-08-04 15:49:05 +0000
2910+++ src/graphic/minimap_renderer.h 2016-10-24 20:07:47 +0000
2911@@ -22,15 +22,12 @@
2912
2913 #include <memory>
2914
2915-#include "base/point.h"
2916-
2917-class StreamWrite;
2918-class Texture;
2919-
2920-namespace Widelands {
2921-class Player;
2922-class EditorGameBase;
2923-}
2924+#include "base/rect.h"
2925+#include "base/vector.h"
2926+#include "graphic/texture.h"
2927+#include "logic/editor_game_base.h"
2928+#include "logic/map.h"
2929+#include "logic/player.h"
2930
2931 // Layers for selecting what do display on the minimap.
2932 enum class MiniMapLayer {
2933@@ -54,20 +51,31 @@
2934 return MiniMapLayer(static_cast<int>(left) ^ static_cast<int>(right));
2935 }
2936
2937-/// Render the minimap. If player is not nullptr, it renders from that player's
2938-/// point of view.
2939-/// \param viewpoint top left corner in map coordinates
2940+enum class MiniMapType {
2941+ // Keep the view window always in the center of the minimap and pan the underlying map.
2942+ kStaticViewWindow,
2943+
2944+ // Always align the map at (0, 0) and move the view window instead.
2945+ kStaticMap,
2946+};
2947+
2948+// Converts between minimap pixel and map pixel.
2949+// Remember to call 'normalize_pix' after applying the transformation.
2950+Vector2f minimap_pixel_to_mappixel(const Widelands::Map& map,
2951+ const Vector2i& minimap_pixel,
2952+ const Rectf& view_area,
2953+ MiniMapType minimap_type,
2954+ const bool zoom);
2955+
2956+// Render the minimap. If player is not nullptr, it renders from that player's
2957+// point of view. The 'view_area' designates the currently visible area in the
2958+// main view in map pixel coordinates and is used to draw the wire frame view
2959+// window. The 'view_point' is map pixel that will be drawn as the top-left
2960+// point in the resulting minimap.
2961 std::unique_ptr<Texture> draw_minimap(const Widelands::EditorGameBase& egbase,
2962 const Widelands::Player* player,
2963- const Point& viewpoint,
2964+ const Rectf& view_area,
2965+ const MiniMapType& map_draw_type,
2966 MiniMapLayer layers);
2967
2968-/// Render the minimap to a file. 1 pixel will be used for each fields.
2969-/// \param viewpoint : The game point of view as returned by interactive_base.get_viewpoint();
2970-void write_minimap_image(const Widelands::EditorGameBase& egbase,
2971- Widelands::Player const* player,
2972- const Point& viewpoint,
2973- MiniMapLayer layers,
2974- StreamWrite* const streamwrite);
2975-
2976 #endif // end of include guard: WL_GRAPHIC_MINIMAP_RENDERER_H
2977
2978=== modified file 'src/graphic/render_queue.cc'
2979--- src/graphic/render_queue.cc 2016-08-04 15:49:05 +0000
2980+++ src/graphic/render_queue.cc 2016-10-24 20:07:47 +0000
2981@@ -120,14 +120,14 @@
2982 // creation. Disables GL_SCISSOR_TEST at desctruction again.
2983 class ScopedScissor {
2984 public:
2985- ScopedScissor(const FloatRect& rect);
2986+ ScopedScissor(const Rectf& rect);
2987 ~ScopedScissor();
2988
2989 private:
2990 DISALLOW_COPY_AND_ASSIGN(ScopedScissor);
2991 };
2992
2993-ScopedScissor::ScopedScissor(const FloatRect& rect) {
2994+ScopedScissor::ScopedScissor(const Rectf& rect) {
2995 glScissor(rect.x, rect.y, rect.w, rect.h);
2996 glEnable(GL_SCISSOR_TEST);
2997 }
2998@@ -249,9 +249,10 @@
2999
3000 case Program::kTerrainRoad: {
3001 ScopedScissor scoped_scissor(item.terrain_arguments.destination_rect);
3002- road_program_->draw(
3003- item.terrain_arguments.renderbuffer_width, item.terrain_arguments.renderbuffer_height,
3004- *item.terrain_arguments.fields_to_draw, item.z_value + 2 * kOpenGlZDelta);
3005+ road_program_->draw(item.terrain_arguments.renderbuffer_width,
3006+ item.terrain_arguments.renderbuffer_height,
3007+ *item.terrain_arguments.fields_to_draw, item.terrain_arguments.scale,
3008+ item.z_value + 2 * kOpenGlZDelta);
3009 ++i;
3010 } break;
3011
3012
3013=== modified file 'src/graphic/render_queue.h'
3014--- src/graphic/render_queue.h 2016-08-04 15:49:05 +0000
3015+++ src/graphic/render_queue.h 2016-10-24 20:07:47 +0000
3016@@ -99,12 +99,12 @@
3017 BlitData texture;
3018 BlitData mask;
3019 RGBAColor blend;
3020- FloatRect destination_rect;
3021+ Rectf destination_rect;
3022 };
3023
3024 struct RectArguments {
3025 RGBAColor color;
3026- FloatRect destination_rect;
3027+ Rectf destination_rect;
3028 };
3029
3030 // TODO(sirver): these are really triangle arguments.
3031@@ -121,7 +121,8 @@
3032 int renderbuffer_height;
3033 const DescriptionMaintainer<Widelands::TerrainDescription>* terrains;
3034 FieldsToDraw* fields_to_draw;
3035- FloatRect destination_rect;
3036+ float scale;
3037+ Rectf destination_rect;
3038 };
3039
3040 // The union of all possible program arguments represents an Item that is
3041
3042=== modified file 'src/graphic/rendertarget.cc'
3043--- src/graphic/rendertarget.cc 2016-08-04 15:49:05 +0000
3044+++ src/graphic/rendertarget.cc 2016-10-24 20:07:47 +0000
3045@@ -35,7 +35,7 @@
3046 /**
3047 * Sets an arbitrary drawing window.
3048 */
3049-void RenderTarget::set_window(const Rect& rc, const Point& ofs) {
3050+void RenderTarget::set_window(const Recti& rc, const Vector2i& ofs) {
3051 rect_ = rc;
3052 offset_ = ofs;
3053
3054@@ -69,15 +69,15 @@
3055 * Returns false if the subwindow is invisible. In that case, the window state
3056 * is not changed at all. Otherwise, the function returns true.
3057 */
3058-bool RenderTarget::enter_window(const Rect& rc, Rect* previous, Point* prevofs) {
3059- Rect newrect = rc;
3060-
3061- if (clip(newrect)) {
3062+bool RenderTarget::enter_window(const Recti& rc, Recti* previous, Vector2i* prevofs) {
3063+ Rectf newrect_f = rc.cast<float>();
3064+ if (clip(newrect_f)) {
3065 if (previous)
3066 *previous = rect_;
3067 if (prevofs)
3068 *prevofs = offset_;
3069
3070+ const Recti newrect = newrect_f.cast<int>();
3071 // Apply the changes
3072 offset_ = rc.origin() - (newrect.origin() - rect_.origin() - offset_);
3073 rect_ = newrect;
3074@@ -104,10 +104,10 @@
3075 /**
3076 * This functions draws a line in the target
3077 */
3078-void RenderTarget::draw_line_strip(const std::vector<FloatPoint>& points,
3079+void RenderTarget::draw_line_strip(const std::vector<Vector2f>& points,
3080 const RGBColor& color,
3081 float line_width) {
3082- std::vector<FloatPoint> adjusted_points;
3083+ std::vector<Vector2f> adjusted_points;
3084 adjusted_points.reserve(points.size());
3085 for (const auto& p : points) {
3086 adjusted_points.emplace_back(p.x + offset_.x + rect_.x, p.y + offset_.y + rect_.y);
3087@@ -118,21 +118,21 @@
3088 /**
3089 * Clip against window and pass those primitives along to the bitmap.
3090 */
3091-void RenderTarget::draw_rect(const Rect& rect, const RGBColor& clr) {
3092- Rect r(rect);
3093+void RenderTarget::draw_rect(const Rectf& rect, const RGBColor& clr) {
3094+ Rectf r(rect);
3095 if (clip(r)) {
3096 ::draw_rect(r, clr, surface_);
3097 }
3098 }
3099
3100-void RenderTarget::fill_rect(const Rect& rect, const RGBAColor& clr, BlendMode blend_mode) {
3101- Rect r(rect);
3102+void RenderTarget::fill_rect(const Rectf& rect, const RGBAColor& clr, BlendMode blend_mode) {
3103+ Rectf r(rect);
3104 if (clip(r))
3105 surface_->fill_rect(r, clr, blend_mode);
3106 }
3107
3108-void RenderTarget::brighten_rect(const Rect& rect, int32_t factor) {
3109- Rect r(rect);
3110+void RenderTarget::brighten_rect(const Rectf& rect, int32_t factor) {
3111+ Rectf r(rect);
3112 if (clip(r))
3113 surface_->brighten_rect(r, factor);
3114 }
3115@@ -142,30 +142,32 @@
3116 *
3117 * This blit function copies the pixels to the destination surface.
3118 */
3119-void RenderTarget::blit(const Point& dst,
3120+void RenderTarget::blit(const Vector2f& dst,
3121 const Image* image,
3122 BlendMode blend_mode,
3123 UI::Align align) {
3124- Point destination_point(dst);
3125+ Vector2f destination_point(dst);
3126 UI::correct_for_align(align, image->width(), image->height(), &destination_point);
3127
3128- Rect source_rect(Point(0, 0), image->width(), image->height());
3129- Rect destination_rect(destination_point.x, destination_point.y, source_rect.w, source_rect.h);
3130+ Rectf source_rect(Vector2i(0, 0), image->width(), image->height());
3131+ Rectf destination_rect(destination_point.x, destination_point.y, source_rect.w, source_rect.h);
3132
3133 if (to_surface_geometry(&destination_rect, &source_rect)) {
3134- surface_->blit(destination_rect, *image, source_rect, 1., blend_mode);
3135+ // I seem to remember seeing 1. a lot in blitting calls.
3136+ constexpr float kFullyOpaque = 1.f;
3137+ surface_->blit(destination_rect, *image, source_rect, kFullyOpaque, blend_mode);
3138 }
3139 }
3140
3141-void RenderTarget::blit_monochrome(const Point& dst,
3142+void RenderTarget::blit_monochrome(const Vector2f& dst,
3143 const Image* image,
3144 const RGBAColor& blend_mode,
3145 UI::Align align) {
3146- Point destination_point(dst);
3147+ Vector2f destination_point(dst);
3148 UI::correct_for_align(align, image->width(), image->height(), &destination_point);
3149
3150- Rect source_rect(Point(0, 0), image->width(), image->height());
3151- Rect destination_rect(destination_point.x, destination_point.y, source_rect.w, source_rect.h);
3152+ Rectf source_rect(Vector2i(0, 0), image->width(), image->height());
3153+ Rectf destination_rect(destination_point.x, destination_point.y, source_rect.w, source_rect.h);
3154
3155 if (to_surface_geometry(&destination_rect, &source_rect)) {
3156 surface_->blit_monochrome(destination_rect, *image, source_rect, blend_mode);
3157@@ -175,38 +177,40 @@
3158 /**
3159 * Like \ref blit, but use only a sub-rectangle of the source image.
3160 */
3161-void RenderTarget::blitrect(const Point& dst,
3162+void RenderTarget::blitrect(const Vector2f& dst,
3163 const Image* image,
3164- const Rect& gsrcrc,
3165+ const Recti& gsrcrc,
3166 BlendMode blend_mode) {
3167 assert(0 <= gsrcrc.x);
3168 assert(0 <= gsrcrc.y);
3169
3170 // We want to use the given srcrc, but we must make sure that we are not
3171 // blitting outside of the boundaries of 'image'.
3172- Rect source_rect(gsrcrc.x, gsrcrc.y, std::min<int32_t>(image->width() - gsrcrc.x, gsrcrc.w),
3173- std::min<int32_t>(image->height() - gsrcrc.y, gsrcrc.h));
3174- Rect destination_rect(dst.x, dst.y, source_rect.w, source_rect.h);
3175+ Rectf source_rect(gsrcrc.x, gsrcrc.y, std::min<int32_t>(image->width() - gsrcrc.x, gsrcrc.w),
3176+ std::min<int32_t>(image->height() - gsrcrc.y, gsrcrc.h));
3177+ Rectf destination_rect(dst.x, dst.y, source_rect.w, source_rect.h);
3178
3179 if (to_surface_geometry(&destination_rect, &source_rect)) {
3180 surface_->blit(destination_rect, *image, source_rect, 1., blend_mode);
3181 }
3182 }
3183
3184-void RenderTarget::blitrect_scale(Rect destination_rect,
3185+void RenderTarget::blitrect_scale(Rectf destination_rect,
3186 const Image* image,
3187- Rect source_rect,
3188+ Recti source_rect_i,
3189 const float opacity,
3190 const BlendMode blend_mode) {
3191+ Rectf source_rect = source_rect_i.cast<float>();
3192 if (to_surface_geometry(&destination_rect, &source_rect)) {
3193 surface_->blit(destination_rect, *image, source_rect, opacity, blend_mode);
3194 }
3195 }
3196
3197-void RenderTarget::blitrect_scale_monochrome(Rect destination_rect,
3198+void RenderTarget::blitrect_scale_monochrome(Rectf destination_rect,
3199 const Image* image,
3200- Rect source_rect,
3201+ Recti source_rect_i,
3202 const RGBAColor& blend) {
3203+ Rectf source_rect = source_rect_i.cast<float>();
3204 if (to_surface_geometry(&destination_rect, &source_rect)) {
3205 surface_->blit_monochrome(destination_rect, *image, source_rect, blend);
3206 }
3207@@ -218,15 +222,15 @@
3208 * The pixel from ofs inside image is placed at the top-left corner of
3209 * the filled rectangle.
3210 */
3211-void RenderTarget::tile(const Rect& rect,
3212+void RenderTarget::tile(const Recti& rect,
3213 const Image* image,
3214- const Point& gofs,
3215+ const Vector2i& gofs,
3216 BlendMode blend_mode) {
3217 int32_t srcw = image->width();
3218 int32_t srch = image->height();
3219
3220- Rect r(rect);
3221- Point ofs(gofs);
3222+ Rectf r = rect.cast<float>();
3223+ Vector2i ofs(gofs);
3224 if (clip(r)) {
3225 if (offset_.x < 0)
3226 ofs.x -= offset_.x;
3227@@ -251,7 +255,7 @@
3228 while (ty < r.h) {
3229 int tx = 0;
3230 int32_t tofsx = ofs.x;
3231- Rect srcrc;
3232+ Rectf srcrc;
3233
3234 srcrc.y = ofs.y;
3235 srcrc.h = srch - ofs.y;
3236@@ -266,7 +270,7 @@
3237 if (tx + srcrc.w > r.w)
3238 srcrc.w = r.w - tx;
3239
3240- const Rect dst_rect(r.x + tx, r.y + ty, srcrc.w, srcrc.h);
3241+ const Rectf dst_rect(r.x + tx, r.y + ty, srcrc.w, srcrc.h);
3242 surface_->blit(dst_rect, *image, srcrc, 1., blend_mode);
3243
3244 tx += srcrc.w;
3245@@ -280,54 +284,50 @@
3246 }
3247 }
3248
3249-/**
3250- * Draws a frame of an animation at the given location
3251- * Plays sound effect that is registered with this frame (the SoundHandler
3252- * decides if the sound really does get played)
3253- *
3254- * \param dstx, dsty the on-screen location of the animation hot spot
3255- * \param animation the animation ID
3256- * \param time the time, in milliseconds, in the animation
3257- * \param player the player this object belongs to, for player colour
3258- * purposes. May be 0 (for example, for world objects).
3259- */
3260-// TODO(unknown): Correctly calculate the stereo position for sound effects
3261-// TODO(unknown): The chosen semantics of animation sound effects is problematic:
3262-// What if the game runs very slowly or very quickly?
3263-void RenderTarget::blit_animation(const Point& dst, uint32_t animation, uint32_t time) {
3264+void RenderTarget::blit_animation(const Vector2f& dst,
3265+ const float scale,
3266+ uint32_t animation,
3267+ uint32_t time) {
3268+ // TODO(unknown): Correctly calculate the stereo position for sound effects
3269+ // TODO(unknown): The chosen semantics of animation sound effects is problematic:
3270+ // What if the game runs very slowly or very quickly?
3271 const Animation& anim = g_gr->animations().get_animation(animation);
3272- do_blit_animation(dst, anim, time, nullptr, Rect(Point(0, 0), anim.width(), anim.height()));
3273+ do_blit_animation(
3274+ dst, scale, anim, time, nullptr, Recti(Vector2i(0, 0), anim.width(), anim.height()));
3275 }
3276
3277-void RenderTarget::blit_animation(const Point& dst,
3278+void RenderTarget::blit_animation(const Vector2f& dst,
3279+ const float scale,
3280 uint32_t animation,
3281 uint32_t time,
3282 const RGBColor& player_color) {
3283 const Animation& anim = g_gr->animations().get_animation(animation);
3284 do_blit_animation(
3285- dst, anim, time, &player_color, Rect(Point(0, 0), anim.width(), anim.height()));
3286+ dst, scale, anim, time, &player_color, Recti(Vector2i(0, 0), anim.width(), anim.height()));
3287 }
3288
3289-void RenderTarget::blit_animation(const Point& dst,
3290+void RenderTarget::blit_animation(const Vector2f& dst,
3291+ const float scale,
3292 uint32_t animation,
3293 uint32_t time,
3294 const RGBColor& player_color,
3295- const Rect& source_rect) {
3296+ const Recti& source_rect) {
3297 do_blit_animation(
3298- dst, g_gr->animations().get_animation(animation), time, &player_color, source_rect);
3299+ dst, scale, g_gr->animations().get_animation(animation), time, &player_color, source_rect);
3300 }
3301
3302-void RenderTarget::do_blit_animation(const Point& dst,
3303+void RenderTarget::do_blit_animation(const Vector2f& dst,
3304+ const float scale,
3305 const Animation& animation,
3306 uint32_t time,
3307 const RGBColor* player_color,
3308- const Rect& source_rect) {
3309- Rect destination_rect(dst.x - animation.hotspot().x + source_rect.x,
3310- dst.y - animation.hotspot().y + source_rect.y, source_rect.w,
3311- source_rect.h);
3312- Rect srcrc(source_rect);
3313- if (to_surface_geometry(&destination_rect, &srcrc)) {
3314- animation.blit(time, destination_rect.origin(), srcrc, player_color, surface_);
3315+ const Recti& source_rect_i) {
3316+ Rectf source_rect = source_rect_i.cast<float>();
3317+ Rectf destination_rect(dst.x - (animation.hotspot().x - source_rect.x) * scale,
3318+ dst.y - (animation.hotspot().y - source_rect.y) * scale,
3319+ source_rect.w * scale, source_rect.h * scale);
3320+ if (to_surface_geometry(&destination_rect, &source_rect)) {
3321+ animation.blit(time, destination_rect, source_rect, player_color, surface_);
3322 }
3323
3324 // Look if there is a sound effect registered for this frame and trigger the
3325@@ -355,7 +355,7 @@
3326 * If true is returned, r a valid rectangle that can be used.
3327 * If false is returned, r may not be used and may be partially modified.
3328 */
3329-bool RenderTarget::clip(Rect& r) const {
3330+bool RenderTarget::clip(Rectf& r) const {
3331 r.x += offset_.x;
3332 r.y += offset_.y;
3333
3334@@ -397,7 +397,7 @@
3335 * Clip against window and source bitmap, returns false if blitting is
3336 * unnecessary because image is not inside the target surface.
3337 */
3338-bool RenderTarget::to_surface_geometry(Rect* destination_rect, Rect* source_rect) const {
3339+bool RenderTarget::to_surface_geometry(Rectf* destination_rect, Rectf* source_rect) const {
3340 assert(0 <= source_rect->x);
3341 assert(0 <= source_rect->y);
3342 destination_rect->x += offset_.x;
3343@@ -409,17 +409,16 @@
3344 // destination_rect, we do this by making the proportional change.
3345
3346 // Clipping, from the left.
3347- if (destination_rect->x < 0) {
3348+ if (destination_rect->x < 0.f) {
3349 if (destination_rect->w <= -destination_rect->x) {
3350 return false;
3351 }
3352- // Adding 0.5 is a cheap way of turning integer truncation into a rounded value.
3353- const int source_rect_pixel_change =
3354- 0.5 + -static_cast<double>(destination_rect->x) / destination_rect->w * source_rect->w;
3355+ const float source_rect_pixel_change =
3356+ -destination_rect->x / destination_rect->w * source_rect->w;
3357 source_rect->x += source_rect_pixel_change;
3358 source_rect->w -= source_rect_pixel_change;
3359 destination_rect->w += destination_rect->x;
3360- destination_rect->x = 0;
3361+ destination_rect->x = 0.f;
3362 }
3363
3364 // Clipping, from the right.
3365@@ -427,25 +426,22 @@
3366 if (rect_.w <= destination_rect->x) {
3367 return false;
3368 }
3369- const int new_destination_w = rect_.w - destination_rect->x;
3370- // Adding 0.5 is a cheap way of turning integer truncation into a rounded value.
3371- source_rect->w =
3372- 0.5 + static_cast<double>(new_destination_w) / destination_rect->w * source_rect->w;
3373+ const float new_destination_w = rect_.w - destination_rect->x;
3374+ source_rect->w = new_destination_w / destination_rect->w * source_rect->w;
3375 destination_rect->w = new_destination_w;
3376 }
3377
3378 // Clipping, from the top.
3379- if (destination_rect->y < 0) {
3380+ if (destination_rect->y < 0.f) {
3381 if (destination_rect->h <= -destination_rect->y) {
3382 return false;
3383 }
3384- // Adding 0.5 is a cheap way of turning integer truncation into a rounded value.
3385- const int source_rect_pixel_change =
3386- 0.5 + -static_cast<double>(destination_rect->y) / destination_rect->h * source_rect->h;
3387+ const float source_rect_pixel_change =
3388+ -destination_rect->y / destination_rect->h * source_rect->h;
3389 source_rect->y += source_rect_pixel_change;
3390 source_rect->h -= source_rect_pixel_change;
3391 destination_rect->h += destination_rect->y;
3392- destination_rect->y = 0;
3393+ destination_rect->y = 0.f;
3394 }
3395
3396 // Clipping, from the bottom.
3397@@ -453,13 +449,10 @@
3398 if (rect_.h <= destination_rect->y) {
3399 return false;
3400 }
3401- const int new_destination_h = rect_.h - destination_rect->y;
3402- // Adding 0.5 is a cheap way of turning integer truncation into a rounded value.
3403- source_rect->h =
3404- 0.5 + static_cast<double>(new_destination_h) / destination_rect->h * source_rect->h;
3405+ const float new_destination_h = rect_.h - destination_rect->y;
3406+ source_rect->h = new_destination_h / destination_rect->h * source_rect->h;
3407 destination_rect->h = new_destination_h;
3408 }
3409-
3410 destination_rect->x += rect_.x;
3411 destination_rect->y += rect_.y;
3412 return true;
3413
3414=== modified file 'src/graphic/rendertarget.h'
3415--- src/graphic/rendertarget.h 2016-08-04 15:49:05 +0000
3416+++ src/graphic/rendertarget.h 2016-10-24 20:07:47 +0000
3417@@ -51,31 +51,31 @@
3418 class RenderTarget {
3419 public:
3420 RenderTarget(Surface*);
3421- void set_window(const Rect& rc, const Point& ofs);
3422- bool enter_window(const Rect& rc, Rect* previous, Point* prevofs);
3423+ void set_window(const Recti& rc, const Vector2i& ofs);
3424+ bool enter_window(const Recti& rc, Recti* previous, Vector2i* prevofs);
3425
3426 int32_t width() const;
3427 int32_t height() const;
3428
3429- void draw_line_strip(const std::vector<FloatPoint>& points, const RGBColor& color, float width);
3430- void draw_rect(const Rect&, const RGBColor&);
3431- void fill_rect(const Rect&, const RGBAColor&, BlendMode blend_mode = BlendMode::Copy);
3432- void brighten_rect(const Rect&, int32_t factor);
3433+ void draw_line_strip(const std::vector<Vector2f>& points, const RGBColor& color, float width);
3434+ void draw_rect(const Rectf&, const RGBColor&);
3435+ void fill_rect(const Rectf&, const RGBAColor&, BlendMode blend_mode = BlendMode::Copy);
3436+ void brighten_rect(const Rectf&, int32_t factor);
3437
3438- void blit(const Point& dst,
3439+ void blit(const Vector2f& dst,
3440 const Image* image,
3441 BlendMode blend_mode = BlendMode::UseAlpha,
3442 UI::Align = UI::Align::kTopLeft);
3443
3444 // Like blit. See MonochromeBlitProgram for details.
3445- void blit_monochrome(const Point& dst,
3446+ void blit_monochrome(const Vector2f& dst,
3447 const Image* image,
3448 const RGBAColor& blend_mode,
3449 UI::Align = UI::Align::kTopLeft);
3450
3451- void blitrect(const Point& dst,
3452+ void blitrect(const Vector2f& dst,
3453 const Image* image,
3454- const Rect& src,
3455+ const Recti& src,
3456 BlendMode blend_mode = BlendMode::UseAlpha);
3457
3458 // Blits the 'source_rect' from 'image' into the
3459@@ -83,68 +83,71 @@
3460 // multiplied with 'opacity' before blitting. The 'blend_mode'
3461 // defines if values are blended with whats already there or just
3462 // copied over.
3463- // Rect's are taken by value on purpose.
3464- void blitrect_scale(Rect destination_rect,
3465+ // Takes by value on purpose.
3466+ void blitrect_scale(Rectf destination_rect,
3467 const Image* image,
3468- Rect source_rect,
3469+ Recti source_rect,
3470 float opacity,
3471 BlendMode blend_mode);
3472
3473- // Like blitrect_scale. See MonochromeBlitProgram for details. Rect's are
3474- // taken by value on purpose.
3475- void blitrect_scale_monochrome(Rect destination_rect,
3476+ // Like blitrect_scale. See MonochromeBlitProgram for details. Takes by
3477+ // value on purpose.
3478+ void blitrect_scale_monochrome(Rectf destination_rect,
3479 const Image* image,
3480- Rect source_rect,
3481+ Recti source_rect,
3482 const RGBAColor& blend);
3483
3484- void tile(const Rect&,
3485+ void tile(const Recti&,
3486 const Image* image,
3487- const Point& ofs,
3488+ const Vector2i& ofs,
3489 BlendMode blend_mode = BlendMode::UseAlpha);
3490
3491- // Draw the 'animation' as it should appear at 'time' in this target at 'dst'. Optionally, the
3492- // animation is
3493- // tinted with 'player_color' and cropped to 'source_rect'.
3494- void blit_animation(const Point& dst, uint32_t animation, uint32_t time);
3495- void blit_animation(const Point& dst,
3496+ // Draw the 'animation' as it should appear at 'time' in this target at
3497+ // 'dst'. Optionally, the animation is tinted with 'player_color' and
3498+ // cropped to 'source_rect'.
3499+ void blit_animation(const Vector2f& dst, float scale, uint32_t animation, uint32_t time);
3500+ void blit_animation(const Vector2f& dst,
3501+ float scale,
3502 uint32_t animation,
3503 uint32_t time,
3504 const RGBColor& player_color);
3505- void blit_animation(const Point& dst,
3506+ void blit_animation(const Vector2f& dst,
3507+ float scale,
3508 uint32_t animation,
3509 uint32_t time,
3510 const RGBColor& player_color,
3511- const Rect& source_rect);
3512+ const Recti& source_rect);
3513
3514 void reset();
3515
3516 Surface* get_surface() const {
3517 return surface_;
3518 }
3519- const Rect& get_rect() const {
3520+ const Recti& get_rect() const {
3521 return rect_;
3522 }
3523- const Point& get_offset() const {
3524+ const Vector2i& get_offset() const {
3525 return offset_;
3526 }
3527
3528 protected:
3529- bool clip(Rect& r) const;
3530- bool to_surface_geometry(Rect* destination_rect, Rect* source_rect) const;
3531+ bool clip(Rectf& r) const;
3532+ bool to_surface_geometry(Rectf* destination_rect, Rectf* source_rect) const;
3533
3534 // Does the actual blitting.
3535- void do_blit_animation(const Point& dst,
3536+ void do_blit_animation(const Vector2f& dst,
3537+ const float scale,
3538 const Animation& animation,
3539 uint32_t time,
3540 const RGBColor* player_color,
3541- const Rect& source_rect);
3542+ const Recti& source_rect);
3543
3544 /// The target surface
3545 Surface* surface_;
3546 /// The current clip rectangle
3547- Rect rect_;
3548+ Recti rect_;
3549 /// Drawing offset
3550- Point offset_;
3551+ Vector2i offset_;
3552 };
3553
3554 #endif // end of include guard: WL_GRAPHIC_RENDERTARGET_H
3555
3556=== modified file 'src/graphic/richtext.cc'
3557--- src/graphic/richtext.cc 2016-08-04 16:24:09 +0000
3558+++ src/graphic/richtext.cc 2016-10-24 20:07:47 +0000
3559@@ -41,7 +41,7 @@
3560 * rectangular bounding box.
3561 */
3562 struct Element {
3563- explicit Element(const Rect& bounding_box) : bbox(bounding_box) {
3564+ explicit Element(const Recti& bounding_box) : bbox(bounding_box) {
3565 }
3566 virtual ~Element() {
3567 }
3568@@ -52,23 +52,23 @@
3569 */
3570 virtual void draw(RenderTarget& dst) = 0;
3571
3572- Rect bbox;
3573+ Recti bbox;
3574 };
3575
3576 struct ImageElement : Element {
3577- ImageElement(const Rect& bounding_box, const Image* init_image)
3578+ ImageElement(const Recti& bounding_box, const Image* init_image)
3579 : Element(bounding_box), image(init_image) {
3580 }
3581
3582 void draw(RenderTarget& dst) override {
3583- dst.blit(Point(0, 0), image);
3584+ dst.blit(Vector2f(0, 0), image);
3585 }
3586
3587 const Image* image;
3588 };
3589
3590 struct TextlineElement : Element {
3591- TextlineElement(const Rect& bounding_box,
3592+ TextlineElement(const Recti& bounding_box,
3593 const TextStyle& init_style,
3594 std::vector<std::string>::const_iterator words_begin,
3595 std::vector<std::string>::const_iterator words_end)
3596@@ -107,16 +107,16 @@
3597 }
3598 }
3599 // Now render
3600- uint32_t x = g_fh->draw_text_raw(dst, style, Point(0, 0), result_words[0]);
3601+ uint32_t x = g_fh->draw_text_raw(dst, style, Vector2i(0, 0), result_words[0]);
3602
3603 it = result_words.begin() + 1;
3604 if (it != result_words.end()) {
3605 do {
3606 if (style.underline)
3607- x += g_fh->draw_text_raw(dst, style, Point(x, 0), " ");
3608+ x += g_fh->draw_text_raw(dst, style, Vector2i(x, 0), " ");
3609 else
3610 x += spacewidth;
3611- x += g_fh->draw_text_raw(dst, style, Point(x, 0), *it++);
3612+ x += g_fh->draw_text_raw(dst, style, Vector2i(x, 0), *it++);
3613 } while (it != result_words.end());
3614 }
3615 }
3616@@ -357,7 +357,7 @@
3617 if (!image)
3618 continue;
3619
3620- Rect bbox;
3621+ Recti bbox;
3622 bbox.x = text.images_width;
3623 bbox.y = m->height;
3624 bbox.w = image->width();
3625@@ -423,7 +423,7 @@
3626 TextBuilder::Elt elt;
3627 elt.miny = elt.maxy = 0;
3628
3629- Rect bbox;
3630+ Recti bbox;
3631 bbox.x = text.linewidth ? text.linewidth + text.spacewidth : 0;
3632 bbox.y = 0; // filled in later
3633 bbox.w = 0;
3634@@ -486,16 +486,16 @@
3635 * @note this function may draw content outside the box given offset
3636 * and @ref width and @ref height, if there were wrapping problems.
3637 */
3638-void RichText::draw(RenderTarget& dst, const Point& offset, bool background) {
3639+void RichText::draw(RenderTarget& dst, const Vector2i& offset, bool background) {
3640 for (std::vector<Element*>::const_iterator elt = m->elements.begin(); elt != m->elements.end();
3641 ++elt) {
3642- Rect oldbox;
3643- Point oldofs;
3644- Rect bbox((*elt)->bbox.origin() + offset, (*elt)->bbox.w, (*elt)->bbox.h);
3645+ Recti oldbox;
3646+ Vector2i oldofs;
3647+ Recti bbox((*elt)->bbox.origin() + offset, (*elt)->bbox.w, (*elt)->bbox.h);
3648
3649 if (dst.enter_window(bbox, &oldbox, &oldofs)) {
3650 if (background)
3651- dst.fill_rect(Rect(Point(0, 0), bbox.w, bbox.h), m->background_color);
3652+ dst.fill_rect(Rectf(0.f, 0.f, bbox.w, bbox.h), m->background_color);
3653 (*elt)->draw(dst);
3654 dst.set_window(oldbox, oldofs);
3655 }
3656
3657=== modified file 'src/graphic/richtext.h'
3658--- src/graphic/richtext.h 2016-08-04 15:49:05 +0000
3659+++ src/graphic/richtext.h 2016-10-24 20:07:47 +0000
3660@@ -24,7 +24,7 @@
3661 #include <memory>
3662 #include <string>
3663
3664-#include "base/point.h"
3665+#include "base/vector.h"
3666 #include "graphic/color.h"
3667
3668 class RenderTarget;
3669@@ -50,7 +50,7 @@
3670 uint32_t height();
3671
3672 void parse(const std::string& text);
3673- void draw(RenderTarget& dst, const Point& offset, bool background = false);
3674+ void draw(RenderTarget& dst, const Vector2i& offset, bool background = false);
3675
3676 private:
3677 std::unique_ptr<RichTextImpl> m;
3678
3679=== modified file 'src/graphic/screen.cc'
3680--- src/graphic/screen.cc 2016-08-04 15:49:05 +0000
3681+++ src/graphic/screen.cc 2016-10-24 20:07:47 +0000
3682@@ -53,7 +53,7 @@
3683 return std::unique_ptr<Texture>(new Texture(surface));
3684 }
3685
3686-void Screen::do_blit(const FloatRect& dst_rect,
3687+void Screen::do_blit(const Rectf& dst_rect,
3688 const BlitData& texture,
3689 float opacity,
3690 BlendMode blend_mode) {
3691@@ -68,7 +68,7 @@
3692 RenderQueue::instance().enqueue(i);
3693 }
3694
3695-void Screen::do_blit_blended(const FloatRect& dst_rect,
3696+void Screen::do_blit_blended(const Rectf& dst_rect,
3697 const BlitData& texture,
3698 const BlitData& mask,
3699 const RGBColor& blend) {
3700@@ -83,7 +83,7 @@
3701 RenderQueue::instance().enqueue(i);
3702 }
3703
3704-void Screen::do_blit_monochrome(const FloatRect& dst_rect,
3705+void Screen::do_blit_monochrome(const Rectf& dst_rect,
3706 const BlitData& texture,
3707 const RGBAColor& blend) {
3708 RenderQueue::Item i;
3709@@ -105,7 +105,7 @@
3710 RenderQueue::instance().enqueue(i);
3711 }
3712
3713-void Screen::do_fill_rect(const FloatRect& dst_rect, const RGBAColor& color, BlendMode blend_mode) {
3714+void Screen::do_fill_rect(const Rectf& dst_rect, const RGBAColor& color, BlendMode blend_mode) {
3715 RenderQueue::Item i;
3716 i.blend_mode = blend_mode;
3717 i.program_id = RenderQueue::Program::kRect;
3718
3719=== modified file 'src/graphic/screen.h'
3720--- src/graphic/screen.h 2016-08-04 15:49:05 +0000
3721+++ src/graphic/screen.h 2016-10-24 20:07:47 +0000
3722@@ -43,20 +43,20 @@
3723 std::unique_ptr<Texture> to_texture() const;
3724
3725 private:
3726- void do_blit(const FloatRect& dst_rect,
3727+ void do_blit(const Rectf& dst_rect,
3728 const BlitData& texture,
3729 float opacity,
3730 BlendMode blend_mode) override;
3731- void do_blit_blended(const FloatRect& dst_rect,
3732+ void do_blit_blended(const Rectf& dst_rect,
3733 const BlitData& texture,
3734 const BlitData& mask,
3735 const RGBColor& blend) override;
3736- void do_blit_monochrome(const FloatRect& dst_rect,
3737+ void do_blit_monochrome(const Rectf& dst_rect,
3738 const BlitData& texture,
3739 const RGBAColor& blend) override;
3740 void do_draw_line_strip(std::vector<DrawLineProgram::PerVertexData> vertices) override;
3741 void
3742- do_fill_rect(const FloatRect& dst_rect, const RGBAColor& color, BlendMode blend_mode) override;
3743+ do_fill_rect(const Rectf& dst_rect, const RGBAColor& color, BlendMode blend_mode) override;
3744
3745 const int w_, h_;
3746
3747
3748=== modified file 'src/graphic/surface.cc'
3749--- src/graphic/surface.cc 2016-08-04 15:49:05 +0000
3750+++ src/graphic/surface.cc 2016-10-24 20:07:47 +0000
3751@@ -26,15 +26,15 @@
3752 #include <SDL.h>
3753
3754 #include "base/macros.h"
3755-#include "base/point.h"
3756 #include "base/rect.h"
3757+#include "base/vector.h"
3758 #include "graphic/gl/coordinate_conversion.h"
3759 #include "graphic/gl/utils.h"
3760
3761 namespace {
3762
3763 // Adjust 'original' so that only 'src_rect' is actually blitted.
3764-BlitData adjust_for_src(BlitData blit_data, const Rect& src_rect) {
3765+BlitData adjust_for_src(BlitData blit_data, const Rectf& src_rect) {
3766 blit_data.rect.x += src_rect.x;
3767 blit_data.rect.y += src_rect.y;
3768 blit_data.rect.w = src_rect.w;
3769@@ -44,11 +44,11 @@
3770
3771 // Get the normal of the line between 'start' and 'end'.
3772 template <typename PointType>
3773-FloatPoint calculate_line_normal(const PointType& start, const PointType& end) {
3774+Vector2f calculate_line_normal(const PointType& start, const PointType& end) {
3775 const float dx = end.x - start.x;
3776 const float dy = end.y - start.y;
3777 const float len = std::hypot(dx, dy);
3778- return FloatPoint(-dy / len, dx / len);
3779+ return Vector2f(-dy / len, dx / len);
3780 }
3781
3782 // Tesselates the line made up of 'points' ino triangles and converts them into
3783@@ -60,7 +60,7 @@
3784 int h,
3785 const RGBColor& color,
3786 float line_width,
3787- const std::vector<FloatPoint>& points,
3788+ const std::vector<Vector2f>& points,
3789 std::vector<DrawLineProgram::PerVertexData>* vertices) {
3790 const float r = color.r / 255.;
3791 const float g = color.g / 255.;
3792@@ -69,27 +69,27 @@
3793 // Iterate over each line segment, i.e. all points but the last, convert
3794 // them from pixel space to gl space and draw them.
3795 for (size_t i = 0; i < points.size() - 1; ++i) {
3796- const FloatPoint p1 = FloatPoint(points[i].x, points[i].y);
3797- const FloatPoint p2 = FloatPoint(points[i + 1].x, points[i + 1].y);
3798+ const Vector2f p1 = Vector2f(points[i].x, points[i].y);
3799+ const Vector2f p2 = Vector2f(points[i + 1].x, points[i + 1].y);
3800
3801- const FloatPoint normal = calculate_line_normal(p1, p2);
3802- const FloatPoint scaled_normal(0.5f * line_width * normal.x, 0.5f * line_width * normal.y);
3803+ const Vector2f normal = calculate_line_normal(p1, p2);
3804+ const Vector2f scaled_normal(0.5f * line_width * normal.x, 0.5f * line_width * normal.y);
3805
3806 // Quad points are created in rendering order for OpenGL.
3807 {
3808- FloatPoint p = p1 - scaled_normal;
3809- pixel_to_gl_renderbuffer(w, h, &p.x, &p.y);
3810- vertices->emplace_back(DrawLineProgram::PerVertexData{p.x, p.y, 0.f, r, g, b, 1.});
3811- }
3812-
3813- {
3814- FloatPoint p = p2 - scaled_normal;
3815- pixel_to_gl_renderbuffer(w, h, &p.x, &p.y);
3816- vertices->emplace_back(DrawLineProgram::PerVertexData{p.x, p.y, 0.f, r, g, b, 1.});
3817- }
3818-
3819- {
3820- FloatPoint p = p1 + scaled_normal;
3821+ Vector2f p = p1 - scaled_normal;
3822+ pixel_to_gl_renderbuffer(w, h, &p.x, &p.y);
3823+ vertices->emplace_back(DrawLineProgram::PerVertexData{p.x, p.y, 0.f, r, g, b, 1.});
3824+ }
3825+
3826+ {
3827+ Vector2f p = p2 - scaled_normal;
3828+ pixel_to_gl_renderbuffer(w, h, &p.x, &p.y);
3829+ vertices->emplace_back(DrawLineProgram::PerVertexData{p.x, p.y, 0.f, r, g, b, 1.});
3830+ }
3831+
3832+ {
3833+ Vector2f p = p1 + scaled_normal;
3834 pixel_to_gl_renderbuffer(w, h, &p.x, &p.y);
3835 vertices->emplace_back(DrawLineProgram::PerVertexData{p.x, p.y, 0.f, r, g, b, -1.});
3836 }
3837@@ -98,7 +98,7 @@
3838 vertices->push_back(vertices->at(vertices->size() - 2));
3839
3840 {
3841- FloatPoint p = p2 + scaled_normal;
3842+ Vector2f p = p2 + scaled_normal;
3843 pixel_to_gl_renderbuffer(w, h, &p.x, &p.y);
3844 vertices->emplace_back(DrawLineProgram::PerVertexData{p.x, p.y, 0.f, r, g, b, -1.});
3845 }
3846@@ -107,12 +107,12 @@
3847
3848 } // namespace
3849
3850-void Surface::fill_rect(const Rect& rc, const RGBAColor& clr, BlendMode blend_mode) {
3851- const FloatRect rect = rect_to_gl_renderbuffer(width(), height(), rc);
3852+void Surface::fill_rect(const Rectf& rc, const RGBAColor& clr, BlendMode blend_mode) {
3853+ const Rectf rect = rect_to_gl_renderbuffer(width(), height(), rc);
3854 do_fill_rect(rect, clr, blend_mode);
3855 }
3856
3857-void Surface::brighten_rect(const Rect& rc, const int32_t factor) {
3858+void Surface::brighten_rect(const Rectf& rc, const int32_t factor) {
3859 if (!factor) {
3860 return;
3861 }
3862@@ -120,11 +120,11 @@
3863 const BlendMode blend_mode = factor < 0 ? BlendMode::Subtract : BlendMode::UseAlpha;
3864 const int abs_factor = std::abs(factor);
3865 const RGBAColor color(abs_factor, abs_factor, abs_factor, 0);
3866- const FloatRect rect = rect_to_gl_renderbuffer(width(), height(), rc);
3867+ const Rectf rect = rect_to_gl_renderbuffer(width(), height(), rc);
3868 do_fill_rect(rect, color, blend_mode);
3869 }
3870
3871-void Surface::draw_line_strip(std::vector<FloatPoint> points,
3872+void Surface::draw_line_strip(std::vector<Vector2f> points,
3873 const RGBColor& color,
3874 float line_width) {
3875 if (points.size() < 2) {
3876@@ -138,41 +138,41 @@
3877 do_draw_line_strip(std::move(vertices));
3878 }
3879
3880-void Surface::blit_monochrome(const Rect& dst_rect,
3881+void Surface::blit_monochrome(const Rectf& dst_rect,
3882 const Image& image,
3883- const Rect& src_rect,
3884+ const Rectf& src_rect,
3885 const RGBAColor& blend) {
3886- const FloatRect rect = rect_to_gl_renderbuffer(width(), height(), dst_rect);
3887+ const Rectf rect = rect_to_gl_renderbuffer(width(), height(), dst_rect);
3888 do_blit_monochrome(rect, adjust_for_src(image.blit_data(), src_rect), blend);
3889 }
3890
3891-void Surface::blit_blended(const Rect& dst_rect,
3892+void Surface::blit_blended(const Rectf& dst_rect,
3893 const Image& image,
3894 const Image& texture_mask,
3895- const Rect& src_rect,
3896+ const Rectf& src_rect,
3897 const RGBColor& blend) {
3898- const FloatRect rect = rect_to_gl_renderbuffer(width(), height(), dst_rect);
3899+ const Rectf rect = rect_to_gl_renderbuffer(width(), height(), dst_rect);
3900 do_blit_blended(rect, adjust_for_src(image.blit_data(), src_rect),
3901 adjust_for_src(texture_mask.blit_data(), src_rect), blend);
3902 }
3903
3904-void Surface::blit(const Rect& dst_rect,
3905+void Surface::blit(const Rectf& dst_rect,
3906 const Image& image,
3907- const Rect& src_rect,
3908+ const Rectf& src_rect,
3909 float opacity,
3910 BlendMode blend_mode) {
3911- const FloatRect rect = rect_to_gl_renderbuffer(width(), height(), dst_rect);
3912+ const Rectf rect = rect_to_gl_renderbuffer(width(), height(), dst_rect);
3913 do_blit(rect, adjust_for_src(image.blit_data(), src_rect), opacity, blend_mode);
3914 }
3915
3916-void draw_rect(const Rect& rc, const RGBColor& clr, Surface* surface) {
3917- const FloatPoint top_left = FloatPoint(rc.x + 0.5f, rc.y + 0.5f);
3918- const FloatPoint top_right = FloatPoint(rc.x + rc.w - 0.5f, rc.y + 0.5f);
3919- const FloatPoint bottom_right = FloatPoint(rc.x + rc.w - 0.5f, rc.y + rc.h - 0.5f);
3920- const FloatPoint bottom_left = FloatPoint(rc.x + 0.5f, rc.y + rc.h - 0.5f);
3921+void draw_rect(const Rectf& rc, const RGBColor& clr, Surface* surface) {
3922+ const Vector2f top_left = Vector2f(rc.x + 0.5f, rc.y + 0.5f);
3923+ const Vector2f top_right = Vector2f(rc.x + rc.w - 0.5f, rc.y + 0.5f);
3924+ const Vector2f bottom_right = Vector2f(rc.x + rc.w - 0.5f, rc.y + rc.h - 0.5f);
3925+ const Vector2f bottom_left = Vector2f(rc.x + 0.5f, rc.y + rc.h - 0.5f);
3926
3927 surface->draw_line_strip({top_left, top_right, bottom_right}, clr, 1);
3928 // We need to split this up in order not to miss a pixel on the bottom right corner.
3929 surface->draw_line_strip(
3930- {FloatPoint(bottom_right.x + 1, bottom_right.y), bottom_left, top_left}, clr, 1);
3931+ {Vector2f(bottom_right.x + 1, bottom_right.y), bottom_left, top_left}, clr, 1);
3932 }
3933
3934=== modified file 'src/graphic/surface.h'
3935--- src/graphic/surface.h 2016-08-04 15:49:05 +0000
3936+++ src/graphic/surface.h 2016-10-24 20:07:47 +0000
3937@@ -46,42 +46,42 @@
3938
3939 /// This draws a part of 'texture'.
3940 void blit(
3941- const Rect& dst, const Image&, const Rect& srcrc, const float opacity, BlendMode blend_mode);
3942+ const Rectf& dst, const Image&, const Rectf& srcrc, const float opacity, BlendMode blend_mode);
3943
3944 /// This draws a playercolor blended image.
3945- void blit_blended(const Rect& dst,
3946+ void blit_blended(const Rectf& dst,
3947 const Image& image,
3948 const Image& texture_mask,
3949- const Rect& srcrc,
3950+ const Rectf& srcrc,
3951 const RGBColor& blend);
3952
3953 /// This draws a grayed out version.
3954 void
3955- blit_monochrome(const Rect& dst, const Image&, const Rect& srcrc, const RGBAColor& multiplier);
3956+ blit_monochrome(const Rectf& dst, const Image&, const Rectf& srcrc, const RGBAColor& multiplier);
3957
3958 /// Draws a filled rect to the destination.
3959- void fill_rect(const Rect&, const RGBAColor&, BlendMode blend_mode = BlendMode::Copy);
3960+ void fill_rect(const Rectf& dst, const RGBAColor&, BlendMode blend_mode = BlendMode::Copy);
3961
3962 // Draw a 'width' pixel wide line to the destination. 'points' are taken by
3963 // value on purpose.
3964- void draw_line_strip(std::vector<FloatPoint> points, const RGBColor& color, float width);
3965+ void draw_line_strip(std::vector<Vector2f> points, const RGBColor& color, float width);
3966
3967 /// makes a rectangle on the destination brighter (or darker).
3968- void brighten_rect(const Rect&, int factor);
3969+ void brighten_rect(const Rectf&, int factor);
3970
3971 private:
3972 /// The actual implementation of the methods below.
3973- virtual void do_blit(const FloatRect& dst_rect,
3974+ virtual void do_blit(const Rectf& dst_rect,
3975 const BlitData& texture,
3976 float opacity,
3977 BlendMode blend_mode) = 0;
3978
3979- virtual void do_blit_blended(const FloatRect& dst_rect,
3980+ virtual void do_blit_blended(const Rectf& dst_rect,
3981 const BlitData& texture,
3982 const BlitData& mask,
3983 const RGBColor& blend) = 0;
3984
3985- virtual void do_blit_monochrome(const FloatRect& dst_rect,
3986+ virtual void do_blit_monochrome(const Rectf& dst_rect,
3987 const BlitData& texture,
3988 const RGBAColor& blend) = 0;
3989
3990@@ -90,7 +90,7 @@
3991 virtual void do_draw_line_strip(std::vector<DrawLineProgram::PerVertexData> vertices) = 0;
3992
3993 virtual void
3994- do_fill_rect(const FloatRect& dst_rect, const RGBAColor& color, BlendMode blend_mode) = 0;
3995+ do_fill_rect(const Rectf& dst_rect, const RGBAColor& color, BlendMode blend_mode) = 0;
3996
3997 DISALLOW_COPY_AND_ASSIGN(Surface);
3998 };
3999@@ -98,6 +98,6 @@
4000 /// Draws a rect (frame only) to the surface. The width of the surrounding line
4001 /// is 1 pixel, i.e. the transparent inner box of the drawn rectangle starts at
4002 /// (x+1, y+1) and has dimension (w - 2, h - 2).
4003-void draw_rect(const Rect& rect, const RGBColor&, Surface* destination);
4004+void draw_rect(const Rectf& rect, const RGBColor&, Surface* destination);
4005
4006 #endif // end of include guard: WL_GRAPHIC_SURFACE_H
4007
4008=== modified file 'src/graphic/text/rt_render.cc'
4009--- src/graphic/text/rt_render.cc 2016-08-04 15:49:05 +0000
4010+++ src/graphic/text/rt_render.cc 2016-10-24 20:07:47 +0000
4011@@ -32,8 +32,8 @@
4012 #include "base/i18n.h"
4013 #include "base/log.h"
4014 #include "base/macros.h"
4015-#include "base/point.h"
4016 #include "base/rect.h"
4017+#include "base/vector.h"
4018 #include "base/wexception.h"
4019 #include "graphic/align.h"
4020 #include "graphic/graphic.h"
4021@@ -173,7 +173,7 @@
4022 }
4023
4024 struct Reference {
4025- Rect dim;
4026+ Recti dim;
4027 string ref;
4028 };
4029
4030@@ -185,7 +185,7 @@
4031 // Should this linear algorithm proof to be too slow (doubtful), the
4032 // RefMap could also be efficiently implemented using an R-Tree
4033 for (const Reference& c : refs_)
4034- if (c.dim.contains(Point(x, y)))
4035+ if (c.dim.contains(Vector2i(x, y)))
4036 return c.ref;
4037 return "";
4038 }
4039@@ -469,7 +469,7 @@
4040 const vector<Reference> get_references() override {
4041 vector<Reference> rv;
4042 if (!nodestyle_.reference.empty()) {
4043- Reference r = {Rect(0, 0, w_, h_), nodestyle_.reference};
4044+ Reference r = {Recti(0, 0, w_, h_), nodestyle_.reference};
4045 rv.push_back(r);
4046 }
4047 return rv;
4048@@ -501,7 +501,7 @@
4049 const Texture& img =
4050 font_.render(txt_, nodestyle_.font_color, nodestyle_.font_style, texture_cache);
4051 Texture* rv = new Texture(img.width(), img.height());
4052- rv->blit(Rect(0, 0, img.width(), img.height()), img, Rect(0, 0, img.width(), img.height()), 1.,
4053+ rv->blit(Rectf(0, 0, img.width(), img.height()), img, Rectf(0, 0, img.width(), img.height()), 1.,
4054 BlendMode::Copy);
4055 return rv;
4056 }
4057@@ -536,8 +536,8 @@
4058 font_.render(txt_, nodestyle_.font_color, nodestyle_.font_style, texture_cache);
4059 Texture* rv = new Texture(w_, h_);
4060 for (uint16_t curx = 0; curx < w_; curx += t.width()) {
4061- Rect srcrect(Point(0, 0), min<int>(t.width(), w_ - curx), h_);
4062- rv->blit(Rect(curx, 0, srcrect.w, srcrect.h), t, srcrect, 1., BlendMode::Copy);
4063+ Rectf srcrect(0.f, 0.f, min<int>(t.width(), w_ - curx), h_);
4064+ rv->blit(Rectf(curx, 0, srcrect.w, srcrect.h), t, srcrect, 1., BlendMode::Copy);
4065 }
4066 return rv;
4067 }
4068@@ -557,7 +557,7 @@
4069 Texture* render(TextureCache* texture_cache) override {
4070 if (show_spaces_) {
4071 Texture* rv = new Texture(w_, h_);
4072- rv->fill_rect(Rect(0, 0, w_, h_), RGBAColor(0xcc, 0, 0, 0xcc));
4073+ rv->fill_rect(Rectf(0, 0, w_, h_), RGBAColor(0xcc, 0, 0, 0xcc));
4074 return rv;
4075 }
4076 return TextNode::render(texture_cache);
4077@@ -619,8 +619,8 @@
4078
4079 // Draw background image (tiling)
4080 if (background_image_) {
4081- Rect dst;
4082- Rect srcrect(Point(0, 0), 1, 1);
4083+ Rectf dst;
4084+ Rectf srcrect(0, 0, 1, 1);
4085 for (uint16_t curx = 0; curx < w_; curx += background_image_->width()) {
4086 dst.x = curx;
4087 dst.y = 0;
4088@@ -629,7 +629,7 @@
4089 rv->blit(dst, *background_image_, srcrect, 1., BlendMode::Copy);
4090 }
4091 } else {
4092- rv->fill_rect(Rect(0, 0, w_, h_), RGBAColor(255, 255, 255, 0));
4093+ rv->fill_rect(Rectf(0, 0, w_, h_), RGBAColor(255, 255, 255, 0));
4094 }
4095 return rv;
4096 }
4097@@ -689,19 +689,19 @@
4098 throw TextureTooBig(error_message);
4099 }
4100 Texture* rv = new Texture(width(), height());
4101- rv->fill_rect(Rect(0, 0, rv->width(), rv->height()), RGBAColor(255, 255, 255, 0));
4102+ rv->fill_rect(Rectf(0, 0, rv->width(), rv->height()), RGBAColor(255, 255, 255, 0));
4103
4104 // Draw Solid background Color
4105 bool set_alpha = true;
4106 if (is_background_color_set_) {
4107- rv->fill_rect(Rect(Point(margin_.left, margin_.top), w_, h_), background_color_);
4108+ rv->fill_rect(Rectf(margin_.left, margin_.top, w_, h_), background_color_);
4109 set_alpha = false;
4110 }
4111
4112 // Draw background image (tiling)
4113 if (background_image_) {
4114- Rect dst;
4115- Rect src(0, 0, 0, 0);
4116+ Rectf dst;
4117+ Rectf src(0, 0, 0, 0);
4118
4119 for (uint16_t cury = margin_.top; cury < h_ + margin_.top;
4120 cury += background_image_->height()) {
4121@@ -720,10 +720,9 @@
4122 for (RenderNode* n : nodes_to_render_) {
4123 Texture* node_texture = n->render(texture_cache);
4124 if (node_texture) {
4125- Rect dst = Rect(n->x() + margin_.left, n->y() + margin_.top, node_texture->width(),
4126+ Rectf dst(n->x() + margin_.left, n->y() + margin_.top, node_texture->width(),
4127 node_texture->height());
4128- Rect src = Rect(0, 0, node_texture->width(), node_texture->height());
4129-
4130+ Rectf src(0, 0, node_texture->width(), node_texture->height());
4131 rv->blit(
4132 dst, *node_texture, src, 1., set_alpha ? BlendMode::Copy : BlendMode::UseAlpha);
4133 delete node_texture;
4134@@ -754,7 +753,7 @@
4135 nodes_to_render_ = n;
4136 }
4137 void add_reference(int16_t gx, int16_t gy, uint16_t w, uint16_t h, const string& s) {
4138- Reference r = {Rect(gx, gy, w, h), s};
4139+ Reference r = {Recti(gx, gy, w, h), s};
4140 refs_.push_back(r);
4141 }
4142
4143@@ -790,8 +789,8 @@
4144
4145 Texture* ImgRenderNode::render(TextureCache* /* texture_cache */) {
4146 Texture* rv = new Texture(image_.width(), image_.height());
4147- rv->blit(Rect(0, 0, image_.width(), image_.height()), image_,
4148- Rect(0, 0, image_.width(), image_.height()), 1., BlendMode::Copy);
4149+ rv->blit(Rectf(0, 0, image_.width(), image_.height()), image_,
4150+ Rectf(0, 0, image_.width(), image_.height()), 1., BlendMode::Copy);
4151 return rv;
4152 }
4153 // End: Helper Stuff
4154
4155=== modified file 'src/graphic/texture.cc'
4156--- src/graphic/texture.cc 2016-08-04 15:49:05 +0000
4157+++ src/graphic/texture.cc 2016-10-24 20:07:47 +0000
4158@@ -144,14 +144,14 @@
4159 SDL_FreeSurface(surface);
4160 }
4161
4162-Texture::Texture(const GLuint texture, const Rect& subrect, int parent_w, int parent_h)
4163+Texture::Texture(const GLuint texture, const Recti& subrect, int parent_w, int parent_h)
4164 : owns_texture_(false) {
4165 if (parent_w == 0 || parent_h == 0) {
4166 throw wexception("Created a sub Texture with zero height and width parent.");
4167 }
4168
4169 blit_data_ = BlitData{
4170- texture, parent_w, parent_h, subrect,
4171+ texture, parent_w, parent_h, subrect.cast<float>(),
4172 };
4173 }
4174
4175@@ -172,7 +172,7 @@
4176 void Texture::init(uint16_t w, uint16_t h) {
4177 blit_data_ = {
4178 0, // initialized below
4179- w, h, Rect(0, 0, w, h),
4180+ w, h, Rectf(0, 0, w, h),
4181 };
4182 if (w * h == 0) {
4183 return;
4184@@ -250,7 +250,7 @@
4185 glViewport(0, 0, width(), height());
4186 }
4187
4188-void Texture::do_blit(const FloatRect& dst_rect,
4189+void Texture::do_blit(const Rectf& dst_rect,
4190 const BlitData& texture,
4191 float opacity,
4192 BlendMode blend_mode) {
4193@@ -258,11 +258,11 @@
4194 return;
4195 }
4196 setup_gl();
4197- BlitProgram::instance().draw(dst_rect, 0.f, texture, BlitData{0, 0, 0, Rect()},
4198+ BlitProgram::instance().draw(dst_rect, 0.f, texture, BlitData{0, 0, 0, Rectf()},
4199 RGBAColor(0, 0, 0, 255 * opacity), blend_mode);
4200 }
4201
4202-void Texture::do_blit_blended(const FloatRect& dst_rect,
4203+void Texture::do_blit_blended(const Rectf& dst_rect,
4204 const BlitData& texture,
4205 const BlitData& mask,
4206 const RGBColor& blend) {
4207@@ -274,7 +274,7 @@
4208 BlitProgram::instance().draw(dst_rect, 0.f, texture, mask, blend, BlendMode::UseAlpha);
4209 }
4210
4211-void Texture::do_blit_monochrome(const FloatRect& dst_rect,
4212+void Texture::do_blit_monochrome(const Rectf& dst_rect,
4213 const BlitData& texture,
4214 const RGBAColor& blend) {
4215 if (blit_data_.texture_id == 0) {
4216@@ -293,9 +293,7 @@
4217 {DrawLineProgram::Arguments{vertices, 0.f, BlendMode::UseAlpha}});
4218 }
4219
4220-void Texture::do_fill_rect(const FloatRect& dst_rect,
4221- const RGBAColor& color,
4222- BlendMode blend_mode) {
4223+void Texture::do_fill_rect(const Rectf& dst_rect, const RGBAColor& color, BlendMode blend_mode) {
4224 if (blit_data_.texture_id == 0) {
4225 return;
4226 }
4227
4228=== modified file 'src/graphic/texture.h'
4229--- src/graphic/texture.h 2016-08-04 15:49:05 +0000
4230+++ src/graphic/texture.h 2016-10-24 20:07:47 +0000
4231@@ -39,7 +39,7 @@
4232
4233 // Create a logical texture that is a 'subrect' (in Pixel) in
4234 // another texture. Ownership of 'texture' is not taken.
4235- Texture(const GLuint texture, const Rect& subrect, int parent_w, int parent_h);
4236+ Texture(const GLuint texture, const Recti& subrect, int parent_w, int parent_h);
4237
4238 virtual ~Texture();
4239
4240@@ -83,20 +83,20 @@
4241 void init(uint16_t w, uint16_t h);
4242
4243 // Implements surface.
4244- void do_blit(const FloatRect& dst_rect,
4245+ void do_blit(const Rectf& dst_rect,
4246 const BlitData& texture,
4247 float opacity,
4248 BlendMode blend_mode) override;
4249- void do_blit_blended(const FloatRect& dst_rect,
4250+ void do_blit_blended(const Rectf& dst_rect,
4251 const BlitData& texture,
4252 const BlitData& mask,
4253 const RGBColor& blend) override;
4254- void do_blit_monochrome(const FloatRect& dst_rect,
4255+ void do_blit_monochrome(const Rectf& dst_rect,
4256 const BlitData& texture,
4257 const RGBAColor& blend) override;
4258 void do_draw_line_strip(std::vector<DrawLineProgram::PerVertexData> vertices) override;
4259 void
4260- do_fill_rect(const FloatRect& dst_rect, const RGBAColor& color, BlendMode blend_mode) override;
4261+ do_fill_rect(const Rectf& dst_rect, const RGBAColor& color, BlendMode blend_mode) override;
4262
4263 // True if we own the texture, i.e. if we need to delete it.
4264 bool owns_texture_;
4265
4266=== modified file 'src/graphic/texture_atlas.cc'
4267--- src/graphic/texture_atlas.cc 2016-08-04 15:49:05 +0000
4268+++ src/graphic/texture_atlas.cc 2016-10-24 20:07:47 +0000
4269@@ -34,14 +34,14 @@
4270
4271 } // namespace
4272
4273-TextureAtlas::Node::Node(const Rect& init_r) : used(false), r(init_r) {
4274+TextureAtlas::Node::Node(const Recti& init_r) : used(false), r(init_r) {
4275 }
4276
4277 void TextureAtlas::Node::split(int item_w, int item_h) {
4278 assert(!used);
4279
4280- down.reset(new Node(Rect(r.x, r.y + item_h, r.w, r.h - item_h)));
4281- right.reset(new Node(Rect(r.x + item_w, r.y, r.w - item_w, item_h)));
4282+ down.reset(new Node(Recti(r.x, r.y + item_h, r.w, r.h - item_h)));
4283+ right.reset(new Node(Recti(r.x + item_w, r.y, r.w - item_w, item_h)));
4284 used = true;
4285
4286 // Note: we do not change the size of the root. It is not needed
4287@@ -77,21 +77,21 @@
4288 std::unique_ptr<Texture> TextureAtlas::pack_as_many_as_possible(
4289 const int max_dimension, const int texture_atlas_index, std::vector<PackedTexture>* pack_info) {
4290
4291- std::unique_ptr<Node> root(new Node(Rect(0, 0, blocks_.begin()->texture->width() + kPadding,
4292- blocks_.begin()->texture->height() + kPadding)));
4293+ std::unique_ptr<Node> root(new Node(Recti(0, 0, blocks_.begin()->texture->width() + kPadding,
4294+ blocks_.begin()->texture->height() + kPadding)));
4295
4296 const auto grow_right = [&root](int delta_w) {
4297- std::unique_ptr<Node> new_root(new Node(Rect(0, 0, root->r.w + delta_w, root->r.h)));
4298+ std::unique_ptr<Node> new_root(new Node(Recti(0, 0, root->r.w + delta_w, root->r.h)));
4299 new_root->used = true;
4300- new_root->right.reset(new Node(Rect(root->r.w, 0, delta_w, root->r.h)));
4301+ new_root->right.reset(new Node(Recti(root->r.w, 0, delta_w, root->r.h)));
4302 new_root->down.reset(root.release());
4303 root.reset(new_root.release());
4304 };
4305
4306 const auto grow_down = [&root](int delta_h) {
4307- std::unique_ptr<Node> new_root(new Node(Rect(0, 0, root->r.w, root->r.h + delta_h)));
4308+ std::unique_ptr<Node> new_root(new Node(Recti(0, 0, root->r.w, root->r.h + delta_h)));
4309 new_root->used = true;
4310- new_root->down.reset(new Node(Rect(0, root->r.h, root->r.w, delta_h)));
4311+ new_root->down.reset(new Node(Recti(0, root->r.h, root->r.w, delta_h)));
4312 new_root->right.reset(root.release());
4313 root.reset(new_root.release());
4314 };
4315@@ -134,20 +134,20 @@
4316 }
4317
4318 std::unique_ptr<Texture> texture_atlas(new Texture(root->r.w, root->r.h));
4319- texture_atlas->fill_rect(Rect(0, 0, root->r.w, root->r.h), RGBAColor(0, 0, 0, 0));
4320+ texture_atlas->fill_rect(Rectf(0, 0, root->r.w, root->r.h), RGBAColor(0, 0, 0, 0));
4321
4322 const auto packed_texture_id = texture_atlas->blit_data().texture_id;
4323 for (Block& block : packed) {
4324 texture_atlas->blit(
4325- Rect(block.node->r.x, block.node->r.y, block.texture->width(), block.texture->height()),
4326- *block.texture, Rect(0, 0, block.texture->width(), block.texture->height()), 1.,
4327+ Rectf(block.node->r.x, block.node->r.y, block.texture->width(), block.texture->height()),
4328+ *block.texture, Rectf(0, 0, block.texture->width(), block.texture->height()), 1.,
4329 BlendMode::Copy);
4330
4331 pack_info->emplace_back(PackedTexture(
4332 texture_atlas_index, block.index,
4333 std::unique_ptr<Texture>(new Texture(
4334 packed_texture_id,
4335- Rect(block.node->r.origin(), block.texture->width(), block.texture->height()),
4336+ Recti(block.node->r.origin(), block.texture->width(), block.texture->height()),
4337 root->r.w, root->r.h))));
4338 }
4339 blocks_ = not_packed;
4340
4341=== modified file 'src/graphic/texture_atlas.h'
4342--- src/graphic/texture_atlas.h 2016-08-04 15:49:05 +0000
4343+++ src/graphic/texture_atlas.h 2016-10-24 20:07:47 +0000
4344@@ -68,11 +68,11 @@
4345
4346 private:
4347 struct Node {
4348- Node(const Rect& init_r);
4349+ Node(const Recti& init_r);
4350 void split(int w, int h);
4351
4352 bool used;
4353- Rect r;
4354+ Recti r;
4355 std::unique_ptr<Node> right;
4356 std::unique_ptr<Node> down;
4357
4358
4359=== modified file 'src/graphic/wordwrap.cc'
4360--- src/graphic/wordwrap.cc 2016-08-04 15:49:05 +0000
4361+++ src/graphic/wordwrap.cc 2016-10-24 20:07:47 +0000
4362@@ -303,7 +303,7 @@
4363 *
4364 * \note This also draws the caret, if any.
4365 */
4366-void WordWrap::draw(RenderTarget& dst, Point where, Align align, uint32_t caret) {
4367+void WordWrap::draw(RenderTarget& dst, Vector2i where, Align align, uint32_t caret) {
4368 if (lines_.empty())
4369 return;
4370
4371@@ -329,7 +329,7 @@
4372 if (where.y >= dst.height() || int32_t(where.y + fontheight) <= 0)
4373 continue;
4374
4375- Point point(where.x, where.y);
4376+ Vector2f point(where.x, where.y);
4377
4378 if (static_cast<int>(alignment & UI::Align::kRight)) {
4379 point.x += wrapwidth_ - LINE_MARGIN;
4380@@ -346,9 +346,9 @@
4381 int caret_x = text_width(line_to_caret, style_.font->size());
4382
4383 const Image* caret_image = g_gr->images().get("images/ui_basic/caret.png");
4384- Point caretpt;
4385+ Vector2f caretpt;
4386 caretpt.x = point.x + caret_x - caret_image->width() + LINE_MARGIN;
4387- caretpt.y = point.y + (fontheight - caret_image->height()) / 2;
4388+ caretpt.y = point.y + (fontheight - caret_image->height()) / 2.f;
4389 dst.blit(caretpt, caret_image);
4390 }
4391 }
4392
4393=== modified file 'src/graphic/wordwrap.h'
4394--- src/graphic/wordwrap.h 2016-08-04 15:49:05 +0000
4395+++ src/graphic/wordwrap.h 2016-10-24 20:07:47 +0000
4396@@ -21,7 +21,7 @@
4397
4398 #include <string>
4399
4400-#include "base/point.h"
4401+#include "base/vector.h"
4402 #include "graphic/align.h"
4403 #include "graphic/text_layout.h"
4404
4405@@ -50,7 +50,7 @@
4406 }
4407
4408 void draw(RenderTarget& dst,
4409- Point where,
4410+ Vector2i where,
4411 Align align = UI::Align::kLeft,
4412 uint32_t caret = std::numeric_limits<uint32_t>::max());
4413
4414
4415=== modified file 'src/io/streamread.cc'
4416--- src/io/streamread.cc 2016-08-04 15:49:05 +0000
4417+++ src/io/streamread.cc 2016-10-24 20:07:47 +0000
4418@@ -22,6 +22,7 @@
4419 #include <cassert>
4420 #include <cstdarg>
4421 #include <cstdio>
4422+#include <cstring>
4423
4424 #include "base/wexception.h"
4425
4426@@ -89,6 +90,15 @@
4427 return little_32(x);
4428 }
4429
4430+float StreamRead::float_32() {
4431+ uint32_t x;
4432+ data_complete(&x, 4);
4433+ x = little_32(x);
4434+ float rv;
4435+ memcpy(&rv, &x, 4);
4436+ return rv;
4437+}
4438+
4439 std::string StreamRead::string() {
4440 std::string x;
4441 char ch;
4442
4443=== modified file 'src/io/streamread.h'
4444--- src/io/streamread.h 2016-08-04 15:49:05 +0000
4445+++ src/io/streamread.h 2016-10-24 20:07:47 +0000
4446@@ -67,6 +67,7 @@
4447 uint16_t unsigned_16();
4448 int32_t signed_32();
4449 uint32_t unsigned_32();
4450+ float float_32();
4451 std::string string();
4452 virtual char const* c_string() {
4453 throw;
4454
4455=== modified file 'src/io/streamwrite.cc'
4456--- src/io/streamwrite.cc 2016-08-04 15:49:05 +0000
4457+++ src/io/streamwrite.cc 2016-10-24 20:07:47 +0000
4458@@ -20,6 +20,7 @@
4459 #include "io/streamwrite.h"
4460
4461 #include <cstdarg>
4462+#include <cstring>
4463
4464 #include "base/wexception.h"
4465
4466
4467=== modified file 'src/io/streamwrite.h'
4468--- src/io/streamwrite.h 2016-08-04 15:49:05 +0000
4469+++ src/io/streamwrite.h 2016-10-24 20:07:47 +0000
4470@@ -82,6 +82,12 @@
4471 uint32_t const y = little_32(x);
4472 data(&y, 4);
4473 }
4474+ void float_32(const float x) {
4475+ uint32_t y;
4476+ memcpy(&y, &x, 4);
4477+ y = little_32(y);
4478+ data(&y, 4);
4479+ }
4480 void string(const std::string& str) {
4481 data(str.c_str(), str.size() + 1);
4482 }
4483
4484=== modified file 'src/logic/CMakeLists.txt'
4485--- src/logic/CMakeLists.txt 2016-05-14 07:35:39 +0000
4486+++ src/logic/CMakeLists.txt 2016-10-24 20:07:47 +0000
4487@@ -119,6 +119,7 @@
4488 widelands_geometry_io.cc
4489 widelands_geometry_io.h
4490 widelands.h
4491+ map_objects/draw_text.h
4492 map_objects/attackable.h
4493 map_objects/bob.cc
4494 map_objects/bob.h
4495@@ -126,15 +127,13 @@
4496 map_objects/buildcost.h
4497 map_objects/checkstep.cc
4498 map_objects/checkstep.h
4499- map_objects/immovable_program.h
4500 map_objects/immovable.cc
4501 map_objects/immovable.h
4502+ map_objects/immovable_program.h
4503 map_objects/map_object.cc
4504 map_objects/map_object.h
4505 map_objects/terrain_affinity.cc
4506 map_objects/terrain_affinity.h
4507- map_objects/walkingdir.cc
4508- map_objects/walkingdir.h
4509 map_objects/tribes/battle.cc
4510 map_objects/tribes/battle.h
4511 map_objects/tribes/bill_of_materials.h
4512@@ -181,15 +180,17 @@
4513 map_objects/tribes/warelist.h
4514 map_objects/tribes/wareworker.h
4515 map_objects/tribes/workarea_info.h
4516+ map_objects/tribes/worker.cc
4517+ map_objects/tribes/worker.h
4518 map_objects/tribes/worker_descr.cc
4519 map_objects/tribes/worker_descr.h
4520 map_objects/tribes/worker_program.cc
4521 map_objects/tribes/worker_program.h
4522- map_objects/tribes/worker.cc
4523- map_objects/tribes/worker.h
4524- map_objects/world/critter_program.h
4525+ map_objects/walkingdir.cc
4526+ map_objects/walkingdir.h
4527 map_objects/world/critter.cc
4528 map_objects/world/critter.h
4529+ map_objects/world/critter_program.h
4530 map_objects/world/editor_category.cc
4531 map_objects/world/editor_category.h
4532 map_objects/world/map_gen.cc
4533@@ -209,6 +210,7 @@
4534 base_i18n
4535 base_log
4536 base_macros
4537+ base_math
4538 base_md5
4539 base_scoped_timer
4540 base_time_string
4541
4542=== modified file 'src/logic/game.cc'
4543--- src/logic/game.cc 2016-08-04 15:49:05 +0000
4544+++ src/logic/game.cc 2016-10-24 20:07:47 +0000
4545@@ -455,7 +455,7 @@
4546 }
4547
4548 if (get_ipl())
4549- get_ipl()->move_view_to(map().get_starting_pos(get_ipl()->player_number()));
4550+ get_ipl()->center_view_on_coords(map().get_starting_pos(get_ipl()->player_number()));
4551
4552 // Prepare the map, set default textures
4553 map().recalc_default_resources(world());
4554
4555=== modified file 'src/logic/game_controller.h'
4556--- src/logic/game_controller.h 2016-08-04 15:49:05 +0000
4557+++ src/logic/game_controller.h 2016-10-24 20:07:47 +0000
4558@@ -100,9 +100,6 @@
4559 /**
4560 * Report a player result once he has left the game. This may be done through lua
4561 * by the win_condition scripts.
4562- * \param player : the player idx;
4563- * \param result : the player result
4564- * \param info : The info string (\see \struct PlayerEndStatus)
4565 */
4566 virtual void report_result(uint8_t /* player */,
4567 Widelands::PlayerEndResult /*result*/,
4568
4569=== modified file 'src/logic/map_objects/bob.cc'
4570--- src/logic/map_objects/bob.cc 2016-08-04 15:49:05 +0000
4571+++ src/logic/map_objects/bob.cc 2016-10-24 20:07:47 +0000
4572@@ -25,6 +25,7 @@
4573 #include <stdint.h>
4574
4575 #include "base/macros.h"
4576+#include "base/math.h"
4577 #include "base/wexception.h"
4578 #include "economy/route.h"
4579 #include "economy/transfer.h"
4580@@ -88,7 +89,6 @@
4581
4582 Bob::Bob(const BobDescr& init_descr)
4583 : MapObject(&init_descr),
4584- owner_(nullptr),
4585 position_(FCoords(Coords(0, 0), nullptr)), // not linked anywhere
4586 linknext_(nullptr),
4587 linkpprev_(nullptr),
4588@@ -685,45 +685,51 @@
4589 return schedule_act(game, walkend_ - game.get_gametime());
4590 }
4591
4592-/// Calculates the actual position to draw on from the base node position.
4593-/// This function takes walking etc. into account.
4594-///
4595-/// pos is the location, in pixels, of the node position_ (height is already
4596-/// taken into account).
4597-Point Bob::calc_drawpos(const EditorGameBase& game, const Point pos) const {
4598+// Calculates the actual position to draw on from the base node position. This
4599+// function takes walking etc. into account.
4600+//
4601+// pos is the location, in pixels, of the node position_ on screen with scale
4602+// and height taken into account.
4603+Vector2f Bob::calc_drawpos(const EditorGameBase& game,
4604+ const Vector2f& field_on_dst,
4605+ const float scale) const {
4606 const Map& map = game.get_map();
4607 const FCoords end = position_;
4608 FCoords start;
4609- Point spos = pos, epos = pos;
4610+ Vector2f spos = field_on_dst;
4611+ Vector2f epos = field_on_dst;
4612+
4613+ const float triangle_w = kTriangleWidth * scale;
4614+ const float triangle_h = kTriangleHeight * scale;
4615
4616 switch (walking_) {
4617 case WALK_NW:
4618 map.get_brn(end, &start);
4619- spos.x += kTriangleWidth / 2;
4620- spos.y += kTriangleHeight;
4621+ spos.x += triangle_w / 2.f;
4622+ spos.y += triangle_h;
4623 break;
4624 case WALK_NE:
4625 map.get_bln(end, &start);
4626- spos.x -= kTriangleWidth / 2;
4627- spos.y += kTriangleHeight;
4628+ spos.x -= triangle_w / 2.f;
4629+ spos.y += triangle_h;
4630 break;
4631 case WALK_W:
4632 map.get_rn(end, &start);
4633- spos.x += kTriangleWidth;
4634+ spos.x += triangle_w;
4635 break;
4636 case WALK_E:
4637 map.get_ln(end, &start);
4638- spos.x -= kTriangleWidth;
4639+ spos.x -= triangle_w;
4640 break;
4641 case WALK_SW:
4642 map.get_trn(end, &start);
4643- spos.x += kTriangleWidth / 2;
4644- spos.y -= kTriangleHeight;
4645+ spos.x += triangle_w / 2.f;
4646+ spos.y -= triangle_h;
4647 break;
4648 case WALK_SE:
4649 map.get_tln(end, &start);
4650- spos.x -= kTriangleWidth / 2;
4651- spos.y -= kTriangleHeight;
4652+ spos.x -= triangle_w / 2.f;
4653+ spos.y -= triangle_h;
4654 break;
4655
4656 case IDLE:
4657@@ -732,37 +738,39 @@
4658 }
4659
4660 if (start.field) {
4661- spos.y += end.field->get_height() * kHeightFactor;
4662- spos.y -= start.field->get_height() * kHeightFactor;
4663+ spos.y += end.field->get_height() * kHeightFactor * scale;
4664+ spos.y -= start.field->get_height() * kHeightFactor * scale;
4665
4666 assert(static_cast<uint32_t>(walkstart_) <= game.get_gametime());
4667 assert(walkstart_ < walkend_);
4668- float f = static_cast<float>(game.get_gametime() - walkstart_) / (walkend_ - walkstart_);
4669-
4670- if (f < 0)
4671- f = 0;
4672- else if (f > 1)
4673- f = 1;
4674-
4675- epos.x = static_cast<int32_t>(f * epos.x + (1 - f) * spos.x);
4676- epos.y = static_cast<int32_t>(f * epos.y + (1 - f) * spos.y);
4677+ const float f = math::clamp(
4678+ static_cast<float>(game.get_gametime() - walkstart_) / (walkend_ - walkstart_),
4679+ 0.f, 1.f);
4680+ epos.x = f * epos.x + (1.f - f) * spos.x;
4681+ epos.y = f * epos.y + (1.f - f) * spos.y;
4682 }
4683-
4684 return epos;
4685 }
4686
4687 /// It LERPs between start and end position when we are walking.
4688 /// Note that the current node is actually the node that we are walking to, not
4689 /// the the one that we start from.
4690-void Bob::draw(const EditorGameBase& egbase, RenderTarget& dst, const Point& pos) const {
4691- if (anim_) {
4692- auto* const owner = get_owner();
4693- if (owner != nullptr) {
4694- dst.blit_animation(calc_drawpos(egbase, pos), anim_, egbase.get_gametime() - animstart_,
4695- owner->get_playercolor());
4696- } else {
4697- dst.blit_animation(calc_drawpos(egbase, pos), anim_, egbase.get_gametime() - animstart_);
4698- }
4699+void Bob::draw(const EditorGameBase& egbase,
4700+ const DrawText&,
4701+ const Vector2f& field_on_dst,
4702+ const float scale,
4703+ RenderTarget* dst) const {
4704+ if (!anim_) {
4705+ return;
4706+ }
4707+
4708+ auto* const owner = get_owner();
4709+ const Vector2f point_on_dst = calc_drawpos(egbase, field_on_dst, scale);
4710+ if (owner != nullptr) {
4711+ dst->blit_animation(
4712+ point_on_dst, scale, anim_, egbase.get_gametime() - animstart_, owner->get_playercolor());
4713+ } else {
4714+ dst->blit_animation(point_on_dst, scale, anim_, egbase.get_gametime() - animstart_);
4715 }
4716 }
4717
4718
4719=== modified file 'src/logic/map_objects/bob.h'
4720--- src/logic/map_objects/bob.h 2016-08-04 15:49:05 +0000
4721+++ src/logic/map_objects/bob.h 2016-10-24 20:07:47 +0000
4722@@ -21,10 +21,11 @@
4723 #define WL_LOGIC_MAP_OBJECTS_BOB_H
4724
4725 #include "base/macros.h"
4726-#include "base/point.h"
4727+#include "base/vector.h"
4728 #include "economy/route.h"
4729 #include "graphic/animation.h"
4730 #include "graphic/diranimations.h"
4731+#include "logic/map_objects/draw_text.h"
4732 #include "logic/map_objects/map_object.h"
4733 #include "logic/map_objects/walkingdir.h"
4734 #include "logic/widelands_geometry.h"
4735@@ -240,11 +241,9 @@
4736 void schedule_destroy(Game&);
4737 void schedule_act(Game&, uint32_t tdelta);
4738 void skip_act();
4739- Point calc_drawpos(const EditorGameBase&, Point) const;
4740+ Vector2f calc_drawpos(const EditorGameBase&, const Vector2f& field_on_dst, float scale) const;
4741 void set_owner(Player*);
4742- Player* get_owner() const {
4743- return owner_;
4744- }
4745+
4746 void set_position(EditorGameBase&, const Coords&);
4747 const FCoords& get_position() const {
4748 return position_;
4749@@ -260,7 +259,15 @@
4750 /// onto the \p to node if this function allows it to.
4751 virtual bool check_node_blocked(Game&, const FCoords&, bool commit);
4752
4753- virtual void draw(const EditorGameBase&, RenderTarget&, const Point&) const;
4754+ // Draws the bob onto the screen with 'field_on_dst' being the position of
4755+ // the field associated with this bob (if it is walking, that is its
4756+ // starting field) in pixel space of 'dst' (including scale). The 'scale' is
4757+ // required to draw the bob in the right size.
4758+ virtual void draw(const EditorGameBase&,
4759+ const DrawText& draw_text,
4760+ const Vector2f& field_on_dst,
4761+ float scale,
4762+ RenderTarget* dst) const;
4763
4764 // For debug
4765 void log_general_info(const EditorGameBase&) override;
4766@@ -366,7 +373,6 @@
4767 static Task const taskMovepath;
4768 static Task const taskMove;
4769
4770- Player* owner_; ///< can be 0
4771 FCoords position_; ///< where are we right now?
4772 Bob* linknext_; ///< next object on this node
4773 Bob** linkpprev_;
4774
4775=== added file 'src/logic/map_objects/draw_text.h'
4776--- src/logic/map_objects/draw_text.h 1970-01-01 00:00:00 +0000
4777+++ src/logic/map_objects/draw_text.h 2016-10-24 20:07:47 +0000
4778@@ -0,0 +1,34 @@
4779+/*
4780+ * Copyright (C) 2006-2016 by the Widelands Development Team
4781+ *
4782+ * This program is free software; you can redistribute it and/or
4783+ * modify it under the terms of the GNU General Public License
4784+ * as published by the Free Software Foundation; either version 2
4785+ * of the License, or (at your option) any later version.
4786+ *
4787+ * This program is distributed in the hope that it will be useful,
4788+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4789+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4790+ * GNU General Public License for more details.
4791+ *
4792+ * You should have received a copy of the GNU General Public License
4793+ * along with this program; if not, write to the Free Software
4794+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4795+ *
4796+ */
4797+
4798+#ifndef WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H
4799+#define WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H
4800+
4801+enum DrawText {
4802+ kNone = 0,
4803+ kCensus = 1,
4804+ kStatistics = 2,
4805+};
4806+
4807+inline DrawText operator|(DrawText a, DrawText b) {
4808+ return static_cast<DrawText>(static_cast<int>(a) | static_cast<int>(b));
4809+}
4810+
4811+#endif // end of include guard: WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H
4812+
4813
4814=== modified file 'src/logic/map_objects/immovable.cc'
4815--- src/logic/map_objects/immovable.cc 2016-08-04 15:49:05 +0000
4816+++ src/logic/map_objects/immovable.cc 2016-10-24 20:07:47 +0000
4817@@ -324,7 +324,6 @@
4818 * Create an immovable of this type
4819 */
4820 Immovable& ImmovableDescr::create(EditorGameBase& egbase, const Coords& coords) const {
4821- assert(this != nullptr);
4822 Immovable& result = *new Immovable(*this);
4823 result.position_ = coords;
4824 result.init(egbase);
4825@@ -341,7 +340,6 @@
4826
4827 Immovable::Immovable(const ImmovableDescr& imm_descr)
4828 : BaseImmovable(imm_descr),
4829- owner_(nullptr),
4830 anim_(0),
4831 animstart_(0),
4832 program_(nullptr),
4833@@ -439,19 +437,26 @@
4834 }
4835 }
4836
4837-void Immovable::draw(const EditorGameBase& game,
4838- RenderTarget& dst,
4839- const FCoords&,
4840- const Point& pos) {
4841- if (anim_) {
4842- if (!anim_construction_total_)
4843- dst.blit_animation(pos, anim_, game.get_gametime() - animstart_);
4844- else
4845- draw_construction(game, dst, pos);
4846+void Immovable::draw(uint32_t gametime,
4847+ const DrawText draw_text,
4848+ const Vector2f& point_on_dst,
4849+ float scale,
4850+ RenderTarget* dst) {
4851+ if (!anim_) {
4852+ return;
4853+ }
4854+ if (!anim_construction_total_) {
4855+ dst->blit_animation(point_on_dst, scale, anim_, gametime - animstart_);
4856+ } else {
4857+ draw_construction(gametime, draw_text, point_on_dst, scale, dst);
4858 }
4859 }
4860
4861-void Immovable::draw_construction(const EditorGameBase& game, RenderTarget& dst, const Point pos) {
4862+void Immovable::draw_construction(const uint32_t gametime,
4863+ const DrawText draw_text,
4864+ const Vector2f& point_on_dst,
4865+ const float scale,
4866+ RenderTarget* dst) {
4867 const ImmovableProgram::ActConstruction* constructionact = nullptr;
4868 if (program_ptr_ < program_->size())
4869 constructionact =
4870@@ -462,7 +467,7 @@
4871 uint32_t done = 0;
4872 if (anim_construction_done_ > 0) {
4873 done = steptime * (anim_construction_done_ - 1);
4874- done += std::min(steptime, game.get_gametime() - animstart_);
4875+ done += std::min(steptime, gametime - animstart_);
4876 }
4877
4878 uint32_t total = anim_construction_total_ * steptime;
4879@@ -483,21 +488,19 @@
4880 const RGBColor& player_color = get_owner()->get_playercolor();
4881 if (current_frame > 0) {
4882 // Not the first pic, so draw the previous one in the back
4883- dst.blit_animation(pos, anim_, (current_frame - 1) * frametime, player_color);
4884+ dst->blit_animation(point_on_dst, scale, anim_, (current_frame - 1) * frametime, player_color);
4885 }
4886
4887 assert(lines <= curh);
4888- dst.blit_animation(pos, anim_, current_frame * frametime, player_color,
4889- Rect(Point(0, curh - lines), curw, lines));
4890+ dst->blit_animation(point_on_dst, scale, anim_, current_frame * frametime, player_color,
4891+ Recti(Vector2i(0, curh - lines), curw, lines));
4892
4893 // Additionally, if statistics are enabled, draw a progression string
4894- uint32_t const display_flags = game.get_ibase()->get_display_flags();
4895- do_draw_info(display_flags & InteractiveBase::dfShowCensus, descr().descname(),
4896- display_flags & InteractiveBase::dfShowStatistics,
4897+ do_draw_info(draw_text, descr().descname(),
4898 (boost::format("<font color=%s>%s</font>") % UI_FONT_CLR_DARK.hex_value() %
4899 (boost::format(_("%i%% built")) % (100 * done / total)).str())
4900 .str(),
4901- dst, pos);
4902+ point_on_dst, scale, dst);
4903 }
4904
4905 /**
4906@@ -1179,7 +1182,7 @@
4907 * Zero-initialize
4908 */
4909 PlayerImmovable::PlayerImmovable(const MapObjectDescr& mo_descr)
4910- : BaseImmovable(mo_descr), owner_(nullptr), economy_(nullptr) {
4911+ : BaseImmovable(mo_descr), economy_(nullptr) {
4912 }
4913
4914 /**
4915
4916=== modified file 'src/logic/map_objects/immovable.h'
4917--- src/logic/map_objects/immovable.h 2016-08-04 15:49:05 +0000
4918+++ src/logic/map_objects/immovable.h 2016-10-24 20:07:47 +0000
4919@@ -26,6 +26,7 @@
4920 #include "base/macros.h"
4921 #include "graphic/animation.h"
4922 #include "logic/map_objects/buildcost.h"
4923+#include "logic/map_objects/draw_text.h"
4924 #include "logic/map_objects/map_object.h"
4925 #include "logic/widelands_geometry.h"
4926 #include "notifications/note_ids.h"
4927@@ -91,7 +92,18 @@
4928 * if one can be chosen as main.
4929 */
4930 virtual PositionList get_positions(const EditorGameBase&) const = 0;
4931- virtual void draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) = 0;
4932+
4933+ // Draw this immovable onto 'dst' choosing the frame appropriate for
4934+ // 'gametime'. 'draw_text' decides if census and statistics are written too.
4935+ // The 'coords_to_draw' are passed one to give objects that occupy multiple
4936+ // fields a way to only draw themselves once. The 'point_on_dst' determines
4937+ // the point for the hotspot of the animation and 'scale' determines how big
4938+ // the immovable will be plotted.
4939+ virtual void draw(uint32_t gametime,
4940+ DrawText draw_text,
4941+ const Vector2f& point_on_dst,
4942+ float scale,
4943+ RenderTarget* dst) = 0;
4944
4945 static int32_t string_to_size(const std::string& size);
4946 static std::string size_to_string(int32_t size);
4947@@ -189,10 +201,7 @@
4948 Immovable(const ImmovableDescr&);
4949 ~Immovable();
4950
4951- Player* get_owner() const {
4952- return owner_;
4953- }
4954- void set_owner(Player* player);
4955+ void set_owner(Player*);
4956
4957 Coords get_position() const {
4958 return position_;
4959@@ -212,8 +221,11 @@
4960 void init(EditorGameBase&) override;
4961 void cleanup(EditorGameBase&) override;
4962 void act(Game&, uint32_t data) override;
4963-
4964- void draw(const EditorGameBase&, RenderTarget&, const FCoords&, const Point&) override;
4965+ void draw(uint32_t gametime,
4966+ DrawText draw_text,
4967+ const Vector2f& point_on_dst,
4968+ float scale,
4969+ RenderTarget* dst) override;
4970
4971 void switch_program(Game& game, const std::string& programname);
4972 bool construct_ware(Game& game, DescriptionIndex index);
4973@@ -230,7 +242,6 @@
4974 }
4975
4976 protected:
4977- Player* owner_;
4978 Coords position_;
4979
4980 uint32_t anim_;
4981@@ -289,8 +300,11 @@
4982
4983 private:
4984 void increment_program_pointer();
4985-
4986- void draw_construction(const EditorGameBase&, RenderTarget&, Point);
4987+ void draw_construction(uint32_t gametime,
4988+ DrawText draw_text,
4989+ const Vector2f& point_on_dst,
4990+ float scale,
4991+ RenderTarget* dst);
4992 };
4993
4994 /**
4995@@ -360,7 +374,6 @@
4996 void cleanup(EditorGameBase&) override;
4997
4998 private:
4999- Player* owner_;
5000 Economy* economy_;
The diff has been truncated for viewing.