Author: shadowmaster
Date: Sun Apr 5 04:15:14 2009
New Revision: 34515
URL: http://svn.gna.org/viewcvs/wesnoth?rev=34515&view=rev
Log:
Finish refactoring of storyscreen code.
There are new bugs that must be fixed, thus this code is still disabled
unless the --shadowm-storyscreen switch is used.
Modified:
trunk/src/storyscreen/controller.cpp
trunk/src/storyscreen/controller.hpp
trunk/src/storyscreen/interface.cpp
trunk/src/storyscreen/page.cpp
trunk/src/storyscreen/page.hpp
trunk/src/storyscreen/render.cpp
trunk/src/storyscreen/render.hpp
Modified: trunk/src/storyscreen/controller.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/controller.cpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/controller.cpp (original)
+++ trunk/src/storyscreen/controller.cpp Sun Apr 5 04:15:14 2009
@@ -21,10 +21,9 @@
*/
#include "global.hpp"
-#include "SDL.h"
-
#include "storyscreen/controller.hpp"
#include "storyscreen/page.hpp"
+#include "storyscreen/render.hpp"
#include "asserts.hpp"
#include "foreach.hpp"
@@ -35,10 +34,8 @@
#include "gamestatus.hpp"
#include "gettext.hpp"
#include "intro.hpp"
-#include "language.hpp"
#include "log.hpp"
-#include "sound.hpp"
-#include "text.hpp"
+#include "widgets/button.hpp"
#define ERR_NG LOG_STREAM(err , engine)
#define LOG_NG LOG_STREAM(info, engine)
@@ -144,9 +141,47 @@
pages_.clear();
}
-void controller::show_all_pages() const
+void controller::show_all_pages()
{
- STUB();
+ if(pages_.empty()) {
+ LOG_NG << "no storyscreen pages to show\n";
+ }
+
+ size_t page_n = 0, pages_c = pages_.size();
+ while((page_n = show_page(page_n)) < pages_c)
+ ;
+}
+
+size_t controller::show_page(size_t page_num)
+{
+ if(page_num >= pages_.size()) {
+ ERR_NG << "attempted to display inexistant storyscreen page: "
<< page_num+1 << " (of " << pages_.size() << ")\n";
+ return pages_.size();
+ }
+
+ LOG_NG << "displaying storyscreen page " << page_num+1 << " of " <<
pages_.size() << '\n';
+
+ page* const p = pages_[page_num];
+ ASSERT_LOG( p != NULL, "Ouch: hit NULL storyscreen page in collection"
);
+
+ // TODO:
+ // gui::button back_button(disp_.video(),std::string("< ")+_("Next"));
+ gui::button next_button(disp_.video(),_("Next") + std::string(" >"));
+ gui::button skip_button(disp_.video(),_("Skip"));
+
+ page_ui ui(*p, disp_, next_button, skip_button);
+ switch(ui.show()) {
+ case page_ui::NEXT:
+ return page_num+1;
+ case page_ui::BACK:
+ return(page_num > 0 ? page_num-1 : page_num);
+ case page_ui::SKIP:
+ return pages_.size();
+ default:
+ throw quit();
+ }
+
+ return 0;
}
} // end namespace storyscreen
Modified: trunk/src/storyscreen/controller.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/controller.hpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/controller.hpp (original)
+++ trunk/src/storyscreen/controller.hpp Sun Apr 5 04:15:14 2009
@@ -43,10 +43,14 @@
~controller();
/**
- * Display story screen pages.
- */
- void show_all_pages() const;
-
+ * Display all story screen pages in a first..last sequence.
+ */
+ void show_all_pages();
+ /**
+ * Display a single story screen page.
+ * @return Next page requested by the user interface.
+ */
+ size_t show_page(size_t page_num);
private:
// Executes WML flow instructions and inserts pages.
@@ -73,6 +77,7 @@
public:
struct no_pages {};
+ struct quit {};
};
Modified: trunk/src/storyscreen/interface.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/interface.cpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/interface.cpp (original)
+++ trunk/src/storyscreen/interface.cpp Sun Apr 5 04:15:14 2009
@@ -54,12 +54,16 @@
void show_storyscreen(display& disp, const vconfig& story_cfg, const
std::string& scenario_name)
{
- STUB();
LOG_NG << "entering storyscreen procedure...\n";
storyscreen::controller ctl(disp, story_cfg, scenario_name);
- ctl.show_all_pages();
+ try {
+ ctl.show_all_pages();
+ } catch(storyscreen::controller::quit const&) {
+ LOG_NG << "leaving storyscreen for titlescreen...\n";
+ STUB();
+ }
LOG_NG << "leaving storyscreen procedure...\n";
}
Modified: trunk/src/storyscreen/page.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/page.cpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/page.cpp (original)
+++ trunk/src/storyscreen/page.cpp Sun Apr 5 04:15:14 2009
@@ -21,16 +21,18 @@
#include "global.hpp"
#include "asserts.hpp"
-#include "image.hpp"
+#include "foreach.hpp"
#include "log.hpp"
#include "storyscreen/page.hpp"
#include "config.hpp"
#include "gamestatus.hpp"
#include "game_events.hpp"
+#include "image.hpp"
#include "serialization/string_utils.hpp"
#include "util.hpp"
#include "variable.hpp"
+#include "video.hpp"
// TODO: remove when completed
#include "stub.hpp"
@@ -247,10 +249,5 @@
}
}
-void page::render() const
-{
-}
-
-
} // end namespace storyscreen
Modified: trunk/src/storyscreen/page.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/page.hpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/page.hpp (original)
+++ trunk/src/storyscreen/page.hpp Sun Apr 5 04:15:14 2009
@@ -23,12 +23,14 @@
#define STORYSCREEN_PAGE_HPP_INCLUDED
#include <string>
+#include <utility>
#include <vector>
#include "sdl_utils.hpp"
class config;
class vconfig;
+class display;
class game_state;
namespace storyscreen {
@@ -93,6 +95,11 @@
enum TITLE_ALIGNMENT {
LEFT, CENTERED, RIGHT
};
+ enum RESULT {
+ NEXT,
+ SKIP,
+ QUIT
+ };
page(game_state& state_of_game, const vconfig& page_cfg);
@@ -107,7 +114,9 @@
void set_text(const std::string& text) { text_ = text; }
void set_title(const std::string& title) { text_title_ = title; }
- void render() const;
+ const std::vector<floating_image> get_floating_images() const {
+ return floating_images_;
+ }
private:
page();
@@ -129,6 +138,8 @@
std::string music_;
std::vector<floating_image> floating_images_;
+
+ friend class page_ui;
};
} // end namespace storyscreen
Modified: trunk/src/storyscreen/render.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/render.cpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/render.cpp (original)
+++ trunk/src/storyscreen/render.cpp Sun Apr 5 04:15:14 2009
@@ -1,5 +1,6 @@
/* $Id$ */
/*
+ Copyright (C) 2003 - 2009 by David White <[email protected]>
Copyright (C) 2009 by Ignacio R. Morelle <[email protected]>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
@@ -21,10 +22,366 @@
#include "global.hpp"
#include "asserts.hpp"
#include "foreach.hpp"
+#include "log.hpp"
#include "storyscreen/page.hpp"
#include "storyscreen/render.hpp"
+#include "display.hpp"
+#include "image.hpp"
+#include "image_function.hpp"
+#include "language.hpp"
+#include "marked-up_text.hpp" // TODO: replace with Pango
+#include "sound.hpp"
+#include "text.hpp"
#include "video.hpp"
// TODO: remove when completed
#include "stub.hpp"
+
+#define ERR_NG LOG_STREAM(err, engine)
+
+#ifndef LOW_MEM
+namespace {
+ void blur_area(CVideo& video, int y, int h)
+ {
+ SDL_Rect blur_rect = { 0, y, screen_area().w, h };
+ surface blur = get_surface_portion(video.getSurface(),
blur_rect);
+ blur = blur_surface(blur, 1, false);
+ video.blit_surface(0, y, blur);
+ }
+}
+#endif /* ! LOW_MEM */
+
+namespace storyscreen {
+
+page_ui::page_ui(page& p, display& disp, gui::button& next_button,
gui::button& skip_button)
+ : p_(p)
+ , disp_(disp)
+ , video_(disp.video())
+ , keys_()
+ , next_button_(next_button)
+ , skip_button_(skip_button)
+ , ret_(NEXT)
+ , scale_factor_(1.0)
+ , base_rect_()
+ , background_(NULL)
+ , imgs_()
+ , has_background_(false)
+ , text_x_(200)
+ , text_y_(400)
+ , buttons_x_()
+ , buttons_y_()
+{
+ // Build background surface
+ if(p_.background_file_.empty() != true) {
+ background_.assign( image::get_image(p.background_file_) );
+ }
+ has_background_ = !background_.null();
+ if(background_.null() || background_->w * background_-> h == 0) {
+ background_.assign( create_neutral_surface(video_.getx(),
video_.gety()) );
+ }
+
+ const double xscale = 1.0 * video_.getx() / background_->w;
+ const double yscale = 1.0 * video_.gety() / background_->h;
+ scale_factor_ = p_.scale_background_ ? std::min<double>(xscale,yscale)
: 1.0;
+
+ background_ =
+ scale_surface(background_,
static_cast<int>(background_->w*scale_factor_),
static_cast<int>(background_->h*scale_factor_));
+
+ ASSERT_LOG(background_.null() == false, "Ouch: storyscreen page
background got NULL");
+
+ base_rect_.x = (video_.getx() - background_->w) / 2;
+ base_rect_.y = (video_.gety() - background_->h) / 2;
+ base_rect_.w = background_->w;
+ base_rect_.h = background_->h;
+
+#ifdef USE_TINY_GUI
+ // Use the whole screen for text on tinygui
+ text_x_ = 10;
+ text_y_ = 0;
+ buttons_x_ = video_.getx() - 50;
+ buttons_y_ = base_rect_.y + base_rect_.h - 20;
+
+ next_button_.set_location(buttons_x_, buttons_y_ - 20);
+ skip_button_.set_location(buttons_x_, buttons_y_);
+#else
+ text_x_ = 200;
+ text_y_ = video_.gety() - 200;
+ buttons_x_ = video_.getx() - 200 - 40;
+ buttons_y_ = video_.gety() - 40;
+
+ next_button_.set_location(buttons_x_, buttons_y_ - 30);
+ skip_button_.set_location(buttons_x_, buttons_y_);
+#endif
+
+ // Build floating image surfaces
+ foreach(const floating_image& fi, p_.floating_images_) {
+ imgs_.push_back( fi.get_render_input(scale_factor_, base_rect_)
);
+ }
+}
+
+void page_ui::render_text_box()
+{
+ const bool rtl = current_language_rtl();
+
+ const int max_width = next_button_.location().x - 10 - text_x_;
+ const std::string storytxt =
+ font::word_wrap_text(p_.text_, font::SIZE_PLUS, max_width);
+
+ utils::utf8_iterator itor(storytxt);
+
+ bool skip = false, last_key = true;
+ int update_y = 0, update_h = 0;
+
+ // Draw the text box
+ if(storytxt.empty() != true)
+ {
+ // this should kill the tiniest flickering caused
+ // by the buttons being hidden and unhidden in this scope.
+ update_locker locker(video_);
+
+ const SDL_Rect total_size = font::draw_text(
+ NULL, screen_area(), font::SIZE_PLUS,
+ font::NORMAL_COLOUR, storytxt, 0, 0
+ );
+
+ next_button_.hide();
+ skip_button_.hide();
+
+ if(text_y_ + 20 + total_size.h > screen_area().h) {
+ text_y_ = screen_area().h > total_size.h + 1 ?
screen_area().h - total_size.h - 21 : 0;
+ }
+
+ update_y = text_y_;
+ update_h = screen_area().h - text_y_;
+
+#ifndef LOW_MEM
+ blur_area(video_, update_y, update_h);
+#endif
+
+ draw_solid_tinted_rectangle(
+ 0, text_y_, screen_area().w, screen_area().h-text_y_,
+ 0, 0, 0, 0.5, video_.getSurface()
+ );
+
+ // Draw a nice border
+ if(has_background_) {
+ // FIXME: perhaps hard-coding the image path isn't a
really
+ // good idea - it must not be forgotten if someone
decides to switch
+ // the image directories around.
+ surface top_border =
image::get_image("dialogs/translucent54-border-top.png");
+ top_border = scale_surface_blended(top_border,
screen_area().w, top_border->h);
+ update_y = text_y_ - top_border->h;
+ update_h += top_border->h;
+#ifndef LOW_MEM
+ blur_area(video_, update_y, top_border->h);
+#endif
+ video_.blit_surface(0, text_y_ - top_border->h,
top_border);
+ }
+
+ // Make buttons aware of the changes in the background
+ next_button_.set_location(next_button_.location());
+ next_button_.hide(false);
+ skip_button_.set_location(skip_button_.location());
+ skip_button_.hide(false);
+ }
+
+ if(imgs_.empty()) {
+ update_whole_screen();
+ } else if(update_h > 0) {
+ update_rect(0,update_y,screen_area().w,update_h);
+ }
+
+ if(rtl) {
+ text_x_ += max_width;
+ }
+
+#ifdef USE_TINY_GUI
+ int xpos = text_x_, ypos = text_y_ + 10;
+#else
+ int xpos = text_x_, ypos = text_y_ + 20;
+#endif
+
+ // The maximum position that text can reach before wrapping
+ size_t height = 0;
+
+ while(true) {
+ if(itor != utils::utf8_iterator::end(storytxt)) {
+ if(*itor == '\n') {
+ xpos = text_x_;
+ ypos += height;
+ ++itor;
+ }
+ // Output the character
+ /** @todo FIXME: this is broken: it does not take
kerning into account. */
+ std::string tmp;
+ tmp.append(itor.substr().first, itor.substr().second);
+ if(rtl) {
+ xpos -= font::line_width(tmp, font::SIZE_PLUS);
+ }
+ const SDL_Rect rect = font::draw_text(
+ &video_, screen_area(), font::SIZE_PLUS,
+ font::NORMAL_COLOUR, tmp, xpos, ypos,
+ false
+ );
+
+ if(rect.h > height)
+ height = rect.h;
+ if(!rtl)
+ xpos += rect.w;
+ update_rect(rect);
+
+ ++itor;
+ if(itor == utils::utf8_iterator::end(storytxt)) {
+ skip = true;
+ }
+ }
+
+ const bool keydown = keys_[SDLK_SPACE] || keys_[SDLK_RETURN] ||
keys_[SDLK_KP_ENTER];
+
+ if((keydown && !last_key) || next_button_.pressed()) {
+ if(skip == true || itor ==
utils::utf8_iterator::end(storytxt)) {
+ ret_ = NEXT;
+ break;
+ } else {
+ skip = true;
+ }
+ }
+
+ last_key = keydown;
+
+ if(keys_[SDLK_ESCAPE] || skip_button_.pressed()) {
+ ret_ = SKIP;
+ return;
+ }
+
+ events::pump();
+ events::raise_process_event();
+ events::raise_draw_event();
+ disp_.flip();
+
+ if(!skip || itor == utils::utf8_iterator::end(storytxt)) {
+ disp_.delay(20);
+ }
+ }
+
+ draw_solid_tinted_rectangle(
+ 0, 0, video_.getx(), video_.gety(), 0, 0, 0,
+ 1.0, video_.getSurface()
+ );
+}
+
+void page_ui::render_title_box()
+{
+ // Text color
+ const int r = 0, g = 0, b = 0;
+
+ const SDL_Rect area = { 0, 0, video_.getx(), video_.gety() };
+ const SDL_Rect text_shadow_rect = font::line_size(p_.text_title_,
font::SIZE_XLARGE);
+
+ draw_solid_tinted_rectangle(
+ base_rect_.x + 15, base_rect_.y + 15,
+ text_shadow_rect.w + 10, text_shadow_rect.h + 10, r, g, b, 0.5,
video_.getSurface()
+ );
+
+ update_rect(font::draw_text(
+ &video_, area, font::SIZE_XLARGE, font::BIGMAP_COLOUR,
+ p_.text_title_, base_rect_.x + 20, base_rect_.y + 20
+ ));
+}
+
+void page_ui::render_background()
+{
+ draw_solid_tinted_rectangle(
+ 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0,
+ video_.getSurface()
+ );
+ SDL_BlitSurface(background_, NULL, video_.getSurface(), &base_rect_);
+}
+
+bool page_ui::render_floating_images()
+{
+ events::raise_draw_event();
+ update_whole_screen();
+
+ bool skip = false;
+
+ size_t fi_n = 0;
+ foreach(floating_image::render_input& ri, imgs_) {
+ const floating_image& fi = p_.floating_images_[fi_n];
+
+ if(!ri.image.null()) {
+ SDL_BlitSurface(ri.image, NULL, video_.getSurface(),
&ri.rect);
+ update_rect(ri.rect);
+ }
+
+ if(skip == false) {
+ for(unsigned i = 0; i != 50; ++i) {
+ if(keys_[SDLK_ESCAPE] ||
skip_button_.pressed()) {
+ ret_ = SKIP;
+ return false;
+ }
+ else if(next_button_.pressed()) {
+ ret_ = NEXT;
+ return false;
+ }
+
+ disp_.delay(fi.display_delay() / 50);
+
+ events::pump();
+ events::raise_process_event();
+ events::raise_draw_event();
+
+ int mouse_x, mouse_y;
+ const int mouse_state =
SDL_GetMouseState(&mouse_x, &mouse_y);
+ if(keys_[SDLK_RETURN] || keys_[SDLK_KP_ENTER]
|| keys_[SDLK_SPACE] || mouse_state) {
+ skip = true;
+ ++fi_n;
+ continue;
+ }
+
+ // Update display only if there's a slideshow
going on.
+ // This prevents the textbox from flickering in
the most
+ // common scenario.
+ if(p_.get_floating_images().size() > 1 &&
fi.display_delay() > 0) {
+ disp_.flip();
+ }
+ }
+ }
+
+ if(keys_[SDLK_ESCAPE] || next_button_.pressed() ||
skip_button_.pressed()) {
+ skip = true;
+ ++fi_n;
+ continue;
+ }
+ ++fi_n;
+ }
+
+ return true;
+}
+
+page_ui::RESULT page_ui::show()
+{
+ render_background();
+
+ if(p_.show_title_) {
+ render_title_box();
+ }
+
+ if(!imgs_.empty()) {
+ if(!render_floating_images()) {
+ return ret_;
+ }
+ }
+
+ try {
+ render_text_box();
+ }
+ catch(utils::invalid_utf8_exception const&) {
+ ERR_NG << "invalid UTF-8 sequence in story text, skipping
page...\n";
+ }
+
+ return ret_;
+}
+
+} // end namespace storyscreen
Modified: trunk/src/storyscreen/render.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/storyscreen/render.hpp?rev=34515&r1=34514&r2=34515&view=diff
==============================================================================
--- trunk/src/storyscreen/render.hpp (original)
+++ trunk/src/storyscreen/render.hpp Sun Apr 5 04:15:14 2009
@@ -21,4 +21,57 @@
#ifndef STORYSCREEN_RENDER_HPP_INCLUDED
#define STORYSCREEN_RENDER_HPP_INCLUDED
+#include "key.hpp"
+#include "storyscreen/page.hpp"
+// #include "widgets/button.hpp"
+
+class display;
+class CVideo;
+
+namespace gui { class button; }
+
+namespace storyscreen {
+
+/**
+ * Storyscreen page user interface.
+ * This works on the assumption, like the old one, that the screen
+ * cannot be resized while we are at this. More specifically, it is
+ * assumed that the screen dimensions remain constant between the
+ * constructor call, and the destruction of the objects.
+ */
+class page_ui
+{
+public:
+ enum RESULT { NEXT, BACK, SKIP, QUIT };
+
+ page_ui(page& p, display& disp, gui::button& next_button, gui::button&
skip_button);
+ RESULT show();
+
+private:
+ page& p_;
+ display& disp_;
+ CVideo& video_;
+ CKey keys_;
+ gui::button& next_button_;
+ gui::button& skip_button_;
+
+ RESULT ret_;
+
+ double scale_factor_;
+ SDL_Rect base_rect_;
+
+ surface background_;
+ std::vector< floating_image::render_input > imgs_;
+ bool has_background_;
+
+ int text_x_, text_y_, buttons_x_, buttons_y_;
+
+ void render_background();
+ void render_title_box();
+ bool render_floating_images();
+ void render_text_box();
+};
+
+} // end namespace storyscreen
+
#endif /* !STORYSCREEN_RENDER_HPP_INCLUDED */
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits