use std::convert::TryInto; use std::time::Duration; use minifb::{Key, Window, WindowOptions, MouseMode}; mod actor; mod basic_actors; mod number; mod world; const WIDTH: usize = 1600; const HEIGHT: usize = 900; fn main() { let mut window = Window::new( "the Hope system", WIDTH, HEIGHT, WindowOptions::default() ).unwrap(); window.limit_update_rate(Some(Duration::from_millis(16))); // hard code this for now let mut world = world::World::default(); let nonnegative_int = actor::Type::NumberInRange { min: Some(number::Number::from(0)), max: None, }; let screen_position_type = actor::Type::Record { name: "Screen Position".to_string(), fields: vec![ actor::Slot { name: "X".to_string(), r#type: nonnegative_int.clone() }, actor::Slot { name: "Y".to_string(), r#type: nonnegative_int.clone() }, ], }; let system_inputs = vec![actor::Slot { name: "mouse_position".to_string(), r#type: screen_position_type.clone() }]; let u24 = actor::Type::NumberInRange { min: Some(number::Number::from(0)), max: Some(number::Number::from(1 << 24 - 1)), }; let system_outputs = vec![actor::Slot { name: "screen_buffer".to_string(), r#type: actor::Type::List { contents: Box::new(u24.clone()) }}]; let mut system = actor::ProgrammableActor { inputs: system_inputs, outputs: system_outputs, ..Default::default() }; let zero_constant = basic_actors::Constant { r#type: u24.clone(), value: actor::Value::Number(number::Number::from(0)), }; world.upsert_actor_type("Zero Constant".to_string(), Box::new(zero_constant)); let zero_constant = system.add_child("Zero Constant".to_string()); let buffer_size_constant = basic_actors::Constant { r#type: nonnegative_int.clone(), value: actor::Value::Number(number::Number::from(WIDTH * HEIGHT)), }; world.upsert_actor_type("Buffer Size Constant".to_string(), Box::new(buffer_size_constant)); let buffer_size_constant = system.add_child("Buffer Size Constant".to_string()); let repeat_u24 = basic_actors::RepeatValue { r#type: u24.clone(), }; world.upsert_actor_type("Repeat u24".to_string(), Box::new(repeat_u24)); let repeat_u24 = system.add_child("Repeat u24".to_string()); system.add_cable( actor::ProducerSlotID::ChildOutput(zero_constant, "Value".to_string()), actor::ConsumerSlotID::ChildInput(repeat_u24, "Value".to_string()) ); system.add_cable( actor::ProducerSlotID::ChildOutput(buffer_size_constant, "Value".to_string()), actor::ConsumerSlotID::ChildInput(repeat_u24, "Count".to_string()) ); let deconstruct_record = basic_actors::DeconstructRecord { record_type: screen_position_type, }; world.upsert_actor_type("Deconstruct Screen Position".to_string(), Box::new(deconstruct_record)); let deconstruct_record = system.add_child("Deconstruct Screen Position".to_string()); system.add_cable( actor::ProducerSlotID::Input("mouse_position".to_string()), actor::ConsumerSlotID::ChildInput(deconstruct_record, "Record".to_string()) ); let width_constant = basic_actors::Constant { r#type: nonnegative_int.clone(), value: actor::Value::Number(number::Number::from(WIDTH)), }; world.upsert_actor_type("Width Constant".to_string(), Box::new(width_constant)); let width_constant = system.add_child("Width Constant".to_string()); let multiply = basic_actors::Multiply; world.upsert_actor_type("Multiply".to_string(), Box::new(multiply)); let multiply = system.add_child("Multiply".to_string()); system.add_cable( actor::ProducerSlotID::ChildOutput(deconstruct_record, "Y".to_string()), actor::ConsumerSlotID::ChildInput(multiply, "N1".to_string()) ); system.add_cable( actor::ProducerSlotID::ChildOutput(width_constant, "Value".to_string()), actor::ConsumerSlotID::ChildInput(multiply, "N2".to_string()) ); let add = basic_actors::Add; world.upsert_actor_type("Add".to_string(), Box::new(add)); let add = system.add_child("Add".to_string()); system.add_cable( actor::ProducerSlotID::ChildOutput(deconstruct_record, "X".to_string()), actor::ConsumerSlotID::ChildInput(add, "N1".to_string()) ); system.add_cable( actor::ProducerSlotID::ChildOutput(multiply, "Result".to_string()), actor::ConsumerSlotID::ChildInput(add, "N2".to_string()) ); let red_constant = basic_actors::Constant { r#type: u24.clone(), value: actor::Value::Number(number::Number::from(0xFF << 16)) }; world.upsert_actor_type("Red Constant".to_string(), Box::new(red_constant)); let red_constant = system.add_child("Red Constant".to_string()); let set_u24 = basic_actors::SetListItem { r#type: u24.clone() }; world.upsert_actor_type("Set u24".to_string(), Box::new(set_u24)); let set_u24 = system.add_child("Set u24".to_string()); system.add_cable( actor::ProducerSlotID::ChildOutput(repeat_u24, "List".to_string()), actor::ConsumerSlotID::ChildInput(set_u24, "List".to_string()) ); system.add_cable( actor::ProducerSlotID::ChildOutput(add, "Result".to_string()), actor::ConsumerSlotID::ChildInput(set_u24, "Index".to_string()) ); system.add_cable( actor::ProducerSlotID::ChildOutput(red_constant, "Value".to_string()), actor::ConsumerSlotID::ChildInput(set_u24, "Value".to_string()) ); system.add_cable( actor::ProducerSlotID::ChildOutput(set_u24, "List".to_string()), actor::ConsumerSlotID::Output("screen_buffer".to_string()) ); world.upsert_actor_type("System".to_string(), Box::new(system)); let (_, mut system_inputs, mut system_outputs) = world.spawn_actor("System"); let mouse_position = system_inputs.remove("mouse_position").unwrap(); let screen_buffer = system_outputs.remove("screen_buffer").unwrap(); while window.is_open() && !window.is_key_down(Key::Escape) { if let Some((mouse_x, mouse_y)) = window.get_mouse_pos(MouseMode::Discard) { let mouse_x = mouse_x as u16; let mouse_y = mouse_y as u16; let value = actor::Value::Record(vec![ ("X".to_string(), actor::Value::Number(number::Number::from(mouse_x))), ("Y".to_string(), actor::Value::Number(number::Number::from(mouse_y))), ]); let _ = mouse_position.try_send(value); } if let Ok(value) = screen_buffer.try_recv() { if let actor::Value::List(data) = value { let u32_data: Vec = data.into_iter() .map(|x| { if let actor::Value::Number(x) = x { x.try_into().unwrap() } else { panic!("bruh") } }) .collect(); if u32_data.len() != WIDTH * HEIGHT { panic!("bruhhhhhhhhhhhhhh"); } window.update_with_buffer(&u32_data, WIDTH, HEIGHT).unwrap(); } } else { window.update(); } } }