|
|
|
|
@@ -7,8 +7,10 @@ use crate::messages::prelude::*;
|
|
|
|
|
|
|
|
|
|
use graph_craft::document::value::TaggedValue;
|
|
|
|
|
use graph_craft::document::{DocumentNode, NodeId, NodeInput};
|
|
|
|
|
use graph_craft::imaginate_input::{ImaginateSamplingMethod, ImaginateServerStatus, ImaginateStatus};
|
|
|
|
|
use graph_craft::imaginate_input::{ImaginateMaskStartingFill, ImaginateSamplingMethod, ImaginateServerStatus, ImaginateStatus};
|
|
|
|
|
use graph_craft::Type;
|
|
|
|
|
use graphene_core::memo::IORecord;
|
|
|
|
|
use graphene_core::raster::curve::Curve;
|
|
|
|
|
use graphene_core::raster::{
|
|
|
|
|
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, ImageFrame, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute,
|
|
|
|
|
SelectiveColorChoice,
|
|
|
|
|
@@ -16,13 +18,14 @@ use graphene_core::raster::{
|
|
|
|
|
use graphene_core::text::Font;
|
|
|
|
|
use graphene_core::vector::misc::CentroidType;
|
|
|
|
|
use graphene_core::vector::style::{GradientType, LineCap, LineJoin};
|
|
|
|
|
use graphene_std::vector::style::{Fill, FillChoice};
|
|
|
|
|
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
|
|
|
|
|
|
|
|
|
|
use glam::{DAffine2, DVec2, IVec2, UVec2};
|
|
|
|
|
use graphene_std::transform::Footprint;
|
|
|
|
|
use graphene_std::vector::misc::BooleanOperation;
|
|
|
|
|
use graphene_std::vector::VectorData;
|
|
|
|
|
|
|
|
|
|
pub fn string_properties(text: impl Into<String>) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn string_properties(text: impl Into<String>) -> Vec<LayoutGroup> {
|
|
|
|
|
let widget = TextLabel::new(text).widget_holder();
|
|
|
|
|
vec![LayoutGroup::Row { widgets: vec![widget] }]
|
|
|
|
|
}
|
|
|
|
|
@@ -84,6 +87,158 @@ fn start_widgets(document_node: &DocumentNode, node_id: NodeId, index: usize, na
|
|
|
|
|
widgets
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn property_from_type(
|
|
|
|
|
document_node: &DocumentNode,
|
|
|
|
|
node_id: NodeId,
|
|
|
|
|
index: usize,
|
|
|
|
|
name: &str,
|
|
|
|
|
ty: &Type,
|
|
|
|
|
_context: &mut NodePropertiesContext,
|
|
|
|
|
number_options: (Option<f64>, Option<f64>, Option<(f64, f64)>),
|
|
|
|
|
) -> Vec<LayoutGroup> {
|
|
|
|
|
let (mut number_min, mut number_max, range) = number_options;
|
|
|
|
|
let mut number_input = NumberInput::default();
|
|
|
|
|
if let Some((range_start, range_end)) = range {
|
|
|
|
|
number_min = Some(range_start);
|
|
|
|
|
number_max = Some(range_end);
|
|
|
|
|
number_input = number_input.mode_range().min(range_start).max(range_end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let min = |x: f64| number_min.unwrap_or(x);
|
|
|
|
|
let max = |x: f64| number_max.unwrap_or(x);
|
|
|
|
|
|
|
|
|
|
let mut extra_widgets = vec![];
|
|
|
|
|
let widgets = match ty {
|
|
|
|
|
Type::Concrete(concrete_type) => {
|
|
|
|
|
match concrete_type.alias.as_ref().map(|x| x.as_ref()) {
|
|
|
|
|
// Aliased types (ambiguous values)
|
|
|
|
|
Some("Percentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(0.)).max(max(100.)), true).into(),
|
|
|
|
|
Some("SignedPercentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(-100.)).max(max(100.)), true).into(),
|
|
|
|
|
Some("Angle") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(-180.)).max(max(180.)).unit("°"), true).into(),
|
|
|
|
|
Some("PixelLength") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).unit("px"), true).into(),
|
|
|
|
|
Some("Length") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)), true).into(),
|
|
|
|
|
Some("Fraction") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).max(max(1.)), true).into(),
|
|
|
|
|
Some("IntegerCount") => number_widget(document_node, node_id, index, name, number_input.int().min(min(1.)), true).into(),
|
|
|
|
|
Some("SeedValue") => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)), true).into(),
|
|
|
|
|
Some("Resolution") => vec2_widget(document_node, node_id, index, name, "W", "H", "px", Some(64.), add_blank_assist),
|
|
|
|
|
|
|
|
|
|
// For all other types, use TypeId-based matching
|
|
|
|
|
_ => {
|
|
|
|
|
if let Some(internal_id) = concrete_type.id {
|
|
|
|
|
use std::any::TypeId;
|
|
|
|
|
match internal_id {
|
|
|
|
|
x if x == TypeId::of::<bool>() => bool_widget(document_node, node_id, index, name, CheckboxInput::default(), true).into(),
|
|
|
|
|
x if x == TypeId::of::<f64>() => number_widget(document_node, node_id, index, name, number_input.min(min(f64::NEG_INFINITY)).max(max(f64::INFINITY)), true).into(),
|
|
|
|
|
x if x == TypeId::of::<u32>() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)).max(max(f64::from(u32::MAX))), true).into(),
|
|
|
|
|
x if x == TypeId::of::<u64>() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)), true).into(),
|
|
|
|
|
x if x == TypeId::of::<String>() => text_widget(document_node, node_id, index, name, true).into(),
|
|
|
|
|
x if x == TypeId::of::<Color>() => color_widget(document_node, node_id, index, name, ColorButton::default(), true),
|
|
|
|
|
x if x == TypeId::of::<Option<Color>>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(true), true),
|
|
|
|
|
x if x == TypeId::of::<DVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist),
|
|
|
|
|
x if x == TypeId::of::<UVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", Some(0.), add_blank_assist),
|
|
|
|
|
x if x == TypeId::of::<IVec2>() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist),
|
|
|
|
|
x if x == TypeId::of::<Vec<f64>>() => vec_f64_input(document_node, node_id, index, name, TextInput::default(), true).into(),
|
|
|
|
|
x if x == TypeId::of::<Vec<DVec2>>() => vec_dvec2_input(document_node, node_id, index, name, TextInput::default(), true).into(),
|
|
|
|
|
x if x == TypeId::of::<Font>() => {
|
|
|
|
|
let (font_widgets, style_widgets) = font_inputs(document_node, node_id, index, name, false);
|
|
|
|
|
font_widgets.into_iter().chain(style_widgets.unwrap_or_default()).collect::<Vec<_>>().into()
|
|
|
|
|
}
|
|
|
|
|
x if x == TypeId::of::<Curve>() => curves_widget(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<GradientStops>() => color_widget(document_node, node_id, index, name, ColorButton::default().allow_none(false), true),
|
|
|
|
|
x if x == TypeId::of::<VectorData>() => vector_widget(document_node, node_id, index, name, true).into(),
|
|
|
|
|
x if x == TypeId::of::<Footprint>() => {
|
|
|
|
|
let widgets = footprint_widget(document_node, node_id, index);
|
|
|
|
|
let (last, rest) = widgets.split_last().expect("Footprint widget should return multiple rows");
|
|
|
|
|
extra_widgets = rest.to_vec();
|
|
|
|
|
last.clone()
|
|
|
|
|
}
|
|
|
|
|
x if x == TypeId::of::<BlendMode>() => blend_mode(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<RedGreenBlue>() => color_channel(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<RedGreenBlueAlpha>() => rgba_channel(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<NoiseType>() => noise_type(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<FractalType>() => fractal_type(document_node, node_id, index, name, true, false),
|
|
|
|
|
x if x == TypeId::of::<CellularDistanceFunction>() => cellular_distance_function(document_node, node_id, index, name, true, false),
|
|
|
|
|
x if x == TypeId::of::<CellularReturnType>() => cellular_return_type(document_node, node_id, index, name, true, false),
|
|
|
|
|
x if x == TypeId::of::<DomainWarpType>() => domain_warp_type(document_node, node_id, index, name, true, false),
|
|
|
|
|
x if x == TypeId::of::<RelativeAbsolute>() => vec![DropdownInput::new(vec![vec![
|
|
|
|
|
MenuListEntry::new("Relative")
|
|
|
|
|
.label("Relative")
|
|
|
|
|
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Relative), node_id, index)),
|
|
|
|
|
MenuListEntry::new("Absolute")
|
|
|
|
|
.label("Absolute")
|
|
|
|
|
.on_update(update_value(|_| TaggedValue::RelativeAbsolute(RelativeAbsolute::Absolute), node_id, index)),
|
|
|
|
|
]])
|
|
|
|
|
.widget_holder()]
|
|
|
|
|
.into(),
|
|
|
|
|
x if x == TypeId::of::<LineCap>() => line_cap_widget(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<LineJoin>() => line_join_widget(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<FillType>() => vec![DropdownInput::new(vec![vec![
|
|
|
|
|
MenuListEntry::new("Solid")
|
|
|
|
|
.label("Solid")
|
|
|
|
|
.on_update(update_value(|_| TaggedValue::FillType(FillType::Solid), node_id, index)),
|
|
|
|
|
MenuListEntry::new("Gradient")
|
|
|
|
|
.label("Gradient")
|
|
|
|
|
.on_update(update_value(|_| TaggedValue::FillType(FillType::Gradient), node_id, index)),
|
|
|
|
|
]])
|
|
|
|
|
.widget_holder()]
|
|
|
|
|
.into(),
|
|
|
|
|
x if x == TypeId::of::<GradientType>() => vec![DropdownInput::new(vec![vec![
|
|
|
|
|
MenuListEntry::new("Linear")
|
|
|
|
|
.label("Linear")
|
|
|
|
|
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Linear), node_id, index)),
|
|
|
|
|
MenuListEntry::new("Radial")
|
|
|
|
|
.label("Radial")
|
|
|
|
|
.on_update(update_value(|_| TaggedValue::GradientType(GradientType::Radial), node_id, index)),
|
|
|
|
|
]])
|
|
|
|
|
.widget_holder()]
|
|
|
|
|
.into(),
|
|
|
|
|
x if x == TypeId::of::<BooleanOperation>() => boolean_operation_radio_buttons(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<CentroidType>() => centroid_widget(document_node, node_id, index),
|
|
|
|
|
x if x == TypeId::of::<LuminanceCalculation>() => luminance_calculation(document_node, node_id, index, name, true),
|
|
|
|
|
x if x == TypeId::of::<ImaginateSamplingMethod>() => vec![DropdownInput::new(
|
|
|
|
|
ImaginateSamplingMethod::list()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|method| {
|
|
|
|
|
vec![MenuListEntry::new(format!("{:?}", method)).label(method.to_string()).on_update(update_value(
|
|
|
|
|
move |_| TaggedValue::ImaginateSamplingMethod(method),
|
|
|
|
|
node_id,
|
|
|
|
|
index,
|
|
|
|
|
))]
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
)
|
|
|
|
|
.widget_holder()]
|
|
|
|
|
.into(),
|
|
|
|
|
x if x == TypeId::of::<ImaginateMaskStartingFill>() => vec![DropdownInput::new(
|
|
|
|
|
ImaginateMaskStartingFill::list()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|fill| {
|
|
|
|
|
vec![MenuListEntry::new(format!("{:?}", fill)).label(fill.to_string()).on_update(update_value(
|
|
|
|
|
move |_| TaggedValue::ImaginateMaskStartingFill(fill),
|
|
|
|
|
node_id,
|
|
|
|
|
index,
|
|
|
|
|
))]
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
)
|
|
|
|
|
.widget_holder()]
|
|
|
|
|
.into(),
|
|
|
|
|
_ => vec![TextLabel::new(format!("Unsupported type: {}", concrete_type.name)).widget_holder()].into(),
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
vec![TextLabel::new(format!("Unsupported type: {}", concrete_type.name)).widget_holder()].into()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Type::Generic(_) => vec![TextLabel::new("Generic type (not supported)").widget_holder()].into(),
|
|
|
|
|
Type::Fn(_, out) => return property_from_type(document_node, node_id, index, name, out, _context, number_options),
|
|
|
|
|
Type::Future(_) => vec![TextLabel::new("Future type (not supported)").widget_holder()].into(),
|
|
|
|
|
};
|
|
|
|
|
extra_widgets.push(widgets);
|
|
|
|
|
extra_widgets
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn text_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec<WidgetHolder> {
|
|
|
|
|
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
|
|
|
|
|
|
|
|
|
@@ -498,6 +653,14 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
|
|
|
|
|
.on_commit(commit_value)
|
|
|
|
|
.widget_holder(),
|
|
|
|
|
]),
|
|
|
|
|
Some(&TaggedValue::U64(x)) => widgets.extend_from_slice(&[
|
|
|
|
|
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
|
|
|
|
number_props
|
|
|
|
|
.value(Some(x as f64))
|
|
|
|
|
.on_update(update_value(move |x: &NumberInput| TaggedValue::U64((x.value.unwrap()) as u64), node_id, index))
|
|
|
|
|
.on_commit(commit_value)
|
|
|
|
|
.widget_holder(),
|
|
|
|
|
]),
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -930,137 +1093,27 @@ fn centroid_widget(document_node: &DocumentNode, node_id: NodeId, index: usize)
|
|
|
|
|
LayoutGroup::Row { widgets }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn levels_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let input_shadows = number_widget(document_node, node_id, 1, "Shadows", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
let input_midtones = number_widget(document_node, node_id, 2, "Midtones", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
let input_highlights = number_widget(document_node, node_id, 3, "Highlights", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
let output_minimums = number_widget(document_node, node_id, 4, "Output Minimums", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
let output_maximums = number_widget(document_node, node_id, 5, "Output Maximums", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
LayoutGroup::Row { widgets: input_shadows },
|
|
|
|
|
LayoutGroup::Row { widgets: input_midtones },
|
|
|
|
|
LayoutGroup::Row { widgets: input_highlights },
|
|
|
|
|
LayoutGroup::Row { widgets: output_minimums },
|
|
|
|
|
LayoutGroup::Row { widgets: output_maximums },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn black_and_white_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
const MIN: f64 = -200.;
|
|
|
|
|
const MAX: f64 = 300.;
|
|
|
|
|
// TODO: Add tint color (blended above using the "Color" blend mode)
|
|
|
|
|
let tint = color_widget(document_node, node_id, 1, "Tint", ColorButton::default(), true);
|
|
|
|
|
let r_weight = number_widget(document_node, node_id, 2, "Reds", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
|
|
|
|
|
let y_weight = number_widget(document_node, node_id, 3, "Yellows", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
|
|
|
|
|
let g_weight = number_widget(document_node, node_id, 4, "Greens", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
|
|
|
|
|
let c_weight = number_widget(document_node, node_id, 5, "Cyans", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
|
|
|
|
|
let b_weight = number_widget(document_node, node_id, 6, "Blues", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
|
|
|
|
|
let m_weight = number_widget(document_node, node_id, 7, "Magentas", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
tint,
|
|
|
|
|
LayoutGroup::Row { widgets: r_weight },
|
|
|
|
|
LayoutGroup::Row { widgets: y_weight },
|
|
|
|
|
LayoutGroup::Row { widgets: g_weight },
|
|
|
|
|
LayoutGroup::Row { widgets: c_weight },
|
|
|
|
|
LayoutGroup::Row { widgets: b_weight },
|
|
|
|
|
LayoutGroup::Row { widgets: m_weight },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn blend_color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let under = color_widget(document_node, node_id, 1, "Under", ColorButton::default(), true);
|
|
|
|
|
let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true);
|
|
|
|
|
let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
|
|
|
|
|
vec![under, blend_mode, LayoutGroup::Row { widgets: opacity }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn blend_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let backdrop = color_widget(document_node, node_id, 1, "Backdrop", ColorButton::default(), true);
|
|
|
|
|
let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true);
|
|
|
|
|
let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
|
|
|
|
|
vec![backdrop, blend_mode, LayoutGroup::Row { widgets: opacity }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn number_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 0, "Number", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn percentage_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 0, "Percentage", NumberInput::default().min(0.).max(100.).mode_range(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn vector2_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let x = number_widget(document_node, node_id, 1, "X", NumberInput::default(), true);
|
|
|
|
|
let y = number_widget(document_node, node_id, 2, "Y", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: x }, LayoutGroup::Row { widgets: y }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn boolean_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = bool_widget(document_node, node_id, 0, "Bool", CheckboxInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![color_widget(document_node, node_id, 0, "Color", ColorButton::default(), true)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn gradient_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![color_widget(document_node, node_id, 0, "Gradient", ColorButton::default().allow_none(false), true)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn load_image_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn load_image_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let url = text_widget(document_node, node_id, 1, "URL", true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: url }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn output_properties(_document_node: &DocumentNode, _node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let label = TextLabel::new("Graphics fed into the Output are drawn in the viewport").widget_holder();
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: vec![label] }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn mask_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn mask_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let mask = color_widget(document_node, node_id, 1, "Stencil", ColorButton::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![mask]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn color_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![color_channel(document_node, node_id, 0, "Channel", true)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn luminance_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let luminance_calc = luminance_calculation(document_node, node_id, 1, "Luminance Calc", true);
|
|
|
|
|
|
|
|
|
|
vec![luminance_calc]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn insert_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn insert_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let color_channel = color_channel(document_node, node_id, 2, "Into", true);
|
|
|
|
|
|
|
|
|
|
vec![color_channel]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn extract_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let color_channel = rgba_channel(document_node, node_id, 1, "From", true);
|
|
|
|
|
|
|
|
|
|
vec![color_channel]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Noise Type is commented out for now as there is only one type of noise (White Noise).
|
|
|
|
|
// As soon as there are more types of noise, this should be uncommented.
|
|
|
|
|
pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
// Get the current values of the inputs of interest so they can set whether certain inputs are disabled based on various conditions.
|
|
|
|
|
let current_noise_type = match &document_node.inputs[3].as_value() {
|
|
|
|
|
Some(&TaggedValue::NoiseType(noise_type)) => Some(noise_type),
|
|
|
|
|
@@ -1208,62 +1261,52 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn hue_saturation_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let hue_shift = number_widget(document_node, node_id, 1, "Hue Shift", NumberInput::default().min(-180.).max(180.).unit("°"), true);
|
|
|
|
|
let saturation_shift = number_widget(document_node, node_id, 2, "Saturation Shift", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
|
|
|
|
|
let lightness_shift = number_widget(document_node, node_id, 3, "Lightness Shift", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
|
|
|
|
|
pub(crate) fn brightness_contrast_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let is_use_classic = match &document_node.inputs[3].as_value() {
|
|
|
|
|
Some(&TaggedValue::Bool(value)) => value,
|
|
|
|
|
_ => false,
|
|
|
|
|
};
|
|
|
|
|
let ((b_min, b_max), (c_min, c_max)) = if is_use_classic { ((-100., 100.), (-100., 100.)) } else { ((-100., 150.), (-50., 100.)) };
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
LayoutGroup::Row { widgets: hue_shift },
|
|
|
|
|
LayoutGroup::Row { widgets: saturation_shift },
|
|
|
|
|
LayoutGroup::Row { widgets: lightness_shift },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn brightness_contrast_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let brightness = number_widget(document_node, node_id, 1, "Brightness", NumberInput::default().min(-150.).max(150.), true);
|
|
|
|
|
let contrast = number_widget(document_node, node_id, 2, "Contrast", NumberInput::default().min(-100.).max(100.), true);
|
|
|
|
|
let use_legacy = bool_widget(document_node, node_id, 3, "Use Legacy", CheckboxInput::default(), true);
|
|
|
|
|
let brightness = number_widget(
|
|
|
|
|
document_node,
|
|
|
|
|
node_id,
|
|
|
|
|
1,
|
|
|
|
|
"Brightness",
|
|
|
|
|
NumberInput::default().mode_range().range_min(Some(b_min)).range_max(Some(b_max)).unit("%").display_decimal_places(2),
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
let contrast = number_widget(
|
|
|
|
|
document_node,
|
|
|
|
|
node_id,
|
|
|
|
|
2,
|
|
|
|
|
"Contrast",
|
|
|
|
|
NumberInput::default().mode_range().range_min(Some(c_min)).range_max(Some(c_max)).unit("%").display_decimal_places(2),
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
let use_classic = bool_widget(document_node, node_id, 3, "Use Classic", CheckboxInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
LayoutGroup::Row { widgets: brightness },
|
|
|
|
|
LayoutGroup::Row { widgets: contrast },
|
|
|
|
|
LayoutGroup::Row { widgets: use_legacy },
|
|
|
|
|
LayoutGroup::Row { widgets: use_classic },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn curves_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn curves_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let curves = curves_widget(document_node, node_id, 1, "Curve", true);
|
|
|
|
|
|
|
|
|
|
vec![curves]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn _blur_image_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn _blur_image_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let radius = number_widget(document_node, node_id, 1, "Radius", NumberInput::default().min(0.).max(20.).int(), true);
|
|
|
|
|
let sigma = number_widget(document_node, node_id, 2, "Sigma", NumberInput::default().min(0.).max(10000.), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: radius }, LayoutGroup::Row { widgets: sigma }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn threshold_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let thereshold_min = number_widget(document_node, node_id, 1, "Min Luminance", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
let thereshold_max = number_widget(document_node, node_id, 2, "Max Luminance", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
let luminance_calc = luminance_calculation(document_node, node_id, 3, "Luminance Calc", true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: thereshold_min }, LayoutGroup::Row { widgets: thereshold_max }, luminance_calc]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn gradient_map_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let gradient_index = 1;
|
|
|
|
|
let reverse_index = 2;
|
|
|
|
|
|
|
|
|
|
let gradient_row = color_widget(document_node, node_id, gradient_index, "Gradient", ColorButton::default().allow_none(false), true);
|
|
|
|
|
let reverse_row = bool_widget(document_node, node_id, reverse_index, "Reverse", CheckboxInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![gradient_row, LayoutGroup::Row { widgets: reverse_row }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn assign_colors_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn assign_colors_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let fill_index = 1;
|
|
|
|
|
let stroke_index = 2;
|
|
|
|
|
let gradient_index = 3;
|
|
|
|
|
@@ -1303,22 +1346,7 @@ pub fn assign_colors_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn vibrance_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let vibrance_index = 1;
|
|
|
|
|
|
|
|
|
|
let vibrance = number_widget(
|
|
|
|
|
document_node,
|
|
|
|
|
node_id,
|
|
|
|
|
vibrance_index,
|
|
|
|
|
"Vibrance",
|
|
|
|
|
NumberInput::default().mode_range().min(-100.).max(100.).unit("%"),
|
|
|
|
|
true,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: vibrance }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn channel_mixer_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn channel_mixer_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
// Monochrome
|
|
|
|
|
let monochrome_index = 1;
|
|
|
|
|
let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", CheckboxInput::default(), true);
|
|
|
|
|
@@ -1418,7 +1446,7 @@ pub fn channel_mixer_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|
|
|
|
layout
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn selective_color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn selective_color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
// Colors choice
|
|
|
|
|
let colors_index = 38;
|
|
|
|
|
let mut colors = vec![TextLabel::new("Colors").widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder()];
|
|
|
|
|
@@ -1508,40 +1536,13 @@ pub fn selective_color_properties(document_node: &DocumentNode, node_id: NodeId,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "gpu")]
|
|
|
|
|
pub fn _gpu_map_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn _gpu_map_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let map = text_widget(document_node, node_id, 1, "Map", true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: map }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn opacity_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let gamma = number_widget(document_node, node_id, 1, "Factor", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: gamma }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn blend_mode_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![blend_mode(document_node, node_id, 1, "Blend Mode", true)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn blend_mode_value_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![blend_mode(document_node, node_id, 0, "Blend Mode", true)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn posterize_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let value = number_widget(document_node, node_id, 1, "Levels", NumberInput::default().min(2.).max(255.).int(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: value }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "quantization")]
|
|
|
|
|
pub fn quantize_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let value = number_widget(document_node, node_id, 1, "Levels", NumberInput::default().min(1.).max(1000.).int(), true);
|
|
|
|
|
let index = number_widget(document_node, node_id, 1, "Fit Fn Index", NumberInput::default().min(0.).max(2.).int(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: value }, LayoutGroup::Row { widgets: index }]
|
|
|
|
|
}
|
|
|
|
|
pub fn exposure_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn exposure_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let exposure = number_widget(document_node, node_id, 1, "Exposure", NumberInput::default().min(-20.).max(20.), true);
|
|
|
|
|
let offset = number_widget(document_node, node_id, 2, "Offset", NumberInput::default().min(-0.5).max(0.5), true);
|
|
|
|
|
let gamma_input = NumberInput::default().min(0.01).max(9.99).increment_step(0.1);
|
|
|
|
|
@@ -1554,82 +1555,7 @@ pub fn exposure_properties(document_node: &DocumentNode, node_id: NodeId, _conte
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Addend", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn subtract_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Subtrahend", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn divide_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Divisor", NumberInput::new(Some(1.)), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn multiply_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Multiplicand", NumberInput::new(Some(1.)), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn exponent_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Power", NumberInput::new(Some(2.)), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn log_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Base", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn max_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Maximum", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn min_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Minimum", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn eq_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Equals", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn modulo_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, 1, "Modulo", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn circle_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::Row {
|
|
|
|
|
widgets: number_widget(document_node, node_id, 1, "Radius", NumberInput::default(), true),
|
|
|
|
|
}]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn ellipse_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let operand = |name: &str, index| {
|
|
|
|
|
let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
LayoutGroup::Row { widgets }
|
|
|
|
|
};
|
|
|
|
|
vec![operand("Radius X", 1), operand("Radius Y", 2)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn rectangle_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn rectangle_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let size_x_index = 1;
|
|
|
|
|
let size_y_index = 2;
|
|
|
|
|
let corner_rounding_type_index = 3;
|
|
|
|
|
@@ -1754,37 +1680,17 @@ pub fn rectangle_properties(document_node: &DocumentNode, node_id: NodeId, _cont
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn regular_polygon_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let points = number_widget(document_node, node_id, 1, "Points", NumberInput::default().min(3.), true);
|
|
|
|
|
let radius = number_widget(document_node, node_id, 2, "Radius", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: points }, LayoutGroup::Row { widgets: radius }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn star_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let points = number_widget(document_node, node_id, 1, "Points", NumberInput::default().min(2.), true);
|
|
|
|
|
let radius = number_widget(document_node, node_id, 2, "Radius", NumberInput::default(), true);
|
|
|
|
|
let inner_radius = number_widget(document_node, node_id, 3, "Inner Radius", NumberInput::default(), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: points }, LayoutGroup::Row { widgets: radius }, LayoutGroup::Row { widgets: inner_radius }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn line_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn line_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let operand = |name: &str, index| vec2_widget(document_node, node_id, index, name, "X", "Y", "px", None, add_blank_assist);
|
|
|
|
|
vec![operand("Start", 1), operand("End", 2)]
|
|
|
|
|
}
|
|
|
|
|
pub fn spline_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn spline_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
vec![LayoutGroup::Row {
|
|
|
|
|
widgets: vec_dvec2_input(document_node, node_id, 1, "Points", TextInput::default().centered(true), true),
|
|
|
|
|
}]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn logic_operator_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let widgets = bool_widget(document_node, node_id, 0, "Operand B", CheckboxInput::default(), true);
|
|
|
|
|
vec![LayoutGroup::Row { widgets }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn transform_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn transform_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let translation = vec2_widget(document_node, node_id, 1, "Translation", "X", "Y", " px", None, add_blank_assist);
|
|
|
|
|
|
|
|
|
|
let rotation = {
|
|
|
|
|
@@ -1817,11 +1723,11 @@ pub fn transform_properties(document_node: &DocumentNode, node_id: NodeId, _cont
|
|
|
|
|
|
|
|
|
|
vec![translation, rotation, scale]
|
|
|
|
|
}
|
|
|
|
|
pub fn rasterize_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn rasterize_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
footprint_widget(document_node, node_id, 1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn text_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn text_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let text = text_area_widget(document_node, node_id, 1, "Text", true);
|
|
|
|
|
let (font, style) = font_inputs(document_node, node_id, 2, "Font", true);
|
|
|
|
|
let size = number_widget(document_node, node_id, 3, "Size", NumberInput::default().unit(" px").min(1.), true);
|
|
|
|
|
@@ -1834,7 +1740,7 @@ pub fn text_properties(document_node: &DocumentNode, node_id: NodeId, _context:
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let imaginate_node = [context.selection_network_path, &[node_id]].concat();
|
|
|
|
|
|
|
|
|
|
let resolve_input = |name: &str| {
|
|
|
|
|
@@ -2328,7 +2234,7 @@ fn unknown_node_properties(reference: &String) -> Vec<LayoutGroup> {
|
|
|
|
|
string_properties(format!("Node '{}' cannot be found in library", reference))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn node_no_properties(_document_node: &DocumentNode, node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn node_no_properties(_document_node: &DocumentNode, node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
string_properties(if context.network_interface.is_layer(&node_id, context.selection_network_path) {
|
|
|
|
|
"Layer has no properties"
|
|
|
|
|
} else {
|
|
|
|
|
@@ -2336,13 +2242,13 @@ pub fn node_no_properties(_document_node: &DocumentNode, node_id: NodeId, contex
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn index_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn index_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let index = number_widget(document_node, node_id, 1, "Index", NumberInput::default().min(0.), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: index }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn generate_node_properties(document_node: &DocumentNode, node_id: NodeId, context: &mut NodePropertiesContext) -> LayoutGroup {
|
|
|
|
|
pub(crate) fn generate_node_properties(document_node: &DocumentNode, node_id: NodeId, context: &mut NodePropertiesContext) -> LayoutGroup {
|
|
|
|
|
let reference = context.network_interface.reference(&node_id, context.selection_network_path).clone();
|
|
|
|
|
let layout = if let Some(ref reference) = reference {
|
|
|
|
|
match super::document_node_definitions::resolve_document_node_type(reference) {
|
|
|
|
|
@@ -2361,66 +2267,7 @@ pub fn generate_node_properties(document_node: &DocumentNode, node_id: NodeId, c
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn stroke_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let color_index = 1;
|
|
|
|
|
let weight_index = 2;
|
|
|
|
|
let dash_lengths_index = 3;
|
|
|
|
|
let dash_offset_index = 4;
|
|
|
|
|
let line_cap_index = 5;
|
|
|
|
|
let line_join_index = 6;
|
|
|
|
|
let miter_limit_index = 7;
|
|
|
|
|
|
|
|
|
|
let color = color_widget(document_node, node_id, color_index, "Color", ColorButton::default(), true);
|
|
|
|
|
let weight = number_widget(document_node, node_id, weight_index, "Weight", NumberInput::default().unit("px").min(0.), true);
|
|
|
|
|
|
|
|
|
|
let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() {
|
|
|
|
|
Some(TaggedValue::VecF64(x)) => x,
|
|
|
|
|
_ => &vec![],
|
|
|
|
|
};
|
|
|
|
|
let dash_lengths = vec_f64_input(document_node, node_id, dash_lengths_index, "Dash Lengths", TextInput::default().centered(true), true);
|
|
|
|
|
let number_input = NumberInput::default().unit("px").disabled(dash_lengths_val.is_empty());
|
|
|
|
|
let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", number_input, true);
|
|
|
|
|
let line_cap = line_cap_widget(document_node, node_id, line_cap_index, "Line Cap", true);
|
|
|
|
|
let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", true);
|
|
|
|
|
let line_join_val = match &document_node.inputs[line_join_index].as_value() {
|
|
|
|
|
Some(TaggedValue::LineJoin(x)) => x,
|
|
|
|
|
_ => &LineJoin::Miter,
|
|
|
|
|
};
|
|
|
|
|
let number_input = NumberInput::default().min(0.).disabled(line_join_val != &LineJoin::Miter);
|
|
|
|
|
let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", number_input, true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
color,
|
|
|
|
|
LayoutGroup::Row { widgets: weight },
|
|
|
|
|
LayoutGroup::Row { widgets: dash_lengths },
|
|
|
|
|
LayoutGroup::Row { widgets: dash_offset },
|
|
|
|
|
line_cap,
|
|
|
|
|
line_join,
|
|
|
|
|
LayoutGroup::Row { widgets: miter_limit },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn repeat_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let direction = vec2_widget(document_node, node_id, 1, "Direction", "X", "Y", " px", None, add_blank_assist);
|
|
|
|
|
let angle = number_widget(document_node, node_id, 2, "Angle", NumberInput::default().unit("°"), true);
|
|
|
|
|
let instances = number_widget(document_node, node_id, 3, "Instances", NumberInput::default().min(1.).is_integer(true), true);
|
|
|
|
|
|
|
|
|
|
vec![direction, LayoutGroup::Row { widgets: angle }, LayoutGroup::Row { widgets: instances }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn circular_repeat_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let angle_offset = number_widget(document_node, node_id, 1, "Angle Offset", NumberInput::default().unit("°"), true);
|
|
|
|
|
let radius = number_widget(document_node, node_id, 2, "Radius", NumberInput::default(), true); // TODO: What units?
|
|
|
|
|
let instances = number_widget(document_node, node_id, 3, "Instances", NumberInput::default().min(1.).is_integer(true), true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
LayoutGroup::Row { widgets: angle_offset },
|
|
|
|
|
LayoutGroup::Row { widgets: radius },
|
|
|
|
|
LayoutGroup::Row { widgets: instances },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn boolean_operation_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn boolean_operation_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let group_of_paths_index = 0;
|
|
|
|
|
let operation_index = 1;
|
|
|
|
|
|
|
|
|
|
@@ -2434,7 +2281,7 @@ pub fn boolean_operation_properties(document_node: &DocumentNode, node_id: NodeI
|
|
|
|
|
vec![LayoutGroup::Row { widgets }, operation]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let instance_index = 1;
|
|
|
|
|
let random_scale_min_index = 2;
|
|
|
|
|
let random_scale_max_index = 3;
|
|
|
|
|
@@ -2493,7 +2340,7 @@ pub fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId,
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn sample_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn sample_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let spacing = number_widget(document_node, node_id, 1, "Spacing", NumberInput::default().min(1.).unit(" px"), true);
|
|
|
|
|
let start_offset = number_widget(document_node, node_id, 2, "Start Offset", NumberInput::default().min(0.).unit(" px"), true);
|
|
|
|
|
let stop_offset = number_widget(document_node, node_id, 3, "Stop Offset", NumberInput::default().min(0.).unit(" px"), true);
|
|
|
|
|
@@ -2507,7 +2354,7 @@ pub fn sample_points_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn poisson_disk_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn poisson_disk_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let separation_disk_diameter_index = 1;
|
|
|
|
|
let seed_index = 2;
|
|
|
|
|
|
|
|
|
|
@@ -2525,18 +2372,8 @@ pub fn poisson_disk_points_properties(document_node: &DocumentNode, node_id: Nod
|
|
|
|
|
vec![LayoutGroup::Row { widgets: spacing }, LayoutGroup::Row { widgets: seed }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn morph_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let start_index = number_widget(document_node, node_id, 2, "Start Index", NumberInput::default().min(0.), true);
|
|
|
|
|
let time = number_widget(document_node, node_id, 3, "Time", NumberInput::default().min(0.).max(1.).mode_range(), true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
LayoutGroup::Row { widgets: start_index }.with_tooltip("The index of point on the target that morphs to the first point of the source"),
|
|
|
|
|
LayoutGroup::Row { widgets: time }.with_tooltip("Linear time of transition - 0. is source, 1. is target"),
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Fill Node Widgets LayoutGroup
|
|
|
|
|
pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let fill_index = 1;
|
|
|
|
|
let backup_color_index = 2;
|
|
|
|
|
let backup_gradient_index = 3;
|
|
|
|
|
@@ -2711,7 +2548,46 @@ pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context:
|
|
|
|
|
widgets
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub fn stroke_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let color_index = 1;
|
|
|
|
|
let weight_index = 2;
|
|
|
|
|
let dash_lengths_index = 3;
|
|
|
|
|
let dash_offset_index = 4;
|
|
|
|
|
let line_cap_index = 5;
|
|
|
|
|
let line_join_index = 6;
|
|
|
|
|
let miter_limit_index = 7;
|
|
|
|
|
|
|
|
|
|
let color = color_widget(document_node, node_id, color_index, "Color", ColorButton::default(), true);
|
|
|
|
|
let weight = number_widget(document_node, node_id, weight_index, "Weight", NumberInput::default().unit("px").min(0.), true);
|
|
|
|
|
|
|
|
|
|
let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() {
|
|
|
|
|
Some(TaggedValue::VecF64(x)) => x,
|
|
|
|
|
_ => &vec![],
|
|
|
|
|
};
|
|
|
|
|
let dash_lengths = vec_f64_input(document_node, node_id, dash_lengths_index, "Dash Lengths", TextInput::default().centered(true), true);
|
|
|
|
|
let number_input = NumberInput::default().unit("px").disabled(dash_lengths_val.is_empty());
|
|
|
|
|
let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", number_input, true);
|
|
|
|
|
let line_cap = line_cap_widget(document_node, node_id, line_cap_index, "Line Cap", true);
|
|
|
|
|
let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", true);
|
|
|
|
|
let line_join_val = match &document_node.inputs[line_join_index].as_value() {
|
|
|
|
|
Some(TaggedValue::LineJoin(x)) => x,
|
|
|
|
|
_ => &LineJoin::Miter,
|
|
|
|
|
};
|
|
|
|
|
let number_input = NumberInput::default().min(0.).disabled(line_join_val != &LineJoin::Miter);
|
|
|
|
|
let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", number_input, true);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
color,
|
|
|
|
|
LayoutGroup::Row { widgets: weight },
|
|
|
|
|
LayoutGroup::Row { widgets: dash_lengths },
|
|
|
|
|
LayoutGroup::Row { widgets: dash_offset },
|
|
|
|
|
line_cap,
|
|
|
|
|
line_join,
|
|
|
|
|
LayoutGroup::Row { widgets: miter_limit },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let location = vec2_widget(document_node, node_id, 2, "Location", "X", "Y", " px", None, add_blank_assist);
|
|
|
|
|
let dimensions = vec2_widget(document_node, node_id, 3, "Dimensions", "W", "H", " px", None, add_blank_assist);
|
|
|
|
|
let background = color_widget(document_node, node_id, 4, "Background", ColorButton::default().allow_none(false), true);
|
|
|
|
|
@@ -2722,27 +2598,7 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte
|
|
|
|
|
vec![location, dimensions, background, clip_row]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn color_fill_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
pub(crate) fn color_fill_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let color = color_widget(document_node, node_id, 1, "Color", ColorButton::default(), true);
|
|
|
|
|
vec![color]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn color_overlay_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let color = color_widget(document_node, node_id, 1, "Color", ColorButton::default(), true);
|
|
|
|
|
let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true);
|
|
|
|
|
let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true);
|
|
|
|
|
|
|
|
|
|
vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn image_color_palette(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let size = number_widget(document_node, node_id, 1, "Max Size", NumberInput::default().int().min(1.).max(28.), true);
|
|
|
|
|
|
|
|
|
|
vec![LayoutGroup::Row { widgets: size }]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn centroid_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
|
|
|
|
let centroid_type = centroid_widget(document_node, node_id, 1);
|
|
|
|
|
|
|
|
|
|
vec![centroid_type]
|
|
|
|
|
}
|
|
|
|
|
|