Fix gradient tool
This commit is contained in:
parent
6173662a40
commit
9a39c4a0cc
|
|
@ -41,6 +41,14 @@ impl DocumentMetadata {
|
|||
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
|
||||
fn get_relations(&self, node_identifier: LayerNodeIdentifier) -> Option<&NodeRelations> {
|
||||
self.structure.get(&node_identifier)
|
||||
|
|
@ -90,12 +98,27 @@ impl DocumentMetadata {
|
|||
.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))))
|
||||
}
|
||||
|
||||
/// 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
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct LayerNodeIdentifier(NonZeroU64);
|
||||
|
||||
impl Default for LayerNodeIdentifier {
|
||||
fn default() -> Self {
|
||||
Self::ROOT
|
||||
}
|
||||
}
|
||||
|
||||
impl LayerNodeIdentifier {
|
||||
const ROOT: Self = LayerNodeIdentifier::new_unchecked(0);
|
||||
|
||||
|
|
@ -283,6 +306,10 @@ impl LayerNodeIdentifier {
|
|||
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 {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ use crate::messages::portfolio::document::node_graph::VectorDataModification;
|
|||
use crate::messages::prelude::*;
|
||||
|
||||
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 graphene_core::uuid::ManipulatorGroupId;
|
||||
use graphene_core::vector::style::{FillType, Gradient};
|
||||
|
||||
use glam::DAffine2;
|
||||
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>) {
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
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 });
|
||||
}
|
||||
|
||||
/// 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>) {
|
||||
for manipulator_group in manipulator_groups {
|
||||
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.
|
||||
pub struct NodeGraphLayer<'a> {
|
||||
node_graph: &'a NodeNetwork,
|
||||
|
|
@ -84,18 +145,18 @@ impl<'a> NodeGraphLayer<'a> {
|
|||
self.node_graph.primary_flow_from_opt(Some(self.layer_node))
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
/// Find all of the inputs of a specific node within the layer's primary flow
|
||||
pub fn find_node_inputs(&self, node_name: &str) -> Option<&'a Vec<NodeInput>> {
|
||||
for (node, _id) in self.primary_layer_flow() {
|
||||
if node.name == node_name {
|
||||
let subpaths_input = node.inputs.get(index)?;
|
||||
let NodeInput::Value { tagged_value, .. } = subpaths_input else {
|
||||
continue;
|
||||
};
|
||||
|
||||
return Some(tagged_value);
|
||||
return Some(&node.inputs);
|
||||
}
|
||||
}
|
||||
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::{COLOR_ACCENT, HIDE_HANDLE_DISTANCE, MANIPULATOR_GROUP_MARKER_SIZE, PATH_OUTLINE_WEIGHT};
|
||||
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 document_legacy::document::Document;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::consts::DRAG_THRESHOLD;
|
||||
use crate::messages::portfolio::document::node_graph::VectorDataModification;
|
||||
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 document_legacy::document::Document;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use super::tool_prelude::*;
|
||||
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 document_legacy::intersection::Quad;
|
||||
use document_legacy::layers::layer_info::Layer;
|
||||
use document_legacy::layers::layer_layer::CachedOutputData;
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use document_legacy::layers::style::{Fill, Gradient, GradientType, PathStyle, RenderData, Stroke};
|
||||
use document_legacy::LayerId;
|
||||
use document_legacy::Operation;
|
||||
|
|
@ -115,12 +114,12 @@ enum GradientToolFsmState {
|
|||
Drawing,
|
||||
}
|
||||
|
||||
/// Computes the transform from gradient space to layer space (where gradient space is 0..1 in layer space)
|
||||
fn gradient_space_transform(path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> DAffine2 {
|
||||
let bounds = layer.aabb_for_transform(DAffine2::IDENTITY, render_data).unwrap();
|
||||
/// Computes the transform from gradient space to viewport space (where gradient space is 0..1)
|
||||
fn gradient_space_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 {
|
||||
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 multiplied = document.document_legacy.multiply_transforms(path).unwrap();
|
||||
let multiplied = document.document_legacy.metadata.transform_from_viewport(layer);
|
||||
|
||||
multiplied * bound_transform
|
||||
}
|
||||
|
|
@ -131,7 +130,7 @@ pub struct GradientOverlay {
|
|||
pub handles: [Vec<LayerId>; 2],
|
||||
pub line: Vec<LayerId>,
|
||||
pub steps: Vec<Vec<LayerId>>,
|
||||
path: Vec<LayerId>,
|
||||
layer: LayerNodeIdentifier,
|
||||
transform: DAffine2,
|
||||
gradient: Gradient,
|
||||
}
|
||||
|
|
@ -174,17 +173,9 @@ impl GradientOverlay {
|
|||
path
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
fill: &Gradient,
|
||||
dragging: Option<GradientDragTarget>,
|
||||
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;
|
||||
pub fn new(gradient: Gradient, dragging: Option<GradientDragTarget>, layer: LayerNodeIdentifier, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) -> Self {
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
let Gradient { start, end, positions, .. } = &gradient;
|
||||
let [start, end] = [transform.transform_point2(*start), transform.transform_point2(*end)];
|
||||
|
||||
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 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 {
|
||||
handles,
|
||||
steps,
|
||||
line,
|
||||
path,
|
||||
layer,
|
||||
transform,
|
||||
gradient,
|
||||
}
|
||||
|
|
@ -240,17 +228,17 @@ pub enum GradientDragTarget {
|
|||
/// Contains information about the selected gradient handle
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct SelectedGradient {
|
||||
path: Vec<LayerId>,
|
||||
layer: LayerNodeIdentifier,
|
||||
transform: DAffine2,
|
||||
gradient: Gradient,
|
||||
dragging: GradientDragTarget,
|
||||
}
|
||||
|
||||
impl SelectedGradient {
|
||||
pub fn new(gradient: Gradient, path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> Self {
|
||||
let transform = gradient_space_transform(path, layer, document, render_data);
|
||||
pub fn new(gradient: Gradient, layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> Self {
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
Self {
|
||||
path: path.to_vec(),
|
||||
layer,
|
||||
transform,
|
||||
gradient,
|
||||
dragging: GradientDragTarget::End,
|
||||
|
|
@ -258,23 +246,23 @@ impl SelectedGradient {
|
|||
}
|
||||
|
||||
/// 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 {
|
||||
return;
|
||||
};
|
||||
|
||||
// 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);
|
||||
*gradient = None;
|
||||
return;
|
||||
};
|
||||
|
||||
// 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
|
||||
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);
|
||||
*gradient = None;
|
||||
return;
|
||||
|
|
@ -340,7 +328,7 @@ impl SelectedGradient {
|
|||
pub fn render_gradient(&mut self, responses: &mut VecDeque<Message>) {
|
||||
self.gradient.transform = self.transform;
|
||||
let fill = Fill::Gradient(self.gradient.clone());
|
||||
let layer = self.path.clone();
|
||||
let layer = self.layer.to_path();
|
||||
responses.add(GraphOperationMessage::FillSet { layer, fill });
|
||||
}
|
||||
}
|
||||
|
|
@ -400,20 +388,16 @@ impl Fsm for GradientToolFsmState {
|
|||
}
|
||||
|
||||
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() {
|
||||
let layer = document.document_legacy.layer(path).unwrap();
|
||||
|
||||
if let Ok(Fill::Gradient(gradient)) = layer.style().map(|style| style.fill()) {
|
||||
for layer in document.document_legacy.metadata.selected_visible_layers() {
|
||||
if let Some(gradient) = get_gradient(layer, &document.document_legacy) {
|
||||
let dragging = tool_data
|
||||
.selected_gradient
|
||||
.as_ref()
|
||||
.and_then(|selected| if selected.path == path { Some(selected.dragging) } else { None });
|
||||
tool_data
|
||||
.gradient_overlays
|
||||
.push(GradientOverlay::new(gradient, dragging, path, layer, document, responses, render_data))
|
||||
.and_then(|selected| if selected.layer == layer { Some(selected.dragging) } else { None });
|
||||
tool_data.gradient_overlays.push(GradientOverlay::new(gradient, dragging, layer, document, responses))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +423,7 @@ impl Fsm for GradientToolFsmState {
|
|||
// The gradient has only one point and so should become a fill
|
||||
if selected_gradient.gradient.positions.len() == 1 {
|
||||
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 });
|
||||
return self;
|
||||
}
|
||||
|
|
@ -481,18 +465,15 @@ impl Fsm for GradientToolFsmState {
|
|||
if let Some(index) = gradient.insert_stop(mouse, overlay.transform) {
|
||||
document.backup_nonmut(responses);
|
||||
|
||||
let layer = document.document_legacy.layer(&overlay.path);
|
||||
if let Ok(layer) = layer {
|
||||
let mut selected_gradient = SelectedGradient::new(gradient, &overlay.path, layer, document, render_data);
|
||||
let mut selected_gradient = SelectedGradient::new(gradient, overlay.layer, document);
|
||||
|
||||
// Select the new point
|
||||
selected_gradient.dragging = GradientDragTarget::Step(index);
|
||||
// Select the new point
|
||||
selected_gradient.dragging = GradientDragTarget::Step(index);
|
||||
|
||||
// Update the layer fill
|
||||
selected_gradient.render_gradient(responses);
|
||||
// Update the layer fill
|
||||
selected_gradient.render_gradient(responses);
|
||||
|
||||
tool_data.selected_gradient = Some(selected_gradient);
|
||||
}
|
||||
tool_data.selected_gradient = Some(selected_gradient);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -516,7 +497,7 @@ impl Fsm for GradientToolFsmState {
|
|||
if pos.distance_squared(mouse) < tolerance {
|
||||
dragging = true;
|
||||
tool_data.selected_gradient = Some(SelectedGradient {
|
||||
path: overlay.path.clone(),
|
||||
layer: overlay.layer.clone(),
|
||||
transform: overlay.transform,
|
||||
gradient: overlay.gradient.clone(),
|
||||
dragging: GradientDragTarget::Step(index),
|
||||
|
|
@ -533,7 +514,7 @@ impl Fsm for GradientToolFsmState {
|
|||
dragging = true;
|
||||
start_snap(&mut tool_data.snap_manager, document, input, render_data);
|
||||
tool_data.selected_gradient = Some(SelectedGradient {
|
||||
path: overlay.path.clone(),
|
||||
layer: overlay.layer.clone(),
|
||||
transform: overlay.transform,
|
||||
gradient: overlay.gradient.clone(),
|
||||
dragging: dragging_target,
|
||||
|
|
@ -545,34 +526,30 @@ impl Fsm for GradientToolFsmState {
|
|||
document.backup_nonmut(responses);
|
||||
GradientToolFsmState::Drawing
|
||||
} else {
|
||||
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
|
||||
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();
|
||||
let selected_layer = document.document_legacy.metadata.click(input.mouse.position);
|
||||
|
||||
// the intersection is the layer where the gradient is being applied
|
||||
if let Some(intersection) = intersection {
|
||||
let is_bitmap = document
|
||||
.document_legacy
|
||||
.layer(&intersection)
|
||||
.ok()
|
||||
.and_then(|layer| layer.as_layer().ok())
|
||||
.map_or(false, |layer| matches!(layer.cached_output_data, CachedOutputData::BlobURL(_) | CachedOutputData::SurfaceId(_)));
|
||||
if is_bitmap {
|
||||
return self;
|
||||
}
|
||||
// Apply the gradient to the selected layer
|
||||
if let Some((layer, _)) = selected_layer {
|
||||
// let is_bitmap = document
|
||||
// .document_legacy
|
||||
// .layer(&layer)
|
||||
// .ok()
|
||||
// .and_then(|layer| layer.as_layer().ok())
|
||||
// .map_or(false, |layer| matches!(layer.cached_output_data, CachedOutputData::BlobURL(_) | CachedOutputData::SurfaceId(_)));
|
||||
// if is_bitmap {
|
||||
// return self;
|
||||
// }
|
||||
|
||||
if !document.selected_layers_contains(&intersection) {
|
||||
let replacement_selected_layers = vec![intersection.clone()];
|
||||
if !document.document_legacy.metadata.selected_layers_contains(layer) {
|
||||
let replacement_selected_layers = vec![layer.to_path()];
|
||||
|
||||
responses.add(DocumentMessage::SetSelectedLayers { replacement_selected_layers });
|
||||
}
|
||||
|
||||
let layer = document.document_legacy.layer(&intersection).unwrap();
|
||||
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
// 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()
|
||||
} else {
|
||||
// Generate a new gradient
|
||||
|
|
@ -586,7 +563,7 @@ impl Fsm for GradientToolFsmState {
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,11 @@ use crate::consts::LINE_ROTATE_SNAP_ANGLE;
|
|||
use crate::messages::portfolio::document::node_graph::VectorDataModification;
|
||||
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::get_subpaths;
|
||||
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::LayerId;
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graphene_core::uuid::ManipulatorGroupId;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::vector::{ManipulatorPointId, SelectedType};
|
||||
|
|
@ -767,26 +764,3 @@ fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64)
|
|||
|
||||
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::snapping::SnapManager;
|
||||
|
||||
use document_legacy::{LayerId, Operation};
|
||||
use document_legacy::LayerId;
|
||||
use graphene_core::vector::style::{Fill, Stroke};
|
||||
use graphene_core::Color;
|
||||
|
||||
|
|
|
|||
|
|
@ -239,6 +239,13 @@ impl NodeInput {
|
|||
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)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue