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
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
use crate::{
    interface::{ResourceAccess, ResourceModify},
    json_asset_protocol::JsonAsset,
    scriptable::{ScriptableMap, ScriptableValue},
};
use core::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
pub struct AppLifeCycleScripted {
    pub running: bool,
    pub delta_time_seconds: Scalar,
    pub current_state_token: StateToken,
}

impl From<&AppLifeCycle> for AppLifeCycleScripted {
    fn from(value: &AppLifeCycle) -> Self {
        Self {
            running: value.running,
            delta_time_seconds: value.delta_time_seconds(),
            current_state_token: value.current_state_token(),
        }
    }
}

impl ResourceModify<AppLifeCycleScripted> for AppLifeCycle {
    fn modify_resource(&mut self, source: AppLifeCycleScripted) {
        self.running = source.running;
    }
}

impl ResourceAccess for AppLifeCycle {
    fn access_resource(&mut self, _value: ScriptableValue) -> ScriptableValue {
        ScriptableValue::Null
    }
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct AssetsDatabaseLoaderScripted {
    pub ready: bool,
    pub loaded_count: usize,
    pub loaded_paths: Vec<String>,
    pub loading_count: usize,
    pub loading_paths: Vec<String>,
    pub lately_loaded_paths: Vec<String>,
    pub lately_unloaded_paths: Vec<String>,
}

impl From<&AssetsDatabase> for AssetsDatabaseLoaderScripted {
    fn from(value: &AssetsDatabase) -> Self {
        Self {
            ready: value.is_ready(),
            loaded_count: value.loaded_count(),
            loaded_paths: value.loaded_paths(),
            loading_count: value.loading_count(),
            loading_paths: value.loading_paths(),
            lately_loaded_paths: value
                .lately_loaded_paths()
                .map(|p| p.to_owned())
                .collect::<Vec<_>>(),
            lately_unloaded_paths: value
                .lately_unloaded_paths()
                .map(|p| p.to_owned())
                .collect::<Vec<_>>(),
        }
    }
}

impl ResourceModify<AssetsDatabaseLoaderScripted> for AssetsDatabase {
    fn modify_resource(&mut self, _: AssetsDatabaseLoaderScripted) {}
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct AssetsDatabaseScripted {
    #[serde(default)]
    pub load: Option<Vec<String>>,
    #[serde(default)]
    pub unload: Option<Vec<String>>,
}

impl From<&AssetsDatabase> for AssetsDatabaseScripted {
    fn from(_: &AssetsDatabase) -> Self {
        Self {
            load: None,
            unload: None,
        }
    }
}

impl ResourceModify<AssetsDatabaseScripted> for AssetsDatabase {
    fn modify_resource(&mut self, _source: AssetsDatabaseScripted) {}
}

impl ResourceAccess for AssetsDatabase {
    fn access_resource(&mut self, value: ScriptableValue) -> ScriptableValue {
        match value {
            ScriptableValue::Object(object) => {
                if let Some(ScriptableValue::Array(load)) = object.get("load") {
                    for path in load {
                        if let ScriptableValue::String(path) = path {
                            drop(self.load(&path));
                        }
                    }
                    return ScriptableValue::Bool(true);
                } else if let Some(ScriptableValue::Array(load)) = object.get("unload") {
                    for path in load {
                        if let ScriptableValue::String(path) = path {
                            self.remove_by_path(&path);
                        }
                    }
                    return ScriptableValue::Bool(true);
                } else if let Some(ScriptableValue::String(path)) = object.get("serve-pack") {
                    if let Some(asset) = self.asset_by_path(path) {
                        if let Some(pack) = asset.get::<PackAsset>() {
                            let engine = pack.make_fetch_engine();
                            self.push_fetch_engine(Box::new(engine));
                            return ScriptableValue::Bool(true);
                        }
                    }
                } else if let Some(ScriptableValue::Array(paths)) = object.get("loaded") {
                    let map = paths
                        .iter()
                        .filter_map(|path| {
                            if let ScriptableValue::String(path) = path {
                                let path = path.to_string();
                                let result =
                                    ScriptableValue::Bool(self.id_by_path(&path).is_some());
                                Some((path, result))
                            } else {
                                None
                            }
                        })
                        .collect::<ScriptableMap<_, _>>();
                    return ScriptableValue::Object(map);
                }
            }
            ScriptableValue::Array(paths) => {
                let map = paths
                    .into_iter()
                    .filter_map(|path| {
                        let path = path.to_string();
                        if let Some(asset) = self.asset_by_path(&path) {
                            if let Some(protocol) = path.split("://").next() {
                                let data = match protocol {
                                    "text" => ScriptableValue::String(
                                        asset.get::<TextAsset>().unwrap().get().to_owned(),
                                    ),
                                    "json" => asset.get::<JsonAsset>().unwrap().get().clone(),
                                    "binary" => ScriptableValue::Array(
                                        asset
                                            .get::<BinaryAsset>()
                                            .unwrap()
                                            .get()
                                            .iter()
                                            .map(|byte| ScriptableValue::Number((*byte).into()))
                                            .collect::<Vec<_>>(),
                                    ),
                                    _ => return None,
                                };
                                return Some((path, data));
                            }
                        }
                        None
                    })
                    .collect::<ScriptableMap<_, _>>();
                return ScriptableValue::Object(map);
            }
            _ => {}
        }
        ScriptableValue::Null
    }
}