use crate::common::LeakManager;
pub trait FilterConfigItems: Sized {
fn to_config_items() -> Vec<FilterConfigItem>;
fn from_config_items(items: &[FilterConfigItem]) -> Self;
}
#[doc(inline)]
pub use aviutl2_macros::FilterConfigItems;
pub trait FilterConfigItemSliceExt {
fn to_struct<T: FilterConfigItems>(&self) -> T;
}
impl FilterConfigItemSliceExt for &[FilterConfigItem] {
fn to_struct<T: FilterConfigItems>(&self) -> T {
T::from_config_items(self)
}
}
#[derive(Debug, Clone)]
pub enum FilterConfigItem {
Track(FilterConfigTrack),
Checkbox(FilterConfigCheckbox),
Color(FilterConfigColor),
Select(FilterConfigSelect),
File(FilterConfigFile),
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum FilterConfigItemValue {
Track(f64),
Checkbox(bool),
Color(FilterConfigColorValue),
Select(i32),
File(String),
}
impl FilterConfigItem {
pub fn name(&self) -> &str {
match self {
FilterConfigItem::Track(item) => &item.name,
FilterConfigItem::Checkbox(item) => &item.name,
FilterConfigItem::Color(item) => &item.name,
FilterConfigItem::Select(item) => &item.name,
FilterConfigItem::File(item) => &item.name,
}
}
pub(crate) fn to_raw(&self, leak_manager: &LeakManager) -> aviutl2_sys::filter2::FILTER_ITEM {
match self {
FilterConfigItem::Track(item) => {
let step: f64 = item.step.into();
aviutl2_sys::filter2::FILTER_ITEM {
track: aviutl2_sys::filter2::FILTER_ITEM_TRACK {
r#type: leak_manager.leak_as_wide_string("track"),
name: leak_manager.leak_as_wide_string(&item.name),
value: item.value,
s: *item.range.start(),
e: *item.range.end(),
step,
},
}
}
FilterConfigItem::Checkbox(item) => aviutl2_sys::filter2::FILTER_ITEM {
checkbox: aviutl2_sys::filter2::FILTER_ITEM_CHECKBOX {
r#type: leak_manager.leak_as_wide_string("check"),
name: leak_manager.leak_as_wide_string(&item.name),
value: item.value,
},
},
FilterConfigItem::Color(item) => aviutl2_sys::filter2::FILTER_ITEM {
color: aviutl2_sys::filter2::FILTER_ITEM_COLOR {
r#type: leak_manager.leak_as_wide_string("color"),
name: leak_manager.leak_as_wide_string(&item.name),
value: item.value.into(),
},
},
FilterConfigItem::Select(item) => {
let mut raw_items: Vec<aviutl2_sys::filter2::FILTER_ITEM_SELECT_ITEM> = item
.items
.iter()
.map(|i| aviutl2_sys::filter2::FILTER_ITEM_SELECT_ITEM {
name: leak_manager.leak_as_wide_string(&i.name),
value: i.value,
})
.collect();
raw_items.push(aviutl2_sys::filter2::FILTER_ITEM_SELECT_ITEM {
name: std::ptr::null(),
value: 0,
}); let raw_items_ptrs = leak_manager.leak_value_vec(raw_items);
aviutl2_sys::filter2::FILTER_ITEM {
select: aviutl2_sys::filter2::FILTER_ITEM_SELECT {
r#type: leak_manager.leak_as_wide_string("select"),
name: leak_manager.leak_as_wide_string(&item.name),
value: item.value,
items: raw_items_ptrs,
},
}
}
FilterConfigItem::File(item) => {
let raw_filters = crate::common::format_file_filters(&item.filters);
aviutl2_sys::filter2::FILTER_ITEM {
file: aviutl2_sys::filter2::FILTER_ITEM_FILE {
r#type: leak_manager.leak_as_wide_string("file"),
name: leak_manager.leak_as_wide_string(&item.name),
value: leak_manager.leak_as_wide_string(&item.value),
filefilter: leak_manager.leak_as_wide_string(&raw_filters),
},
}
}
}
}
pub(crate) unsafe fn get_value(
raw: *const aviutl2_sys::filter2::FILTER_ITEM,
) -> FilterConfigItemValue {
let item_type = unsafe {
crate::common::load_wide_string(
*(raw as *const aviutl2_sys::common::LPCWSTR),
)
};
match item_type.as_str() {
"track" => {
let raw_track = unsafe { &(*raw).track };
FilterConfigItemValue::Track(raw_track.value)
}
"check" => {
let raw_checkbox = unsafe { &(*raw).checkbox };
FilterConfigItemValue::Checkbox(raw_checkbox.value)
}
"color" => {
let raw_color = unsafe { &(*raw).color };
FilterConfigItemValue::Color(raw_color.value.into())
}
"select" => {
let raw_select = unsafe { &(*raw).select };
FilterConfigItemValue::Select(raw_select.value)
}
"file" => {
let raw_file = unsafe { &(*raw).file };
let value = unsafe { crate::common::load_wide_string(raw_file.value) };
FilterConfigItemValue::File(value)
}
_ => panic!("Unknown filter config item type: {}", item_type),
}
}
pub(crate) unsafe fn should_apply_from_raw(
&self,
raw: *const aviutl2_sys::filter2::FILTER_ITEM,
) -> bool {
let value = unsafe { Self::get_value(raw) };
match (self, value) {
(FilterConfigItem::Track(item), FilterConfigItemValue::Track(v)) => item.value != v,
(FilterConfigItem::Checkbox(item), FilterConfigItemValue::Checkbox(v)) => {
item.value != v
}
(FilterConfigItem::Color(item), FilterConfigItemValue::Color(v)) => item.value != v,
(FilterConfigItem::Select(item), FilterConfigItemValue::Select(v)) => item.value != v,
(FilterConfigItem::File(item), FilterConfigItemValue::File(v)) => item.value != v,
_ => {
panic!("Mismatched filter config item type");
}
}
}
pub(crate) unsafe fn apply_from_raw(&mut self, raw: *const aviutl2_sys::filter2::FILTER_ITEM) {
let value = unsafe { Self::get_value(raw) };
match (self, value) {
(FilterConfigItem::Track(item), FilterConfigItemValue::Track(v)) => {
item.value = v;
}
(FilterConfigItem::Checkbox(item), FilterConfigItemValue::Checkbox(v)) => {
item.value = v;
}
(FilterConfigItem::Color(item), FilterConfigItemValue::Color(v)) => {
item.value = v;
}
(FilterConfigItem::Select(item), FilterConfigItemValue::Select(v)) => {
item.value = v;
}
(FilterConfigItem::File(item), FilterConfigItemValue::File(v)) => {
item.value = v;
}
_ => {
panic!("Mismatched filter config item type");
}
}
}
}
#[derive(Debug, Clone)]
pub struct FilterConfigTrack {
pub name: String,
pub value: f64,
pub range: std::ops::RangeInclusive<f64>,
pub step: FilterConfigTrackStep,
}
#[derive(Clone, Copy)]
pub enum FilterConfigTrackStep {
One,
PointOne,
PointZeroOne,
PointZeroZeroOne,
}
impl TryFrom<f64> for FilterConfigTrackStep {
type Error = anyhow::Error;
fn try_from(value: f64) -> Result<Self, Self::Error> {
match value {
1.0 => Ok(FilterConfigTrackStep::One),
0.1 => Ok(FilterConfigTrackStep::PointOne),
0.01 => Ok(FilterConfigTrackStep::PointZeroOne),
0.001 => Ok(FilterConfigTrackStep::PointZeroZeroOne),
_ => Err(anyhow::anyhow!("Invalid step value: {}", value)),
}
}
}
impl From<FilterConfigTrackStep> for f64 {
fn from(value: FilterConfigTrackStep) -> Self {
match value {
FilterConfigTrackStep::One => 1.0,
FilterConfigTrackStep::PointOne => 0.1,
FilterConfigTrackStep::PointZeroOne => 0.01,
FilterConfigTrackStep::PointZeroZeroOne => 0.001,
}
}
}
impl std::fmt::Debug for FilterConfigTrackStep {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let value: f64 = (*self).into();
f.debug_tuple("FilterConfigTrackStep")
.field(&value)
.finish()
}
}
#[derive(Debug, Clone)]
pub struct FilterConfigCheckbox {
pub name: String,
pub value: bool,
}
#[derive(Debug, Clone)]
pub struct FilterConfigColor {
pub name: String,
pub value: FilterConfigColorValue,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FilterConfigColorValue(pub u32);
impl FilterConfigColorValue {
pub fn to_rgb(&self) -> (u8, u8, u8) {
let r = ((self.0 >> 16) & 0xFF) as u8;
let g = ((self.0 >> 8) & 0xFF) as u8;
let b = (self.0 & 0xFF) as u8;
(r, g, b)
}
pub fn from_rgb(r: u8, g: u8, b: u8) -> Self {
let value = (r as u32) << 16 | (g as u32) << 8 | (b as u32);
FilterConfigColorValue(value)
}
}
impl From<u32> for FilterConfigColorValue {
fn from(value: u32) -> Self {
FilterConfigColorValue(value)
}
}
impl From<FilterConfigColorValue> for u32 {
fn from(value: FilterConfigColorValue) -> Self {
value.0
}
}
impl From<aviutl2_sys::filter2::FILTER_ITEM_COLOR_VALUE> for FilterConfigColorValue {
fn from(value: aviutl2_sys::filter2::FILTER_ITEM_COLOR_VALUE) -> Self {
unsafe { FilterConfigColorValue(value.code) }
}
}
impl From<FilterConfigColorValue> for aviutl2_sys::filter2::FILTER_ITEM_COLOR_VALUE {
fn from(value: FilterConfigColorValue) -> Self {
aviutl2_sys::filter2::FILTER_ITEM_COLOR_VALUE { code: value.0 }
}
}
impl std::fmt::Display for FilterConfigColorValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (r, g, b) = self.to_rgb();
write!(f, "#{:02X}{:02X}{:02X}", r, g, b)
}
}
impl std::fmt::LowerHex for FilterConfigColorValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:06x}", self.0 & 0xFFFFFF)
}
}
impl std::fmt::UpperHex for FilterConfigColorValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:06X}", self.0 & 0xFFFFFF)
}
}
#[derive(Debug, Clone)]
pub struct FilterConfigSelect {
pub name: String,
pub value: i32,
pub items: Vec<FilterConfigSelectItem>,
}
#[derive(Debug, Clone)]
pub struct FilterConfigSelectItem {
pub name: String,
pub value: i32,
}
pub trait FilterConfigSelectItems {
fn to_select_items() -> Vec<FilterConfigSelectItem>;
fn from_select_item_value(item: i32) -> Self;
fn to_select_item_value(&self) -> i32;
}
#[doc(inline)]
pub use aviutl2_macros::FilterConfigSelectItems;
#[derive(Debug, Clone)]
pub struct FilterConfigFile {
pub name: String,
pub value: String,
pub filters: Vec<crate::common::FileFilter>,
}