storyscreen/controller.cpp

Go to the documentation of this file.
00001 /* $Id: controller.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Copyright (C) 2009 - 2012 by Ignacio R. Morelle <shadowm2006@gmail.com>
00005    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY.
00013 
00014    See the COPYING file for more details.
00015 */
00016 
00017 /**
00018  * @file
00019  * Storyscreen controller (implementation).
00020  */
00021 
00022 #include "global.hpp"
00023 #include "storyscreen/controller.hpp"
00024 #include "storyscreen/part.hpp"
00025 #include "storyscreen/render.hpp"
00026 
00027 #include "asserts.hpp"
00028 #include "foreach.hpp"
00029 #include "variable.hpp"
00030 
00031 #include "display.hpp"
00032 #include "game_events.hpp"
00033 #include "gamestatus.hpp"
00034 #include "gettext.hpp"
00035 #include "intro.hpp"
00036 #include "log.hpp"
00037 #include "resources.hpp"
00038 #include "widgets/button.hpp"
00039 
00040 static lg::log_domain log_engine("engine");
00041 #define ERR_NG LOG_STREAM(err, log_engine)
00042 #define LOG_NG LOG_STREAM(info, log_engine)
00043 
00044 namespace storyscreen {
00045 
00046 controller::controller(display& disp, const vconfig& data, const std::string& scenario_name,
00047                int segment_index, int total_segments)
00048     : disp_(disp)
00049     , disp_resize_lock_()
00050     , evt_context_()
00051     , scenario_name_(scenario_name)
00052     , segment_index_(segment_index)
00053     , total_segments_(total_segments)
00054     , parts_()
00055 {
00056     ASSERT_LOG(resources::state_of_game != NULL, "Ouch: gamestate is NULL when initializing storyscreen controller");
00057     resolve_wml(data);
00058 }
00059 
00060 void controller::resolve_wml(const vconfig& cfg)
00061 {
00062     for(vconfig::all_children_iterator i = cfg.ordered_begin(); i != cfg.ordered_end(); ++i)
00063     {
00064         // i->first and i->second are goddamn temporaries; do not make references
00065         const std::string key = i->first;
00066         const vconfig node = i->second;
00067 
00068         if(key == "part" && !node.empty()) {
00069             part_pointer_type const story_part(new part(node));
00070             // Use scenario name as part title if the WML doesn't supply a custom one.
00071             if((*story_part).show_title() && (*story_part).title().empty()) {
00072                 (*story_part).set_title( scenario_name_ );
00073             }
00074             parts_.push_back(story_part);
00075         }
00076         // [if]
00077         else if(key == "if") {
00078             const std::string branch_label =
00079                 game_events::conditional_passed(node) ?
00080                 "then" : "else";
00081             if(node.has_child(branch_label)) {
00082                 const vconfig branch = node.child(branch_label);
00083                 resolve_wml(branch);
00084             }
00085         }
00086         // [switch]
00087         else if(key == "switch") {
00088             const std::string var_name = node["variable"];
00089             const std::string var_actual_value = resources::state_of_game->get_variable_const(var_name);
00090             bool case_not_found = true;
00091 
00092             for(vconfig::all_children_iterator j = node.ordered_begin(); j != node.ordered_end(); ++j) {
00093                 if(j->first != "case") continue;
00094 
00095                 // Enter all matching cases.
00096                 const std::string var_expected_value = (j->second)["value"];
00097                 if(var_actual_value == var_expected_value) {
00098                     case_not_found = false;
00099                     resolve_wml(j->second);
00100                 }
00101             }
00102 
00103             if(case_not_found) {
00104                 for(vconfig::all_children_iterator j = node.ordered_begin(); j != node.ordered_end(); ++j) {
00105                     if(j->first != "else") continue;
00106 
00107                     // Enter all elses.
00108                     resolve_wml(j->second);
00109                 }
00110             }
00111         }
00112         // [deprecated_message]
00113         else if(key == "deprecated_message") {
00114             // Won't appear until the scenario start event finishes.
00115             game_events::handle_deprecated_message(node.get_parsed_config());
00116         }
00117         // [wml_message]
00118         else if(key == "wml_message") {
00119             // Pass to game events handler. As with [deprecated_message],
00120             // it won't appear until the scenario start event is complete.
00121             game_events::handle_wml_log_message(node.get_parsed_config());
00122         }
00123     }
00124 }
00125 
00126 STORY_RESULT controller::show(START_POSITION startpos)
00127 {
00128     if(parts_.empty()) {
00129         LOG_NG << "no storyscreen parts to show\n";
00130         return NEXT;
00131     }
00132 
00133     gui::button back_button (disp_.video(), "", gui::button::TYPE_PRESS, "big-arrow-button-left");
00134     gui::button next_button (disp_.video(), "", gui::button::TYPE_PRESS, "big-arrow-button-right");
00135     gui::button play_button (disp_.video(), _("Skip"));
00136 
00137     // Build renderer cache unless built for a low-memory environment;
00138     // caching the scaled backgrounds can take over a decent amount of memory.
00139 #ifndef LOW_MEM
00140     std::vector< render_pointer_type > uis_;
00141     foreach(part_pointer_type p, parts_) {
00142         ASSERT_LOG( p != NULL, "Ouch: hit NULL storyscreen part in collection" );
00143         render_pointer_type const rpt(new part_ui(*p, disp_, next_button, back_button, play_button));
00144         uis_.push_back(rpt);
00145     }
00146 #endif
00147 
00148     size_t k = 0;
00149     switch(startpos) {
00150     case START_BEGINNING:
00151         break;
00152     case START_END:
00153         k = parts_.size() -1;
00154         break;
00155     default:
00156         assert(false);
00157         break;
00158     }
00159 
00160     while(k < parts_.size()) {
00161 #ifndef LOW_MEM
00162         part_ui &render_interface = *uis_[k];
00163 #else
00164         part_ui render_interface(*parts_[k], disp_, next_button, back_button, play_button);
00165 #endif
00166 
00167         LOG_NG << "displaying storyscreen part " << k+1 << " of " << parts_.size() << '\n';
00168 
00169         back_button.enable(segment_index_ != 0 || k != 0);
00170 
00171         switch(render_interface.show()) {
00172         case part_ui::NEXT:
00173             ++k;
00174             break;
00175         case part_ui::BACK:
00176             if(k > 0) {
00177                 --k;
00178             }
00179             else if(segment_index_ > 0) {
00180                 return BACK;
00181             }
00182             break;
00183         case part_ui::QUIT:
00184             return QUIT;
00185         }
00186     }
00187     return NEXT;
00188 }
00189 
00190 } // end namespace storyscreen
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:53 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs