oxygengine_audio/
system.rs

1use crate::{
2    audio_asset_protocol::AudioAsset,
3    component::{AudioSource, AudioSourceDirtyMode},
4    resource::{Audio, AudioPlayState},
5};
6use core::{
7    assets::database::AssetsDatabase,
8    ecs::{life_cycle::EntityChanges, Comp, Universe, WorldRef},
9};
10
11pub type AudioSystemResources<'a, A> = (
12    WorldRef,
13    &'a EntityChanges,
14    &'a AssetsDatabase,
15    &'a mut A,
16    Comp<&'a mut AudioSource>,
17);
18
19pub fn audio_system<A>(universe: &mut Universe)
20where
21    A: Audio + 'static,
22{
23    let (world, changes, assets, mut audio, ..) =
24        universe.query_resources::<AudioSystemResources<A>>();
25
26    audio.update_cache(&assets);
27
28    for entity in changes.despawned() {
29        audio.destroy_source(entity);
30    }
31
32    for (entity, source) in world.query::<&mut AudioSource>().iter() {
33        if source.dirty != AudioSourceDirtyMode::None {
34            if !audio.has_source(entity) {
35                if let Some(id) = audio.get_asset_id(source.audio()) {
36                    if let Some(asset) = assets.asset_by_id(id) {
37                        if let Some(asset) = asset.get::<AudioAsset>() {
38                            audio.create_source(
39                                entity,
40                                asset.bytes(),
41                                source.streaming(),
42                                source.looped(),
43                                source.playback_rate(),
44                                source.volume(),
45                                source.is_playing(),
46                                source.ready.clone(),
47                            );
48                            source.dirty = AudioSourceDirtyMode::None;
49                        }
50                    }
51                }
52            } else {
53                audio.update_source(
54                    entity,
55                    source.looped(),
56                    source.playback_rate(),
57                    source.volume(),
58                    if source.dirty == AudioSourceDirtyMode::All {
59                        Some(source.is_playing())
60                    } else {
61                        None
62                    },
63                );
64                source.dirty = AudioSourceDirtyMode::None;
65            }
66        }
67        if let Some(state) = audio.get_source_state(entity) {
68            source.current_time = state.current_time;
69            match state.is_playing {
70                AudioPlayState::Ended(v) => {
71                    if v {
72                        source.stop();
73                    }
74                }
75                AudioPlayState::State(v) => {
76                    if v != source.is_playing() {
77                        if v {
78                            source.play();
79                        } else {
80                            source.stop();
81                        }
82                    }
83                }
84            }
85        }
86    }
87}