math-mumu 0.1.12

Math functions plugin for the MuMu / Lava language
Documentation
use mumu::parser::types::Value;
use mumu::parser::interpreter::Interpreter;
use crate::partials::{is_placeholder, make_three_arg_partial};

pub fn math_rotate_point_bridge(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
    match args.len() {
        0 => Ok(make_three_arg_partial(rotate_point_finalize, None, None, None)),
        1 => {
            let a = &args[0];
            if is_placeholder(a) {
                Ok(make_three_arg_partial(rotate_point_finalize, None, None, None))
            } else {
                Ok(make_three_arg_partial(rotate_point_finalize, Some(a.clone()), None, None))
            }
        }
        2 => {
            let lp = is_placeholder(&args[0]);
            let rp = is_placeholder(&args[1]);
            Ok(make_three_arg_partial(
                rotate_point_finalize,
                if lp { None } else { Some(args[0].clone()) },
                if rp { None } else { Some(args[1].clone()) },
                None,
            ))
        }
        3 => {
            let lp = is_placeholder(&args[0]);
            let mp = is_placeholder(&args[1]);
            let rp = is_placeholder(&args[2]);
            if !lp && !mp && !rp {
                rotate_point_finalize(vec![args[0].clone(), args[1].clone(), args[2].clone()])
            } else {
                Ok(make_three_arg_partial(
                    rotate_point_finalize,
                    if lp { None } else { Some(args[0].clone()) },
                    if mp { None } else { Some(args[1].clone()) },
                    if rp { None } else { Some(args[2].clone()) },
                ))
            }
        }
        n => Err(format!("math:rotate_point expects 3 arguments, got {}", n)),
    }
}

fn rotate_point_finalize(args: Vec<Value>) -> Result<Value, String> {
    if args.len() != 3 {
        return Err(format!("rotate_point_finalize => expected 3 args, got {}", args.len()));
    }
    let x = match &args[0] {
        Value::Float(f) => *f,
        Value::Int(i) => *i as f64,
        other => return Err(format!("math:rotate_point: first arg (x) must be float or int, got {:?}", other)),
    };
    let y = match &args[1] {
        Value::Float(f) => *f,
        Value::Int(i) => *i as f64,
        other => return Err(format!("math:rotate_point: second arg (y) must be float or int, got {:?}", other)),
    };
    let rad = match &args[2] {
        Value::Float(f) => *f,
        Value::Int(i) => *i as f64,
        other => return Err(format!("math:rotate_point: third arg (rad) must be float or int, got {:?}", other)),
    };
    let cos_a = rad.cos();
    let sin_a = rad.sin();
    let out_x = x * cos_a - y * sin_a;
    let out_y = x * sin_a + y * cos_a;
    Ok(Value::FloatArray(vec![out_x, out_y]))
}