use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, Ordering};
use crate::info::ParamInfo;
use crate::smooth::{Smoother, SmoothingStyle};
pub struct AtomicF64 {
bits: std::sync::atomic::AtomicU64,
}
impl AtomicF64 {
pub fn new(value: f64) -> Self {
Self {
bits: std::sync::atomic::AtomicU64::new(value.to_bits()),
}
}
#[inline]
pub fn load(&self) -> f64 {
f64::from_bits(self.bits.load(Ordering::Relaxed))
}
#[inline]
pub fn store(&self, value: f64) {
self.bits.store(value.to_bits(), Ordering::Relaxed);
}
}
pub struct FloatParam {
pub info: ParamInfo,
value: AtomicF64,
pub smoother: Smoother,
}
impl FloatParam {
pub fn new(info: ParamInfo, smoothing: SmoothingStyle) -> Self {
let default = info.default_plain;
let smoother = Smoother::new(smoothing);
smoother.snap(default);
Self {
info,
value: AtomicF64::new(default),
smoother,
}
}
#[inline]
pub fn value(&self) -> f32 {
self.value.load() as f32
}
#[inline]
pub fn set_value(&self, v: f64) {
self.value.store(v);
}
#[inline]
pub fn smoothed_next(&self) -> f32 {
let target = self.value.load();
self.smoother.next(target)
}
#[inline]
pub fn smoothed(&self) -> f32 {
self.smoother.current()
}
pub fn id(&self) -> u32 {
self.info.id
}
}
pub struct BoolParam {
pub info: ParamInfo,
value: AtomicBool,
}
impl BoolParam {
pub fn new(info: ParamInfo) -> Self {
let default = info.default_plain != 0.0;
Self {
info,
value: AtomicBool::new(default),
}
}
pub fn value(&self) -> bool {
self.value.load(Ordering::Relaxed)
}
pub fn set_value(&self, v: bool) {
self.value.store(v, Ordering::Relaxed);
}
pub fn id(&self) -> u32 {
self.info.id
}
}
pub struct IntParam {
pub info: ParamInfo,
value: AtomicI64,
}
impl IntParam {
pub fn new(info: ParamInfo) -> Self {
let default = info.default_plain as i64;
Self {
info,
value: AtomicI64::new(default),
}
}
pub fn value(&self) -> i64 {
self.value.load(Ordering::Relaxed)
}
pub fn set_value(&self, v: i64) {
self.value.store(v, Ordering::Relaxed);
}
pub fn id(&self) -> u32 {
self.info.id
}
}
pub trait ParamEnum: Clone + Copy + Send + Sync + 'static {
fn from_index(index: usize) -> Self;
fn to_index(&self) -> usize;
fn name(&self) -> &'static str;
fn variant_count() -> usize;
fn variant_names() -> &'static [&'static str];
}
pub struct EnumParam<E: ParamEnum> {
pub info: ParamInfo,
value: AtomicU32,
_phantom: std::marker::PhantomData<E>,
}
impl<E: ParamEnum> EnumParam<E> {
pub fn new(info: ParamInfo) -> Self {
let default = info.default_plain as u32;
Self {
info,
value: AtomicU32::new(default),
_phantom: std::marker::PhantomData,
}
}
pub fn value(&self) -> E {
E::from_index(self.value.load(Ordering::Relaxed) as usize)
}
pub fn set_value(&self, v: E) {
self.value.store(v.to_index() as u32, Ordering::Relaxed);
}
pub fn set_index(&self, idx: u32) {
self.value.store(idx, Ordering::Relaxed);
}
pub fn index(&self) -> u32 {
self.value.load(Ordering::Relaxed)
}
pub fn id(&self) -> u32 {
self.info.id
}
pub fn format_by_index(&self, value: f64) -> String {
E::from_index(value.round() as usize).name().to_string()
}
}