use std::fmt::{self, Write};
use std::ops::RangeInclusive;
use crate::core_types::GodotString;
use crate::core_types::VariantType;
use crate::sys;
use super::ExportInfo;
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
pub struct RangeHint<T> {
pub min: T,
pub max: T,
pub step: Option<T>,
pub or_greater: bool,
pub or_lesser: bool,
}
impl<T> RangeHint<T>
where
T: fmt::Display,
{
#[inline]
pub fn new(min: T, max: T) -> Self {
RangeHint {
min,
max,
step: None,
or_greater: false,
or_lesser: false,
}
}
#[inline]
pub fn with_step(mut self, step: T) -> Self {
self.step.replace(step);
self
}
#[inline]
pub fn or_greater(mut self) -> Self {
self.or_greater = true;
self
}
#[inline]
pub fn or_lesser(mut self) -> Self {
self.or_lesser = true;
self
}
fn to_godot_hint_string(&self) -> GodotString {
let mut s = String::new();
write!(s, "{},{}", self.min, self.max).unwrap();
if let Some(step) = &self.step {
write!(s, ",{}", step).unwrap();
}
if self.or_greater {
s.push_str(",or_greater");
}
if self.or_lesser {
s.push_str(",or_lesser");
}
s.into()
}
}
impl<T> From<RangeInclusive<T>> for RangeHint<T>
where
T: fmt::Display,
{
#[inline]
fn from(range: RangeInclusive<T>) -> Self {
let (min, max) = range.into_inner();
RangeHint::new(min, max)
}
}
#[derive(Clone, Eq, PartialEq, Debug, Default)]
pub struct EnumHint {
values: Vec<String>,
}
impl EnumHint {
#[inline]
pub fn new(values: Vec<String>) -> Self {
EnumHint { values }
}
fn to_godot_hint_string(&self) -> GodotString {
let mut s = String::new();
let mut iter = self.values.iter();
if let Some(first) = iter.next() {
write!(s, "{}", first).unwrap();
}
for rest in iter {
write!(s, ",{}", rest).unwrap();
}
s.into()
}
}
#[derive(Clone, Debug)]
pub enum IntHint<T> {
Range(RangeHint<T>),
ExpRange(RangeHint<T>),
Enum(EnumHint),
Flags(EnumHint),
Layers2DRender,
Layers2DPhysics,
Layers3DRender,
Layers3DPhysics,
}
impl<T> IntHint<T>
where
T: fmt::Display,
{
#[inline]
pub fn export_info(self) -> ExportInfo {
use IntHint as IH;
let hint_kind = match &self {
IH::Range(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_RANGE,
IH::ExpRange(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_EXP_RANGE,
IH::Enum(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_ENUM,
IH::Flags(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_FLAGS,
IH::Layers2DRender => sys::godot_property_hint_GODOT_PROPERTY_HINT_LAYERS_2D_RENDER,
IH::Layers2DPhysics => sys::godot_property_hint_GODOT_PROPERTY_HINT_LAYERS_2D_PHYSICS,
IH::Layers3DRender => sys::godot_property_hint_GODOT_PROPERTY_HINT_LAYERS_3D_RENDER,
IH::Layers3DPhysics => sys::godot_property_hint_GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS,
};
let hint_string = match self {
IH::Range(range) | IH::ExpRange(range) => range.to_godot_hint_string(),
IH::Enum(e) | IH::Flags(e) => e.to_godot_hint_string(),
_ => GodotString::new(),
};
ExportInfo {
variant_type: VariantType::I64,
hint_kind,
hint_string,
}
}
}
impl<T> From<RangeHint<T>> for IntHint<T>
where
T: fmt::Display,
{
#[inline]
fn from(hint: RangeHint<T>) -> Self {
Self::Range(hint)
}
}
impl<T> From<RangeInclusive<T>> for IntHint<T>
where
T: fmt::Display,
{
#[inline]
fn from(range: RangeInclusive<T>) -> Self {
Self::Range(range.into())
}
}
impl<T> From<EnumHint> for IntHint<T> {
#[inline]
fn from(hint: EnumHint) -> Self {
Self::Enum(hint)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
pub struct ExpEasingHint {
pub is_attenuation: bool,
pub is_in_out: bool,
}
impl ExpEasingHint {
#[inline]
pub fn new() -> Self {
Self::default()
}
fn to_godot_hint_string(self) -> GodotString {
let mut s = String::new();
if self.is_attenuation {
s.push_str("attenuation");
}
if self.is_in_out {
if self.is_attenuation {
s.push(',');
}
s.push_str("inout");
}
s.into()
}
}
#[derive(Clone, Debug)]
pub enum FloatHint<T> {
Range(RangeHint<T>),
ExpRange(RangeHint<T>),
Enum(EnumHint),
ExpEasing(ExpEasingHint),
}
impl<T> FloatHint<T>
where
T: fmt::Display,
{
#[inline]
pub fn export_info(self) -> ExportInfo {
use FloatHint as FH;
let hint_kind = match &self {
FH::Range(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_RANGE,
FH::ExpRange(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_EXP_RANGE,
FH::Enum(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_ENUM,
FH::ExpEasing(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_EXP_EASING,
};
let hint_string = match self {
FH::Range(range) | FH::ExpRange(range) => range.to_godot_hint_string(),
FH::Enum(e) => e.to_godot_hint_string(),
FH::ExpEasing(e) => e.to_godot_hint_string(),
};
ExportInfo {
variant_type: VariantType::F64,
hint_kind,
hint_string,
}
}
}
impl<T> From<RangeHint<T>> for FloatHint<T>
where
T: fmt::Display,
{
#[inline]
fn from(hint: RangeHint<T>) -> Self {
Self::Range(hint)
}
}
impl<T> From<RangeInclusive<T>> for FloatHint<T>
where
T: fmt::Display,
{
#[inline]
fn from(range: RangeInclusive<T>) -> Self {
Self::Range(range.into())
}
}
impl<T> From<EnumHint> for FloatHint<T> {
#[inline]
fn from(hint: EnumHint) -> Self {
Self::Enum(hint)
}
}
impl<T> From<ExpEasingHint> for FloatHint<T> {
#[inline]
fn from(hint: ExpEasingHint) -> Self {
Self::ExpEasing(hint)
}
}
#[derive(Clone, Debug)]
pub enum StringHint {
Enum(EnumHint),
File(EnumHint),
GlobalFile(EnumHint),
Dir,
GlobalDir,
Multiline,
Placeholder { placeholder: String },
}
impl StringHint {
#[inline]
pub fn export_info(self) -> ExportInfo {
use StringHint as SH;
let hint_kind = match &self {
SH::Enum(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_ENUM,
SH::File(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_FILE,
SH::GlobalFile(_) => sys::godot_property_hint_GODOT_PROPERTY_HINT_GLOBAL_FILE,
SH::Dir => sys::godot_property_hint_GODOT_PROPERTY_HINT_DIR,
SH::GlobalDir => sys::godot_property_hint_GODOT_PROPERTY_HINT_GLOBAL_DIR,
SH::Multiline => sys::godot_property_hint_GODOT_PROPERTY_HINT_MULTILINE_TEXT,
SH::Placeholder { .. } => sys::godot_property_hint_GODOT_PROPERTY_HINT_PLACEHOLDER_TEXT,
};
let hint_string = match self {
SH::Enum(e) | SH::File(e) | SH::GlobalFile(e) => e.to_godot_hint_string(),
SH::Placeholder { placeholder } => placeholder.into(),
_ => GodotString::new(),
};
ExportInfo {
variant_type: VariantType::GodotString,
hint_kind,
hint_string,
}
}
}
#[derive(Clone, Debug)]
pub enum ColorHint {
NoAlpha,
}
impl ColorHint {
#[inline]
pub fn export_info(self) -> ExportInfo {
ExportInfo {
variant_type: VariantType::Color,
hint_kind: match self {
ColorHint::NoAlpha => sys::godot_property_hint_GODOT_PROPERTY_HINT_COLOR_NO_ALPHA,
},
hint_string: GodotString::new(),
}
}
}