mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Auto-generate enum type widget boilerplate for radio buttons and dropdown menus (#2589)
* First draft of factoring out the dropdown boilerplate * Add proc macro for enum boilerplate * Detect whether to say `crate` or the name * Clean up the input and naming of the enum macro * Rename a file * Do the rename of code too * Use the attribute-driven selection of radio vs dropdown * Add a metadata struct and tooltips * Move the new traits to a better place. * Use ChoiceType, part 1 * Use ChoiceType, part 2 * Introduce a builder API for choice widgets * Start using the new new API * DomainWarpType should be a dropdown still * Handle the case where a node property can never have a socket * Rustfmt * Code review * Update stable node IDs in test --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -2,9 +2,10 @@ use crate::{Ctx, ExtractAnimationTime, ExtractTime};
|
||||
|
||||
const DAY: f64 = 1000. * 3600. * 24.;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, dyn_any::DynAny, Default, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, dyn_any::DynAny, Default, Hash, node_macro::ChoiceType)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum RealTimeMode {
|
||||
#[label("UTC")]
|
||||
Utc,
|
||||
Year,
|
||||
Hour,
|
||||
@@ -13,18 +14,6 @@ pub enum RealTimeMode {
|
||||
Second,
|
||||
Millisecond,
|
||||
}
|
||||
impl core::fmt::Display for RealTimeMode {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
RealTimeMode::Utc => write!(f, "UTC"),
|
||||
RealTimeMode::Year => write!(f, "Year"),
|
||||
RealTimeMode::Hour => write!(f, "Hour"),
|
||||
RealTimeMode::Minute => write!(f, "Minute"),
|
||||
RealTimeMode::Second => write!(f, "Second"),
|
||||
RealTimeMode::Millisecond => write!(f, "Millisecond"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum AnimationTimeMode {
|
||||
|
||||
@@ -533,22 +533,16 @@ fn extract_xy<T: Into<DVec2>>(_: impl Ctx, #[implementations(DVec2, IVec2, UVec2
|
||||
}
|
||||
}
|
||||
|
||||
/// The X or Y component of a vector2.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
#[widget(Dropdown)]
|
||||
pub enum XY {
|
||||
#[default]
|
||||
X,
|
||||
Y,
|
||||
}
|
||||
impl core::fmt::Display for XY {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
XY::X => write!(f, "X"),
|
||||
XY::Y => write!(f, "Y"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Rename to "Passthrough"
|
||||
/// Passes-through the input value without changing it. This is useful for rerouting wires for organization purposes.
|
||||
|
||||
@@ -34,9 +34,11 @@ use spirv_std::num_traits::float::Float;
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, DynAny, Hash)]
|
||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, DynAny, Hash, node_macro::ChoiceType)]
|
||||
#[widget(Dropdown)]
|
||||
pub enum LuminanceCalculation {
|
||||
#[default]
|
||||
#[label("sRGB")]
|
||||
SRGB,
|
||||
Perceptual,
|
||||
AverageChannels,
|
||||
@@ -44,30 +46,6 @@ pub enum LuminanceCalculation {
|
||||
MaximumChannels,
|
||||
}
|
||||
|
||||
impl LuminanceCalculation {
|
||||
pub fn list() -> [LuminanceCalculation; 5] {
|
||||
[
|
||||
LuminanceCalculation::SRGB,
|
||||
LuminanceCalculation::Perceptual,
|
||||
LuminanceCalculation::AverageChannels,
|
||||
LuminanceCalculation::MinimumChannels,
|
||||
LuminanceCalculation::MaximumChannels,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for LuminanceCalculation {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
LuminanceCalculation::SRGB => write!(f, "sRGB"),
|
||||
LuminanceCalculation::Perceptual => write!(f, "Perceptual"),
|
||||
LuminanceCalculation::AverageChannels => write!(f, "Average Channels"),
|
||||
LuminanceCalculation::MinimumChannels => write!(f, "Minimum Channels"),
|
||||
LuminanceCalculation::MaximumChannels => write!(f, "Maximum Channels"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, DynAny, Hash)]
|
||||
@@ -844,9 +822,11 @@ async fn vibrance<T: Adjust<Color>>(
|
||||
image
|
||||
}
|
||||
|
||||
/// Color Channel
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum RedGreenBlue {
|
||||
#[default]
|
||||
Red,
|
||||
@@ -854,19 +834,11 @@ pub enum RedGreenBlue {
|
||||
Blue,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for RedGreenBlue {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
RedGreenBlue::Red => write!(f, "Red"),
|
||||
RedGreenBlue::Green => write!(f, "Green"),
|
||||
RedGreenBlue::Blue => write!(f, "Blue"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Color Channel
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum RedGreenBlueAlpha {
|
||||
#[default]
|
||||
Red,
|
||||
@@ -875,24 +847,17 @@ pub enum RedGreenBlueAlpha {
|
||||
Alpha,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for RedGreenBlueAlpha {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
RedGreenBlueAlpha::Red => write!(f, "Red"),
|
||||
RedGreenBlueAlpha::Green => write!(f, "Green"),
|
||||
RedGreenBlueAlpha::Blue => write!(f, "Blue"),
|
||||
RedGreenBlueAlpha::Alpha => write!(f, "Alpha"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Style of noise pattern
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
#[widget(Dropdown)]
|
||||
pub enum NoiseType {
|
||||
#[default]
|
||||
Perlin,
|
||||
#[label("OpenSimplex2")]
|
||||
OpenSimplex2,
|
||||
#[label("OpenSimplex2S")]
|
||||
OpenSimplex2S,
|
||||
Cellular,
|
||||
ValueCubic,
|
||||
@@ -900,176 +865,71 @@ pub enum NoiseType {
|
||||
WhiteNoise,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for NoiseType {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
NoiseType::Perlin => write!(f, "Perlin"),
|
||||
NoiseType::OpenSimplex2 => write!(f, "OpenSimplex2"),
|
||||
NoiseType::OpenSimplex2S => write!(f, "OpenSimplex2S"),
|
||||
NoiseType::Cellular => write!(f, "Cellular"),
|
||||
NoiseType::ValueCubic => write!(f, "Value Cubic"),
|
||||
NoiseType::Value => write!(f, "Value"),
|
||||
NoiseType::WhiteNoise => write!(f, "White Noise"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NoiseType {
|
||||
pub fn list() -> &'static [NoiseType; 7] {
|
||||
&[
|
||||
NoiseType::Perlin,
|
||||
NoiseType::OpenSimplex2,
|
||||
NoiseType::OpenSimplex2S,
|
||||
NoiseType::Cellular,
|
||||
NoiseType::ValueCubic,
|
||||
NoiseType::Value,
|
||||
NoiseType::WhiteNoise,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
/// Style of layered levels of the noise pattern
|
||||
pub enum FractalType {
|
||||
#[default]
|
||||
None,
|
||||
#[label("Fractional Brownian Motion")]
|
||||
FBm,
|
||||
Ridged,
|
||||
PingPong,
|
||||
#[label("Progressive (Domain Warp Only)")]
|
||||
DomainWarpProgressive,
|
||||
#[label("Independent (Domain Warp Only)")]
|
||||
DomainWarpIndependent,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for FractalType {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
FractalType::None => write!(f, "None"),
|
||||
FractalType::FBm => write!(f, "Fractional Brownian Motion"),
|
||||
FractalType::Ridged => write!(f, "Ridged"),
|
||||
FractalType::PingPong => write!(f, "Ping Pong"),
|
||||
FractalType::DomainWarpProgressive => write!(f, "Progressive (Domain Warp Only)"),
|
||||
FractalType::DomainWarpIndependent => write!(f, "Independent (Domain Warp Only)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FractalType {
|
||||
pub fn list() -> &'static [FractalType; 6] {
|
||||
&[
|
||||
FractalType::None,
|
||||
FractalType::FBm,
|
||||
FractalType::Ridged,
|
||||
FractalType::PingPong,
|
||||
FractalType::DomainWarpProgressive,
|
||||
FractalType::DomainWarpIndependent,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Distance function used by the cellular noise
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
pub enum CellularDistanceFunction {
|
||||
#[default]
|
||||
Euclidean,
|
||||
#[label("Euclidean Squared (Faster)")]
|
||||
EuclideanSq,
|
||||
Manhattan,
|
||||
Hybrid,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for CellularDistanceFunction {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
CellularDistanceFunction::Euclidean => write!(f, "Euclidean"),
|
||||
CellularDistanceFunction::EuclideanSq => write!(f, "Euclidean Squared (Faster)"),
|
||||
CellularDistanceFunction::Manhattan => write!(f, "Manhattan"),
|
||||
CellularDistanceFunction::Hybrid => write!(f, "Hybrid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CellularDistanceFunction {
|
||||
pub fn list() -> &'static [CellularDistanceFunction; 4] {
|
||||
&[
|
||||
CellularDistanceFunction::Euclidean,
|
||||
CellularDistanceFunction::EuclideanSq,
|
||||
CellularDistanceFunction::Manhattan,
|
||||
CellularDistanceFunction::Hybrid,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
pub enum CellularReturnType {
|
||||
CellValue,
|
||||
#[default]
|
||||
#[label("Nearest (F1)")]
|
||||
Nearest,
|
||||
#[label("Next Nearest (F2)")]
|
||||
NextNearest,
|
||||
#[label("Average (F1 / 2 + F2 / 2)")]
|
||||
Average,
|
||||
#[label("Difference (F2 - F1)")]
|
||||
Difference,
|
||||
#[label("Product (F2 * F1 / 2)")]
|
||||
Product,
|
||||
#[label("Division (F1 / F2)")]
|
||||
Division,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for CellularReturnType {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
CellularReturnType::CellValue => write!(f, "Cell Value"),
|
||||
CellularReturnType::Nearest => write!(f, "Nearest (F1)"),
|
||||
CellularReturnType::NextNearest => write!(f, "Next Nearest (F2)"),
|
||||
CellularReturnType::Average => write!(f, "Average (F1 / 2 + F2 / 2)"),
|
||||
CellularReturnType::Difference => write!(f, "Difference (F2 - F1)"),
|
||||
CellularReturnType::Product => write!(f, "Product (F2 * F1 / 2)"),
|
||||
CellularReturnType::Division => write!(f, "Division (F1 / F2)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CellularReturnType {
|
||||
pub fn list() -> &'static [CellularReturnType; 7] {
|
||||
&[
|
||||
CellularReturnType::CellValue,
|
||||
CellularReturnType::Nearest,
|
||||
CellularReturnType::NextNearest,
|
||||
CellularReturnType::Average,
|
||||
CellularReturnType::Difference,
|
||||
CellularReturnType::Product,
|
||||
CellularReturnType::Division,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of domain warp
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
#[widget(Dropdown)]
|
||||
pub enum DomainWarpType {
|
||||
#[default]
|
||||
None,
|
||||
#[label("OpenSimplex2")]
|
||||
OpenSimplex2,
|
||||
#[label("OpenSimplex2 Reduced")]
|
||||
OpenSimplex2Reduced,
|
||||
BasicGrid,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for DomainWarpType {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
DomainWarpType::None => write!(f, "None"),
|
||||
DomainWarpType::OpenSimplex2 => write!(f, "OpenSimplex2"),
|
||||
DomainWarpType::OpenSimplex2Reduced => write!(f, "OpenSimplex2 Reduced"),
|
||||
DomainWarpType::BasicGrid => write!(f, "Basic Grid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DomainWarpType {
|
||||
pub fn list() -> &'static [DomainWarpType; 4] {
|
||||
&[DomainWarpType::None, DomainWarpType::OpenSimplex2, DomainWarpType::OpenSimplex2Reduced, DomainWarpType::BasicGrid]
|
||||
}
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27mixr%27%20%3D%20Channel%20Mixer
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Lab%20color%20only-,Channel%20Mixer,-Key%20is%20%27mixr
|
||||
@@ -1169,26 +1029,18 @@ async fn channel_mixer<T: Adjust<Color>>(
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum RelativeAbsolute {
|
||||
#[default]
|
||||
Relative,
|
||||
Absolute,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for RelativeAbsolute {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
RelativeAbsolute::Relative => write!(f, "Relative"),
|
||||
RelativeAbsolute::Absolute => write!(f, "Absolute"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, DynAny, node_macro::ChoiceType)]
|
||||
pub enum SelectiveColorChoice {
|
||||
#[default]
|
||||
Reds,
|
||||
@@ -1197,27 +1049,13 @@ pub enum SelectiveColorChoice {
|
||||
Cyans,
|
||||
Blues,
|
||||
Magentas,
|
||||
|
||||
#[menu_separator]
|
||||
Whites,
|
||||
Neutrals,
|
||||
Blacks,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for SelectiveColorChoice {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
SelectiveColorChoice::Reds => write!(f, "Reds"),
|
||||
SelectiveColorChoice::Yellows => write!(f, "Yellows"),
|
||||
SelectiveColorChoice::Greens => write!(f, "Greens"),
|
||||
SelectiveColorChoice::Cyans => write!(f, "Cyans"),
|
||||
SelectiveColorChoice::Blues => write!(f, "Blues"),
|
||||
SelectiveColorChoice::Magentas => write!(f, "Magentas"),
|
||||
SelectiveColorChoice::Whites => write!(f, "Whites"),
|
||||
SelectiveColorChoice::Neutrals => write!(f, "Neutrals"),
|
||||
SelectiveColorChoice::Blacks => write!(f, "Blacks"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aims for interoperable compatibility with:
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27selc%27%20%3D%20Selective%20color
|
||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=from%20%2D100...100.%20.-,Selective%20Color,-Selective%20Color%20settings
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{Node, NodeIO, NodeIOTypes, Type, WasmNotSend};
|
||||
use dyn_any::{DynAny, StaticType};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
@@ -53,6 +54,33 @@ pub struct FieldMetadata {
|
||||
pub number_mode_range: Option<(f64, f64)>,
|
||||
}
|
||||
|
||||
pub trait ChoiceTypeStatic: Sized + Copy + crate::vector::misc::AsU32 + Send + Sync {
|
||||
const WIDGET_HINT: ChoiceWidgetHint;
|
||||
const DESCRIPTION: Option<&'static str>;
|
||||
fn list() -> &'static [&'static [(Self, VariantMetadata)]];
|
||||
}
|
||||
|
||||
pub enum ChoiceWidgetHint {
|
||||
Dropdown,
|
||||
RadioButtons,
|
||||
}
|
||||
|
||||
/// Translation struct between macro and definition.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VariantMetadata {
|
||||
/// Name as declared in source code.
|
||||
pub name: Cow<'static, str>,
|
||||
|
||||
/// Name to be displayed in UI.
|
||||
pub label: Cow<'static, str>,
|
||||
|
||||
/// User-facing documentation text.
|
||||
pub docstring: Option<Cow<'static, str>>,
|
||||
|
||||
/// Name of icon to display in radio buttons and such.
|
||||
pub icon: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum RegistryWidgetOverride {
|
||||
None,
|
||||
|
||||
@@ -3,7 +3,8 @@ use glam::DVec2;
|
||||
use kurbo::Point;
|
||||
|
||||
/// Represents different ways of calculating the centroid.
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type)]
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum CentroidType {
|
||||
/// The center of mass for the area of a solid shape's interior, as if made out of an infinitely flat material.
|
||||
#[default]
|
||||
@@ -12,41 +13,28 @@ pub enum CentroidType {
|
||||
Length,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type)]
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum BooleanOperation {
|
||||
#[default]
|
||||
#[icon("BooleanUnion")]
|
||||
Union,
|
||||
#[icon("BooleanSubtractFront")]
|
||||
SubtractFront,
|
||||
#[icon("BooleanSubtractBack")]
|
||||
SubtractBack,
|
||||
#[icon("BooleanIntersect")]
|
||||
Intersect,
|
||||
#[icon("BooleanDifference")]
|
||||
Difference,
|
||||
}
|
||||
|
||||
impl BooleanOperation {
|
||||
pub fn list() -> [BooleanOperation; 5] {
|
||||
[
|
||||
BooleanOperation::Union,
|
||||
BooleanOperation::SubtractFront,
|
||||
BooleanOperation::SubtractBack,
|
||||
BooleanOperation::Intersect,
|
||||
BooleanOperation::Difference,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn icons() -> [&'static str; 5] {
|
||||
["BooleanUnion", "BooleanSubtractFront", "BooleanSubtractBack", "BooleanIntersect", "BooleanDifference"]
|
||||
}
|
||||
pub trait AsU32 {
|
||||
fn as_u32(&self) -> u32;
|
||||
}
|
||||
|
||||
impl core::fmt::Display for BooleanOperation {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
BooleanOperation::Union => write!(f, "Union"),
|
||||
BooleanOperation::SubtractFront => write!(f, "Subtract Front"),
|
||||
BooleanOperation::SubtractBack => write!(f, "Subtract Back"),
|
||||
BooleanOperation::Intersect => write!(f, "Intersect"),
|
||||
BooleanOperation::Difference => write!(f, "Difference"),
|
||||
}
|
||||
impl AsU32 for u32 {
|
||||
fn as_u32(&self) -> u32 {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +76,8 @@ impl AsI64 for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type)]
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum GridType {
|
||||
#[default]
|
||||
Rectangular,
|
||||
@@ -96,7 +85,8 @@ pub enum GridType {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum ArcType {
|
||||
#[default]
|
||||
Open,
|
||||
|
||||
@@ -5,9 +5,10 @@ use crate::consts::{LAYER_OUTLINE_STROKE_COLOR, LAYER_OUTLINE_STROKE_WEIGHT};
|
||||
use crate::renderer::format_transform_matrix;
|
||||
use dyn_any::DynAny;
|
||||
use glam::{DAffine2, DVec2};
|
||||
use std::fmt::{self, Display, Write};
|
||||
use std::fmt::Write;
|
||||
|
||||
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, serde::Serialize, serde::Deserialize, DynAny, specta::Type)]
|
||||
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, serde::Serialize, serde::Deserialize, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum GradientType {
|
||||
#[default]
|
||||
Linear,
|
||||
@@ -462,7 +463,8 @@ impl From<Fill> for FillChoice {
|
||||
|
||||
/// Enum describing the type of [Fill].
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, serde::Serialize, serde::Deserialize, DynAny, Hash, specta::Type)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, serde::Serialize, serde::Deserialize, DynAny, Hash, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum FillType {
|
||||
#[default]
|
||||
Solid,
|
||||
@@ -471,7 +473,8 @@ pub enum FillType {
|
||||
|
||||
/// The stroke (outline) style of an SVG element.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum LineCap {
|
||||
#[default]
|
||||
Butt,
|
||||
@@ -479,18 +482,19 @@ pub enum LineCap {
|
||||
Square,
|
||||
}
|
||||
|
||||
impl Display for LineCap {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl LineCap {
|
||||
fn svg_name(&self) -> &'static str {
|
||||
match self {
|
||||
LineCap::Butt => write!(f, "butt"),
|
||||
LineCap::Round => write!(f, "round"),
|
||||
LineCap::Square => write!(f, "square"),
|
||||
LineCap::Butt => "butt",
|
||||
LineCap::Round => "round",
|
||||
LineCap::Square => "square",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||
#[widget(Radio)]
|
||||
pub enum LineJoin {
|
||||
#[default]
|
||||
Miter,
|
||||
@@ -498,12 +502,12 @@ pub enum LineJoin {
|
||||
Round,
|
||||
}
|
||||
|
||||
impl Display for LineJoin {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl LineJoin {
|
||||
fn svg_name(&self) -> &'static str {
|
||||
match self {
|
||||
LineJoin::Bevel => write!(f, "bevel"),
|
||||
LineJoin::Miter => write!(f, "miter"),
|
||||
LineJoin::Round => write!(f, "round"),
|
||||
LineJoin::Bevel => "bevel",
|
||||
LineJoin::Miter => "miter",
|
||||
LineJoin::Round => "round",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -652,10 +656,10 @@ impl Stroke {
|
||||
let _ = write!(&mut attributes, r#" stroke-dashoffset="{}""#, dash_offset);
|
||||
}
|
||||
if let Some(line_cap) = line_cap {
|
||||
let _ = write!(&mut attributes, r#" stroke-linecap="{}""#, line_cap);
|
||||
let _ = write!(&mut attributes, r#" stroke-linecap="{}""#, line_cap.svg_name());
|
||||
}
|
||||
if let Some(line_join) = line_join {
|
||||
let _ = write!(&mut attributes, r#" stroke-linejoin="{}""#, line_join);
|
||||
let _ = write!(&mut attributes, r#" stroke-linejoin="{}""#, line_join.svg_name());
|
||||
}
|
||||
if let Some(line_join_miter_limit) = line_join_miter_limit {
|
||||
let _ = write!(&mut attributes, r#" stroke-miterlimit="{}""#, line_join_miter_limit);
|
||||
|
||||
Reference in New Issue
Block a user