2022-01-16 15:45:25 +01:00
|
|
|
//! Implementation of the Event Handler With State Pattern - Main Style
|
|
|
|
|
2022-07-26 11:05:42 +02:00
|
|
|
#[cfg(feature = "no_function")]
|
|
|
|
pub fn main() {
|
|
|
|
panic!("This example does not run under 'no_function'.")
|
|
|
|
}
|
2022-01-16 15:45:25 +01:00
|
|
|
|
2022-07-26 11:05:42 +02:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
pub fn main() {
|
2022-11-21 16:42:29 +01:00
|
|
|
use rhai::{CallFnOptions, Dynamic, Engine, Scope, AST};
|
2022-07-26 11:05:42 +02:00
|
|
|
use std::io::{stdin, stdout, Write};
|
2022-01-16 15:45:25 +01:00
|
|
|
|
2022-07-26 11:05:42 +02:00
|
|
|
const SCRIPT_FILE: &str = "event_handler_main/script.rhai";
|
2022-01-16 15:45:25 +01:00
|
|
|
|
2022-07-26 11:05:42 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct Handler {
|
|
|
|
pub engine: Engine,
|
|
|
|
pub scope: Scope<'static>,
|
|
|
|
pub ast: AST,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn print_scope(scope: &Scope) {
|
|
|
|
for (i, (name, constant, value)) in scope.iter_raw().enumerate() {
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
let value_is_shared = if value.is_shared() { " (shared)" } else { "" };
|
|
|
|
#[cfg(feature = "no_closure")]
|
|
|
|
let value_is_shared = "";
|
|
|
|
|
|
|
|
println!(
|
|
|
|
"[{}] {}{}{} = {:?}",
|
|
|
|
i + 1,
|
|
|
|
if constant { "const " } else { "" },
|
|
|
|
name,
|
|
|
|
value_is_shared,
|
|
|
|
*value.read_lock::<Dynamic>().unwrap(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
println!();
|
2022-01-28 11:59:18 +01:00
|
|
|
}
|
2022-01-16 15:45:25 +01:00
|
|
|
|
|
|
|
println!("Events Handler Example - Main Style");
|
|
|
|
println!("===================================");
|
|
|
|
|
|
|
|
let mut input = String::new();
|
|
|
|
|
|
|
|
// Read script file
|
|
|
|
print!("Script file [{}]: ", SCRIPT_FILE);
|
|
|
|
stdout().flush().expect("flush stdout");
|
|
|
|
|
|
|
|
input.clear();
|
|
|
|
|
|
|
|
stdin().read_line(&mut input).expect("read input");
|
|
|
|
|
|
|
|
let path = match input.trim() {
|
|
|
|
"" => SCRIPT_FILE,
|
|
|
|
path => path,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create Engine
|
|
|
|
let engine = Engine::new();
|
|
|
|
|
|
|
|
// Create a custom 'Scope' to hold state
|
|
|
|
let mut scope = Scope::new();
|
|
|
|
|
|
|
|
// Add any system-provided state into the custom 'Scope'.
|
|
|
|
// Constants can be used to optimize the script.
|
|
|
|
scope.push_constant("MY_CONSTANT", 42_i64);
|
|
|
|
|
|
|
|
// Compile the handler script.
|
2022-10-27 07:38:21 +02:00
|
|
|
println!("> Loading script file: {path}");
|
2022-01-16 15:45:25 +01:00
|
|
|
|
|
|
|
let ast = match engine.compile_file_with_scope(&mut scope, path.into()) {
|
|
|
|
Ok(ast) => ast,
|
|
|
|
Err(err) => {
|
|
|
|
eprintln!("! Error: {}", err);
|
|
|
|
println!("Cannot continue. Bye!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
println!("> Script file loaded.");
|
|
|
|
println!();
|
|
|
|
println!("quit = exit program");
|
|
|
|
println!("scope = print scope");
|
|
|
|
println!("event arg = run function with argument");
|
|
|
|
println!();
|
|
|
|
|
|
|
|
// Run the 'init' function to initialize the state, retaining variables.
|
2022-11-21 16:42:29 +01:00
|
|
|
let options = CallFnOptions::new().eval_ast(false).rewind_scope(false);
|
|
|
|
|
|
|
|
let result = engine.call_fn_with_options::<()>(options, &mut scope, &ast, "init", ());
|
2022-01-16 15:45:25 +01:00
|
|
|
|
|
|
|
if let Err(err) = result {
|
2022-10-27 07:38:21 +02:00
|
|
|
eprintln!("! {err}")
|
2022-01-16 15:45:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create handler instance
|
|
|
|
let mut handler = Handler { engine, scope, ast };
|
|
|
|
|
|
|
|
// Events loop
|
|
|
|
loop {
|
|
|
|
print!("event> ");
|
|
|
|
stdout().flush().expect("flush stdout");
|
|
|
|
|
|
|
|
// Read event
|
|
|
|
input.clear();
|
|
|
|
stdin().read_line(&mut input).expect("read input");
|
|
|
|
|
|
|
|
let mut fields = input.trim().splitn(2, ' ');
|
|
|
|
|
|
|
|
let event = fields.next().expect("event").trim();
|
2022-11-21 16:42:29 +01:00
|
|
|
let arg = fields.next().unwrap_or("").to_string();
|
2022-01-16 15:45:25 +01:00
|
|
|
|
|
|
|
// Process event
|
|
|
|
match event {
|
|
|
|
"quit" => break,
|
|
|
|
|
|
|
|
"scope" => {
|
|
|
|
print_scope(&handler.scope);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Map all other events to function calls
|
|
|
|
_ => {
|
|
|
|
let engine = &handler.engine;
|
|
|
|
let scope = &mut handler.scope;
|
|
|
|
let ast = &handler.ast;
|
|
|
|
|
2022-11-21 16:42:29 +01:00
|
|
|
let result = engine.call_fn::<()>(scope, ast, event, (arg,));
|
2022-01-16 15:45:25 +01:00
|
|
|
|
|
|
|
if let Err(err) = result {
|
2022-10-27 07:38:21 +02:00
|
|
|
eprintln!("! {err}")
|
2022-01-16 15:45:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("Bye!");
|
|
|
|
}
|