1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::{
    audio_asset_protocol::AudioAsset,
    component::{AudioSource, AudioSourceDirtyMode},
    resource::Audio,
};
use core::{
    assets::database::AssetsDatabase,
    ecs::{life_cycle::EntityChanges, Comp, Universe, WorldRef},
};

pub type AudioSystemResources<'a, A> = (
    WorldRef,
    &'a EntityChanges,
    &'a AssetsDatabase,
    &'a mut A,
    Comp<&'a mut AudioSource>,
);

pub fn audio_system<A>(universe: &mut Universe)
where
    A: Audio + 'static,
{
    let (world, changes, assets, mut audio, ..) =
        universe.query_resources::<AudioSystemResources<A>>();

    audio.update_cache(&assets);

    for entity in changes.despawned() {
        audio.destroy_source(entity);
    }

    for (entity, source) in world.query::<&mut AudioSource>().iter() {
        if source.dirty != AudioSourceDirtyMode::None {
            if !audio.has_source(entity) {
                if let Some(id) = audio.get_asset_id(source.audio()) {
                    if let Some(asset) = assets.asset_by_id(id) {
                        if let Some(asset) = asset.get::<AudioAsset>() {
                            audio.create_source(
                                entity,
                                asset.bytes(),
                                source.streaming(),
                                source.looped(),
                                source.playback_rate(),
                                source.volume(),
                                source.must_play(),
                                source.ready.clone(),
                            );
                            source.dirty = AudioSourceDirtyMode::None;
                        }
                    }
                }
            } else {
                audio.update_source(
                    entity,
                    source.looped(),
                    source.playback_rate(),
                    source.volume(),
                    if source.dirty == AudioSourceDirtyMode::All {
                        Some(source.must_play())
                    } else {
                        None
                    },
                );
                source.dirty = AudioSourceDirtyMode::None;
            }
        }
        if let Some(state) = audio.get_source_state(entity) {
            source.current_time = state.current_time;
        }
    }
}