Review: Resubmit Addressed all comments and merged trunk.
Diff comments: > === modified file 'src/editor/editorinteractive.cc' > --- src/editor/editorinteractive.cc 2014-11-23 14:34:38 +0000 > +++ src/editor/editorinteractive.cc 2014-11-28 07:21:07 +0000 > @@ -243,8 +243,6 @@ > frametime = m_realtime - lasttime; > > egbase().get_gametime_pointer() += frametime; > - > - g_gr->animate_maptextures(egbase().get_gametime()); > } > > > > === modified file 'src/editor/tools/editor_info_tool.cc' > --- src/editor/tools/editor_info_tool.cc 2014-10-13 10:48:33 +0000 > +++ src/editor/tools/editor_info_tool.cc 2014-11-28 07:21:07 +0000 > @@ -99,7 +99,6 @@ > center.triangle.t == Widelands::TCoords<>::D ? tf.terrain_d() : > tf.terrain_r()); > > buf += "• " + (boost::format(_("Name: %s")) % ter.descname()).str() + > "\n"; > - buf += "• " + (boost::format(_("Texture Number: %i")) % > ter.get_texture()).str() + "\n"; > > // *** Resources info > buf += std::string("\n") + _("Resources:") + "\n"; > > === modified file > 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc' > --- src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc > 2014-11-24 07:25:21 +0000 > +++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc > 2014-11-28 07:21:07 +0000 > @@ -30,7 +30,6 @@ > #include "graphic/graphic.h" > #include "graphic/in_memory_image.h" > #include "graphic/rendertarget.h" > -#include "graphic/terrain_texture.h" > #include "graphic/texture.h" > #include "logic/map.h" > #include "logic/world/editor_category.h" > @@ -75,11 +74,12 @@ > if (ter_is != check[checkfor]) > continue; > > - const Image* tex = g_gr->images().get( > - > g_gr->get_maptexture_data(terrain_descr.get_texture())->get_texture_image()); > - Texture* texture = new Texture(tex->width(), tex->height()); > - texture->blit(Point(0, 0), tex->texture(), Rect(0, 0, > tex->width(), tex->height()), BlendMode::Copy); > - Point pt(1, tex->height() - kSmallPicHeight - 1); > + const Texture& terrain_texture = terrain_descr.get_texture(0); > + Texture* texture = new Texture(terrain_texture.width(), > terrain_texture.height()); > + texture->blit(Point(0, 0), > + &terrain_texture, > + Rect(0, 0, terrain_texture.width(), > terrain_texture.height())); > + Point pt(1, terrain_texture.height() - kSmallPicHeight - 1); > > if (ter_is == TerrainDescription::GREEN) { > texture->blit(pt, green->texture(), Rect(0, 0, > green->width(), green->height())); > > === modified file 'src/graphic/CMakeLists.txt' > --- src/graphic/CMakeLists.txt 2014-11-24 07:25:21 +0000 > +++ src/graphic/CMakeLists.txt 2014-11-28 07:21:07 +0000 > @@ -28,7 +28,6 @@ > image_cache.cc > image_cache.h > USES_SDL2 > - USES_SDL2_IMAGE > DEPENDS > base_log > base_macros > @@ -68,6 +67,16 @@ > graphic_sdl_utils > ) > > +wl_library(graphic_texture_atlas > + SRCS > + texture_atlas.h > + texture_atlas.cc > + DEPENDS > + base_exceptions > + base_macros > + graphic_surface > +) > + > wl_library(graphic > SRCS > align.cc > @@ -116,8 +125,6 @@ > rendertarget.h > richtext.cc > richtext.h > - terrain_texture.cc > - terrain_texture.h > text_parser.cc > text_parser.h > wordwrap.cc > @@ -125,7 +132,6 @@ > USES_OPENGL > USES_SDL2 > USES_SDL2_GFX > - USES_SDL2_IMAGE > USES_SDL2_TTF > DEPENDS > base_deprecated > @@ -150,7 +156,6 @@ > profile > scripting > sound > - ui_basic > wui > wui_text_layout > ) > > === modified file 'src/graphic/gl/dither_program.cc' > --- src/graphic/gl/dither_program.cc 2014-11-24 07:10:03 +0000 > +++ src/graphic/gl/dither_program.cc 2014-11-28 07:21:07 +0000 > @@ -21,35 +21,33 @@ > > #include "base/wexception.h" > #include "graphic/gl/fields_to_draw.h" > -#include "graphic/graphic.h" > #include "graphic/image_io.h" > -#include "graphic/terrain_texture.h" > #include "graphic/texture.h" > -#include "io/fileread.h" > #include "io/filesystem/layered_filesystem.h" > > namespace { > > -using namespace Widelands; > - > const char kDitherVertexShader[] = R"( > #version 120 > > // Attributes. > attribute float attr_brightness; > +attribute vec2 attr_dither_texture_position; > attribute vec2 attr_position; > +attribute vec2 attr_texture_offset; > attribute vec2 attr_texture_position; > -attribute vec2 attr_dither_texture_position; > > // Output of vertex shader. > +varying float var_brightness; > +varying vec2 var_dither_texture_position; > +varying vec2 var_texture_offset; > varying vec2 var_texture_position; > -varying vec2 var_dither_texture_position; > -varying float var_brightness; > > void main() { > + var_brightness = attr_brightness; > + var_dither_texture_position = attr_dither_texture_position; > + var_texture_offset = attr_texture_offset; > var_texture_position = attr_texture_position; > - var_dither_texture_position = attr_dither_texture_position; > - var_brightness = attr_brightness; > gl_Position = vec4(attr_position, 0., 1.); > } > )"; > @@ -59,52 +57,62 @@ > > uniform sampler2D u_dither_texture; > uniform sampler2D u_terrain_texture; > +uniform vec2 u_texture_dimensions; > > varying float var_brightness; > +varying vec2 var_dither_texture_position; > varying vec2 var_texture_position; > -varying vec2 var_dither_texture_position; > +varying vec2 var_texture_offset; > > void main() { > - vec4 clr = texture2D(u_terrain_texture, var_texture_position); > + vec4 clr = texture2D(u_terrain_texture, > + var_texture_offset + u_texture_dimensions * > fract(var_texture_position)); > clr.rgb *= var_brightness; > clr.a = 1. - texture2D(u_dither_texture, var_dither_texture_position).a; > gl_FragColor = clr; > } > )"; > > - > } // namespace > > DitherProgram::DitherProgram() { > gl_program_.build(kDitherVertexShader, kDitherFragmentShader); > > attr_brightness_ = glGetAttribLocation(gl_program_.object(), > "attr_brightness"); > - attr_dither_texture_position_ = > - glGetAttribLocation(gl_program_.object(), > "attr_dither_texture_position"); > + attr_dither_texture_position_ = > glGetAttribLocation(gl_program_.object(), "attr_dither_texture_position"); > attr_position_ = glGetAttribLocation(gl_program_.object(), > "attr_position"); > - attr_texture_position_ = > - glGetAttribLocation(gl_program_.object(), "attr_texture_position"); > + attr_texture_offset_ = glGetAttribLocation(gl_program_.object(), > "attr_texture_offset"); > + attr_texture_position_ = glGetAttribLocation(gl_program_.object(), > "attr_texture_position"); > > u_dither_texture_ = glGetUniformLocation(gl_program_.object(), > "u_dither_texture"); > u_terrain_texture_ = glGetUniformLocation(gl_program_.object(), > "u_terrain_texture"); > - > - SDL_Surface* sdlsurf = load_image_as_sdl_surface("world/pics/edge.png", > g_fs); > - dither_mask_.reset(new Texture(sdlsurf, true)); > + u_texture_dimensions_ = glGetUniformLocation(gl_program_.object(), > "u_texture_dimensions"); > + > + dither_mask_.reset(new > Texture(load_image_as_sdl_surface("world/pics/edge.png", g_fs), true)); > + > + glBindTexture(GL_TEXTURE_2D, dither_mask_->get_gl_texture()); > + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); > + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); > + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); > + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); > + glBindTexture(GL_TEXTURE_2D, 0); > } > > DitherProgram::~DitherProgram() {} > > void DitherProgram::add_vertex(const FieldsToDraw::Field& field, > const int order_index, > - const int terrain) { > - vertices_[terrain].emplace_back(); > - PerVertexData& back = vertices_[terrain].back(); > + const FloatPoint& texture_offset) { > + vertices_.emplace_back(); > + PerVertexData& back = vertices_.back(); > > back.gl_x = field.gl_x; > back.gl_y = field.gl_y; > back.texture_x = field.texture_x; > back.texture_y = field.texture_y; > back.brightness = field.brightness; > + back.texture_offset_x = texture_offset.x; > + back.texture_offset_y = texture_offset.y; > > switch (order_index) { > case 0: > @@ -125,6 +133,7 @@ > } > > void DitherProgram::maybe_add_dithering_triangle( > + const uint32_t gametime, > const DescriptionMaintainer<Widelands::TerrainDescription>& terrains, > const FieldsToDraw& fields_to_draw, > const int idx1, > @@ -135,29 +144,82 @@ > if (my_terrain == other_terrain) { > return; > } > + const Widelands::TerrainDescription& other_terrain_description = > + terrains.get_unmutable(other_terrain); > if (terrains.get_unmutable(my_terrain).dither_layer() < > - terrains.get_unmutable(other_terrain).dither_layer()) { > - add_vertex(fields_to_draw.at(idx1), 0, other_terrain); > - add_vertex(fields_to_draw.at(idx2), 1, other_terrain); > - add_vertex(fields_to_draw.at(idx3), 2, other_terrain); > + other_terrain_description.dither_layer()) { > + const FloatPoint texture_offset = > + > other_terrain_description.get_texture(gametime).texture_coordinates().top_left(); > + add_vertex(fields_to_draw.at(idx1), 0, texture_offset); > + add_vertex(fields_to_draw.at(idx2), 1, texture_offset); > + add_vertex(fields_to_draw.at(idx3), 2, texture_offset); > } > } > > -void DitherProgram::draw(const DescriptionMaintainer<TerrainDescription>& > terrains, > - const FieldsToDraw& fields_to_draw) { > +void DitherProgram::gl_draw(int gl_texture, float texture_w, float > texture_h) { > glUseProgram(gl_program_.object()); > > glEnableVertexAttribArray(attr_brightness_); > glEnableVertexAttribArray(attr_dither_texture_position_); > glEnableVertexAttribArray(attr_position_); > + glEnableVertexAttribArray(attr_texture_offset_); > glEnableVertexAttribArray(attr_texture_position_); > > - if (vertices_.size() != terrains.size()) { > - vertices_.resize(terrains.size()); > - } > - for (auto& container : vertices_) { > - container.clear(); > - } > + glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object()); > + glBufferData(GL_ARRAY_BUFFER, > + sizeof(PerVertexData) * vertices_.size(), > + vertices_.data(), > + GL_STREAM_DRAW); > + > + const auto set_attrib_pointer = [](const int vertex_index, int > num_items, int offset) { > + glVertexAttribPointer(vertex_index, > + num_items, > + GL_FLOAT, > + GL_FALSE, > + sizeof(PerVertexData), > + reinterpret_cast<void*>(offset)); > + }; > + set_attrib_pointer(attr_brightness_, 1, offsetof(PerVertexData, > brightness)); > + set_attrib_pointer(attr_dither_texture_position_, 2, > offsetof(PerVertexData, dither_texture_x)); > + set_attrib_pointer(attr_position_, 2, offsetof(PerVertexData, gl_x)); > + set_attrib_pointer(attr_texture_offset_, 2, offsetof(PerVertexData, > texture_offset_x)); > + set_attrib_pointer(attr_texture_position_, 2, offsetof(PerVertexData, > texture_x)); > + > + glBindBuffer(GL_ARRAY_BUFFER, 0); > + > + // Set the sampler texture unit to 0 > + glActiveTexture(GL_TEXTURE0); > + glBindTexture(GL_TEXTURE_2D, dither_mask_->get_gl_texture()); > + > + glActiveTexture(GL_TEXTURE1); > + glBindTexture(GL_TEXTURE_2D, gl_texture); > + > + glUniform1i(u_dither_texture_, 0); > + glUniform1i(u_terrain_texture_, 1); > + glUniform2f(u_texture_dimensions_, texture_w, texture_h); > + > + glDrawArrays(GL_TRIANGLES, 0, vertices_.size()); > + > + glBindTexture(GL_TEXTURE_2D, 0); > + glActiveTexture(GL_TEXTURE0); > + glBindTexture(GL_TEXTURE_2D, 0); > + > + glDisableVertexAttribArray(attr_brightness_); > + glDisableVertexAttribArray(attr_dither_texture_position_); > + glDisableVertexAttribArray(attr_position_); > + glDisableVertexAttribArray(attr_texture_offset_); > + glDisableVertexAttribArray(attr_texture_position_); > +} > + > +void DitherProgram::draw(const uint32_t gametime, > + const > DescriptionMaintainer<Widelands::TerrainDescription>& terrains, > + const FieldsToDraw& fields_to_draw) { > + // This method expects that all terrains have the same dimensions and > that > + // all are packed into the same texture atlas, i.e. all are in the same > GL > + // texture. It does not check for this invariance for speeds sake. > + > + vertices_.clear(); > + vertices_.reserve(fields_to_draw.size() * 3); > > for (size_t current_index = 0; current_index < fields_to_draw.size(); > ++current_index) { > const FieldsToDraw::Field& field = > fields_to_draw.at(current_index); > @@ -174,17 +236,17 @@ > const int bln_index = > fields_to_draw.calculate_index(field.fx + (field.fy & 1) - > 1, field.fy + 1); > if (bln_index != -1) { > - maybe_add_dithering_triangle(terrains, fields_to_draw, > + maybe_add_dithering_triangle(gametime, terrains, > fields_to_draw, > brn_index, current_index, bln_index, field.ter_d, > field.ter_r); > > const int terrain_dd = > fields_to_draw.at(bln_index).ter_r; > - maybe_add_dithering_triangle(terrains, fields_to_draw, > + maybe_add_dithering_triangle(gametime, terrains, > fields_to_draw, > bln_index, brn_index, current_index, field.ter_d, > terrain_dd); > > const int ln_index = > fields_to_draw.calculate_index(field.fx - 1, field.fy); > if (ln_index != -1) { > const int terrain_l = > fields_to_draw.at(ln_index).ter_r; > - maybe_add_dithering_triangle(terrains, > fields_to_draw, > + maybe_add_dithering_triangle(gametime, > terrains, fields_to_draw, > current_index, bln_index, brn_index, > field.ter_d, terrain_l); > } > } > @@ -192,70 +254,22 @@ > // Dithering for right triangle. > const int rn_index = fields_to_draw.calculate_index(field.fx + > 1, field.fy); > if (rn_index != -1) { > - maybe_add_dithering_triangle(terrains, fields_to_draw, > + maybe_add_dithering_triangle(gametime, terrains, > fields_to_draw, > current_index, brn_index, rn_index, field.ter_r, > field.ter_d); > int terrain_rr = fields_to_draw.at(rn_index).ter_d; > - maybe_add_dithering_triangle(terrains, fields_to_draw, > - brn_index, rn_index, current_index, field.ter_r, > terrain_rr); > + maybe_add_dithering_triangle(gametime, terrains, > fields_to_draw, > + brn_index, rn_index, current_index, > field.ter_r, terrain_rr); > > const int trn_index = > - fields_to_draw.calculate_index(field.fx + (field.fy > & 1), field.fy - 1); > + fields_to_draw.calculate_index(field.fx + > (field.fy & 1), field.fy - 1); > if (trn_index != -1) { > const int terrain_u = > fields_to_draw.at(trn_index).ter_d; > - maybe_add_dithering_triangle(terrains, > fields_to_draw, > + maybe_add_dithering_triangle(gametime, > terrains, fields_to_draw, > rn_index, current_index, brn_index, > field.ter_r, terrain_u); > } > } > } > > - // Set the sampler texture unit to 0 > - glActiveTexture(GL_TEXTURE0); > - glUniform1i(u_dither_texture_, 0); > - glBindTexture(GL_TEXTURE_2D, dither_mask_->get_gl_texture()); > - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); > - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); > - > - glActiveTexture(GL_TEXTURE1); > - glUniform1i(u_terrain_texture_, 1); > - > - // Which triangles to draw? > - glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object()); > - for (size_t i = 0; i < vertices_.size(); ++i) { > - const auto& current_data = vertices_[i]; > - if (current_data.empty()) { > - continue; > - } > - glBindTexture(GL_TEXTURE_2D, > - > g_gr->get_maptexture_data(terrains.get_unmutable(i).get_texture()) > - ->texture() > - .get_gl_texture()); > - > - glBufferData(GL_ARRAY_BUFFER, > - sizeof(PerVertexData) * current_data.size(), > - current_data.data(), > - GL_STREAM_DRAW); > - > - const auto set_attrib_pointer = [](const int vertex_index, int > num_items, int offset) { > - glVertexAttribPointer(vertex_index, > - num_items, > - GL_FLOAT, > - GL_FALSE, > - sizeof(PerVertexData), > - reinterpret_cast<void*>(offset)); > - }; > - set_attrib_pointer(attr_brightness_, 1, offsetof(PerVertexData, > brightness)); > - set_attrib_pointer(attr_dither_texture_position_, 2, > offsetof(PerVertexData, dither_texture_x)); > - set_attrib_pointer(attr_position_, 2, offsetof(PerVertexData, > gl_x)); > - set_attrib_pointer(attr_texture_position_, 2, > offsetof(PerVertexData, texture_x)); > - > - glDrawArrays(GL_TRIANGLES, 0, current_data.size()); > - } > - glBindBuffer(GL_ARRAY_BUFFER, 0); > - > - glDisableVertexAttribArray(attr_brightness_); > - glDisableVertexAttribArray(attr_dither_texture_position_); > - glDisableVertexAttribArray(attr_position_); > - glDisableVertexAttribArray(attr_texture_position_); > - > - glActiveTexture(GL_TEXTURE0); > + const Texture& texture = terrains.get_unmutable(0).get_texture(0); > + gl_draw(texture.get_gl_texture(), texture.texture_coordinates().w, > texture.texture_coordinates().h); > } > > === modified file 'src/graphic/gl/dither_program.h' > --- src/graphic/gl/dither_program.h 2014-11-24 07:10:03 +0000 > +++ src/graphic/gl/dither_program.h 2014-11-28 07:21:07 +0000 > @@ -22,6 +22,7 @@ > > #include <memory> > > +#include "base/point.h" > #include "graphic/gl/fields_to_draw.h" > #include "graphic/gl/utils.h" > #include "logic/description_maintainer.h" > @@ -35,14 +36,16 @@ > ~DitherProgram(); > > // Draws the terrain. > - void draw(const DescriptionMaintainer<Widelands::TerrainDescription>& > terrains, > + void draw(uint32_t gametime, > + const DescriptionMaintainer<Widelands::TerrainDescription>& > terrains, > const FieldsToDraw& fields_to_draw); > > private: > - // Adds the triangle between the indexes (which index 'fields_to_draw' > to > + // Adds the triangle between the indexes (which index 'fields_to_draw') > to > // vertices_ if the my_terrain != other_terrain and the dither_layer() > // agree. > void maybe_add_dithering_triangle( > + uint32_t gametime, > const DescriptionMaintainer<Widelands::TerrainDescription>& terrains, > const FieldsToDraw& fields_to_draw, > int idx1, > @@ -51,10 +54,10 @@ > int my_terrain, > int other_terrain); > > - // Adds the 'field' as an vertex to the 'vertices_' entry for > 'terrain'. The > - // 'order_index' defines which texture position will be used for this > - // vertcx. > - void add_vertex(const FieldsToDraw::Field& field, int order_index, int > terrain); > + // Adds the 'field' as an vertex to the 'vertices_'. The 'order_index' > + // defines which texture position in the dithering texture will be used > for > + // this vertex. > + void add_vertex(const FieldsToDraw::Field& field, int order_index, > const FloatPoint& texture_offset); > > struct PerVertexData { > float gl_x; > @@ -64,8 +67,13 @@ > float brightness; > float dither_texture_x; > float dither_texture_y; > + float texture_offset_x; > + float texture_offset_y; > }; > > + // Call through to GL. > + void gl_draw(int gl_texture, float texture_w, float texture_h); > + > // The program used for drawing the terrain. > Gl::Program gl_program_; > > @@ -73,22 +81,23 @@ > Gl::Buffer gl_array_buffer_; > > // Attributes. > + GLint attr_brightness_; > + GLint attr_dither_texture_position_; > GLint attr_position_; > + GLint attr_texture_offset_; > GLint attr_texture_position_; > - GLint attr_dither_texture_position_; > - GLint attr_brightness_; > > // Uniforms. > + GLint u_dither_texture_; > GLint u_terrain_texture_; > - GLint u_dither_texture_; > + GLint u_texture_dimensions_; > > // The texture mask for the dithering step. > std::unique_ptr<Texture> dither_mask_; > > // Objects below are here to avoid memory allocations on each frame, > they > - // could theoretically also always be recreated. Index as follows: > - // vertices_[terrain_index][vertex_index] > - std::vector<std::vector<PerVertexData>> vertices_; > + // could theoretically also always be recreated. > + std::vector<PerVertexData> vertices_; > }; > > #endif // end of include guard: WL_GRAPHIC_GL_DITHER_PROGRAM_H > > === modified file 'src/graphic/gl/game_renderer.cc' > --- src/graphic/gl/game_renderer.cc 2014-11-24 06:21:16 +0000 > +++ src/graphic/gl/game_renderer.cc 2014-11-28 07:21:07 +0000 > @@ -28,7 +28,6 @@ > #include "graphic/graphic.h" > #include "graphic/rendertarget.h" > #include "graphic/surface.h" > -#include "graphic/terrain_texture.h" > #include "logic/editor_game_base.h" > #include "logic/player.h" > #include "logic/world/world.h" > @@ -165,8 +164,8 @@ > map.normalize_coords(coords); > const FCoords& fcoords = map.get_fcoords(coords); > > - f.texture_x = float(x) / kTextureWidth; > - f.texture_y = float(y) / kTextureHeight; > + f.texture_x = float(x) / kTextureSideLength; > + f.texture_y = float(y) / kTextureSideLength; > > f.gl_x = f.pixel_x = x + surface_offset.x; > f.gl_y = f.pixel_y = y + surface_offset.y - > fcoords.field->get_height() * HEIGHT_FACTOR; > @@ -182,8 +181,8 @@ > } > > const World& world = m_egbase->world(); > - terrain_program_->draw(world.terrains(), fields_to_draw); > - dither_program_->draw(world.terrains(), fields_to_draw); > + terrain_program_->draw(gametime, world.terrains(), fields_to_draw); > + dither_program_->draw(gametime, world.terrains(), fields_to_draw); > road_program_->draw(*surface, fields_to_draw); > > draw_objects(); > > === modified file 'src/graphic/gl/terrain_program.cc' > --- src/graphic/gl/terrain_program.cc 2014-11-24 07:10:03 +0000 > +++ src/graphic/gl/terrain_program.cc 2014-11-28 07:21:07 +0000 > @@ -20,8 +20,6 @@ > #include "graphic/gl/terrain_program.h" > > #include "graphic/gl/fields_to_draw.h" > -#include "graphic/graphic.h" > -#include "graphic/terrain_texture.h" > #include "graphic/texture.h" > > namespace { > @@ -37,17 +35,20 @@ > #version 120 > > // Attributes. > +attribute float attr_brightness; > attribute vec2 attr_position; > -attribute float attr_brightness; > +attribute vec2 attr_texture_offset; > attribute vec2 attr_texture_position; > > // Output of vertex shader. > varying float var_brightness; > +varying vec2 var_texture_offset; > varying vec2 var_texture_position; > > void main() { > var_texture_position = attr_texture_position; > var_brightness = attr_brightness; > + var_texture_offset = attr_texture_offset; > gl_Position = vec4(attr_position, 0., 1.); > } > )"; > @@ -56,12 +57,15 @@ > #version 120 > > uniform sampler2D u_terrain_texture; > +uniform vec2 u_texture_dimensions; > > varying float var_brightness; > varying vec2 var_texture_position; > +varying vec2 var_texture_offset; > > void main() { > - vec4 clr = texture2D(u_terrain_texture, var_texture_position); > + vec4 clr = texture2D(u_terrain_texture, > + var_texture_offset + u_texture_dimensions * > fract(var_texture_position)); > clr.rgb *= var_brightness; > gl_FragColor = clr; > } > @@ -72,25 +76,26 @@ > TerrainProgram::TerrainProgram() { > gl_program_.build(kTerrainVertexShader, kTerrainFragmentShader); > > + attr_brightness_ = glGetAttribLocation(gl_program_.object(), > "attr_brightness"); > attr_position_ = glGetAttribLocation(gl_program_.object(), > "attr_position"); > - attr_texture_position_ = > - glGetAttribLocation(gl_program_.object(), "attr_texture_position"); > - attr_brightness_ = glGetAttribLocation(gl_program_.object(), > "attr_brightness"); > + attr_texture_offset_ = glGetAttribLocation(gl_program_.object(), > "attr_texture_offset"); > + attr_texture_position_ = glGetAttribLocation(gl_program_.object(), > "attr_texture_position"); > > u_terrain_texture_ = glGetUniformLocation(gl_program_.object(), > "u_terrain_texture"); > + u_texture_dimensions_ = glGetUniformLocation(gl_program_.object(), > "u_texture_dimensions"); > } > > -void TerrainProgram::gl_draw(int num_vertices, > - const > DescriptionMaintainer<TerrainDescription>& terrains) { > +void TerrainProgram::gl_draw(int gl_texture, float texture_w, float > texture_h) { > glUseProgram(gl_program_.object()); > > + glEnableVertexAttribArray(attr_brightness_); > glEnableVertexAttribArray(attr_position_); > + glEnableVertexAttribArray(attr_texture_offset_); > glEnableVertexAttribArray(attr_texture_position_); > - glEnableVertexAttribArray(attr_brightness_); > > glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object()); > glBufferData(GL_ARRAY_BUFFER, > - sizeof(TerrainProgram::PerVertexData) * num_vertices, > + sizeof(TerrainProgram::PerVertexData) * vertices_.size(), > vertices_.data(), > GL_STREAM_DRAW); > > @@ -102,55 +107,56 @@ > sizeof(TerrainProgram::PerVertexData), > reinterpret_cast<void*>(offset)); > }; > + set_attrib_pointer(attr_brightness_, 1, offsetof(PerVertexData, > brightness)); > set_attrib_pointer(attr_position_, 2, offsetof(PerVertexData, gl_x)); > - set_attrib_pointer(attr_brightness_, 1, offsetof(PerVertexData, > brightness)); > + set_attrib_pointer(attr_texture_offset_, 2, offsetof(PerVertexData, > texture_offset_x)); > set_attrib_pointer(attr_texture_position_, 2, offsetof(PerVertexData, > texture_x)); > > glBindBuffer(GL_ARRAY_BUFFER, 0); > > - // Set the sampler texture unit to 0 > glActiveTexture(GL_TEXTURE0); > + glBindTexture(GL_TEXTURE_2D, gl_texture); > + > glUniform1i(u_terrain_texture_, 0); > - > - // Which triangles to draw? > - for (size_t i = 0; i < terrains_to_indices_.size(); ++i) { > - const auto& indices = terrains_to_indices_[i]; > - if (indices.empty()) { > - continue; > - } > - glBindTexture(GL_TEXTURE_2D, > - > g_gr->get_maptexture_data(terrains.get_unmutable(i).get_texture()) > - ->texture() > - .get_gl_texture()); > - glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, > indices.data()); > - } > - > + glUniform2f(u_texture_dimensions_, texture_w, texture_h); > + > + glDrawArrays(GL_TRIANGLES, 0, vertices_.size()); > + > + glBindTexture(GL_TEXTURE_2D, 0); > + > + glDisableVertexAttribArray(attr_brightness_); > glDisableVertexAttribArray(attr_position_); > + glDisableVertexAttribArray(attr_texture_offset_); > glDisableVertexAttribArray(attr_texture_position_); > - glDisableVertexAttribArray(attr_brightness_); > -} > - > -void TerrainProgram::draw(const DescriptionMaintainer<TerrainDescription>& > terrains, > +} > + > +void TerrainProgram::add_vertex(const FieldsToDraw::Field& field, > + const FloatPoint& texture_offset) { > + vertices_.emplace_back(); > + PerVertexData& back = vertices_.back(); > + > + back.gl_x = field.gl_x; > + back.gl_y = field.gl_y; > + back.brightness = field.brightness; > + back.texture_x = field.texture_x; > + back.texture_y = field.texture_y; > + back.texture_offset_x = texture_offset.x; > + back.texture_offset_y = texture_offset.y; > +} > + > +void TerrainProgram::draw(uint32_t gametime, > + const DescriptionMaintainer<TerrainDescription>& > terrains, > const FieldsToDraw& fields_to_draw) { > - if (vertices_.size() < fields_to_draw.size()) { > - vertices_.resize(fields_to_draw.size()); > - terrains_to_indices_.resize(terrains.size()); > - } > - for (auto& container : terrains_to_indices_) { > - container.clear(); > - container.reserve(fields_to_draw.size()); > - } > + // This method expects that all terrains have the same dimensions and > that > + // all are packed into the same texture atlas, i.e. all are in the same > GL > + // texture. It does not check for this invariance for speeds sake. > + > + vertices_.clear(); > + vertices_.reserve(fields_to_draw.size() * 3); > > for (size_t current_index = 0; current_index < fields_to_draw.size(); > ++current_index) { > const FieldsToDraw::Field& field = > fields_to_draw.at(current_index); > > - PerVertexData& vertex = vertices_[current_index]; > - vertex.texture_x = field.texture_x; > - vertex.texture_y = field.texture_y; > - vertex.gl_x = field.gl_x; > - vertex.gl_y = field.gl_y; > - vertex.brightness = field.brightness; > - > // The bottom right neighbor fields_to_draw is needed for both > triangles > // associated with this field. If it is not in fields_to_draw, > there is no need to > // draw any triangles. > @@ -163,19 +169,24 @@ > const int bln_index = > fields_to_draw.calculate_index(field.fx + (field.fy & 1) - > 1, field.fy + 1); > if (bln_index != -1) { > - > terrains_to_indices_[field.ter_d].push_back(current_index); > - terrains_to_indices_[field.ter_d].push_back(bln_index); > - terrains_to_indices_[field.ter_d].push_back(brn_index); > + const FloatPoint texture_offset = > + > terrains.get_unmutable(field.ter_d).get_texture(gametime).texture_coordinates().top_left(); > + add_vertex(fields_to_draw.at(current_index), > texture_offset); > + add_vertex(fields_to_draw.at(bln_index), > texture_offset); > + add_vertex(fields_to_draw.at(brn_index), > texture_offset); > } > > // Right triangle. > const int rn_index = fields_to_draw.calculate_index(field.fx + > 1, field.fy); > if (rn_index != -1) { > - > terrains_to_indices_[field.ter_r].push_back(current_index); > - terrains_to_indices_[field.ter_r].push_back(brn_index); > - terrains_to_indices_[field.ter_r].push_back(rn_index); > + const FloatPoint texture_offset = > + > terrains.get_unmutable(field.ter_r).get_texture(gametime).texture_coordinates().top_left(); > + add_vertex(fields_to_draw.at(current_index), > texture_offset); > + add_vertex(fields_to_draw.at(brn_index), > texture_offset); > + add_vertex(fields_to_draw.at(rn_index), texture_offset); > } > } > > - gl_draw(fields_to_draw.size(), terrains); > + const Texture& texture = terrains.get_unmutable(0).get_texture(0); > + gl_draw(texture.get_gl_texture(), texture.texture_coordinates().w, > texture.texture_coordinates().h); > } > > === modified file 'src/graphic/gl/terrain_program.h' > --- src/graphic/gl/terrain_program.h 2014-11-08 18:06:17 +0000 > +++ src/graphic/gl/terrain_program.h 2014-11-28 07:21:07 +0000 > @@ -22,11 +22,12 @@ > > #include <vector> > > +#include "base/point.h" > +#include "graphic/gl/fields_to_draw.h" > #include "graphic/gl/utils.h" > #include "logic/description_maintainer.h" > #include "logic/world/terrain_description.h" > > -class FieldsToDraw; > > class TerrainProgram { > public: > @@ -34,7 +35,7 @@ > TerrainProgram(); > > // Draws the terrain. > - void draw(const DescriptionMaintainer<Widelands::TerrainDescription>& > terrains, > + void draw(uint32_t gametime, const > DescriptionMaintainer<Widelands::TerrainDescription>& terrains, > const FieldsToDraw& fields_to_draw); > > private: > @@ -44,36 +45,36 @@ > float brightness; > float texture_x; > float texture_y; > + float texture_offset_x; > + float texture_offset_y; > }; > - static_assert(sizeof(PerVertexData) == 20, "Wrong padding."); > - > - void gl_draw(int num_vertices, > - const > DescriptionMaintainer<Widelands::TerrainDescription>& terrains); > + static_assert(sizeof(PerVertexData) == 28, "Wrong padding."); > + > + void gl_draw(int gl_texture, float texture_w, float texture_h); > + > + // Adds a vertex to the end of vertices with data from 'field' and > 'texture_coordinates'. > + void add_vertex(const FieldsToDraw::Field& field, const FloatPoint& > texture_coordinates); > + > + // The program used for drawing the terrain. > + Gl::Program gl_program_; > > // The buffer that will contain 'vertices_' for rendering. > Gl::Buffer gl_array_buffer_; > > - // The program used for drawing the terrain. > - Gl::Program gl_program_; > - > // Attributes. > + GLint attr_brightness_; > GLint attr_position_; > + GLint attr_texture_offset_; > GLint attr_texture_position_; > - GLint attr_brightness_; > > // Uniforms. > GLint u_terrain_texture_; > + GLint u_texture_dimensions_; > > // Objects below are kept around to avoid memory allocations on each > frame. > // They could theoretically also be recreated. > - > - // All vertices that are going to get rendered this frame. > std::vector<PerVertexData> vertices_; > > - // A map from terrain index in world.terrains() to indices in > 'vertices_' > - // that have this terrain type. > - std::vector<std::vector<uint16_t>> terrains_to_indices_; > - > DISALLOW_COPY_AND_ASSIGN(TerrainProgram); > }; > > > === modified file 'src/graphic/graphic.cc' > --- src/graphic/graphic.cc 2014-11-24 07:10:03 +0000 > +++ src/graphic/graphic.cc 2014-11-28 07:21:07 +0000 > @@ -19,21 +19,10 @@ > > #include "graphic/graphic.h" > > -#include <cstring> > -#include <iostream> > -#include <memory> > - > -#include <SDL_image.h> > - > -#include "base/deprecated.h" > -#include "base/i18n.h" > #include "base/log.h" > -#include "base/macros.h" > #include "base/wexception.h" > #include "build_info.h" > -#include "config.h" > #include "graphic/animation.h" > -#include "graphic/diranimations.h" > #include "graphic/font_handler.h" > #include "graphic/gl/system_headers.h" > #include "graphic/image.h" > @@ -41,15 +30,11 @@ > #include "graphic/image_transformations.h" > #include "graphic/rendertarget.h" > #include "graphic/screen.h" > -#include "graphic/terrain_texture.h" > #include "graphic/texture.h" > #include "graphic/texture_cache.h" > -#include "io/fileread.h" > #include "io/filesystem/layered_filesystem.h" > #include "io/streamwrite.h" > -#include "logic/roadtype.h" > #include "notifications/notifications.h" > -#include "ui_basic/progresswindow.h" > > using namespace std; > > @@ -162,7 +147,6 @@ > > Graphic::~Graphic() > { > - m_maptextures.clear(); > texture_cache_->flush(); > // TODO(unknown): this should really not be needed, but currently is :( > if (UI::g_fh) > @@ -303,22 +287,6 @@ > save_surface_to_png(image->texture(), sw); > } > > -uint32_t Graphic::new_maptexture(const std::vector<std::string>& > texture_files, const uint32_t frametime) > -{ > - m_maptextures.emplace_back(new TerrainTexture(texture_files, > frametime)); > - return m_maptextures.size(); // ID 1 is at m_maptextures[0] > -} > - > -/** > - * Advance frames for animated textures > -*/ > -void Graphic::animate_maptextures(uint32_t time) > -{ > - for (uint32_t i = 0; i < m_maptextures.size(); ++i) { > - m_maptextures[i]->animate(time); > - } > -} > - > /** > * Save a screenshot to the given file. > */ > @@ -329,15 +297,3 @@ > save_surface_to_png(screen_.get(), sw); > delete sw; > } > - > -/** > - * Retrieve the map texture with the given number > - * \return the actual texture data associated with the given ID. > - */ > -TerrainTexture * Graphic::get_maptexture_data(uint32_t id) > -{ > - --id; // ID 1 is at m_maptextures[0] > - > - assert(id < m_maptextures.size()); > - return m_maptextures[id].get(); > -} > > === modified file 'src/graphic/graphic.h' > --- src/graphic/graphic.h 2014-11-24 07:12:35 +0000 > +++ src/graphic/graphic.h 2014-11-28 07:21:07 +0000 > @@ -20,13 +20,10 @@ > #ifndef WL_GRAPHIC_GRAPHIC_H > #define WL_GRAPHIC_GRAPHIC_H > > -#include <map> > #include <memory> > -#include <vector> > > #include <SDL.h> > > -#include "base/rect.h" > #include "graphic/image_cache.h" > #include "notifications/notifications.h" > #include "notifications/note_ids.h" > @@ -38,7 +35,6 @@ > class Surface; > class TextureCache; > class StreamWrite; > -struct TerrainTexture; > > // Will be send whenever the resolution changes. > struct GraphicResolutionChanged { > @@ -83,13 +79,7 @@ > > void save_png(const Image*, StreamWrite*) const; > > - // Creates a new TerrainTexture() with the given 'frametime' and using > the given > - // 'texture_files' as the images for it and returns it id. > - uint32_t new_maptexture(const std::vector<std::string>& texture_files, > uint32_t frametime); > - void animate_maptextures(uint32_t time); > - > void screenshot(const std::string& fname) const; > - TerrainTexture * get_maptexture_data(uint32_t id); > > private: > // Called when the resolution (might) have changed. > @@ -119,8 +109,6 @@ > std::unique_ptr<ImageCache> image_cache_; > /// This holds all animations. > std::unique_ptr<AnimationManager> animation_manager_; > - > - std::vector<std::unique_ptr<TerrainTexture>> m_maptextures; > }; > > extern Graphic * g_gr; > > === modified file 'src/graphic/minimap_renderer.cc' > --- src/graphic/minimap_renderer.cc 2014-11-24 07:10:03 +0000 > +++ src/graphic/minimap_renderer.cc 2014-11-28 07:21:07 +0000 > @@ -27,7 +27,6 @@ > #include "graphic/graphic.h" > #include "graphic/image.h" > #include "graphic/in_memory_image.h" > -#include "graphic/terrain_texture.h" > #include "graphic/texture.h" > #include "logic/field.h" > #include "logic/map.h" > @@ -61,9 +60,8 @@ > uint32_t pixelcolor = 0; > > if (layers & MiniMapLayer::Terrain) { > - const RGBColor color = > - > g_gr->get_maptexture_data(egbase.world().terrain_descr(f.field->terrain_d()).get_texture()) > - ->get_minimap_color(f.field->get_brightness()); > + const RGBColor& color = > egbase.world().terrain_descr(f.field->terrain_d()).get_minimap_color( > + f.field->get_brightness()); > > pixelcolor = SDL_MapRGBA(&format, color.r, color.g, color.b, > 255); > } > > === modified file 'src/graphic/surface.cc' > --- src/graphic/surface.cc 2014-11-24 07:25:21 +0000 > +++ src/graphic/surface.cc 2014-11-28 07:21:07 +0000 > @@ -162,15 +162,26 @@ > { > glViewport(0, 0, width(), height()); > > - // Source Rectangle. > + // Source Rectangle. We have to take into account that the texture > might be > + // a subtexture in another bigger texture. So we first figure out the > pixel > + // coordinates given it is a full texture (values between 0 and 1) and > then > + // adjust these for the texture coordinates in the parent texture. > FloatRect gl_src_rect; > { > + const FloatRect& texture_coordinates = > texture->texture_coordinates(); > + > float x1 = srcrc.x; > float y1 = srcrc.y; > pixel_to_gl_texture(texture->width(), texture->height(), &x1, > &y1); > + x1 = texture_coordinates.x + x1 * texture_coordinates.w; > + y1 = texture_coordinates.y + y1 * texture_coordinates.h; > + > float x2 = srcrc.x + srcrc.w; > float y2 = srcrc.y + srcrc.h; > pixel_to_gl_texture(texture->width(), texture->height(), &x2, > &y2); > + x2 = texture_coordinates.x + x2 * texture_coordinates.w; > + y2 = texture_coordinates.y + y2 * texture_coordinates.h; > + > gl_src_rect.x = x1; > gl_src_rect.y = y1; > gl_src_rect.w = x2 - x1; > > === removed file 'src/graphic/terrain_texture.cc' > --- src/graphic/terrain_texture.cc 2014-11-24 07:10:03 +0000 > +++ src/graphic/terrain_texture.cc 1970-01-01 00:00:00 +0000 > @@ -1,98 +0,0 @@ > -/* > - * Copyright (C) 2002-2004, 2006, 2010, 2012 by the Widelands Development > Team > - * > - * This program is free software; you can redistribute it and/or > - * modify it under the terms of the GNU General Public License > - * as published by the Free Software Foundation; either version 2 > - * of the License, or (at your option) any later version. > - * > - * This program is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > - * GNU General Public License for more details. > - * > - * You should have received a copy of the GNU General Public License > - * along with this program; if not, write to the Free Software > - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > 02110-1301, USA. > - * > - */ > - > -#include "graphic/terrain_texture.h" > - > -#include <SDL_image.h> > - > -#include "base/deprecated.h" > -#include "base/log.h" > -#include "base/wexception.h" > -#include "graphic/image_io.h" > -#include "graphic/texture.h" > -#include "io/fileread.h" > -#include "io/filesystem/layered_filesystem.h" > - > -using namespace std; > - > -/** > - * Create a texture, taking the pixel data from an Image. > - * Currently it converts a 16 bit image to a 8 bit texture. This should > - * be changed to load a 8 bit file directly, however. > - */ > -TerrainTexture::TerrainTexture(const std::vector<std::string>& > texture_files, const uint32_t frametime) > - : m_frame_num(0), m_frametime(frametime) { > - if (texture_files.empty()) { > - throw wexception("No images for texture."); > - } > - > - for (const std::string& fname : texture_files) { > - if (!g_fs->file_exists(fname)) { > - throw wexception("Could not find %s.", fname.c_str()); > - } > - > - m_texture_image = fname; > - SDL_Surface* sdl_surface = load_image_as_sdl_surface(fname, > g_fs); > - if (!sdl_surface) { > - throw wexception( > - "WARNING: Failed to load texture frame %s: %s\n", > fname.c_str(), IMG_GetError()); > - } > - if (sdl_surface->w != kTextureWidth || sdl_surface->h != > kTextureHeight) { > - SDL_FreeSurface(sdl_surface); > - throw wexception("WARNING: %s: texture must be %ix%i > pixels big\n", > - fname.c_str(), > - kTextureWidth, > - kTextureHeight); > - } > - > - // calculate shades on the first frame > - if (m_textures.empty()) { > - uint8_t top_left_pixel = > static_cast<uint8_t*>(sdl_surface->pixels)[0]; > - SDL_Color top_left_pixel_color = > sdl_surface->format->palette->colors[top_left_pixel]; > - for (int i = -128; i < 128; i++) { > - const int shade = 128 + i; > - int32_t r = > std::min<int32_t>((top_left_pixel_color.r * shade) >> 7, 255); > - int32_t g = > std::min<int32_t>((top_left_pixel_color.g * shade) >> 7, 255); > - int32_t b = > std::min<int32_t>((top_left_pixel_color.b * shade) >> 7, 255); > - m_minimap_colors[shade] = RGBColor(r, g, b); > - } > - } > - m_textures.emplace_back(new Texture(sdl_surface)); > - } > - > - if (m_textures.empty()) > - throw wexception("TerrainTexture has no frames"); > -} > - > -RGBColor TerrainTexture::get_minimap_color(int8_t shade) { > - return m_minimap_colors[128 + shade]; > -} > - > -void TerrainTexture::animate(uint32_t time) > -{ > - m_frame_num = (time / m_frametime) % m_textures.size(); > -} > - > -const std::string& TerrainTexture::get_texture_image() const { > - return m_texture_image; > -} > - > -const Texture& TerrainTexture::texture() const { > - return *m_textures.at(m_frame_num); > -} > > === removed file 'src/graphic/terrain_texture.h' > --- src/graphic/terrain_texture.h 2014-11-24 07:10:03 +0000 > +++ src/graphic/terrain_texture.h 1970-01-01 00:00:00 +0000 > @@ -1,62 +0,0 @@ > -/* > - * Copyright (C) 2002-2004, 2006, 2008-2010, 2012 by the Widelands > Development Team > - * > - * This program is free software; you can redistribute it and/or > - * modify it under the terms of the GNU General Public License > - * as published by the Free Software Foundation; either version 2 > - * of the License, or (at your option) any later version. > - * > - * This program is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > - * GNU General Public License for more details. > - * > - * You should have received a copy of the GNU General Public License > - * along with this program; if not, write to the Free Software > - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > 02110-1301, USA. > - * > - */ > - > -#ifndef WL_GRAPHIC_TERRAIN_TEXTURE_H > -#define WL_GRAPHIC_TERRAIN_TEXTURE_H > - > -#include <memory> > -#include <string> > -#include <vector> > - > -#include <stdint.h> > - > -#include "graphic/colormap.h" > - > -class Texture; > - > -/// TerrainTextures have a fixed size and are squares. > -constexpr int kTextureWidth = 64; > -constexpr int kTextureHeight = kTextureWidth; > - > -// TerrainTexture represents are terrain texture, which is strictly > kTextureWidth by > -// kTextureHeight pixels in size. > -struct TerrainTexture { > - TerrainTexture(const std::vector<std::string>& texture_files, uint32_t > frametime); > - > - // Returns the path to a representative image for this texture. > - const std::string& get_texture_image() const; > - > - // Returns the texture for the current animation phase. > - const Texture& texture() const; > - > - // Return the basic terrain colour to be used in the minimap. > - RGBColor get_minimap_color(int8_t shade); > - > - // Set the current frame according to the game time. > - void animate(uint32_t time); > - > -private: > - RGBColor m_minimap_colors[256]; > - int32_t m_frame_num; > - std::string m_texture_image; > - uint32_t m_frametime; > - std::vector<std::unique_ptr<Texture>> m_textures; > -}; > - > -#endif // end of include guard: WL_GRAPHIC_TERRAIN_TEXTURE_H > > === modified file 'src/graphic/texture.cc' > --- src/graphic/texture.cc 2014-11-24 07:25:21 +0000 > +++ src/graphic/texture.cc 2014-11-28 07:21:07 +0000 > @@ -72,11 +72,6 @@ > > } // namespace > > -/** > - * Initialize an OpenGL texture of the given dimensions. > - * > - * The initial data of the texture is undefined. > - */ > Texture::Texture(int w, int h) > { > init(w, h); > @@ -89,11 +84,6 @@ > GL_UNSIGNED_BYTE, nullptr); > } > > -/** > - * Initialize an OpenGL texture with the contents of the given surface. > - * > - * \note Takes ownership of the given surface. > - */ > Texture::Texture(SDL_Surface * surface, bool intensity) > { > init(surface->w, surface->h); > @@ -132,9 +122,24 @@ > SDL_FreeSurface(surface); > } > > +Texture::Texture(const GLuint texture, const Rect& subrect, int parent_w, > int parent_h) { > + m_w = subrect.w; > + m_h = subrect.h; > + > + m_texture = texture; > + m_owns_texture = false; > + > + m_texture_coordinates.w = static_cast<float>(m_w - 1) / parent_w; > + m_texture_coordinates.h = static_cast<float>(m_h - 1) / parent_h; > + m_texture_coordinates.x = (static_cast<float>(subrect.x) + 0.5) / > parent_w; > + m_texture_coordinates.y = (static_cast<float>(subrect.y) + 0.5) / > parent_h; > +} > + > Texture::~Texture() > { > - glDeleteTextures(1, &m_texture); > + if (m_owns_texture) { > + glDeleteTextures(1, &m_texture); > + } > } > > void Texture::pixel_to_gl(float* x, float* y) const { > @@ -150,6 +155,12 @@ > return; > } > > + m_owns_texture = true; > + m_texture_coordinates.x = 0.f; > + m_texture_coordinates.y = 0.f; > + m_texture_coordinates.w = 1.f; > + m_texture_coordinates.h = 1.f; > + > glGenTextures(1, &m_texture); > glBindTexture(GL_TEXTURE_2D, m_texture); > > @@ -164,13 +175,20 @@ > if (m_w <= 0 || m_h <= 0) { > return; > } > - assert(!m_pixels); > + > + if (m_pixels) { > + throw wexception("Called lock() on locked surface."); > + } > + if (!m_owns_texture) { > + throw wexception("A surface that does not own its pixels can > not be locked.."); > + } > > m_pixels.reset(new uint8_t[m_w * m_h * 4]); > > if (mode == Lock_Normal) { > glBindTexture(GL_TEXTURE_2D, m_texture); > glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, > m_pixels.get()); > + glBindTexture(GL_TEXTURE_2D, 0); > } > } > > @@ -185,6 +203,7 @@ > glTexImage2D > (GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, GL_RGBA, > GL_UNSIGNED_BYTE, m_pixels.get()); > + glBindTexture(GL_TEXTURE_2D, 0); > } > > m_pixels.reset(nullptr); > > === modified file 'src/graphic/texture.h' > --- src/graphic/texture.h 2014-11-24 07:25:21 +0000 > +++ src/graphic/texture.h 2014-11-28 07:21:07 +0000 > @@ -19,6 +19,7 @@ > #ifndef WL_GRAPHIC_TEXTURE_H > #define WL_GRAPHIC_TEXTURE_H > > +#include "base/rect.h" > #include "graphic/gl/system_headers.h" > #include "graphic/surface.h" > > @@ -34,6 +35,10 @@ > // dimensions. > Texture(int w, int h); > > + // Create a logical texture that is a 'subrect' (in Pixel) in > + // another texture. Ownership of 'texture' is not taken. > + Texture(const GLuint texture, const Rect& subrect, int parent_w, int > parent_h); > + > virtual ~Texture(); > > /// Interface implementation > @@ -60,10 +65,20 @@ > > GLuint get_gl_texture() const {return m_texture;} > > + const FloatRect& texture_coordinates() const { > + return m_texture_coordinates; > + } > + > private: > void pixel_to_gl(float* x, float* y) const override; > void init(uint16_t w, uint16_t h); > > + // True if we own the texture, i.e. if we need to delete it. > + bool m_owns_texture; > + > + // Texture coordinates in m_texture. > + FloatRect m_texture_coordinates; > + > GLuint m_texture; > }; > > > === added file 'src/graphic/texture_atlas.cc' > --- src/graphic/texture_atlas.cc 1970-01-01 00:00:00 +0000 > +++ src/graphic/texture_atlas.cc 2014-11-28 07:21:07 +0000 > @@ -0,0 +1,153 @@ > +/* > + * Copyright (C) 2006-2014 by the Widelands Development Team > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + * > + */ > + > +#include "graphic/texture_atlas.h" > + > +#include <cassert> > +#include <memory> > + > +#include "base/wexception.h" > + > +TextureAtlas::Node::Node(const Rect& init_r) : used(false), r(init_r) { > +} > + > +void TextureAtlas::Node::split(int item_w, int item_h) { > + assert(!used); > + > + down.reset(new Node(Rect(r.x, r.y + item_h, r.w, r.h - item_h))); > + right.reset(new Node(Rect(r.x + item_w, r.y, r.w - item_w, item_h))); > + used = true; > + > + // Note: we do not change the size of the root. It is not needed > + // for the remaining algorithm, but we use it to remember the > + // size of the full canvas. > +} > + > + > +TextureAtlas::TextureAtlas() : > + next_index_(0) > +{ > +} > + > +void TextureAtlas::add(const Texture& texture) { > + blocks_.emplace_back(next_index_++, &texture); > +} > + > +// static > +TextureAtlas::Node* TextureAtlas::find_node(Node* node, int w, int h) { > + if (node->used) { > + Node* child_node = find_node(node->right.get(), w, h); > + if (child_node != nullptr) { > + return child_node; > + } > + return find_node(node->down.get(), w, h); > + } > + assert(!node->used); > + > + if ((w <= node->r.w) && (h <= node->r.h)) { > + return node; > + } > + > + return nullptr; > +} > + > +std::unique_ptr<Texture> > TextureAtlas::pack(std::vector<std::unique_ptr<Texture>>* textures) { > + if (blocks_.empty()) { > + throw wexception("Called pack() without blocks."); > + } > + > + // Sort blocks by their biggest side length. This heuristically gives > the > + // best packing. > + std::sort(blocks_.begin(), blocks_.end(), [](const Block& i, const > Block& j) { > + return std::max(i.texture->width(), i.texture->height()) > > + std::max(j.texture->width(), j.texture->height()); > + }); > + > + std::unique_ptr<Node> root( > + new Node(Rect(0, 0, blocks_.begin()->texture->width(), > blocks_.begin()->texture->height()))); > + > + // TODO(sirver): when growing, keep maximum size of gl textures in mind. > + const auto grow_right = [&root](int delta_w) { > + std::unique_ptr<Node> new_root(new Node(Rect(0, 0, root->r.w + > delta_w, root->r.h))); > + new_root->used = true; > + new_root->right.reset(new Node(Rect(root->r.w, 0, delta_w, > root->r.h))); > + new_root->down.reset(root.release()); > + root.reset(new_root.release()); > + }; > + > + const auto grow_down = [&root](int delta_h) { > + std::unique_ptr<Node> new_root(new Node(Rect(0, 0, root->r.w, > root->r.h + delta_h))); > + new_root->used = true; > + new_root->down.reset(new Node(Rect(0, root->r.h, root->r.w, > delta_h))); > + new_root->right.reset(root.release()); > + root.reset(new_root.release()); > + }; > + > + for (Block& block : blocks_) { > + const int block_width = block.texture->width(); > + const int block_height = block.texture->height(); > + > + Node* fitting_node = find_node(root.get(), block_width, > block_height); > + if (fitting_node == nullptr) { > + // Atlas is not big enough to contain this. Grow it and > try again. > + bool can_grow_down = (block_width <= root->r.w); > + bool can_grow_right = (block_height <= root->r.h); > + This is best explained with a picture: http://codeincomplete.com/posts/2011/5/7/bin_packing/ > + // Attempt to keep the texture square-ish. > + bool should_grow_right = can_grow_right && (root->r.h > >= root->r.w + block_width); > + bool should_grow_down = can_grow_down && (root->r.w >= > root->r.h + block_height); > + > + if (should_grow_right) { > + grow_right(block_width); > + } else if (should_grow_down) { > + grow_down(block_height); > + } else if (can_grow_right) { > + grow_right(block_width); > + } else if (can_grow_down) { > + grow_down(block_height); > + } > + fitting_node = find_node(root.get(), block_width, > block_height); > + } > + if (!fitting_node) { > + throw wexception("Unable to fit node in texture > atlas."); > + } > + fitting_node->split(block_width, block_height); > + block.node = fitting_node; > + } > + > + std::unique_ptr<Texture> packed_texture(new Texture(root->r.w, > root->r.h)); > + packed_texture->fill_rect(Rect(0, 0, root->r.w, root->r.h), > RGBAColor(0, 0, 0, 0)); > + > + // Sort blocks by index so that they come back in the correct ordering. > + std::sort(blocks_.begin(), blocks_.end(), [](const Block& i, const > Block& j) { > + return i.index < j.index; > + }); > + > + for (Block& block : blocks_) { > + packed_texture->blit(block.node->r.top_left(), > + block.texture, > + Rect(0, 0, block.texture->width(), > block.texture->height())); > + textures->emplace_back(new Texture( > + packed_texture->get_gl_texture(), > + Rect(block.node->r.top_left(), block.texture->width(), > block.texture->height()), > + root->r.w, > + root->r.h)); > + } > + return packed_texture; > +} > > === added file 'src/graphic/texture_atlas.h' > --- src/graphic/texture_atlas.h 1970-01-01 00:00:00 +0000 > +++ src/graphic/texture_atlas.h 2014-11-28 07:21:07 +0000 > @@ -0,0 +1,78 @@ > +/* > + * Copyright (C) 2006-2014 by the Widelands Development Team > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + * > + */ > + > +#ifndef WL_GRAPHIC_TEXTURE_ATLAS_H > +#define WL_GRAPHIC_TEXTURE_ATLAS_H > + > +#include <memory> > +#include <vector> > + > +#include "base/macros.h" > +#include "graphic/texture.h" > + > +// A 2d bin packer based on the blog post > +// http://codeincomplete.com/posts/2011/5/7/bin_packing/. > +class TextureAtlas { > +public: > + TextureAtlas(); > + > + // Add 'texture' as one of the textures to be packed. Ownership is > + // not taken, but 'texture' must be valid until pack() has been > + // called. > + void add(const Texture& texture); > + > + // Packs the textures and returns the packed texture. 'textures' > + // contains the individual sub textures (that do not own their > + // memory) in the order they have been added by 'add'. > + std::unique_ptr<Texture> pack(std::vector<std::unique_ptr<Texture>>* > textures); > + > +private: > + struct Node { > + Node(const Rect& init_r); > + void split(int w, int h); > + > + bool used; > + Rect r; > + std::unique_ptr<Node> right; > + std::unique_ptr<Node> down; > + > + DISALLOW_COPY_AND_ASSIGN(Node); > + }; > + > + struct Block { > + Block(int init_index, const Texture* init_texture) > + : index(init_index), texture(init_texture) { > + } > + > + int index; > + const Texture* texture; > + Node* node; > + }; > + > + static Node* find_node(Node* root, int w, int h); > + > + int next_index_; > + > + // Unpacked items. > + std::vector<Block> blocks_; > + > + DISALLOW_COPY_AND_ASSIGN(TextureAtlas); > +}; > + > +#endif // end of include guard: WL_GRAPHIC_TEXTURE_ATLAS_H > > === modified file 'src/logic/CMakeLists.txt' > --- src/logic/CMakeLists.txt 2014-10-13 15:04:50 +0000 > +++ src/logic/CMakeLists.txt 2014-11-28 07:21:07 +0000 > @@ -230,6 +230,9 @@ > game_io > graphic > graphic_color > + graphic_image_io > + graphic_surface > + graphic_texture_atlas > helper > io_fileread > io_filesystem > > === modified file 'src/logic/description_maintainer.h' > --- src/logic/description_maintainer.h 2014-09-19 23:33:35 +0000 > +++ src/logic/description_maintainer.h 2014-11-28 07:21:07 +0000 > @@ -55,9 +55,13 @@ > > // Returns the entry with the given 'idx' or nullptr if 'idx' is out of > // bound. Ownership is retained. > + // TODO(sirver): remove get() and use get_mutable > T* get(const int32_t idx) const { > return (idx >= 0 && idx < static_cast<int32_t>(items_.size())) > ? items_[idx].get() : nullptr; > } > + T* get_mutable(const int32_t idx) const { > + return get(idx); > + } > > // Returns the entry at 'index'. If 'index' is out of bounds the result > is > // undefined. > > === modified file 'src/logic/editor_game_base.cc' > --- src/logic/editor_game_base.cc 2014-09-19 12:54:54 +0000 > +++ src/logic/editor_game_base.cc 2014-11-28 07:21:07 +0000 > @@ -20,6 +20,7 @@ > #include "logic/editor_game_base.h" > > #include <algorithm> > +#include <memory> > #include <set> > > #include "base/i18n.h" > @@ -113,11 +114,12 @@ > > try { > lua_->run_script("world/init.lua"); > - } > - catch (const WException& e) { > + } catch (const WException& e) { > log("Could not read world information: %s", e.what()); > throw; > } > + > + world_->load_graphics(); > } > return world_.get(); > } > > === modified file 'src/logic/field.cc' > --- src/logic/field.cc 2014-07-22 09:54:49 +0000 > +++ src/logic/field.cc 2014-11-28 07:21:07 +0000 > @@ -50,7 +50,7 @@ > b = -128; > else if (b > 127) > b = 127; > - brightness = static_cast<int8_t>(b); //TODO(unknown): ARGH !! > + brightness = static_cast<int8_t>(b); > } > > } > > === modified file 'src/logic/game.cc' > --- src/logic/game.cc 2014-10-11 15:56:02 +0000 > +++ src/logic/game.cc 2014-11-28 07:21:07 +0000 > @@ -613,9 +613,6 @@ > // the timings of savings. > cmdqueue().run_queue(m_ctrl->get_frametime(), > get_gametime_pointer()); > > - if (g_gr) // not in dedicated server mode > - g_gr->animate_maptextures(get_gametime()); > - > // check if autosave is needed > m_savehandler.think(*this, WLApplication::get()->get_time()); > } > > === modified file 'src/logic/world/terrain_description.cc' > --- src/logic/world/terrain_description.cc 2014-09-19 12:54:54 +0000 > +++ src/logic/world/terrain_description.cc 2014-11-28 07:21:07 +0000 > @@ -19,9 +19,12 @@ > > #include "logic/world/terrain_description.h" > > +#include <memory> > + > #include <boost/format.hpp> > > #include "graphic/graphic.h" > +#include "graphic/texture.h" > #include "logic/game_data_error.h" > #include "logic/world/editor_category.h" > #include "logic/world/world.h" > @@ -86,19 +89,18 @@ > throw GameDataError("%s: temperature is not in Kelvin.", > name_.c_str()); > } > > - const std::vector<std::string> textures = > + texture_paths_ = > table.get_table("textures")->array_entries<std::string>(); > - int frame_length = FRAME_LENGTH; > - if (textures.empty()) { > + frame_length_ = FRAME_LENGTH; > + if (texture_paths_.empty()) { > throw GameDataError("Terrain %s has no images.", name_.c_str()); > - } else if (textures.size() == 1) { > + } else if (texture_paths_.size() == 1) { > if (table.has_key("fps")) { > throw GameDataError("Terrain %s with one images must > not have fps.", name_.c_str()); > } > } else { > - frame_length = 1000 / get_positive_int(table, "fps"); > + frame_length_ = 1000 / get_positive_int(table, "fps"); > } > - texture_ = g_gr->new_maptexture(textures, frame_length); > > for (const std::string& resource : > table.get_table("valid_resources")->array_entries<std::string>()) { > @@ -121,8 +123,19 @@ > TerrainDescription::~TerrainDescription() { > } > > -uint32_t TerrainDescription::get_texture() const { > - return texture_; > +const Texture& TerrainDescription::get_texture(uint32_t gametime) const { > + return *textures_.at((gametime / frame_length_) % textures_.size()); > +} > + > +void TerrainDescription::add_texture(std::unique_ptr<Texture> texture) { > + if (texture->width() != kTextureSideLength || texture->height() != > kTextureSideLength) { > + throw wexception("Tried to add a texture with wrong size."); > + } > + textures_.emplace_back(std::move(texture)); > +} > + > +const std::vector<std::string>& TerrainDescription::texture_paths() const { > + return texture_paths_; > } > > TerrainDescription::Type TerrainDescription::get_is() const { > @@ -149,7 +162,7 @@ > return valid_resources_.size(); > } > > -bool TerrainDescription::is_resource_valid(const int32_t res) const { > +bool TerrainDescription::is_resource_valid(const int res) const { > for (const uint8_t resource_index : valid_resources_) { > if (resource_index == res) { > return true; > @@ -158,15 +171,15 @@ > return false; > } > > -int8_t TerrainDescription::get_default_resource() const { > +int TerrainDescription::get_default_resource() const { > return default_resource_index_; > } > > -int32_t TerrainDescription::get_default_resource_amount() const { > +int TerrainDescription::get_default_resource_amount() const { > return default_resource_amount_; > } > > -int32_t TerrainDescription::dither_layer() const { > +int TerrainDescription::dither_layer() const { > return dither_layer_; > } > > @@ -182,4 +195,19 @@ > return fertility_; > } > > +void TerrainDescription::set_minimap_color(const RGBColor& color) { > + for (int i = -128; i < 128; i++) { > + const int shade = 128 + i; > + int new_r = std::min<int>((color.r * shade) >> 7, 255); > + int new_g = std::min<int>((color.g * shade) >> 7, 255); > + int new_b = std::min<int>((color.b * shade) >> 7, 255); > + minimap_colors_[shade] = RGBColor(new_r, new_g, new_b); > + } > +} > + > +const RGBColor& TerrainDescription::get_minimap_color(int shade) { > + assert(-128 <= shade && shade <= 127); > + return minimap_colors_[128 + shade]; > +} > + > } // namespace Widelands > > === modified file 'src/logic/world/terrain_description.h' > --- src/logic/world/terrain_description.h 2014-09-10 10:18:46 +0000 > +++ src/logic/world/terrain_description.h 2014-11-28 07:21:07 +0000 > @@ -20,19 +20,26 @@ > #ifndef WL_LOGIC_WORLD_TERRAIN_DESCRIPTION_H > #define WL_LOGIC_WORLD_TERRAIN_DESCRIPTION_H > > +#include <memory> > #include <string> > +#include <vector> > > #include "base/macros.h" > +#include "graphic/color.h" > #include "logic/widelands.h" > #include "logic/world/resource_description.h" > > class LuaTable; > +class Texture; > > namespace Widelands { > > class EditorCategory; > class World; > > +/// TerrainTextures have a fixed size and are squares. > +constexpr int kTextureSideLength = 64; > + > class TerrainDescription { > public: > enum Type { > @@ -53,8 +60,19 @@ > /// The name showed to users of Widelands. Usually translated. > const std::string& descname() const; > > - /// Returns the texture index for this terrain. > - uint32_t get_texture() const; > + > + const std::vector<std::string>& texture_paths() const; > + > + /// Returns the texture for the given gametime. > + const Texture& get_texture(uint32_t gametime) const; > + void add_texture(std::unique_ptr<Texture> texture); > + > + // Sets the base minimap color. > + void set_minimap_color(const RGBColor& color); > + > + // Return the basic terrain colour to be used in the minimap. > + // 'shade' must be a brightness value, i.e. in [-128, 127]. > + const RGBColor& get_minimap_color(int shade); > > /// Returns the type of terrain this is (water, walkable, and so on). > Type get_is() const; > @@ -70,7 +88,7 @@ > > /// Returns the resource index that can by default always be found in > this > /// terrain. > - int8_t get_default_resource() const; > + int get_default_resource() const; > > /// Returns the default amount of resources you can find in this > terrain. > int32_t get_default_resource_amount() const; > @@ -98,14 +116,16 @@ > const EditorCategory* editor_category_; ///< not owned. > Type is_; > std::vector<uint8_t> valid_resources_; > - int8_t default_resource_index_; > - int32_t default_resource_amount_; > - const std::vector<std::string> texture_paths_; > - int32_t dither_layer_; > - uint32_t texture_; ///< renderer's texture > + int default_resource_index_; > + int default_resource_amount_; > + int dither_layer_; > + int frame_length_; > double temperature_; > double fertility_; > double humidity_; > + std::vector<std::string> texture_paths_; > + std::vector<std::unique_ptr<Texture>> textures_; > + RGBColor minimap_colors_[256]; > > DISALLOW_COPY_AND_ASSIGN(TerrainDescription); > }; > > === modified file 'src/logic/world/world.cc' > --- src/logic/world/world.cc 2014-09-10 10:18:46 +0000 > +++ src/logic/world/world.cc 2014-11-28 07:21:07 +0000 > @@ -19,26 +19,18 @@ > > #include "logic/world/world.h" > > -#include <iostream> > #include <memory> > -#include <sstream> > > -#include "base/i18n.h" > -#include "base/log.h" > -#include "base/wexception.h" > -#include "graphic/graphic.h" > -#include "io/fileread.h" > -#include "io/filesystem/layered_filesystem.h" > -#include "io/filewrite.h" > +#include "graphic/image_io.h" > +#include "graphic/texture.h" > +#include "graphic/texture_atlas.h" > +#include "logic/bob.h" > #include "logic/critter.h" > #include "logic/game_data_error.h" > #include "logic/immovable.h" > -#include "logic/parse_map_object_types.h" > -#include "logic/widelands.h" > #include "logic/world/editor_category.h" > #include "logic/world/resource_description.h" > #include "logic/world/terrain_description.h" > -#include "profile/profile.h" > > namespace Widelands { > > @@ -54,6 +46,42 @@ > World::~World() { > } > > +void World::load_graphics() { > + TextureAtlas ta; > + > + // These will be deleted at the end of the method. > + std::vector<std::unique_ptr<Texture>> individual_textures_; > + > + for (size_t i = 0; i < terrains_->size(); ++i) { > + TerrainDescription* terrain = terrains_->get_mutable(i); > + for (size_t j = 0; j < terrain->texture_paths().size(); ++j) { > + SDL_Surface* sdl_surface = > load_image_as_sdl_surface(terrain->texture_paths()[j]); > + > + // Set the minimap color on the first loaded image. > + if (j == 0) { > + uint8_t top_left_pixel = > static_cast<uint8_t*>(sdl_surface->pixels)[0]; > + const SDL_Color top_left_pixel_color = > + > sdl_surface->format->palette->colors[top_left_pixel]; > + terrain->set_minimap_color( > + RGBColor(top_left_pixel_color.r, > top_left_pixel_color.g, top_left_pixel_color.b)); > + } > + individual_textures_.emplace_back(new > Texture(sdl_surface)); > + ta.add(*individual_textures_.back()); > + } > + } > + > + std::vector<std::unique_ptr<Texture>> textures; > + terrain_texture_ = ta.pack(&textures); > + > + int next_texture_to_move = 0; > + for (size_t i = 0; i < terrains_->size(); ++i) { > + TerrainDescription* terrain = terrains_->get_mutable(i); > + for (size_t j = 0; j < terrain->texture_paths().size(); ++j) { > + > terrain->add_texture(std::move(textures.at(next_texture_to_move++))); > + } > + } > +} > + > const DescriptionMaintainer<TerrainDescription>& World::terrains() const { > return *terrains_; > } > > === modified file 'src/logic/world/world.h' > --- src/logic/world/world.h 2014-09-10 10:18:46 +0000 > +++ src/logic/world/world.h 2014-11-28 07:21:07 +0000 > @@ -23,11 +23,16 @@ > #include <memory> > > #include "base/macros.h" > -#include "logic/bob.h" > #include "logic/description_maintainer.h" > +#include "logic/widelands.h" > + > +class LuaInterface; > +class LuaTable; > +class Texture; > > namespace Widelands { > > +class BobDescr; > class EditorCategory; > class EditorGameBase; > class ResourceDescription; > @@ -40,7 +45,7 @@ > class World { > public: > World(); > - ~World(); // Defined in .cc because all forward declarations are known > then. > + ~World(); > > // TODO(sirver): Refactor these to only return the > description_maintainer so that world > // becomes a pure container. > @@ -83,6 +88,10 @@ > const DescriptionMaintainer<EditorCategory>& > editor_terrain_categories() const; > const DescriptionMaintainer<EditorCategory>& > editor_immovable_categories() const; > > + // Load the graphics for the world. Animations are loaded on > + // demand. > + void load_graphics(); > + > private: > std::unique_ptr<DescriptionMaintainer<BobDescr>> bobs_; > std::unique_ptr<DescriptionMaintainer<ImmovableDescr>> immovables_; > @@ -90,6 +99,7 @@ > std::unique_ptr<DescriptionMaintainer<ResourceDescription>> resources_; > std::unique_ptr<DescriptionMaintainer<EditorCategory>> > editor_terrain_categories_; > std::unique_ptr<DescriptionMaintainer<EditorCategory>> > editor_immovable_categories_; > + std::unique_ptr<Texture> terrain_texture_; > > DISALLOW_COPY_AND_ASSIGN(World); > }; > > === modified file 'src/wui/interactive_base.cc' > --- src/wui/interactive_base.cc 2014-11-27 11:15:34 +0000 > +++ src/wui/interactive_base.cc 2014-11-28 07:21:07 +0000 > @@ -446,7 +446,10 @@ > ((fps_format % > (1000.0 / m_frametime) % (1000.0 / (m_avg_usframetime > / 1000))) > .str(), UI_FONT_SIZE_SMALL); > - dst.blit(Point(5, (is_game) ? 25 : 5), > UI::g_fh1->render(fps_text), BlendMode::UseAlpha, UI::Align_Left); > + dst.blit(Point(5, (is_game) ? 25 : 5), > + UI::g_fh1->render(fps_text), > + BlendMode::UseAlpha, > + UI::Align_Left); > } > } > > -- https://code.launchpad.net/~widelands-dev/widelands/texture_atlas/+merge/243119 Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/texture_atlas. _______________________________________________ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp