summaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/lua.rs67
-rw-r--r--src/script/wasm.rs380
2 files changed, 336 insertions, 111 deletions
diff --git a/src/script/lua.rs b/src/script/lua.rs
index a5c7f6a..92d455d 100644
--- a/src/script/lua.rs
+++ b/src/script/lua.rs
@@ -50,12 +50,7 @@ impl LuaModule {
warn,
error,
exit,
- is_scene_loaded,
- preload_scene,
switch_scene,
- is_script_loaded,
- preload_script,
- unload_script,
activate_script,
deactivate_script,
state,
@@ -246,29 +241,6 @@ fn exit(lua: &Lua, _: ()) -> mlua::Result<()> {
Ok(())
}
-fn is_scene_loaded(lua: &Lua, scene: String) -> mlua::Result<()> {
- puffin::profile_function!();
- let context = unsafe { context(lua) };
- let scene = scene_id_by_name(&context.manifest.scenes, &scene)
- .ok_or(mlua::Error::runtime("No scene with the given name found"))?;
- crate::scene::is_scene_loaded(
- &context.manifest.scenes,
- context.scripts,
- &context.files,
- scene,
- );
- Ok(())
-}
-
-fn preload_scene(lua: &Lua, scene: String) -> mlua::Result<()> {
- puffin::profile_function!();
- let context = unsafe { context(lua) };
- let scene = scene_id_by_name(&context.manifest.scenes, &scene)
- .ok_or(mlua::Error::runtime("No scene with the given name found"))?;
- context.operation_queue.push(Operation::PreloadScene(scene));
- Ok(())
-}
-
fn switch_scene(lua: &Lua, scene: String) -> mlua::Result<()> {
puffin::profile_function!();
let context = unsafe { context(lua) };
@@ -278,43 +250,6 @@ fn switch_scene(lua: &Lua, scene: String) -> mlua::Result<()> {
Ok(())
}
-fn is_script_loaded(lua: &Lua, script: String) -> mlua::Result<()> {
- puffin::profile_function!();
- let context = unsafe { context(lua) };
- let script = context
- .scripts
- .script_id_by_name(&script)
- .ok_or(mlua::Error::runtime("No script with the given name found"))?;
- context.scripts.is_script_loaded(script, &context.files);
- Ok(())
-}
-
-fn preload_script(lua: &Lua, script: String) -> mlua::Result<()> {
- puffin::profile_function!();
- let context = unsafe { context(lua) };
- let script = context
- .scripts
- .script_id_by_name(&script)
- .ok_or(mlua::Error::runtime("No script with the given name found"))?;
- context
- .operation_queue
- .push(Operation::PreloadScript(script));
- Ok(())
-}
-
-fn unload_script(lua: &Lua, script: String) -> mlua::Result<()> {
- puffin::profile_function!();
- let context = unsafe { context(lua) };
- let script = context
- .scripts
- .script_id_by_name(&script)
- .ok_or(mlua::Error::runtime("No script with the given name found"))?;
- context
- .operation_queue
- .push(Operation::UnloadScript(script));
- Ok(())
-}
-
fn activate_script(lua: &Lua, script: String) -> mlua::Result<()> {
puffin::profile_function!();
let context = unsafe { context(lua) };
@@ -436,7 +371,7 @@ fn storage(lua: &Lua, default: MyLuaValue) -> mlua::Result<MyLuaValue> {
let context = unsafe { context(lua) };
Ok(context
.storage
- .get()
+ .data()
.map(|state| postcard::from_bytes(state).unwrap())
.unwrap_or(default))
}
diff --git a/src/script/wasm.rs b/src/script/wasm.rs
index 9b9cd91..aaf25cf 100644
--- a/src/script/wasm.rs
+++ b/src/script/wasm.rs
@@ -1,4 +1,4 @@
-use std::time::UNIX_EPOCH;
+use std::time::{Duration, UNIX_EPOCH};
use crossterm::{
event::KeyCode,
@@ -35,6 +35,60 @@ fn context_ref<'b>(address: u64) -> &'b FullScriptContext<'b> {
}
}
+fn number_to_button(number: u32) -> gilrs::Button {
+ match number {
+ 0 => gilrs::Button::Unknown,
+ 1 => gilrs::Button::South,
+ 2 => gilrs::Button::East,
+ 3 => gilrs::Button::C,
+ 4 => gilrs::Button::North,
+ 5 => gilrs::Button::West,
+ 6 => gilrs::Button::Z,
+ 7 => gilrs::Button::LeftTrigger,
+ 8 => gilrs::Button::RightTrigger,
+ 9 => gilrs::Button::LeftTrigger2,
+ 10 => gilrs::Button::RightTrigger2,
+ 11 => gilrs::Button::Select,
+ 12 => gilrs::Button::Start,
+ 13 => gilrs::Button::Mode,
+ 14 => gilrs::Button::LeftThumb,
+ 15 => gilrs::Button::RightThumb,
+ 16 => gilrs::Button::DPadUp,
+ 17 => gilrs::Button::DPadDown,
+ 18 => gilrs::Button::DPadLeft,
+ 19 => gilrs::Button::DPadRight,
+ _ => gilrs::Button::Unknown,
+ }
+}
+
+fn number_to_axis(number: u32) -> gilrs::Axis {
+ match number {
+ 0 => gilrs::Axis::Unknown,
+ 1 => gilrs::Axis::LeftStickX,
+ 2 => gilrs::Axis::LeftStickY,
+ 3 => gilrs::Axis::LeftZ,
+ 4 => gilrs::Axis::RightStickX,
+ 5 => gilrs::Axis::RightStickY,
+ 6 => gilrs::Axis::RightZ,
+ 7 => gilrs::Axis::DPadX,
+ 8 => gilrs::Axis::DPadY,
+ _ => gilrs::Axis::Unknown,
+ }
+}
+
+fn set_framerate_limit(
+ _caller: FuncContext<'_>,
+ (context, limit): (u64, u32),
+) -> tinywasm::Result<()> {
+ puffin::profile_function!();
+ let context = context_mut(context);
+ let duration = (limit != 0).then(|| Duration::from_nanos(1_000_000_000 / limit as u64));
+ context
+ .operation_queue
+ .push(Operation::SetFrameLimit(duration));
+ Ok(())
+}
+
fn add_cell(
_caller: FuncContext<'_>,
(
@@ -219,6 +273,174 @@ fn is_key_pressed_this_frame(
)
}
+fn is_mouse_clicked_this_frame(
+ _caller: FuncContext<'_>,
+ (context,): (u64,),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ if context_ref(context).input.is_mouse_clicked_this_frame() {
+ Ok(1)
+ } else {
+ Ok(0)
+ }
+}
+
+fn mouse_location(_caller: FuncContext<'_>, (context,): (u64,)) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ let location = context_ref(context).input.mouse_location();
+
+ if let Some(location) = location {
+ Ok(((location.y as u32) << 16) | location.x as u32)
+ } else {
+ Ok(u32::MAX)
+ }
+}
+
+fn scroll_direction_this_frame(
+ _caller: FuncContext<'_>,
+ (context,): (u64,),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ let direction = context_ref(context).input.scroll_direction_this_frame();
+ Ok(direction.map(|d| d as u32).unwrap_or_default())
+}
+
+fn is_focused(_caller: FuncContext<'_>, (context,): (u64,)) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).input.is_focused() {
+ 1
+ } else {
+ 0
+ })
+}
+
+fn is_gamepad_connected_this_frame(
+ _caller: FuncContext<'_>,
+ context: u64,
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(context_ref(context)
+ .input
+ .is_gamepad_connected_this_frame()
+ .unwrap_or_default() as u32)
+}
+
+fn is_button_pressed_this_frame(
+ _caller: FuncContext<'_>,
+ (context, gamepad_id, button): (u64, u32, u32),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(
+ if context_ref(context)
+ .input
+ .is_button_pressed_this_frame(gamepad_id as usize, number_to_button(button))
+ {
+ 1
+ } else {
+ 0
+ },
+ )
+}
+
+fn is_button_released_this_frame(
+ _caller: FuncContext<'_>,
+ (context, gamepad_id, button): (u64, u32, u32),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(
+ if context_ref(context)
+ .input
+ .is_button_released_this_frame(gamepad_id as usize, number_to_button(button))
+ {
+ 1
+ } else {
+ 0
+ },
+ )
+}
+
+fn is_button_down(
+ _caller: FuncContext<'_>,
+ (context, gamepad_id, button): (u64, u32, u32),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(
+ if context_ref(context)
+ .input
+ .is_button_down(gamepad_id as usize, number_to_button(button))
+ {
+ 1
+ } else {
+ 0
+ },
+ )
+}
+
+fn is_gamepad_connected(
+ _caller: FuncContext<'_>,
+ (context, gamepad_id): (u64, u32),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(
+ if context_ref(context)
+ .input
+ .is_gamepad_connected(gamepad_id as usize)
+ {
+ 1
+ } else {
+ 0
+ },
+ )
+}
+
+fn axis_value(
+ _caller: FuncContext<'_>,
+ (context, gamepad_id, axis): (u64, u32, u32),
+) -> tinywasm::Result<f32> {
+ puffin::profile_function!();
+ Ok(context_ref(context)
+ .input
+ .axis_value(gamepad_id as usize, number_to_axis(axis))
+ .unwrap_or_default())
+}
+
+fn gamepad_power_info(
+ _caller: FuncContext<'_>,
+ (context, gamepad_id): (u64, u32),
+) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(
+ match context_ref(context)
+ .input
+ .gamepad_power_info(gamepad_id as usize)
+ {
+ None | Some(gilrs::PowerInfo::Unknown) => 0,
+ Some(gilrs::PowerInfo::Wired) => 1 << 16,
+ Some(gilrs::PowerInfo::Discharging(power)) => 2 << 16 | power as u32,
+ Some(gilrs::PowerInfo::Charging(power)) => 3 << 16 | power as u32,
+ Some(gilrs::PowerInfo::Charged) => 4 << 16,
+ },
+ )
+}
+
+fn was_focused_this_frame(_caller: FuncContext<'_>, (context,): (u64,)) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).input.was_focused_this_frame() {
+ 1
+ } else {
+ 0
+ })
+}
+
+fn was_unfocused_this_frame(_caller: FuncContext<'_>, (context,): (u64,)) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).input.was_unfocused_this_frame() {
+ 1
+ } else {
+ 0
+ })
+}
+
fn log(
caller: FuncContext<'_>,
(severity, offset, length): (u32, u32, u32),
@@ -261,30 +483,31 @@ fn scene_id_by_name(
)
}
-fn preload_scene(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<()> {
+fn switch_scene(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<()> {
puffin::profile_function!();
context_mut(context)
.operation_queue
- .push(Operation::PreloadScene(id as usize));
+ .push(Operation::SwitchScene(id as usize));
Ok(())
}
-fn is_scene_loaded(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<u32> {
+fn script_name_size(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32> {
puffin::profile_function!();
let context = context_ref(context);
- Ok(crate::scene::is_scene_loaded(
- &context.manifest.scenes,
- context.scripts,
- &context.files,
- id as usize,
- ) as u32)
+ Ok(context.scripts.scripts[context.script_id].name().len() as u32)
}
-fn switch_scene(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<()> {
+fn load_script_name(
+ mut caller: FuncContext<'_>,
+ (context, offset): (u64, u32),
+) -> tinywasm::Result<()> {
puffin::profile_function!();
- context_mut(context)
- .operation_queue
- .push(Operation::SwitchScene(id as usize));
+ let memory = caller.memory("memory").unwrap();
+ let context = context_ref(context);
+ let name = context.scripts.scripts[context.script_id].name();
+ memory
+ .write(&mut caller, offset as usize, name.as_bytes())
+ .unwrap();
Ok(())
}
@@ -302,30 +525,6 @@ fn script_id_by_name(
.unwrap_or(u32::MAX))
}
-fn preload_script(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<()> {
- puffin::profile_function!();
- context_mut(context)
- .operation_queue
- .push(Operation::PreloadScript(id as usize));
- Ok(())
-}
-
-fn is_script_loaded(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<u32> {
- puffin::profile_function!();
- let context = context_ref(context);
- Ok(context
- .scripts
- .is_script_loaded(id as usize, &context.files) as u32)
-}
-
-fn unload_script(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<()> {
- puffin::profile_function!();
- context_mut(context)
- .operation_queue
- .push(Operation::UnloadScript(id as usize));
- Ok(())
-}
-
fn activate_script(_caller: FuncContext<'_>, (context, id): (u64, u32)) -> tinywasm::Result<()> {
puffin::profile_function!();
context_mut(context)
@@ -444,7 +643,7 @@ fn storage_size(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32>
puffin::profile_function!();
Ok(context_ref(context)
.storage
- .get()
+ .data()
.map(|data| data.len())
.unwrap_or_default() as u32)
}
@@ -456,7 +655,7 @@ fn load_storage(
puffin::profile_function!();
let memory = caller.memory("memory").unwrap();
let context = context_ref(context);
- let state = context.storage.get().unwrap_or(&[]);
+ let state = context.storage.data().unwrap_or(&[]);
memory.write(&mut caller, offset as usize, state).unwrap();
Ok(())
}
@@ -480,6 +679,79 @@ fn save_storage(
Ok(())
}
+fn is_saving_storage(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).storage.is_saving_data() {
+ 1
+ } else {
+ 0
+ })
+}
+
+fn saving_storage_failed(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).storage.saving_data_failed() {
+ 1
+ } else {
+ 0
+ })
+}
+
+fn config_size(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(context_ref(context)
+ .storage
+ .config()
+ .map(|data| data.len())
+ .unwrap_or_default() as u32)
+}
+
+fn load_config(mut caller: FuncContext<'_>, (context, offset): (u64, u32)) -> tinywasm::Result<()> {
+ puffin::profile_function!();
+ let memory = caller.memory("memory").unwrap();
+ let context = context_ref(context);
+ let state = context.storage.config().unwrap_or(&[]);
+ memory.write(&mut caller, offset as usize, state).unwrap();
+ Ok(())
+}
+
+fn save_config(
+ mut caller: FuncContext<'_>,
+ (context, offset, length): (u64, u32, u32),
+) -> tinywasm::Result<()> {
+ puffin::profile_function!();
+ let offset = offset as usize;
+ let length = length as usize;
+ let memory = caller.memory("memory").unwrap();
+ let new_save = memory
+ .read_vec(caller.store_mut(), offset, length)
+ .unwrap()
+ .into_boxed_slice();
+ let context = context_mut(context);
+ context
+ .operation_queue
+ .push(Operation::UpdateConfig { new_save });
+ Ok(())
+}
+
+fn is_saving_config(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).storage.is_saving_config() {
+ 1
+ } else {
+ 0
+ })
+}
+
+fn saving_config_failed(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u32> {
+ puffin::profile_function!();
+ Ok(if context_ref(context).storage.saving_config_failed() {
+ 1
+ } else {
+ 0
+ })
+}
+
fn system_now(_caller: FuncContext<'_>, context: u64) -> tinywasm::Result<u64> {
puffin::profile_function!();
Ok(context_ref(context)
@@ -514,18 +786,29 @@ pub fn linker(store: &mut Store) -> Result<Imports, tinywasm::Error> {
[
add_cell,
window_size,
+ set_framerate_limit,
is_key_pressed_this_frame,
+ is_mouse_clicked_this_frame,
+ mouse_location,
+ scroll_direction_this_frame,
+ is_focused,
+ is_button_pressed_this_frame,
+ is_button_released_this_frame,
+ is_gamepad_connected_this_frame,
+ is_gamepad_connected,
+ is_button_down,
+ axis_value,
+ gamepad_power_info,
+ was_focused_this_frame,
+ was_unfocused_this_frame,
log,
exit,
random_u64,
+ script_name_size,
+ load_script_name,
scene_id_by_name,
- preload_scene,
switch_scene,
- is_scene_loaded,
script_id_by_name,
- preload_script,
- is_script_loaded,
- unload_script,
activate_script,
deactivate_script,
state_size,
@@ -537,6 +820,13 @@ pub fn linker(store: &mut Store) -> Result<Imports, tinywasm::Error> {
storage_size,
load_storage,
save_storage,
+ is_saving_storage,
+ saving_storage_failed,
+ config_size,
+ load_config,
+ save_config,
+ is_saving_config,
+ saving_config_failed,
system_now,
monotonic_now,
delta_time