the countdown timer alert can now start sounding while dialogs are open

added a mechanism for generic monitoring of events::pump()
This commit is contained in:
Patrick Parker 2007-07-27 02:02:17 +00:00
parent 10386174d9
commit c491f73077
13 changed files with 150 additions and 66 deletions

View file

@ -7,7 +7,8 @@ Version 1.3.6+svn:
* language and i18n:
* updated translations: Danish, Japanese, Swedish
* multiplayer:
* improvements to the sound of the timer countdown
* improvements to the sound of the countdown timer
* the countdown timer alert can now start sounding while dialogs are open
* unit descriptions are no longer evaluated for the recruitment checksum
and thus avoiding an OOS error when different languages are used.
The change is incompatible with older trunk versions fixes (bug #9472).

View file

@ -254,7 +254,7 @@ int dialog::show()
//create the event context, remember to instruct any passed-in widgets to join it
const events::event_context dialog_events_context;
const dialog_manager manager;
const events::resize_lock prevent_resizing;
const resize_lock prevent_resizing;
//draw
draw_frame();

View file

@ -30,6 +30,7 @@
#include <vector>
#define ERR_GEN LOG_STREAM(err, general)
#define INFO_GEN LOG_STREAM(info, general)
unsigned input_blocker::instance_count = 0; //static initialization
@ -39,20 +40,6 @@ namespace events
void raise_help_string_event(int mousex, int mousey);
namespace {
int disallow_resize = 0;
}
resize_lock::resize_lock()
{
++disallow_resize;
}
resize_lock::~resize_lock()
{
--disallow_resize;
}
namespace {
struct context
@ -149,8 +136,20 @@ void context::set_focus(const handler* ptr)
//in that context. The current context is the one on the top of the stack
std::deque<context> event_contexts;
std::vector<pump_monitor*> pump_monitors;
} //end anon namespace
pump_monitor::pump_monitor() {
pump_monitors.push_back(this);
}
pump_monitor::~pump_monitor() {
pump_monitors.erase(
std::remove(pump_monitors.begin(), pump_monitors.end(), this),
pump_monitors.end());
}
event_context::event_context()
{
event_contexts.push_back(context());
@ -267,7 +266,7 @@ void pump()
{
SDL_PumpEvents();
static std::pair<int,int> resize_dimensions(0,0);
pump_info info;
//used to keep track of double click events
static int last_mouse_down = -1;
@ -301,15 +300,8 @@ void pump()
case SDL_VIDEORESIZE: {
const SDL_ResizeEvent* const resize = reinterpret_cast<SDL_ResizeEvent*>(&event);
if(resize->w < min_allowed_width || resize->h < min_allowed_height) {
resize_dimensions.first = 0;
resize_dimensions.second = 0;
} else {
resize_dimensions.first = resize->w;
resize_dimensions.second = resize->h;
}
info.resize_dimensions.first = resize->w;
info.resize_dimensions.second = resize->h;
break;
}
@ -329,8 +321,8 @@ void pump()
static const int DoubleClickTime = 500;
static const int DoubleClickMaxMove = 3;
const int current_ticks = ::SDL_GetTicks();
if(last_mouse_down >= 0 && current_ticks - last_mouse_down < DoubleClickTime &&
info.ticks = ::SDL_GetTicks();
if(last_mouse_down >= 0 && info.ticks - last_mouse_down < DoubleClickTime &&
abs(event.button.x - last_click_x) < DoubleClickMaxMove &&
abs(event.button.y - last_click_y) < DoubleClickMaxMove) {
SDL_UserEvent user_event;
@ -341,7 +333,7 @@ void pump()
::SDL_PushEvent(reinterpret_cast<SDL_Event*>(&user_event));
}
last_mouse_down = current_ticks;
last_mouse_down = info.ticks;
last_click_x = event.button.x;
last_click_y = event.button.y;
}
@ -374,14 +366,10 @@ void pump()
}
}
if(resize_dimensions.first > 0 && disallow_resize == 0) {
preferences::set_resolution(resize_dimensions);
resize_dimensions.first = 0;
resize_dimensions.second = 0;
//inform the pump monitors that an events::pump() has occurred
for(size_t i1 = 0, i2 = pump_monitors.size(); i1 != i2 && i1 < pump_monitors.size(); ++i1) {
pump_monitors[i1]->process(info);
}
if (preferences::music_on())
sound::think_about_music();
}
void raise_process_event()

View file

@ -23,13 +23,6 @@
namespace events
{
//an object which prevents resizing of the screen occuring during
//its lifetime.
struct resize_lock {
resize_lock();
~resize_lock();
};
//any classes that derive from this class will automatically
//receive sdl events through the handle function for their lifetime,
//while the event context they were created in is active.
@ -86,6 +79,21 @@ struct event_context
//causes events to be dispatched to all handler objects.
void pump();
struct pump_info {
pump_info() : ticks(0) {}
std::pair<int,int> resize_dimensions;
int ticks; //0 if not calculated
};
class pump_monitor {
//pump_monitors receive notifcation after an events::pump() occurs
public:
pump_monitor();
virtual ~pump_monitor();
virtual void process(pump_info& info) = 0;
};
int flush(Uint32 event_mask=SDL_ALLEVENTS);
void raise_process_event();

View file

@ -2674,7 +2674,7 @@ void show_help(display &disp, const section &toplevel_sec, const std::string sho
{
const events::event_context dialog_events_context;
const gui::dialog_manager manager;
const events::resize_lock prevent_resizing;
const resize_lock prevent_resizing;
CVideo& screen = disp.video();
surface const scr = screen.getSurface();

View file

@ -45,7 +45,7 @@ void show_intro(display &disp, const config& data, const config& level)
LOG_NG << "showing intro sequence...\n";
//stop the screen being resized while we're in this function
const events::resize_lock stop_resizing;
const resize_lock stop_resizing;
const events::event_context context;
bool showing = true;

View file

@ -86,7 +86,7 @@ bool default_map_generator::allow_user_config() const { return true; }
void default_map_generator::user_config(display& disp)
{
const events::resize_lock prevent_resizing;
const resize_lock prevent_resizing;
const events::event_context dialog_events_context;
CVideo& screen = disp.video();

View file

@ -38,9 +38,17 @@ playmp_controller::playmp_controller(const config& level, const game_data& gamei
bool skip_replay)
: playsingle_controller(level, gameinfo, state_of_game, ticks, num_turns, game_config, video, skip_replay)
{
beep_warning_time_ = 0;
turn_data_ = NULL;
}
playmp_controller::~playmp_controller() {
//halt and cancel the countdown timer
if(beep_warning_time_ < 0) {
sound::stop_bell();
}
}
void playmp_controller::set_replay_last_turn(unsigned int turn){
replay_last_turn_ = turn;
}
@ -62,7 +70,6 @@ void playmp_controller::shout(){
}
void playmp_controller::play_side(const unsigned int team_index, bool save){
beep_warning_time_ = 10000; //Starts beeping each second when time is less than this (millisec)
do {
player_type_changed_ = false;
end_turn_ = false;
@ -93,9 +100,6 @@ void playmp_controller::play_side(const unsigned int team_index, bool save){
}
}
LOG_NG << "human finished turn...\n";
if(beep_warning_time_ < 10000) {
sound::stop_bell();
}
} else if(current_team().is_ai()) {
play_ai_turn();
} else if(current_team().is_network()) {
@ -113,6 +117,43 @@ void playmp_controller::before_human_turn(bool save){
turn_data_->replay_error().attach_handler(this);
}
bool playmp_controller::counting_down() {
return beep_warning_time_ > 0;
}
namespace {
const int WARNTIME = 10000; //start beeping when 10 seconds are left (10,000ms)
int timer_refresh = 0;
const int timer_refresh_rate = 50; //prevents calling SDL_GetTicks() too frequently
}
//make sure we think about countdown even while dialogs are open
void playmp_controller::process(events::pump_info &info) {
if(playmp_controller::counting_down()) {
if(info.ticks == 0) {
if(++timer_refresh % timer_refresh_rate == 0) {
playmp_controller::think_about_countdown(::SDL_GetTicks());
}
} else {
playmp_controller::think_about_countdown(info.ticks);
}
}
}
//check if it is time to start playing the timer warning
void playmp_controller::think_about_countdown(int ticks) {
if(ticks >= beep_warning_time_) {
const bool bell_on = preferences::turn_bell();
if(bell_on || preferences::sound_on() || preferences::UI_sound_on()) {
preferences::set_turn_bell(true);
sound::play_bell(game_config::sounds::timer_bell,
WARNTIME - (ticks - beep_warning_time_));
beep_warning_time_ = -1;
preferences::set_turn_bell(bell_on);
}
}
}
void playmp_controller::play_human_turn(){
int cur_ticks = SDL_GetTicks();
@ -148,19 +189,15 @@ void playmp_controller::play_human_turn(){
if (new_time > 0 ){
current_team().set_countdown_time(new_time);
cur_ticks = ticks;
if (current_team().countdown_time() <= beep_warning_time_){
beep_warning_time_ = -1;
const bool bell_on = preferences::turn_bell();
if(bell_on || preferences::sound_on() || preferences::UI_sound_on()) {
preferences::set_turn_bell(true);
sound::play_bell(game_config::sounds::timer_bell, new_time);
preferences::set_turn_bell(bell_on);
}
if(current_team().is_human() && !beep_warning_time_) {
beep_warning_time_ = new_time - WARNTIME + ticks;
}
if(counting_down()) {
think_about_countdown(ticks);
}
} else {
// Clock time ended
// If no turn bonus or action bonus -> defeat
beep_warning_time_ = 10000;
const int action_increment = lexical_cast_default<int>(level_["mp_countdown_action_bonus"],0);
if ( lexical_cast_default<int>(level_["mp_countdown_turn_bonus"],0) == 0
&& (action_increment == 0 || current_team().action_bonus_count() == 0)) {
@ -216,10 +253,14 @@ void playmp_controller::after_human_turn(){
void playmp_controller::finish_side_turn(){
play_controller::finish_side_turn();
//just in case due to an exception turn_data_ has not been deleted in after_human_turn
if (turn_data_ != NULL){
delete turn_data_;
turn_data_ = NULL;
delete turn_data_;
turn_data_ = NULL;
//halt and cancel the countdown timer
if(beep_warning_time_ < 0) {
sound::stop_bell();
}
}

View file

@ -22,15 +22,20 @@
#include <vector>
class playmp_controller : public playsingle_controller
class playmp_controller : public playsingle_controller, public events::pump_monitor
{
public:
playmp_controller(const config& level, const game_data& gameinfo, game_state& state_of_game,
const int ticks, const int num_turns, const config& game_config, CVideo& video, bool skip_replay);
~playmp_controller();
static unsigned int replay_last_turn() { return replay_last_turn_; }
static void set_replay_last_turn(unsigned int turn);
bool counting_down();
void think_about_countdown(int ticks);
void process(events::pump_info &info);
protected:
virtual void handle_generic_event(const std::string& name);

View file

@ -319,7 +319,7 @@ bool compare_resolutions(const std::pair<int,int>& lhs, const std::pair<int,int>
bool show_video_mode_dialog(display& disp)
{
const events::resize_lock prevent_resizing;
const resize_lock prevent_resizing;
const events::event_context dialog_events_context;
CVideo& video = disp.video();

View file

@ -12,7 +12,7 @@
*/
#include "global.hpp"
#include "events.hpp"
#include "filesystem.hpp"
#include "game_config.hpp"
#include "game_preferences.hpp"
@ -463,6 +463,17 @@ void stop_UI_sound() {
}
}
namespace {
class music_thinker : public events::pump_monitor {
void process(events::pump_info &/*info*/) {
if(preferences::music_on()) {
think_about_music();
}
}
};
music_thinker mthink;
}
void think_about_music(void)
{
if (!music_start_time) {

View file

@ -17,9 +17,11 @@
#include <iostream>
#include <vector>
#include "events.hpp"
#include "font.hpp"
#include "image.hpp"
#include "log.hpp"
#include "preferences_display.hpp"
#include "video.hpp"
#define LOG_DP LOG_STREAM(info, display)
@ -68,7 +70,28 @@ int main( int argc, char** argv )
#endif
namespace {
bool fullScreen = false;
bool fullScreen = false;
int disallow_resize = 0;
class resize_monitor : public events::pump_monitor {
void process(events::pump_info &info) {
if(info.resize_dimensions.first >= min_allowed_width
&& info.resize_dimensions.second >= min_allowed_height
&& disallow_resize == 0) {
preferences::set_resolution(info.resize_dimensions);
}
}
};
resize_monitor resize_mon;
}
resize_lock::resize_lock()
{
++disallow_resize;
}
resize_lock::~resize_lock()
{
--disallow_resize;
}
static unsigned int get_flags(unsigned int flags)

View file

@ -134,4 +134,11 @@ private:
bool unlock;
};
//an object which prevents resizing of the screen occuring during
//its lifetime.
struct resize_lock {
resize_lock();
~resize_lock();
};
#endif