From ebe1ae2f408dca3a70c8c50d0f354d1ff44193de Mon Sep 17 00:00:00 2001 From: "Ignacio R. Morelle" Date: Sun, 2 Nov 2008 18:05:11 +0000 Subject: [PATCH] Reworked the interfaces for sound source, ...taking off some uncomfortable coding practices. This is my first step towards fixing a bug in which sound sources are discarded on game load (bug #11495). Functionality should not be affected by this commit. A experimental write() interface was added to class soundspec but it is still unused and untested. --- src/game_events.cpp | 15 ++--- src/soundsource.cpp | 117 +++++++++++++++++++++++----------- src/soundsource.hpp | 152 ++++++++++++++++++++++++++------------------ 3 files changed, 174 insertions(+), 110 deletions(-) diff --git a/src/game_events.cpp b/src/game_events.cpp index 8867acd6980..ee0dfc64492 100644 --- a/src/game_events.cpp +++ b/src/game_events.cpp @@ -1649,25 +1649,20 @@ namespace { soundsource::sourcespec spec(id, sounds, lexical_cast_default(delay, 1000), lexical_cast_default(chance, 100)); - spec.loop(lexical_cast_default(loop, 0)); + spec.set_loops(lexical_cast_default(loop, 0)); + spec.set_check_fogged(utils::string_bool(play_fogged, true)); if(!full_range.empty()) { - spec.full_range(lexical_cast(full_range)); + spec.set_full_range(lexical_cast(full_range)); } if(!fade_range.empty()) { - spec.fade_range(lexical_cast(fade_range)); - } - - if(play_fogged.empty()) { - spec.check_fog(true); - } else { - spec.check_fog(utils::string_bool(play_fogged)); + spec.set_fade_range(lexical_cast(fade_range)); } for(unsigned int i = 0; i < std::min(vx.size(), vy.size()); ++i) { map_location loc(lexical_cast(vx[i]), lexical_cast(vy[i])); - spec.location(loc); + spec.add_location(loc); } (soundsources)->add(spec); diff --git a/src/soundsource.cpp b/src/soundsource.cpp index 15335a08ba9..6af16db98c0 100644 --- a/src/soundsource.cpp +++ b/src/soundsource.cpp @@ -17,31 +17,36 @@ #include #include +#include "config.hpp" #include "display.hpp" +#include "foreach.hpp" #include "pathutils.hpp" #include "sound.hpp" #include "soundsource.hpp" +#include "util.hpp" +#define DEFAULT_FULL_RANGE 3 +#define DEFAULT_FADE_RANGE 14 namespace soundsource { unsigned int positional_source::last_id = 0; manager::manager(const display &disp) : - _sources(), - _disp(disp) + sources_(), + disp_(disp) { - _disp.scroll_event().attach_handler(this); + disp_.scroll_event().attach_handler(this); update_positions(); } manager::~manager() { - for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) { + for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) { delete (*it).second; } - _sources.clear(); + sources_.clear(); } void manager::handle_generic_event(const std::string &event_name) @@ -54,8 +59,8 @@ void manager::add(const sourcespec &spec) { positional_source_iterator it; - if((it = _sources.find(spec.id)) == _sources.end()) { - _sources[spec.id] = new positional_source(spec); + if((it = sources_.find(spec.id())) == sources_.end()) { + sources_[spec.id()] = new positional_source(spec); } else { delete (*it).second; (*it).second = new positional_source(spec); @@ -66,11 +71,11 @@ void manager::remove(const std::string &id) { positional_source_iterator it; - if((it = _sources.find(id)) == _sources.end()) + if((it = sources_.find(id)) == sources_.end()) return; else { delete (*it).second; - _sources.erase(it); + sources_.erase(it); } } @@ -78,8 +83,8 @@ void manager::update() { unsigned int time = SDL_GetTicks(); - for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) { - (*it).second->update(time, _disp); + for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) { + (*it).second->update(time, disp_); } } @@ -87,55 +92,62 @@ void manager::update_positions() { unsigned int time = SDL_GetTicks(); - for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) { - (*it).second->update_positions(time, _disp); + for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) { + (*it).second->update_positions(time, disp_); } } void manager::add_location(const std::string &id, const map_location &loc) { - positional_source_iterator it = _sources.find(id); + positional_source_iterator it = sources_.find(id); - if(it == _sources.end()) + if(it == sources_.end()) return; else (*it).second->add_location(loc); } -positional_source::positional_source(const sourcespec &spec) - : _last_played(0), _min_delay(spec.min_delay), _chance(spec.chance), _loops(spec.loops), - _id(last_id++), _range(spec.range), _faderange(spec.faderange), - _check_fogged(spec.check_fogged), _files(spec.files), _locations(spec.locations) +positional_source::positional_source(const sourcespec &spec) : + last_played_(0), + min_delay_(spec.minimum_delay()), + chance_(spec.chance()), + loops_(spec.loops()), + id_(last_id++), + range_(spec.full_range()), + faderange_(spec.fade_range()), + check_fogged_(spec.check_fogged()), + files_(spec.files()), + locations_(spec.get_locations()) { - assert(_range > 0); - assert(_faderange > 0); + assert(range_ > 0); + assert(faderange_ > 0); } positional_source::~positional_source() { - sound::reposition_sound(_id, DISTANCE_SILENT); + sound::reposition_sound(id_, DISTANCE_SILENT); } void positional_source::update(unsigned int time, const display &disp) { - if(time - _last_played < _min_delay || sound::is_sound_playing(_id)) + if(time - last_played_ < min_delay_ || sound::is_sound_playing(id_)) return; unsigned int i = rand() % 100 + 1; - if(i <= _chance) { - _last_played = time; + if(i <= chance_) { + last_played_ = time; // If no locations have been specified, treat the source as if // it was present everywhere on the map - if(_locations.size() == 0) { - sound::play_sound_positioned(_files, _id, _loops, 0); // max volume + if(locations_.size() == 0) { + sound::play_sound_positioned(files_, id_, loops_, 0); // max volume return; } int distance_volume = DISTANCE_SILENT; - for(std::vector::iterator i = _locations.begin(); i != _locations.end(); ++i) { + for(std::vector::iterator i = locations_.begin(); i != locations_.end(); ++i) { int v = calculate_volume(*i, disp); if(v < distance_volume) { distance_volume = v; @@ -145,15 +157,15 @@ void positional_source::update(unsigned int time, const display &disp) if(distance_volume >= DISTANCE_SILENT) return; - sound::play_sound_positioned(_files, _id, _loops, distance_volume); + sound::play_sound_positioned(files_, id_, loops_, distance_volume); } } void positional_source::update_positions(unsigned int time, const display &disp) { int distance_volume = DISTANCE_SILENT; - for(std::vector::iterator i = _locations.begin(); i != _locations.end(); ++i) { - if(disp.shrouded(*i) || (_check_fogged && disp.fogged(*i))) + for(std::vector::iterator i = locations_.begin(); i != locations_.end(); ++i) { + if(disp.shrouded(*i) || (check_fogged_ && disp.fogged(*i))) continue; int v = calculate_volume(*i, disp); @@ -162,8 +174,8 @@ void positional_source::update_positions(unsigned int time, const display &disp) } } - if(sound::is_sound_playing(_id)) { - sound::reposition_sound(_id, distance_volume); + if(sound::is_sound_playing(id_)) { + sound::reposition_sound(id_, distance_volume); } else { update(time, disp); } @@ -171,23 +183,52 @@ void positional_source::update_positions(unsigned int time, const display &disp) int positional_source::calculate_volume(const map_location &loc, const display &disp) { - assert(_range > 0); - assert(_faderange > 0); + assert(range_ > 0); + assert(faderange_ > 0); SDL_Rect area = disp.map_area(); map_location center = disp.hex_clicked_on(area.x + area.w / 2, area.y + area.h / 2); size_t distance = distance_between(loc, center); - if(distance <= _range) { + if(distance <= range_) { return 0; } - return static_cast(( ( (distance - _range) / (double) _faderange) * DISTANCE_SILENT)); + return static_cast(( ( (distance - range_) / (double) faderange_) * DISTANCE_SILENT)); } void positional_source::add_location(const map_location &loc) { - _locations.push_back(loc); + locations_.push_back(loc); +} + +void sourcespec::write(config& cfg) const +{ + config& info = cfg.add_child("sound_source"); + + info["id"] = this->id_; + info["sounds"] = this->files_; + info["delay"] = str_cast(this->min_delay_); + info["chance"] = str_cast(this->chance_); + info["check_fogged"] = this->check_fogged_ ? "yes" : "no"; + + info["x"] = info["y"] = ""; + bool first_loc = true; + + foreach(const map_location& loc, this->locations_) { + if(!first_loc) { + info["x"] += ","; + info["y"] += ","; + } else { + first_loc = false; + } + info["x"] += str_cast(loc.x); + info["y"] += str_cast(loc.y); + } + + info["loop"] = str_cast(this->loops_); + info["full_range"] = str_cast(this->range_); + info["fade_range"] = str_cast(this->faderange_); } } // namespace soundsource diff --git a/src/soundsource.hpp b/src/soundsource.hpp index 72b8571421e..31c3ff73b39 100644 --- a/src/soundsource.hpp +++ b/src/soundsource.hpp @@ -34,23 +34,23 @@ class manager; * appropriate delays, when sound emiting object is visible on screen. */ class positional_source { - friend class manager; - - unsigned int _last_played; - unsigned int _min_delay; - unsigned int _chance; - unsigned int _loops; - const unsigned int _id; - unsigned int _range; - unsigned int _faderange; - bool _check_fogged; - std::string _files; - std::vector _locations; + unsigned int last_played_; + unsigned int min_delay_; + unsigned int chance_; + unsigned int loops_; + const unsigned int id_; + unsigned int range_; + unsigned int faderange_; + bool check_fogged_; + std::string files_; + std::vector locations_; // Last assigned id; this can, of course, overflow, but I'd // never expect to see 4 billions sound sources being created... static unsigned int last_id; +public: + // min_delay is a minimum time in seconds, which must pass before // this sound source can be played again if it remains visible // @@ -75,8 +75,8 @@ class manager : public events::observer { typedef std::map positional_source_map; typedef positional_source_map::iterator positional_source_iterator; - positional_source_map _sources; - const display &_disp; + positional_source_map sources_; + const display &disp_; // checks which sound sources are visible void update_positions(); @@ -96,67 +96,95 @@ public: void add_location(const std::string &id, const map_location &loc); }; -/* - * A class encapsulating parameters, so that they're easier to pass around/extend/read. +/** + * Sound source info class. + * Encapsulates sound source parameters, so that they're easier to pass + * around/extend/read. */ -class sourcespec { - const std::string &id; - const std::string &files; +class sourcespec +{ + const std::string id_; + const std::string files_; - int min_delay; - int chance; + int min_delay_; + int chance_; - int loops; - int range; - int faderange; - bool check_fogged; + int loops_; + int range_; + int faderange_; + bool check_fogged_; - std::vector locations; + std::vector locations_; public: - sourcespec(const std::string &id_, - const std::string &files_, int min_delay_, int chance_) : - id(id_), - files(files_), - min_delay(min_delay_), - chance(chance_), - loops(0), - range(3), - faderange(14), - check_fogged(false), - locations() - { - } + /** Constructor. */ + sourcespec(const std::string& id, const std::string& files, int min_delay, int chance) : + id_(id), + files_(files), + min_delay_(min_delay), + chance_(chance), + loops_(0), + range_(3), + faderange_(14), + check_fogged_(false), + locations_() + {} + + /** + * Serializes information into cfg as a new (appended) + * child of key "sound_source". + */ + void write(config& cfg) const; + + int loops() const { return loops_; } - sourcespec& loop(int loops_) { - loops = loops_; - return *this; + void set_loops(int value) { + loops_ = value; } - - sourcespec& check_fog(bool fogged) { - check_fogged = fogged; - return *this; + + bool check_fogged() const { return check_fogged_; } + + void set_check_fogged(bool value) { + check_fogged_ = value; } - - sourcespec& location(const map_location &loc) { - locations.push_back(loc); - return *this; + + const std::vector& get_locations() const { + return locations_; } - - sourcespec& full_range(int range_) { - range = std::max(1, range_); - return *this; + + void add_location(const map_location& loc) { + locations_.push_back(loc); } - - sourcespec& fade_range(int range_) { - faderange = range_; - return *this; + + int full_range() const { return range_; } + + void set_full_range(int value) { + range_ = value; } - - friend class manager; - friend class positional_source; + + int fade_range() const { return faderange_; } + + void set_fade_range(int value) { + faderange_ = value; + } + + int minimum_delay() const { return min_delay_; } + + void set_minimum_delay(int value) { + min_delay_ = value; + } + + int chance() const { return chance_; } + + void set_chance(int value) { + chance_ = value; + } + + const std::string& id() const { return id_; } + + const std::string& files() const { return files_; } }; -} // namespace soundsourcespec +} // namespace soundsource #endif