diff --git a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs index a19aac95bf..419d5b3318 100644 --- a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs +++ b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs @@ -421,31 +421,6 @@ pub struct TextInput { pub on_commit: WidgetCallback<()>, } -// #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] -// #[derive(Clone, serde::Serialize, serde::Deserialize, Derivative, WidgetBuilder)] -// #[derivative(Debug, PartialEq, Default)] -// pub struct CurveInput { -// // Content -// #[widget_builder(constructor)] -// pub value: Curve, - -// // Tooltips -// #[serde(rename = "tooltipLabel")] -// pub tooltip_label: String, -// #[serde(rename = "tooltipDescription")] -// pub tooltip_description: String, -// #[serde(rename = "tooltipShortcut")] -// pub tooltip_shortcut: Option, - -// // Callbacks -// #[serde(skip)] -// #[derivative(Debug = "ignore", PartialEq = "ignore")] -// pub on_update: WidgetCallback, -// #[serde(skip)] -// #[derivative(Debug = "ignore", PartialEq = "ignore")] -// pub on_commit: WidgetCallback<()>, -// } - #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] #[derive(Clone, Default, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder)] #[derivative(Debug, PartialEq)] diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index 031fdafc6e..607134d28c 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -1162,28 +1162,6 @@ pub fn font_widget(parameter_widgets_info: ParameterWidgetsInfo) -> LayoutGroup font_widgets.into_iter().chain(style_widgets.unwrap_or_default()).collect::>().into() } -// pub fn curve_widget(parameter_widgets_info: ParameterWidgetsInfo) -> LayoutGroup { -// let ParameterWidgetsInfo { document_node, node_id, index, .. } = parameter_widgets_info; - -// let mut widgets = start_widgets(parameter_widgets_info); - -// let Some(document_node) = document_node else { return LayoutGroup::default() }; -// let Some(input) = document_node.inputs.get(index) else { -// log::warn!("A widget failed to be built because its node's input index is invalid."); -// return LayoutGroup::row(vec![]); -// }; -// if let Some(TaggedValue::Curve(curve)) = &input.as_non_exposed_value() { -// widgets.extend_from_slice(&[ -// Separator::new(SeparatorStyle::Unrelated).widget_instance(), -// CurveInput::new(curve.clone()) -// .on_update(update_value(|x: &CurveInput| TaggedValue::Curve(x.value.clone()), node_id, index)) -// .on_commit(commit_value) -// .widget_instance(), -// ]) -// } -// LayoutGroup::row(widgets) -// } - pub fn get_document_node<'a>(node_id: NodeId, context: &'a NodePropertiesContext<'a>) -> Result<&'a DocumentNode, String> { let network = context .network_interface diff --git a/frontend/src/components/widgets/inputs/CurveInput.svelte b/frontend/src/components/widgets/inputs/CurveInput.svelte deleted file mode 100644 index e59d2b2d85..0000000000 --- a/frontend/src/components/widgets/inputs/CurveInput.svelte +++ /dev/null @@ -1,259 +0,0 @@ - diff --git a/node-graph/libraries/no-std-types/src/color/color_traits.rs b/node-graph/libraries/no-std-types/src/color/color_traits.rs index 05b0242329..945cd9e7ad 100644 --- a/node-graph/libraries/no-std-types/src/color/color_traits.rs +++ b/node-graph/libraries/no-std-types/src/color/color_traits.rs @@ -11,15 +11,6 @@ pub trait Linear { fn to_f32(self) -> f32; fn from_f64(x: f64) -> Self; fn to_f64(self) -> f64; - fn lerp(self, other: Self, value: Self) -> Self - where - Self: Sized + Copy, - Self: core::ops::Sub, - Self: core::ops::Mul, - Self: core::ops::Add, - { - self + (other - self) * value - } } #[rustfmt::skip] @@ -174,10 +165,6 @@ pub trait Luminance { } } -pub trait LuminanceMut: Luminance { - fn set_luminance(&mut self, luminance: Self::LuminanceChannel); -} - // TODO: We might rename this to Raster at some point pub trait Sample { type Pixel: Pixel; diff --git a/node-graph/libraries/no-std-types/src/color/color_types.rs b/node-graph/libraries/no-std-types/src/color/color_types.rs index 51ce385538..2847097416 100644 --- a/node-graph/libraries/no-std-types/src/color/color_types.rs +++ b/node-graph/libraries/no-std-types/src/color/color_types.rs @@ -1,4 +1,4 @@ -use super::color_traits::{Alpha, AlphaMut, AssociatedAlpha, Luminance, LuminanceMut, Pixel, RGB, RGBMut, Rec709Primaries, SRGB}; +use super::color_traits::{Alpha, AlphaMut, AssociatedAlpha, Luminance, Pixel, RGB, RGBMut, Rec709Primaries, SRGB}; use super::discrete_srgb::{float_to_srgb_u8, srgb_u8_to_float}; use bytemuck::{Pod, Zeroable}; use core::fmt::Debug; @@ -236,12 +236,6 @@ impl Luminance for Luma { } } -impl LuminanceMut for Luma { - fn set_luminance(&mut self, luminance: Self::LuminanceChannel) { - self.0 = luminance - } -} - impl RGB for Luma { type ColorChannel = f32; #[inline(always)] @@ -411,28 +405,6 @@ impl Luminance for Color { } } -impl LuminanceMut for Color { - fn set_luminance(&mut self, luminance: f32) { - let current = self.luminance(); - // When we have a black-ish color, we just set the color to a grey-scale value. This prohibits a divide-by-0. - if current < f32::EPSILON { - self.red = 0.2126 * luminance; - self.green = 0.7152 * luminance; - self.blue = 0.0722 * luminance; - return; - } - let fac = luminance / current; - // TODO: when we have for example the rgb color (0, 0, 1) and want to - // TODO: do `.set_luminance(1)`, then the actual luminance is not 1 at - // TODO: the end. With no clamp, the resulting color would be - // TODO: (0, 0, 12.8504). The excess should be spread to the other - // TODO: channels, but is currently just clamped away. - self.red = (self.red * fac).clamp(0., 1.); - self.green = (self.green * fac).clamp(0., 1.); - self.blue = (self.blue * fac).clamp(0., 1.); - } -} - impl Rec709Primaries for Color {} impl SRGB for Color {} diff --git a/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs b/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs index 35e2b2bd2d..b09fe4ea52 100644 --- a/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs +++ b/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs @@ -5,7 +5,6 @@ use crate::vector::algorithms::offset_subpath::MAX_ABSOLUTE_DIFFERENCE; use crate::vector::misc::{PointSpacingType, dvec2_to_point, point_to_dvec2}; use core_types::math::polynomial::pathseg_to_parametric_polynomial; use glam::{DMat2, DVec2}; -use kurbo::common::{solve_cubic, solve_quadratic}; use kurbo::{BezPath, CubicBez, DEFAULT_ACCURACY, Line, ParamCurve, ParamCurveArclen, ParamCurveDeriv, PathEl, PathSeg, Point, QuadBez, Rect, Shape, Vec2}; use std::f64::consts::{FRAC_PI_2, PI}; @@ -201,39 +200,6 @@ pub fn pathseg_compute_lookup_table(segment: PathSeg, steps: Option, eucl }) } -/// Returns an `Iterator` containing all possible parametric `t`-values at the given `x`-coordinate. -pub fn pathseg_find_tvalues_for_x(segment: PathSeg, x: f64) -> impl Iterator + use<> { - match segment { - PathSeg::Line(Line { p0, p1 }) => { - // If the transformed linear bezier is on the x-axis, `a` and `b` will both be zero and `solve_linear` will return no roots - let a = p1.x - p0.x; - let b = p0.x - x; - - // Find the roots of the linear equation `ax + b`. - // There exist roots when `a` is not 0 - if a.abs() > MAX_ABSOLUTE_DIFFERENCE { [Some(-b / a), None, None] } else { [None; 3] } - } - PathSeg::Quad(QuadBez { p0, p1, p2 }) => { - let a = p2.x - 2. * p1.x + p0.x; - let b = 2. * (p1.x - p0.x); - let c = p0.x - x; - let r = solve_quadratic(c, b, a); - [r.first().copied(), r.get(1).copied(), None] - } - PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => { - let a = p3.x - 3. * p2.x + 3. * p1.x - p0.x; - let b = 3. * (p2.x - 2. * p1.x + p0.x); - let c = 3. * (p1.x - p0.x); - let d = p0.x - x; - let r = solve_cubic(d, c, b, a); - [r.first().copied(), r.get(1).copied(), r.get(2).copied()] - } - } - .into_iter() - .flatten() - .filter(|&t| (0.0..1.).contains(&t)) -} - /// Find the `t`-value(s) such that the normal(s) at `t` pass through the specified point. pub fn pathseg_normals_to_point(segment: PathSeg, point: Point) -> Vec { // We solve deriv(t) dot (self(t) - point) = 0. diff --git a/node-graph/nodes/raster/src/curve.rs b/node-graph/nodes/raster/src/curve.rs deleted file mode 100644 index 242715ee03..0000000000 --- a/node-graph/nodes/raster/src/curve.rs +++ /dev/null @@ -1,69 +0,0 @@ -use core_types::Node; -use core_types::color::{Channel, Linear, LuminanceMut}; -use dyn_any::{DynAny, StaticType, StaticTypeSized}; -use std::ops::{Add, Mul, Sub}; - -#[cfg_attr(feature = "wasm", derive(tsify::Tsify))] -#[derive(Debug, Clone, PartialEq, core_types::CacheHash, DynAny)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Curve { - #[cfg_attr(feature = "serde", serde(rename = "manipulatorGroups"))] - pub manipulator_groups: Vec, - #[cfg_attr(feature = "serde", serde(rename = "firstHandle"))] - pub first_handle: [f32; 2], - #[cfg_attr(feature = "serde", serde(rename = "lastHandle"))] - pub last_handle: [f32; 2], -} - -impl Default for Curve { - fn default() -> Self { - Self { - manipulator_groups: vec![], - first_handle: [0.2; 2], - last_handle: [0.8; 2], - } - } -} - -#[cfg_attr(feature = "wasm", derive(tsify::Tsify))] -#[derive(Debug, Clone, Copy, PartialEq, core_types::CacheHash, DynAny)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct CurveManipulatorGroup { - pub anchor: [f32; 2], - pub handles: [[f32; 2]; 2], -} - -pub struct ValueMapperNode { - lut: Vec, -} - -unsafe impl StaticType for ValueMapperNode { - type Static = ValueMapperNode; -} - -impl ValueMapperNode { - pub const fn new(lut: Vec) -> Self { - Self { lut } - } -} - -impl<'i, L: LuminanceMut + 'i> Node<'i, L> for ValueMapperNode -where - L::LuminanceChannel: Linear + Copy, - L::LuminanceChannel: Add, - L::LuminanceChannel: Sub, - L::LuminanceChannel: Mul, -{ - type Output = L; - - fn eval(&'i self, mut val: L) -> L { - let luminance: f32 = val.luminance().to_linear(); - let floating_sample_index = luminance * (self.lut.len() - 1) as f32; - let index_in_lut = floating_sample_index.floor() as usize; - let a = self.lut[index_in_lut]; - let b = self.lut[(index_in_lut + 1).clamp(0, self.lut.len() - 1)]; - let result = a.lerp(b, L::LuminanceChannel::from_linear(floating_sample_index.fract())); - val.set_luminance(result); - val - } -} diff --git a/node-graph/nodes/raster/src/generate_curves.rs b/node-graph/nodes/raster/src/generate_curves.rs deleted file mode 100644 index 7e1e0bd785..0000000000 --- a/node-graph/nodes/raster/src/generate_curves.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use core_types::color::{Channel, Linear}; -use core_types::context::Ctx; -use kurbo::{CubicBez, ParamCurve, PathSeg, Point}; -use vector_types::vector::algorithms::bezpath_algorithms::pathseg_find_tvalues_for_x; - -const WINDOW_SIZE: usize = 1024; - -#[node_macro::node(category(""))] -fn generate_curves(_: impl Ctx, curve: Curve, #[implementations(f32, f64)] _target_format: C) -> ValueMapperNode { - let [mut pos, mut param]: [[f32; 2]; 2] = [[0.; 2], curve.first_handle]; - let mut lut = vec![C::from_f64(0.); WINDOW_SIZE]; - let end = CurveManipulatorGroup { - anchor: [1.; 2], - handles: [curve.last_handle, [0.; 2]], - }; - for sample in curve.manipulator_groups.iter().chain(std::iter::once(&end)) { - let [x0, y0, x1, y1, x2, y2, x3, y3] = [pos[0], pos[1], param[0], param[1], sample.handles[0][0], sample.handles[0][1], sample.anchor[0], sample.anchor[1]].map(f64::from); - - let segment = PathSeg::Cubic(CubicBez::new(Point::new(x0, y0), Point::new(x1, y1), Point::new(x2, y2), Point::new(x3, y3))); - - let [left, right] = [pos[0], sample.anchor[0]].map(|c| c.clamp(0., 1.)); - let lut_index_left: usize = (left * (lut.len() - 1) as f32).floor() as _; - let lut_index_right: usize = (right * (lut.len() - 1) as f32).ceil() as _; - for index in lut_index_left..=lut_index_right { - let x = index as f64 / (lut.len() - 1) as f64; - let y = if x <= x0 { - y0 - } else if x >= x3 { - y3 - } else { - pathseg_find_tvalues_for_x(segment, x) - .next() - .map(|t| segment.eval(t.clamp(0., 1.)).y) - // Fall back to a very bad approximation if the above fails - .unwrap_or_else(|| (x - x0) / (x3 - x0) * (y3 - y0) + y0) - }; - lut[index] = C::from_f64(y); - } - - pos = sample.anchor; - param = sample.handles[1]; - } - ValueMapperNode::new(lut) -}