Here's a first attempt at a patch for the back button for story screens: http://wiki.wesnoth.org/Good_Ideas http://www.wesnoth.org/forum/viewtopic.php?t=8857
There is already a patch in the tracker for this: https://gna.org/patch/?1536 However I didn't realise someone had started when I wrote this, and this is rather further along than that one is. Problems with that patch: * Back doesn't work properly (try it on the last page of the intro where it shows you the map) - can't go back. * Doesn't wire up back button in all the situations next button is clickable. * Probably violates screen size in USE_TINY_GUI mode * There's no key shortcut for back. Features this patch has: * Handles back properly so that you can go all the way back to the start from the end. * Handles skip properly so that all segments are skipped not just per segment (but can still go back so this is ok!) * Adds functional quit button. * Adds key controls: RIGHT is added for next, LEFT and BACKSPACE for back. Improves the implementation: * no longer throws quit exception to quit (was just caught and suppressed anyway). * play story segments from either end so that back can work properly. * adds reverse direction iteration for config::const_child_iterator (was needed)
Index: src/storyscreen/render.cpp =================================================================== --- src/storyscreen/render.cpp (revision 41922) +++ src/storyscreen/render.cpp (working copy) @@ -81,13 +81,17 @@ namespace storyscreen { -part_ui::part_ui(part& p, display& disp, gui::button& next_button, gui::button& skip_button) +part_ui::part_ui(part& p, display& disp, + gui::button& next_button, gui::button& back_button, + gui::button& skip_button, gui::button& quit_button) : p_(p) , disp_(disp) , video_(disp.video()) , keys_() , next_button_(next_button) + , back_button_(back_button) , skip_button_(skip_button) + , quit_button_(quit_button) , ret_(NEXT) , scale_factor_(1.0) , base_rect_() @@ -139,8 +143,10 @@ 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_); + next_button_.set_location(buttons_x_, buttons_y_ - 60); + back_button_.set_location(buttons_x_, buttons_y_ - 40); + skip_button_.set_location(buttons_x_, buttons_y_ - 20); + quit_button_.set_location(buttons_x_, buttons_y_); #else // elif !defined(USE_TINY_GUI) @@ -163,12 +169,16 @@ buttons_y_ = video_.gety() - 40; break; } - next_button_.set_location(buttons_x_, buttons_y_ - 30); - skip_button_.set_location(buttons_x_, buttons_y_); + next_button_.set_location(buttons_x_, buttons_y_ - 90); + back_button_.set_location(buttons_x_, buttons_y_ - 60); + skip_button_.set_location(buttons_x_, buttons_y_ - 30); + quit_button_.set_location(buttons_x_, buttons_y_); #endif next_button_.set_volatile(true); + back_button_.set_volatile(true); skip_button_.set_volatile(true); + quit_button_.set_volatile(true); } void part_ui::prepare_floating_images() @@ -210,10 +220,18 @@ ret_ = SKIP; return false; } + else if(quit_button_.pressed()) { + ret_ = QUIT; + return false; + } else if(next_button_.pressed()) { ret_ = NEXT; return false; } + else if(back_button_.pressed()) { + ret_ = BACK; + return false; + } disp_.delay(fi.display_delay() / 50); @@ -238,7 +256,9 @@ } } - if(keys_[SDLK_ESCAPE] || next_button_.pressed() || skip_button_.pressed()) { + if(keys_[SDLK_ESCAPE] || + next_button_.pressed() || back_button_.pressed() || + skip_button_.pressed() || quit_button_.pressed()) { skip = true; ++fi_n; continue; @@ -429,10 +449,10 @@ // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); - //back_button_.hide(); next_button_.hide(); + back_button_.hide(); skip_button_.hide(); - //quit_button_.hide(); + quit_button_.hide(); #ifndef LOW_MEM blur_area(video_, fix_text_y, fix_text_h); @@ -450,8 +470,12 @@ // Make GUI1 buttons aware of background modifications next_button_.set_location(next_button_.location()); next_button_.hide(false); + back_button_.set_location(back_button_.location()); + back_button_.hide(false); skip_button_.set_location(skip_button_.location()); skip_button_.hide(false); + quit_button_.set_location(quit_button_.location()); + quit_button_.hide(false); } if(imgs_.empty()) { @@ -479,9 +503,9 @@ ++scan.y; } - const bool keydown = keys_[SDLK_SPACE] || keys_[SDLK_RETURN] || keys_[SDLK_KP_ENTER]; + const bool next_keydown = keys_[SDLK_SPACE] || keys_[SDLK_RETURN] || keys_[SDLK_KP_ENTER] || keys_[SDLK_RIGHT]; - if((keydown && !last_key) || next_button_.pressed()) { + if((next_keydown && !last_key) || next_button_.pressed()) { if(skip == true || scan_finished) { ret_ = NEXT; break; @@ -490,11 +514,22 @@ } } - last_key = keydown; + const bool back_keydown = keys_[SDLK_BACKSPACE] || keys_[SDLK_LEFT]; + if((back_keydown && !last_key) || back_button_.pressed()) { + ret_ = BACK; + break; + } + + last_key = next_keydown || back_keydown; + if(keys_[SDLK_ESCAPE] || skip_button_.pressed()) { ret_ = SKIP; return; + } + else if(quit_button_.pressed()) { + ret_ = QUIT; + return; } events::pump(); @@ -517,20 +552,32 @@ { bool last_key = true; while(true) { - const bool keydown = keys_[SDLK_SPACE] || keys_[SDLK_RETURN] || keys_[SDLK_KP_ENTER]; + const bool next_keydown = keys_[SDLK_SPACE] || keys_[SDLK_RETURN] || keys_[SDLK_KP_ENTER] || keys_[SDLK_RIGHT]; - if((keydown && !last_key) || next_button_.pressed()) { + if((next_keydown && !last_key) || next_button_.pressed()) { ret_ = NEXT; break; } - last_key = keydown; + const bool back_keydown = keys_[SDLK_BACKSPACE] || keys_[SDLK_LEFT]; + if((back_keydown && !last_key) || back_button_.pressed()) { + ret_ = BACK; + break; + } + + last_key = next_keydown || back_keydown; + if(keys_[SDLK_ESCAPE] || skip_button_.pressed()) { ret_ = SKIP; return; } + if(quit_button_.pressed()) { + ret_ = QUIT; + return; + } + events::pump(); events::raise_process_event(); events::raise_draw_event(); Index: src/storyscreen/interface.cpp =================================================================== --- src/storyscreen/interface.cpp (revision 41922) +++ src/storyscreen/interface.cpp (working copy) @@ -47,20 +47,19 @@ } } // end anonymous namespace -void show_storyscreen(display& disp, const vconfig& story_cfg, const std::string& scenario_name) +storyscreen::STORY_RESULT show_storyscreen(display& disp, const vconfig& story_cfg, + const std::string& scenario_name, + storyscreen::START_POSITION startpos) { LOG_NG << "entering storyscreen procedure...\n"; storyscreen::controller ctl(disp, story_cfg, scenario_name); - try { - ctl.show(); - } catch(storyscreen::controller::quit const&) { - LOG_NG << "leaving storyscreen for titlescreen...\n"; - STUB(); - } + storyscreen::STORY_RESULT ret = ctl.show(startpos); LOG_NG << "leaving storyscreen procedure...\n"; + + return ret; } void show_endscreen(display& /*disp*/, const t_string& /*text*/, unsigned int /*duration*/) Index: src/storyscreen/controller.cpp =================================================================== --- src/storyscreen/controller.cpp (revision 41922) +++ src/storyscreen/controller.cpp (working copy) @@ -118,17 +118,17 @@ } } -void controller::show() +STORY_RESULT controller::show(START_POSITION startpos) { if(parts_.empty()) { LOG_NG << "no storyscreen parts to show\n"; - return; + return NEXT; } gui::button next_button(disp_.video(),_("Next") + std::string(" >")); + gui::button back_button(disp_.video(),std::string("< ")+_("Back")); gui::button skip_button(disp_.video(),_("Skip")); - // TODO: - // gui::button back_button(disp_.video(),std::string("< ")+_("Next")); + gui::button quit_button(disp_.video(),_("Quit")); // Build renderer cache unless built for a low-memory environment; // caching the scaled backgrounds can take over a decent amount of memory. @@ -136,18 +136,28 @@ std::vector< render_pointer_type > uis_; foreach(part_pointer_type p, parts_) { ASSERT_LOG( p != NULL, "Ouch: hit NULL storyscreen part in collection" ); - render_pointer_type const rpt(new part_ui(*p, disp_, next_button, skip_button)); + render_pointer_type const rpt(new part_ui(*p, disp_, next_button, back_button, skip_button, quit_button)); uis_.push_back(rpt); } #endif size_t k = 0; + switch(startpos) { + case START_BEGINNING: + break; + case START_END: + k = parts_.size() -1; + break; + default: + assert(false); + break; + } while(k < parts_.size()) { #ifndef LOW_MEM render_reference_type render_interface = *uis_[k]; #else - render_value_type render_interface(*parts_[k], disp_, next_button, skip_button); + render_value_type render_interface(*parts_[k], disp_, next_button, back_button, skip_button, quit_button); #endif LOG_NG << "displaying storyscreen part " << k+1 << " of " << parts_.size() << '\n'; @@ -157,18 +167,23 @@ ++k; break; case part_ui::BACK: - // If we are at the first page we can't go back. if(k > 0) { --k; + } + else { + return BACK; } break; case part_ui::SKIP: - k = parts_.size(); - break; + return SKIP; + case part_ui::QUIT: + return QUIT; default: - throw quit(); + assert(false); + return QUIT; } } + return NEXT; } } // end namespace storyscreen Index: src/storyscreen/render.hpp =================================================================== --- src/storyscreen/render.hpp (revision 41922) +++ src/storyscreen/render.hpp (working copy) @@ -45,9 +45,9 @@ /** Storyscreen result. */ enum RESULT { NEXT, /**< The user pressed the go-next button. */ - BACK, /**< The user pressed the go-back button (TODO: not implemented). */ + BACK, /**< The user pressed the go-back button. */ SKIP, /**< The user pressed the skip button. */ - QUIT /**< The user pressed the quit button (TODO: not implemented). */ + QUIT /**< The user pressed the quit button. */ }; /** @@ -57,7 +57,9 @@ * @param next_button Next button. Shouldn't be destroyed before the part_ui object. * @param skip_button Skip button. Shouldn't be destroyed before the part_ui object. */ - part_ui(part& p, display& disp, gui::button& next_button, gui::button& skip_button); + part_ui(part& p, display& disp, + gui::button& next_button, gui::button& back_button, + gui::button& skip_button, gui::button& quit_button); /** * Render and display the storyscreen, process and return user input. @@ -70,10 +72,10 @@ CVideo& video_; // convenience, it's currently obtained from disp_ CKey keys_; // convenience - //gui::button& back_button_; gui::button& next_button_; + gui::button& back_button_; gui::button& skip_button_; - //gui::button& quit_button_; + gui::button& quit_button_; RESULT ret_; Index: src/storyscreen/interface.hpp =================================================================== --- src/storyscreen/interface.hpp (revision 41922) +++ src/storyscreen/interface.hpp (working copy) @@ -27,6 +27,22 @@ #include <string> +namespace storyscreen { + +enum STORY_RESULT { + NEXT, + BACK, + SKIP, + QUIT +}; + +enum START_POSITION { + START_BEGINNING, + START_END +}; + +} /* storyscreen namespace */ + /** * Function to show an introduction sequence using story WML. * The WML config data (story_cfg) has a format similar to: @@ -41,8 +57,11 @@ * storyline,and 'img' is a background image. Each part of the sequence will * be displayed in turn, with the user able to go to the next part, or skip * it entirely. + * @return is NEXT if the story played to the end, BACK if the story played to the beginning, and QUIT if the story was quit */ -void show_storyscreen(display& disp, const vconfig& story_cfg, const std::string& scenario_name); +storyscreen::STORY_RESULT show_storyscreen(display& disp, const vconfig& story_cfg, + const std::string& scenario_name, + storyscreen::START_POSITION startpos); /** * Displays a simple fading screen with any user-provided text. Index: src/storyscreen/controller.hpp =================================================================== --- src/storyscreen/controller.hpp (revision 41922) +++ src/storyscreen/controller.hpp (working copy) @@ -21,6 +21,7 @@ #define STORYSCREEN_CONTROLLER_HPP_INCLUDED #include "events.hpp" +#include "interface.hpp" #include "variable.hpp" #include "video.hpp" @@ -44,7 +45,7 @@ /** * Display all story screen parts in a first..last sequence. */ - void show(); + STORY_RESULT show(START_POSITION startpos=START_BEGINNING); private: typedef boost::shared_ptr< part > part_pointer_type; @@ -73,8 +74,6 @@ public: struct no_parts {}; - struct quit {}; - }; } // end namespace storyscreen Index: src/playsingle_controller.cpp =================================================================== --- src/playsingle_controller.cpp (revision 41922) +++ src/playsingle_controller.cpp (working copy) @@ -286,8 +286,35 @@ sound::commit_music_changes(); if(!skip_replay) { - foreach (const config &s, story) { - show_storyscreen(*gui_, vconfig(s, true), level_["name"]); + config::const_child_iterator itor = story.first; + storyscreen::START_POSITION startpos = storyscreen::START_BEGINNING; + while(itor != story.second) { + storyscreen::STORY_RESULT result = show_storyscreen(*gui_, vconfig(*itor, true), level_["name"], startpos); + switch(result) { + case storyscreen::NEXT: + if(itor != story.second) { + ++itor; + startpos = storyscreen::START_BEGINNING; + } + break; + case storyscreen::BACK: + if(itor != story.first) { + --itor; + startpos = storyscreen::START_END; + } + break; + case storyscreen::SKIP: + itor = story.second; + --itor; + startpos = storyscreen::START_END; + break; + case storyscreen::QUIT: + return QUIT; + default: + assert(false); + itor = story.second; + break; + } } } gui_->labels().read(level_); Index: src/config.hpp =================================================================== --- src/config.hpp (revision 41922) +++ src/config.hpp (working copy) @@ -131,6 +131,8 @@ const_child_iterator &operator++() { ++i_; return *this; } const_child_iterator operator++(int) { return const_child_iterator(i_++); } + const_child_iterator &operator--() { --i_; return *this; } + const_child_iterator operator--(int) { return const_child_iterator(i_--); } const config &operator*() const { return **i_; } const config *operator->() const { return &**i_; } Index: changelog =================================================================== --- changelog (revision 41922) +++ changelog (working copy) @@ -26,6 +26,7 @@ * Fixed picking the proper locale, the problem only occurred on some systems * Added a way to compile wesnoth on windows by using CMake + MSVC9. + * Added back and quit buttons to the story screens. Version 1.8.0: * AI:
_______________________________________________ Wesnoth-dev mailing list Wesnoth-dev@gna.org https://mail.gna.org/listinfo/wesnoth-dev