mirror of
https://github.com/wesnoth/wesnoth
synced 2025-04-28 11:04:14 +00:00
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.
This commit is contained in:
parent
c9bf55b9e6
commit
ebe1ae2f40
@ -1649,25 +1649,20 @@ namespace {
|
||||
|
||||
soundsource::sourcespec spec(id, sounds, lexical_cast_default<int>(delay, 1000), lexical_cast_default<int>(chance, 100));
|
||||
|
||||
spec.loop(lexical_cast_default<int>(loop, 0));
|
||||
spec.set_loops(lexical_cast_default<int>(loop, 0));
|
||||
spec.set_check_fogged(utils::string_bool(play_fogged, true));
|
||||
|
||||
if(!full_range.empty()) {
|
||||
spec.full_range(lexical_cast<int>(full_range));
|
||||
spec.set_full_range(lexical_cast<int>(full_range));
|
||||
}
|
||||
|
||||
if(!fade_range.empty()) {
|
||||
spec.fade_range(lexical_cast<int>(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<int>(fade_range));
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < std::min(vx.size(), vy.size()); ++i) {
|
||||
map_location loc(lexical_cast<int>(vx[i]), lexical_cast<int>(vy[i]));
|
||||
spec.location(loc);
|
||||
spec.add_location(loc);
|
||||
}
|
||||
|
||||
(soundsources)->add(spec);
|
||||
|
@ -17,31 +17,36 @@
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
#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<map_location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
|
||||
for(std::vector<map_location>::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<map_location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
|
||||
if(disp.shrouded(*i) || (_check_fogged && disp.fogged(*i)))
|
||||
for(std::vector<map_location>::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<int>(( ( (distance - _range) / (double) _faderange) * DISTANCE_SILENT));
|
||||
return static_cast<int>(( ( (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<int>(this->min_delay_);
|
||||
info["chance"] = str_cast<int>(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<int>(loc.x);
|
||||
info["y"] += str_cast<int>(loc.y);
|
||||
}
|
||||
|
||||
info["loop"] = str_cast<int>(this->loops_);
|
||||
info["full_range"] = str_cast<int>(this->range_);
|
||||
info["fade_range"] = str_cast<int>(this->faderange_);
|
||||
}
|
||||
|
||||
} // namespace soundsource
|
||||
|
@ -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<map_location> _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<map_location> 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<std::string, positional_source *> 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<map_location> locations;
|
||||
std::vector<map_location> 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<map_location>& get_locations() const {
|
||||
return locations_;
|
||||
}
|
||||
|
||||
sourcespec& full_range(int range_) {
|
||||
range = std::max<int>(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
|
||||
|
Loading…
x
Reference in New Issue
Block a user