Create an early scripting engine #2

Merged
SeanOMik merged 42 commits from feature/early-scripting into main 2024-03-03 03:28:57 +00:00
7 changed files with 66 additions and 64 deletions
Showing only changes of commit aadc8e5094 - Show all commits

40
Cargo.lock generated
View File

@ -45,15 +45,6 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.16" version = "0.2.16"
@ -1567,13 +1558,11 @@ dependencies = [
"anyhow", "anyhow",
"elua", "elua",
"itertools 0.12.0", "itertools 0.12.0",
"lazy_static",
"lyra-ecs", "lyra-ecs",
"lyra-game", "lyra-game",
"lyra-reflect", "lyra-reflect",
"lyra-resource", "lyra-resource",
"lyra-scripting-derive", "lyra-scripting-derive",
"regex",
"thiserror", "thiserror",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
@ -2215,35 +2204,6 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]]
name = "regex"
version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "renderdoc-sys" name = "renderdoc-sys"
version = "0.7.1" version = "0.7.1"

View File

@ -7,7 +7,7 @@ function on_init()
local e = world:spawn(pos, cube) local e = world:spawn(pos, cube)
print("spawned entity " .. tostring(e)) print("spawned entity " .. tostring(e))
local action_handler_tbl = { local handler = ActionHandler.new {
layouts = { 0 }, layouts = { 0 },
actions = { actions = {
MoveForwardBackward = "Axis", MoveForwardBackward = "Axis",
@ -16,6 +16,7 @@ function on_init()
LookLeftRight = "Axis", LookLeftRight = "Axis",
LookUpDown = "Axis", LookUpDown = "Axis",
LookRoll = "Axis", LookRoll = "Axis",
ObjectsMoveUpDown = "Axis"
}, },
mappings = { mappings = {
{ {
@ -40,13 +41,15 @@ function on_init()
}, },
LookRoll = { LookRoll = {
"key:e=-1.0", "key:q=1.0", "key:e=-1.0", "key:q=1.0",
},
ObjectsMoveUpDown = {
"key:u=1.0", "key:j=-1.0"
} }
} }
} }
} }
} }
local handler = ActionHandler.new(action_handler_tbl)
world:add_resource(handler) world:add_resource(handler)
end end
@ -61,15 +64,16 @@ end ]]
function on_update() function on_update()
---@type number ---@type number
local dt = world:resource(DeltaTime) local dt = world:resource(DeltaTime)
local act = world:resource(ActionHandler)
---@type number
local move_objs = act:get_axis("ObjectsMoveUpDown")
world:view(function (t) world:view(function (t)
t:translate(0, 0.5 * dt, 0) if move_objs ~= nil then
t:translate(0, move_objs * 0.35 * dt, 0)
return t return t
end
end, Transform) end, Transform)
--local input = world:resource(Input)
--input.
end end
--[[ function on_post_update() --[[ function on_post_update()

View File

@ -23,8 +23,6 @@ tracing = "0.1.37"
#mlua = { version = "0.9.2", features = ["lua54"], optional = true } # luajit maybe? #mlua = { version = "0.9.2", features = ["lua54"], optional = true } # luajit maybe?
elua = { path = "./elua", optional = true } elua = { path = "./elua", optional = true }
itertools = "0.12.0" itertools = "0.12.0"
regex = "1.10.3"
lazy_static = "1.4.0"
[dev-dependencies] [dev-dependencies]

@ -1 +1 @@
Subproject commit beea6c33fcb2f5bd16f40e1919b61a89b4aaecb6 Subproject commit 936ea606343dbcf5321b4b988de65daf8769ff3f

View File

@ -12,6 +12,7 @@ impl ScriptApiProvider for LyraEcsApiProvider {
fn prepare_world(&mut self, world: &mut lyra_ecs::World) { fn prepare_world(&mut self, world: &mut lyra_ecs::World) {
world.register_lua_convert::<LuaDeltaTime>(); world.register_lua_convert::<LuaDeltaTime>();
world.register_lua_wrapper::<LuaModelComponent>(); world.register_lua_wrapper::<LuaModelComponent>();
world.register_lua_wrapper::<LuaActionHandler>();
} }
fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {

View File

@ -1,7 +1,7 @@
use std::{ptr::NonNull, sync::Arc}; use std::{ptr::NonNull, sync::Arc};
use crate::{ScriptBorrow, ScriptEntity, ScriptWorldPtr}; use crate::{ScriptBorrow, ScriptEntity, ScriptWorldPtr};
use elua::{AnyUserdata, AsLua, Table}; use elua::AsLua;
use lyra_ecs::{query::dynamic::QueryDynamicType, CommandQueue, Commands, DynamicBundle, World}; use lyra_ecs::{query::dynamic::QueryDynamicType, CommandQueue, Commands, DynamicBundle, World};
use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry}; use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry};
use lyra_resource::ResourceManager; use lyra_resource::ResourceManager;
@ -268,7 +268,7 @@ impl elua::Userdata for ScriptWorldPtr {
let reg_type = this let reg_type = this
.as_ref() .as_ref()
.get_type::<RegisteredType>(reflect.reflect_branch.reflect_type_id()) .get_type::<RegisteredType>(reflect.reflect_branch.reflect_type_id())
.unwrap(); .expect("Resource is not type registered!");
let proxy = reg_type let proxy = reg_type
.get_data::<ReflectLuaProxy>() .get_data::<ReflectLuaProxy>()
.expect("Type does not have ReflectLuaProxy as a TypeData"); .expect("Type does not have ReflectLuaProxy as a TypeData");

View File

@ -1,15 +1,11 @@
use lyra_game::input::{keycode_from_str, Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, LayoutId, MouseAxis, MouseInput}; use lyra_game::input::{keycode_from_str, Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, ActionState, LayoutId, MouseAxis, MouseInput};
use crate::lyra_engine;
use lazy_static::lazy_static; use lyra_reflect::Reflect;
use regex::Regex;
use crate::{lua::{FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptBorrow}; use crate::{lua::{LuaWrapper, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptBorrow};
lazy_static! { #[derive(Clone, Reflect)]
static ref BINDING_INPUT_RE: Regex = Regex::new(r"(\w+):(\w+)(?:=(-?\d+(?:.\d+)?))?").unwrap();
}
#[derive(Clone)]
pub struct LuaActionHandler { pub struct LuaActionHandler {
handler: ActionHandler handler: ActionHandler
} }
@ -23,7 +19,7 @@ impl elua::Userdata for LuaActionHandler {
builder.function("new", |_, table: elua::Table| { builder.function("new", |_, table: elua::Table| {
let mut handler = ActionHandler::new(); let mut handler = ActionHandler::new();
// create the layouts // create the layouts and add them to the handler
let layouts = table.get::<_, elua::Table>("layouts") let layouts = table.get::<_, elua::Table>("layouts")
.map_err(|_| elua::Error::runtime("missing 'layouts' in ActionHandler table"))?; .map_err(|_| elua::Error::runtime("missing 'layouts' in ActionHandler table"))?;
for layout_id in layouts.sequence_iter::<u32>() { for layout_id in layouts.sequence_iter::<u32>() {
@ -32,6 +28,7 @@ impl elua::Userdata for LuaActionHandler {
handler.add_layout(LayoutId(layout_id)); handler.add_layout(LayoutId(layout_id));
} }
// add the actions to the handler
let actions = table.get::<_, elua::Table>("actions") let actions = table.get::<_, elua::Table>("actions")
.map_err(|_| elua::Error::runtime("missing 'actions' in ActionHandler table"))?; .map_err(|_| elua::Error::runtime("missing 'actions' in ActionHandler table"))?;
for pair in actions.pairs::<String, String>() { for pair in actions.pairs::<String, String>() {
@ -47,6 +44,7 @@ impl elua::Userdata for LuaActionHandler {
handler.add_action(action_lbl, Action::new(action_type)); handler.add_action(action_lbl, Action::new(action_type));
} }
// find the mappings and start processing them
let mappings= table.get::<_, elua::Table>("mappings") let mappings= table.get::<_, elua::Table>("mappings")
.map_err(|_| elua::Error::runtime("missing 'mappings' in ActionHandler table"))?; .map_err(|_| elua::Error::runtime("missing 'mappings' in ActionHandler table"))?;
for (map_id, tbl) in mappings.sequence_iter::<elua::Table>().enumerate() { for (map_id, tbl) in mappings.sequence_iter::<elua::Table>().enumerate() {
@ -55,6 +53,8 @@ impl elua::Userdata for LuaActionHandler {
let layout_id = tbl.get::<_, u32>("layout")?; let layout_id = tbl.get::<_, u32>("layout")?;
let mut mapping = ActionMapping::new(LayoutId(layout_id), ActionMappingId(map_id as u32)); let mut mapping = ActionMapping::new(LayoutId(layout_id), ActionMappingId(map_id as u32));
// find the binds and start processing them
// the keys are used as the action names, and then the value is an array (lua table)
let binds_tbl = tbl.get::<_, elua::Table>("binds") let binds_tbl = tbl.get::<_, elua::Table>("binds")
.map_err(|_| elua::Error::runtime("missing 'binds' in ActionHandler 'mappings' table"))?; .map_err(|_| elua::Error::runtime("missing 'binds' in ActionHandler 'mappings' table"))?;
for pair in binds_tbl.pairs::<String, elua::Table>() { for pair in binds_tbl.pairs::<String, elua::Table>() {
@ -106,10 +106,43 @@ impl elua::Userdata for LuaActionHandler {
handler, handler,
}) })
}) })
.method("get_axis", |_, this, action: String| {
Ok(this.handler.get_axis_modifier(action))
})
.method("is_pressed", |_, this, action: String| {
Ok(this.handler.is_action_pressed(action))
})
.method("was_just_pressed", |_, this, action: String| {
Ok(this.handler.was_action_just_pressed(action))
})
.method("was_just_released", |_, this, action: String| {
Ok(this.handler.was_action_just_released(action))
})
.method("get_just_pressed", |_, this, action: String| {
Ok(this.handler.get_just_pressed_modifier(action))
})
.method("get_action_state", |lua, this, action: String| {
let state = this.handler.get_action_state(action);
let (name, val) = match state {
ActionState::Idle => ("Idle", None),
ActionState::Pressed(v) => ("Pressed", Some(v)),
ActionState::JustPressed(v) => ("JustPressed", Some(v)),
ActionState::JustReleased => ("JustReleased", None),
ActionState::Axis(v) => ("Axis", Some(v)),
ActionState::Other(v) => ("Other", Some(v)),
};
let mut multi = elua::ValueVec::new();
multi.push_val(lua, name)?;
multi.push_val(lua, val)?;
Ok(elua::Value::Multi(multi))
})
.method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| { .method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
Ok(ScriptBorrow::from_resource::<ActionHandler>(Some(this.handler.clone()))) Ok(ScriptBorrow::from_resource::<ActionHandler>(Some(this.handler.clone())))
}) })
.method(FN_NAME_INTERNAL_REFLECT_TYPE, |_, _, ()| { .function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
Ok(ScriptBorrow::from_resource::<ActionHandler>(None)) Ok(ScriptBorrow::from_resource::<ActionHandler>(None))
}); });
@ -128,6 +161,12 @@ impl<'a> elua::FromLua<'a> for LuaActionHandler {
} }
} }
impl LuaWrapper for LuaActionHandler {
fn wrapped_type_id() -> std::any::TypeId {
std::any::TypeId::of::<ActionHandler>()
}
}
fn process_keyboard_string(key_name: &str) -> Option<ActionSource> { fn process_keyboard_string(key_name: &str) -> Option<ActionSource> {
let key = keycode_from_str(key_name)?; let key = keycode_from_str(key_name)?;