Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
const double DROPOFF_FACTOR = 64.0;
|
||||
const double DROPOFF_FACTOR_SQ = DROPOFF_FACTOR * DROPOFF_FACTOR;
|
||||
|
||||
final class SoundEntry {
|
||||
vec3d pos;
|
||||
double scale;
|
||||
};
|
||||
|
||||
final class AmbienceGroup {
|
||||
map entries;
|
||||
SoundEntry@ active;
|
||||
const SoundSource@ source;
|
||||
Sound@ sound;
|
||||
double volume = 0;
|
||||
|
||||
AmbienceGroup(const SoundSource& soundSource) {
|
||||
@source = soundSource;
|
||||
}
|
||||
|
||||
void addEntry(int id, const vec3d& pos, double scale) {
|
||||
SoundEntry entry;
|
||||
entry.pos = pos;
|
||||
entry.scale = scale;
|
||||
entries.set(id, @entry);
|
||||
}
|
||||
|
||||
void deleteEntry(int id) {
|
||||
entries.delete(id);
|
||||
}
|
||||
|
||||
SoundEntry@ findNearest(const vec3d& to) {
|
||||
SoundEntry@ nearest;
|
||||
double nearDist = 0;
|
||||
|
||||
map_iterator i = entries.iterator();
|
||||
SoundEntry@ entry;
|
||||
while(i.iterate(@entry)) {
|
||||
double d = to.distanceToSQ(entry.pos);
|
||||
if(d < entry.scale * entry.scale * DROPOFF_FACTOR_SQ && (nearest is null || d < nearDist)) {
|
||||
@nearest = entry;
|
||||
nearDist = d;
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
void tick(double time, const vec3d& pos) {
|
||||
auto@ entry = findNearest(pos);
|
||||
if(entry !is active) {
|
||||
if(active !is null && sound !is null) {
|
||||
if(volume > 0) {
|
||||
volume = max(volume - time, 0.0);
|
||||
sound.volume = volume * sqrt(active.scale);
|
||||
}
|
||||
else {
|
||||
sound.pause();
|
||||
@active = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@active = entry;
|
||||
}
|
||||
}
|
||||
else if(active !is null) {
|
||||
if(sound is null) {
|
||||
@sound = source.play(entry.pos, loop=true, pause=true, priority=true);
|
||||
if(sound !is null) {
|
||||
sound.minDistance = entry.scale;
|
||||
sound.maxDistance = entry.scale * DROPOFF_FACTOR;
|
||||
sound.volume = 0;
|
||||
sound.resume();
|
||||
volume = 0;
|
||||
}
|
||||
}
|
||||
else if(volume < 1.0) {
|
||||
if(volume == 0.0) {
|
||||
sound.position = entry.pos;
|
||||
sound.minDistance = entry.scale;
|
||||
sound.maxDistance = entry.scale * DROPOFF_FACTOR;
|
||||
sound.resume();
|
||||
}
|
||||
volume = min(1.0, volume+time);
|
||||
sound.volume = volume * sqrt(entry.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if(sound !is null)
|
||||
sound.stop();
|
||||
entries.deleteAll();
|
||||
}
|
||||
};
|
||||
|
||||
Mutex mtx;
|
||||
dictionary ambientSounds;
|
||||
|
||||
void addAmbientSource(string sound, int id, vec3d pos, double scale) {
|
||||
Lock lck(mtx);
|
||||
AmbienceGroup@ group;
|
||||
if(!ambientSounds.get(sound, @group)) {
|
||||
const auto@ source = getSound(sound);
|
||||
if(source is null)
|
||||
return;
|
||||
@group = AmbienceGroup(source);
|
||||
ambientSounds.set(sound, @group);
|
||||
}
|
||||
|
||||
group.addEntry(id, pos, scale);
|
||||
}
|
||||
|
||||
void removeAmbientSource(int id) {
|
||||
Lock lck(mtx);
|
||||
AmbienceGroup@ group;
|
||||
dictionary_iterator i = ambientSounds.iterator();
|
||||
while(i.iterate(@group))
|
||||
group.deleteEntry(id);
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
Lock lck(mtx);
|
||||
AmbienceGroup@ group;
|
||||
dictionary_iterator i = ambientSounds.iterator();
|
||||
while(i.iterate(@group))
|
||||
group.tick(time, cameraPos);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
Lock lck(mtx);
|
||||
AmbienceGroup@ group;
|
||||
dictionary_iterator i = ambientSounds.iterator();
|
||||
while(i.iterate(@group))
|
||||
group.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user