101 lines
2.5 KiB
Rust
101 lines
2.5 KiB
Rust
use anyhow::anyhow;
|
|
use eframe::egui::Ui;
|
|
|
|
pub struct Type {
|
|
name: &'static str,
|
|
new: fn(settings: ron::Value) -> anyhow::Result<Box<dyn Card>>,
|
|
settings_ui: fn(settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>>,
|
|
default_settings: fn() -> String,
|
|
}
|
|
|
|
impl Type {
|
|
pub const fn new<T: Card + 'static>(name: &'static str) -> Self {
|
|
Self {
|
|
name,
|
|
new: T::new_dyn,
|
|
settings_ui: T::settings_ui_dyn,
|
|
default_settings: T::default_settings,
|
|
}
|
|
}
|
|
|
|
pub fn new_card(&self, settings: ron::Value) -> anyhow::Result<Box<dyn Card>> {
|
|
(self.new)(settings)
|
|
}
|
|
|
|
pub fn settings_ui(&self, settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>> {
|
|
(self.settings_ui)(settings)
|
|
}
|
|
|
|
pub fn default_settings(&self) -> String {
|
|
(self.default_settings)()
|
|
}
|
|
|
|
pub fn get(name: &str) -> anyhow::Result<&'static Self> {
|
|
inventory::iter::<Type>
|
|
.into_iter()
|
|
.find(|card_type| card_type.name == name)
|
|
.ok_or_else(|| anyhow!("Invalid card type {}", name))
|
|
}
|
|
|
|
pub fn name(&self) -> &'static str {
|
|
self.name
|
|
}
|
|
}
|
|
|
|
inventory::collect!(Type);
|
|
|
|
pub trait Card {
|
|
fn new(_settings: ron::Value) -> anyhow::Result<Self>
|
|
where
|
|
Self: Sized;
|
|
#[allow(clippy::new_ret_no_self)]
|
|
fn new_dyn(settings: ron::Value) -> anyhow::Result<Box<dyn Card>>
|
|
where
|
|
Self: Sized + 'static,
|
|
{
|
|
let card = Self::new(settings)?;
|
|
Ok(Box::new(card))
|
|
}
|
|
|
|
fn default_settings() -> String
|
|
where
|
|
Self: Sized;
|
|
|
|
fn read_mem(&mut self, _address: u16) -> Option<u8> {
|
|
None
|
|
}
|
|
fn write_mem(&mut self, _address: u16, _data: u8) -> Option<()> {
|
|
None
|
|
}
|
|
fn read_io(&mut self, _address: u8) -> Option<u8> {
|
|
None
|
|
}
|
|
fn write_io(&mut self, _address: u8, _data: u8) -> Option<()> {
|
|
None
|
|
}
|
|
|
|
fn settings_ui(_settings: ron::Value) -> anyhow::Result<impl SettingsUi>
|
|
where
|
|
Self: Sized;
|
|
#[allow(clippy::settings_ui_ret_no_self)]
|
|
fn settings_ui_dyn(settings: ron::Value) -> anyhow::Result<Box<dyn SettingsUi>>
|
|
where
|
|
Self: Sized + 'static,
|
|
{
|
|
let settings_ui = Self::settings_ui(settings)?;
|
|
Ok(Box::new(settings_ui))
|
|
}
|
|
}
|
|
|
|
pub trait SettingsUi {
|
|
fn draw_ui(&mut self, ui: &mut Ui);
|
|
fn serialize_settings(&self) -> String;
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! register {
|
|
($typ: ty, $name: literal) => {
|
|
inventory::submit!($crate::card::Type::new::<$typ>($name));
|
|
};
|
|
}
|