Fix gradient tool

This commit is contained in:
0hypercube
2023-10-17 11:02:06 -07:00
committed by Keavon Chambers
parent 6173662a40
commit 9a39c4a0cc
8 changed files with 159 additions and 113 deletions
+27
View File
@@ -41,6 +41,14 @@ impl DocumentMetadata {
self.all_layers() self.all_layers()
} }
pub fn selected_layers_contains(&self, layer: LayerNodeIdentifier) -> bool {
self.selected_layers().any(|selected| selected == layer)
}
pub fn selected_visible_layers(&self) -> impl Iterator<Item = LayerNodeIdentifier> + '_ {
self.all_layers()
}
/// Access the [`NodeRelations`] of a layer /// Access the [`NodeRelations`] of a layer
fn get_relations(&self, node_identifier: LayerNodeIdentifier) -> Option<&NodeRelations> { fn get_relations(&self, node_identifier: LayerNodeIdentifier) -> Option<&NodeRelations> {
self.structure.get(&node_identifier) self.structure.get(&node_identifier)
@@ -90,12 +98,27 @@ impl DocumentMetadata {
.filter_map(|layer| self.click_targets.get(&layer).map(|targets| (layer, targets))) .filter_map(|layer| self.click_targets.get(&layer).map(|targets| (layer, targets)))
.find(|(layer, target)| target.iter().any(|target: &ClickTarget| target.intersect_point(point, self.transform_from_document(*layer)))) .find(|(layer, target)| target.iter().any(|target: &ClickTarget| target.intersect_point(point, self.transform_from_document(*layer))))
} }
/// Get the bounding box of the click target of the specified layer in the specified transform space
pub fn bounding_box(&self, layer: LayerNodeIdentifier, transform: DAffine2) -> Option<[DVec2; 2]> {
self.click_targets
.get(&layer)?
.iter()
.filter_map(|click_target| click_target.subpath.bounding_box_with_transform(transform))
.reduce(Quad::combine_bounds)
}
} }
/// Id of a layer node /// Id of a layer node
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LayerNodeIdentifier(NonZeroU64); pub struct LayerNodeIdentifier(NonZeroU64);
impl Default for LayerNodeIdentifier {
fn default() -> Self {
Self::ROOT
}
}
impl LayerNodeIdentifier { impl LayerNodeIdentifier {
const ROOT: Self = LayerNodeIdentifier::new_unchecked(0); const ROOT: Self = LayerNodeIdentifier::new_unchecked(0);
@@ -283,6 +306,10 @@ impl LayerNodeIdentifier {
document_metadata.structure.remove(&node); document_metadata.structure.remove(&node);
} }
} }
pub fn exists(&self, document_metadata: &DocumentMetadata) -> bool {
document_metadata.get_relations(*self).is_some()
}
} }
impl From<NodeId> for LayerNodeIdentifier { impl From<NodeId> for LayerNodeIdentifier {
@@ -2,9 +2,10 @@ use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bezier_rs::{ManipulatorGroup, Subpath}; use bezier_rs::{ManipulatorGroup, Subpath};
use document_legacy::{document_metadata::LayerNodeIdentifier, LayerId, Operation}; use document_legacy::{document::Document, document_metadata::LayerNodeIdentifier, LayerId, Operation};
use graph_craft::document::{value::TaggedValue, DocumentNode, NodeId, NodeInput, NodeNetwork}; use graph_craft::document::{value::TaggedValue, DocumentNode, NodeId, NodeInput, NodeNetwork};
use graphene_core::uuid::ManipulatorGroupId; use graphene_core::uuid::ManipulatorGroupId;
use graphene_core::vector::style::{FillType, Gradient};
use glam::DAffine2; use glam::DAffine2;
use std::collections::VecDeque; use std::collections::VecDeque;
@@ -17,6 +18,7 @@ pub fn new_vector_layer(subpaths: Vec<Subpath<ManipulatorGroupId>>, layer_path:
}); });
} }
/// Create a legacy node graph frame TODO: remove
pub fn new_custom_layer(network: NodeNetwork, layer_path: Vec<LayerId>, responses: &mut VecDeque<Message>) { pub fn new_custom_layer(network: NodeNetwork, layer_path: Vec<LayerId>, responses: &mut VecDeque<Message>) {
responses.add(DocumentMessage::DeselectAllLayers); responses.add(DocumentMessage::DeselectAllLayers);
responses.add(Operation::AddFrame { responses.add(Operation::AddFrame {
@@ -28,6 +30,7 @@ pub fn new_custom_layer(network: NodeNetwork, layer_path: Vec<LayerId>, response
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
} }
/// Batch set all of the manipulator groups to mirror on a specific layer
pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<ManipulatorGroupId>], layer_path: &[u64], mirror_angle: bool, responses: &mut VecDeque<Message>) { pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<ManipulatorGroupId>], layer_path: &[u64], mirror_angle: bool, responses: &mut VecDeque<Message>) {
for manipulator_group in manipulator_groups { for manipulator_group in manipulator_groups {
responses.add(GraphOperationMessage::Vector { responses.add(GraphOperationMessage::Vector {
@@ -40,6 +43,64 @@ pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<Manip
} }
} }
/// Locate the subpaths from the shape nodes of a particular layer
pub fn get_subpaths(layer: LayerNodeIdentifier, document: &Document) -> Option<&Vec<Subpath<ManipulatorGroupId>>> {
if let TaggedValue::Subpaths(subpaths) = NodeGraphLayer::new(layer, document)?.find_input("Shape", 0)? {
Some(subpaths)
} else {
None
}
}
/// Get the currently mirrored handles for a particular layer from the shape node
pub fn get_mirror_handles(layer: LayerNodeIdentifier, document: &Document) -> Option<&Vec<ManipulatorGroupId>> {
if let TaggedValue::ManipulatorGroupIds(mirror_handles) = NodeGraphLayer::new(layer, document)?.find_input("Shape", 1)? {
Some(mirror_handles)
} else {
None
}
}
/// Get the current gradient of a layer from the closest fill node
pub fn get_gradient(layer: LayerNodeIdentifier, document: &Document) -> Option<Gradient> {
let inputs = NodeGraphLayer::new(layer, document)?.find_node_inputs("Fill")?;
let TaggedValue::FillType(FillType::Gradient) = inputs.get(1)?.as_value()? else {
return None;
};
let TaggedValue::GradientType(gradient_type) = inputs.get(3)?.as_value()? else {
return None;
};
let TaggedValue::DVec2(start) = inputs.get(4)?.as_value()? else {
return None;
};
let TaggedValue::DVec2(end) = inputs.get(5)?.as_value()? else {
return None;
};
let TaggedValue::DAffine2(transform) = inputs.get(6)?.as_value()? else {
return None;
};
let TaggedValue::GradientPositions(positions) = inputs.get(7)?.as_value()? else {
return None;
};
Some(Gradient {
start: start.clone(),
end: end.clone(),
transform: transform.clone(),
positions: positions.clone(),
gradient_type: gradient_type.clone(),
})
}
/// Convert subpaths to an iterator of manipulator groups
pub fn get_manipulator_groups(subpaths: &[Subpath<ManipulatorGroupId>]) -> impl Iterator<Item = &bezier_rs::ManipulatorGroup<ManipulatorGroupId>> + DoubleEndedIterator {
subpaths.iter().flat_map(|subpath| subpath.manipulator_groups())
}
/// Find a manipulator group with a specific id from several subpaths
pub fn get_manipulator_from_id(subpaths: &[Subpath<ManipulatorGroupId>], id: ManipulatorGroupId) -> Option<&bezier_rs::ManipulatorGroup<ManipulatorGroupId>> {
subpaths.iter().find_map(|subpath| subpath.manipulator_from_id(id))
}
/// An immutable reference to a layer within the document node graph for easy access. /// An immutable reference to a layer within the document node graph for easy access.
pub struct NodeGraphLayer<'a> { pub struct NodeGraphLayer<'a> {
node_graph: &'a NodeNetwork, node_graph: &'a NodeNetwork,
@@ -84,18 +145,18 @@ impl<'a> NodeGraphLayer<'a> {
self.node_graph.primary_flow_from_opt(Some(self.layer_node)) self.node_graph.primary_flow_from_opt(Some(self.layer_node))
} }
/// Find a specific input of a node within the layer's primary flow /// Find all of the inputs of a specific node within the layer's primary flow
pub fn find_input(&self, node_name: &str, index: usize) -> Option<&'a TaggedValue> { pub fn find_node_inputs(&self, node_name: &str) -> Option<&'a Vec<NodeInput>> {
for (node, _id) in self.primary_layer_flow() { for (node, _id) in self.primary_layer_flow() {
if node.name == node_name { if node.name == node_name {
let subpaths_input = node.inputs.get(index)?; return Some(&node.inputs);
let NodeInput::Value { tagged_value, .. } = subpaths_input else {
continue;
};
return Some(tagged_value);
} }
} }
None None
} }
/// Find a specific input of a node within the layer's primary flow
pub fn find_input(&self, node_name: &str, index: usize) -> Option<&'a TaggedValue> {
self.find_node_inputs(node_name)?.get(index)?.as_value()
}
} }
@@ -3,7 +3,7 @@ use crate::application::generate_uuid;
use crate::consts::VIEWPORT_GRID_ROUNDING_BIAS; use crate::consts::VIEWPORT_GRID_ROUNDING_BIAS;
use crate::consts::{COLOR_ACCENT, HIDE_HANDLE_DISTANCE, MANIPULATOR_GROUP_MARKER_SIZE, PATH_OUTLINE_WEIGHT}; use crate::consts::{COLOR_ACCENT, HIDE_HANDLE_DISTANCE, MANIPULATOR_GROUP_MARKER_SIZE, PATH_OUTLINE_WEIGHT};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::tool_messages::pen_tool::{get_manipulator_groups, get_subpaths}; use crate::messages::tool::common_functionality::graph_modification_utils::{get_manipulator_groups, get_subpaths};
use bezier_rs::ManipulatorGroup; use bezier_rs::ManipulatorGroup;
use document_legacy::document::Document; use document_legacy::document::Document;
@@ -1,7 +1,7 @@
use crate::consts::DRAG_THRESHOLD; use crate::consts::DRAG_THRESHOLD;
use crate::messages::portfolio::document::node_graph::VectorDataModification; use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::tool_messages::pen_tool::{get_manipulator_from_id, get_manipulator_groups, get_mirror_handles, get_subpaths}; use crate::messages::tool::common_functionality::graph_modification_utils::{get_manipulator_from_id, get_manipulator_groups, get_mirror_handles, get_subpaths};
use bezier_rs::{Bezier, ManipulatorGroup, TValue}; use bezier_rs::{Bezier, ManipulatorGroup, TValue};
use document_legacy::document::Document; use document_legacy::document::Document;
@@ -1,11 +1,10 @@
use super::tool_prelude::*; use super::tool_prelude::*;
use crate::application::generate_uuid; use crate::application::generate_uuid;
use crate::consts::{COLOR_ACCENT, LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD, SELECTION_TOLERANCE}; use crate::consts::{COLOR_ACCENT, LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD};
use crate::messages::tool::common_functionality::graph_modification_utils::get_gradient;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::intersection::Quad; use document_legacy::document_metadata::LayerNodeIdentifier;
use document_legacy::layers::layer_info::Layer;
use document_legacy::layers::layer_layer::CachedOutputData;
use document_legacy::layers::style::{Fill, Gradient, GradientType, PathStyle, RenderData, Stroke}; use document_legacy::layers::style::{Fill, Gradient, GradientType, PathStyle, RenderData, Stroke};
use document_legacy::LayerId; use document_legacy::LayerId;
use document_legacy::Operation; use document_legacy::Operation;
@@ -115,12 +114,12 @@ enum GradientToolFsmState {
Drawing, Drawing,
} }
/// Computes the transform from gradient space to layer space (where gradient space is 0..1 in layer space) /// Computes the transform from gradient space to viewport space (where gradient space is 0..1)
fn gradient_space_transform(path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> DAffine2 { fn gradient_space_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 {
let bounds = layer.aabb_for_transform(DAffine2::IDENTITY, render_data).unwrap(); let bounds = document.document_legacy.metadata.bounding_box(layer, DAffine2::IDENTITY).unwrap();
let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]); let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
let multiplied = document.document_legacy.multiply_transforms(path).unwrap(); let multiplied = document.document_legacy.metadata.transform_from_viewport(layer);
multiplied * bound_transform multiplied * bound_transform
} }
@@ -131,7 +130,7 @@ pub struct GradientOverlay {
pub handles: [Vec<LayerId>; 2], pub handles: [Vec<LayerId>; 2],
pub line: Vec<LayerId>, pub line: Vec<LayerId>,
pub steps: Vec<Vec<LayerId>>, pub steps: Vec<Vec<LayerId>>,
path: Vec<LayerId>, layer: LayerNodeIdentifier,
transform: DAffine2, transform: DAffine2,
gradient: Gradient, gradient: Gradient,
} }
@@ -174,17 +173,9 @@ impl GradientOverlay {
path path
} }
pub fn new( pub fn new(gradient: Gradient, dragging: Option<GradientDragTarget>, layer: LayerNodeIdentifier, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) -> Self {
fill: &Gradient, let transform = gradient_space_transform(layer, document);
dragging: Option<GradientDragTarget>, let Gradient { start, end, positions, .. } = &gradient;
path: &[LayerId],
layer: &Layer,
document: &DocumentMessageHandler,
responses: &mut VecDeque<Message>,
render_data: &RenderData,
) -> Self {
let transform = gradient_space_transform(path, layer, document, render_data);
let Gradient { start, end, positions, .. } = fill;
let [start, end] = [transform.transform_point2(*start), transform.transform_point2(*end)]; let [start, end] = [transform.transform_point2(*start), transform.transform_point2(*end)];
let line = Self::generate_overlay_line(start, end, responses); let line = Self::generate_overlay_line(start, end, responses);
@@ -197,14 +188,11 @@ impl GradientOverlay {
let create_step = |(index, pos)| Self::generate_overlay_handle(start.lerp(end, pos), responses, dragging == Some(GradientDragTarget::Step(index))); let create_step = |(index, pos)| Self::generate_overlay_handle(start.lerp(end, pos), responses, dragging == Some(GradientDragTarget::Step(index)));
let steps = positions.iter().map(|(pos, _)| *pos).enumerate().filter(not_at_end).map(create_step).collect(); let steps = positions.iter().map(|(pos, _)| *pos).enumerate().filter(not_at_end).map(create_step).collect();
let path = path.to_vec();
let gradient = fill.clone();
Self { Self {
handles, handles,
steps, steps,
line, line,
path, layer,
transform, transform,
gradient, gradient,
} }
@@ -240,17 +228,17 @@ pub enum GradientDragTarget {
/// Contains information about the selected gradient handle /// Contains information about the selected gradient handle
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
struct SelectedGradient { struct SelectedGradient {
path: Vec<LayerId>, layer: LayerNodeIdentifier,
transform: DAffine2, transform: DAffine2,
gradient: Gradient, gradient: Gradient,
dragging: GradientDragTarget, dragging: GradientDragTarget,
} }
impl SelectedGradient { impl SelectedGradient {
pub fn new(gradient: Gradient, path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> Self { pub fn new(gradient: Gradient, layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> Self {
let transform = gradient_space_transform(path, layer, document, render_data); let transform = gradient_space_transform(layer, document);
Self { Self {
path: path.to_vec(), layer,
transform, transform,
gradient, gradient,
dragging: GradientDragTarget::End, dragging: GradientDragTarget::End,
@@ -258,23 +246,23 @@ impl SelectedGradient {
} }
/// Update the selected gradient, checking for removal or change of gradient. /// Update the selected gradient, checking for removal or change of gradient.
pub fn update(gradient: &mut Option<Self>, document: &DocumentMessageHandler, render_data: &RenderData, responses: &mut VecDeque<Message>) { pub fn update(gradient: &mut Option<Self>, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
let Some(inner_gradient) = gradient else { let Some(inner_gradient) = gradient else {
return; return;
}; };
// Clear the gradient if layer deleted // Clear the gradient if layer deleted
let Ok(layer) = document.document_legacy.layer(&inner_gradient.path) else { if !inner_gradient.layer.exists(&document.document_legacy.metadata) {
responses.add(ToolMessage::RefreshToolOptions); responses.add(ToolMessage::RefreshToolOptions);
*gradient = None; *gradient = None;
return; return;
}; };
// Update transform // Update transform
inner_gradient.transform = gradient_space_transform(&inner_gradient.path, layer, document, render_data); inner_gradient.transform = gradient_space_transform(inner_gradient.layer, document);
// Clear if no longer a gradient // Clear if no longer a gradient
let Some(gradient) = layer.style().ok().and_then(|style| style.fill().as_gradient()) else { let Some(gradient) = get_gradient(inner_gradient.layer, &document.document_legacy) else {
responses.add(ToolMessage::RefreshToolOptions); responses.add(ToolMessage::RefreshToolOptions);
*gradient = None; *gradient = None;
return; return;
@@ -340,7 +328,7 @@ impl SelectedGradient {
pub fn render_gradient(&mut self, responses: &mut VecDeque<Message>) { pub fn render_gradient(&mut self, responses: &mut VecDeque<Message>) {
self.gradient.transform = self.transform; self.gradient.transform = self.transform;
let fill = Fill::Gradient(self.gradient.clone()); let fill = Fill::Gradient(self.gradient.clone());
let layer = self.path.clone(); let layer = self.layer.to_path();
responses.add(GraphOperationMessage::FillSet { layer, fill }); responses.add(GraphOperationMessage::FillSet { layer, fill });
} }
} }
@@ -400,20 +388,16 @@ impl Fsm for GradientToolFsmState {
} }
if self != GradientToolFsmState::Drawing { if self != GradientToolFsmState::Drawing {
SelectedGradient::update(&mut tool_data.selected_gradient, document, render_data, responses); SelectedGradient::update(&mut tool_data.selected_gradient, document, responses);
} }
for path in document.selected_visible_layers() { for layer in document.document_legacy.metadata.selected_visible_layers() {
let layer = document.document_legacy.layer(path).unwrap(); if let Some(gradient) = get_gradient(layer, &document.document_legacy) {
if let Ok(Fill::Gradient(gradient)) = layer.style().map(|style| style.fill()) {
let dragging = tool_data let dragging = tool_data
.selected_gradient .selected_gradient
.as_ref() .as_ref()
.and_then(|selected| if selected.path == path { Some(selected.dragging) } else { None }); .and_then(|selected| if selected.layer == layer { Some(selected.dragging) } else { None });
tool_data tool_data.gradient_overlays.push(GradientOverlay::new(gradient, dragging, layer, document, responses))
.gradient_overlays
.push(GradientOverlay::new(gradient, dragging, path, layer, document, responses, render_data))
} }
} }
@@ -439,7 +423,7 @@ impl Fsm for GradientToolFsmState {
// The gradient has only one point and so should become a fill // The gradient has only one point and so should become a fill
if selected_gradient.gradient.positions.len() == 1 { if selected_gradient.gradient.positions.len() == 1 {
let fill = Fill::Solid(selected_gradient.gradient.positions[0].1.unwrap_or(Color::BLACK)); let fill = Fill::Solid(selected_gradient.gradient.positions[0].1.unwrap_or(Color::BLACK));
let layer = selected_gradient.path.clone(); let layer = selected_gradient.layer.to_path();
responses.add(GraphOperationMessage::FillSet { layer, fill }); responses.add(GraphOperationMessage::FillSet { layer, fill });
return self; return self;
} }
@@ -481,18 +465,15 @@ impl Fsm for GradientToolFsmState {
if let Some(index) = gradient.insert_stop(mouse, overlay.transform) { if let Some(index) = gradient.insert_stop(mouse, overlay.transform) {
document.backup_nonmut(responses); document.backup_nonmut(responses);
let layer = document.document_legacy.layer(&overlay.path); let mut selected_gradient = SelectedGradient::new(gradient, overlay.layer, document);
if let Ok(layer) = layer {
let mut selected_gradient = SelectedGradient::new(gradient, &overlay.path, layer, document, render_data);
// Select the new point // Select the new point
selected_gradient.dragging = GradientDragTarget::Step(index); selected_gradient.dragging = GradientDragTarget::Step(index);
// Update the layer fill // Update the layer fill
selected_gradient.render_gradient(responses); selected_gradient.render_gradient(responses);
tool_data.selected_gradient = Some(selected_gradient); tool_data.selected_gradient = Some(selected_gradient);
}
break; break;
} }
@@ -516,7 +497,7 @@ impl Fsm for GradientToolFsmState {
if pos.distance_squared(mouse) < tolerance { if pos.distance_squared(mouse) < tolerance {
dragging = true; dragging = true;
tool_data.selected_gradient = Some(SelectedGradient { tool_data.selected_gradient = Some(SelectedGradient {
path: overlay.path.clone(), layer: overlay.layer.clone(),
transform: overlay.transform, transform: overlay.transform,
gradient: overlay.gradient.clone(), gradient: overlay.gradient.clone(),
dragging: GradientDragTarget::Step(index), dragging: GradientDragTarget::Step(index),
@@ -533,7 +514,7 @@ impl Fsm for GradientToolFsmState {
dragging = true; dragging = true;
start_snap(&mut tool_data.snap_manager, document, input, render_data); start_snap(&mut tool_data.snap_manager, document, input, render_data);
tool_data.selected_gradient = Some(SelectedGradient { tool_data.selected_gradient = Some(SelectedGradient {
path: overlay.path.clone(), layer: overlay.layer.clone(),
transform: overlay.transform, transform: overlay.transform,
gradient: overlay.gradient.clone(), gradient: overlay.gradient.clone(),
dragging: dragging_target, dragging: dragging_target,
@@ -545,34 +526,30 @@ impl Fsm for GradientToolFsmState {
document.backup_nonmut(responses); document.backup_nonmut(responses);
GradientToolFsmState::Drawing GradientToolFsmState::Drawing
} else { } else {
let tolerance = DVec2::splat(SELECTION_TOLERANCE); let selected_layer = document.document_legacy.metadata.click(input.mouse.position);
let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]);
let intersection = document.document_legacy.intersects_quad_root(quad, render_data).pop();
// the intersection is the layer where the gradient is being applied // Apply the gradient to the selected layer
if let Some(intersection) = intersection { if let Some((layer, _)) = selected_layer {
let is_bitmap = document // let is_bitmap = document
.document_legacy // .document_legacy
.layer(&intersection) // .layer(&layer)
.ok() // .ok()
.and_then(|layer| layer.as_layer().ok()) // .and_then(|layer| layer.as_layer().ok())
.map_or(false, |layer| matches!(layer.cached_output_data, CachedOutputData::BlobURL(_) | CachedOutputData::SurfaceId(_))); // .map_or(false, |layer| matches!(layer.cached_output_data, CachedOutputData::BlobURL(_) | CachedOutputData::SurfaceId(_)));
if is_bitmap { // if is_bitmap {
return self; // return self;
} // }
if !document.selected_layers_contains(&intersection) { if !document.document_legacy.metadata.selected_layers_contains(layer) {
let replacement_selected_layers = vec![intersection.clone()]; let replacement_selected_layers = vec![layer.to_path()];
responses.add(DocumentMessage::SetSelectedLayers { replacement_selected_layers }); responses.add(DocumentMessage::SetSelectedLayers { replacement_selected_layers });
} }
let layer = document.document_legacy.layer(&intersection).unwrap();
responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::StartTransaction);
// Use the already existing gradient if it exists // Use the already existing gradient if it exists
let gradient = if let Some(gradient) = layer.style().ok().map(|style| style.fill()).and_then(|fill| fill.as_gradient()) { let gradient = if let Some(gradient) = get_gradient(layer, &document.document_legacy) {
gradient.clone() gradient.clone()
} else { } else {
// Generate a new gradient // Generate a new gradient
@@ -586,7 +563,7 @@ impl Fsm for GradientToolFsmState {
tool_options.gradient_type, tool_options.gradient_type,
) )
}; };
let selected_gradient = SelectedGradient::new(gradient, &intersection, layer, document, render_data).with_gradient_start(input.mouse.position); let selected_gradient = SelectedGradient::new(gradient, layer, document).with_gradient_start(input.mouse.position);
tool_data.selected_gradient = Some(selected_gradient); tool_data.selected_gradient = Some(selected_gradient);
@@ -3,14 +3,11 @@ use crate::consts::LINE_ROTATE_SNAP_ANGLE;
use crate::messages::portfolio::document::node_graph::VectorDataModification; use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::graph_modification_utils::get_subpaths;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::tool::tool_messages::pen_tool::graph_modification_utils::NodeGraphLayer;
use bezier_rs::Subpath;
use document_legacy::document::Document;
use document_legacy::document_metadata::LayerNodeIdentifier; use document_legacy::document_metadata::LayerNodeIdentifier;
use document_legacy::LayerId; use document_legacy::LayerId;
use graph_craft::document::value::TaggedValue;
use graphene_core::uuid::ManipulatorGroupId; use graphene_core::uuid::ManipulatorGroupId;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::vector::{ManipulatorPointId, SelectedType}; use graphene_core::vector::{ManipulatorPointId, SelectedType};
@@ -767,26 +764,3 @@ fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64)
best best
} }
pub fn get_subpaths(layer: LayerNodeIdentifier, document: &Document) -> Option<&Vec<Subpath<ManipulatorGroupId>>> {
if let TaggedValue::Subpaths(subpaths) = NodeGraphLayer::new(layer, document)?.find_input("Shape", 0)? {
Some(subpaths)
} else {
None
}
}
pub fn get_mirror_handles(layer: LayerNodeIdentifier, document: &Document) -> Option<&Vec<ManipulatorGroupId>> {
if let TaggedValue::ManipulatorGroupIds(mirror_handles) = NodeGraphLayer::new(layer, document)?.find_input("Shape", 1)? {
Some(mirror_handles)
} else {
None
}
}
pub fn get_manipulator_groups(subpaths: &[Subpath<ManipulatorGroupId>]) -> impl Iterator<Item = &bezier_rs::ManipulatorGroup<ManipulatorGroupId>> + DoubleEndedIterator {
subpaths.iter().flat_map(|subpath| subpath.manipulator_groups())
}
pub fn get_manipulator_from_id(subpaths: &[Subpath<ManipulatorGroupId>], id: ManipulatorGroupId) -> Option<&bezier_rs::ManipulatorGroup<ManipulatorGroupId>> {
subpaths.iter().find_map(|subpath| subpath.manipulator_from_id(id))
}
@@ -5,7 +5,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use document_legacy::{LayerId, Operation}; use document_legacy::LayerId;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color; use graphene_core::Color;
+7
View File
@@ -239,6 +239,13 @@ impl NodeInput {
NodeInput::Inline(_) => panic!("ty() called on NodeInput::Inline"), NodeInput::Inline(_) => panic!("ty() called on NodeInput::Inline"),
} }
} }
pub fn as_value(&self) -> Option<&TaggedValue> {
if let NodeInput::Value { tagged_value, .. } = self {
Some(tagged_value)
} else {
None
}
}
} }
#[derive(Clone, Debug, PartialEq, Hash, DynAny)] #[derive(Clone, Debug, PartialEq, Hash, DynAny)]