mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Fix Brush tool drawing into nested layers (#4487)
* Fix Brush tool drawing into nested layers * Remove hardcoded input indices
This commit is contained in:
@@ -9,8 +9,9 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{NodeId, NodeInput};
|
||||
use graphene_std::Color;
|
||||
use graphene_std::NodeParameter;
|
||||
use graphene_std::brush::basic_brush::basic_brush as active_brush;
|
||||
use graphene_std::brush::{Channel, Stroke};
|
||||
use graphene_std::brush::{Channel, Stroke, brush_strokes};
|
||||
use graphene_std::color::SRGBA8;
|
||||
use graphene_std::vector::style::FillChoice;
|
||||
|
||||
@@ -233,16 +234,16 @@ impl BrushTool {
|
||||
return;
|
||||
};
|
||||
let value = |index: usize| node.inputs.get(index).and_then(|input| input.as_value());
|
||||
if let Some(TaggedValue::F64(diameter)) = value(STROKES_DIAMETER_INPUT) {
|
||||
if let Some(TaggedValue::F64(diameter)) = value(brush_strokes::DiameterInput::INDEX) {
|
||||
self.options.diameter = *diameter;
|
||||
}
|
||||
if let Some(TaggedValue::F64(hardness)) = value(STROKES_HARDNESS_INPUT) {
|
||||
if let Some(TaggedValue::F64(hardness)) = value(brush_strokes::HardnessInput::INDEX) {
|
||||
self.options.hardness = *hardness;
|
||||
}
|
||||
if let Some(TaggedValue::F64(flow)) = value(STROKES_FLOW_INPUT) {
|
||||
if let Some(TaggedValue::F64(flow)) = value(brush_strokes::FlowInput::INDEX) {
|
||||
self.options.flow = *flow;
|
||||
}
|
||||
if let Some(TaggedValue::Color(color)) = value(STROKES_COLOR_INPUT)
|
||||
if let Some(TaggedValue::Color(color)) = value(brush_strokes::ColorInput::INDEX)
|
||||
&& *color != self.options.active_color()
|
||||
{
|
||||
responses.add(ToolMessage::SelectWorkingColor { color: *color, primary: true });
|
||||
@@ -252,11 +253,6 @@ impl BrushTool {
|
||||
}
|
||||
}
|
||||
|
||||
const STROKES_COLOR_INPUT: usize = 1;
|
||||
const STROKES_DIAMETER_INPUT: usize = 2;
|
||||
const STROKES_HARDNESS_INPUT: usize = 3;
|
||||
const STROKES_FLOW_INPUT: usize = 4;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct BrushToolData {
|
||||
stroke: Stroke,
|
||||
@@ -292,12 +288,13 @@ impl BrushToolData {
|
||||
}
|
||||
|
||||
let parent = selected_layer.parent(document.metadata()).filter(|&parent| parent != LayerNodeIdentifier::ROOT_PARENT)?;
|
||||
if !self.load_brush_layer(document, parent) {
|
||||
return None;
|
||||
}
|
||||
let brush_layer = parent
|
||||
.ancestors(document.metadata())
|
||||
.take_while(|&ancestor| ancestor != LayerNodeIdentifier::ROOT_PARENT)
|
||||
.find(|&ancestor| self.load_brush_layer(document, ancestor))?;
|
||||
|
||||
let Some(output) = document.network_interface.upstream_output_connector(&InputConnector::node_at_index(selected_layer.to_node(), 1), &[]) else {
|
||||
return Some((parent, BrushTarget::FillEmpty { layer: selected_layer }));
|
||||
return Some((brush_layer, BrushTarget::FillEmpty { layer: selected_layer }));
|
||||
};
|
||||
|
||||
let new_group = || {
|
||||
@@ -305,22 +302,22 @@ impl BrushToolData {
|
||||
BrushTarget::NewGroup { parent, insert_index }
|
||||
};
|
||||
let OutputConnector::Node { node_id: strokes_node_id, .. } = output else {
|
||||
return Some((parent, new_group()));
|
||||
return Some((brush_layer, new_group()));
|
||||
};
|
||||
if document.network_interface.reference(&strokes_node_id, &[]) != Some(DefinitionIdentifier::ProtoNode(graphene_std::brush::brush_strokes::IDENTIFIER)) {
|
||||
return Some((parent, new_group()));
|
||||
if document.network_interface.reference(&strokes_node_id, &[]) != Some(DefinitionIdentifier::ProtoNode(brush_strokes::IDENTIFIER)) {
|
||||
return Some((brush_layer, new_group()));
|
||||
}
|
||||
let strokes = document
|
||||
.network_interface
|
||||
.document_network()
|
||||
.nodes
|
||||
.get(&strokes_node_id)
|
||||
.and_then(|node| node.inputs.first())
|
||||
.and_then(|node| node.inputs.get(brush_strokes::StrokesInput::INDEX))
|
||||
.and_then(|input| input.as_value())
|
||||
.and_then(|value| if let TaggedValue::Strokes(strokes) = value { Some(strokes.clone()) } else { None });
|
||||
match strokes {
|
||||
Some(strokes) if Self::style_matches(document, strokes_node_id, options) => Some((parent, BrushTarget::Existing { strokes_node_id, strokes })),
|
||||
_ => Some((parent, new_group())),
|
||||
Some(strokes) if Self::style_matches(document, strokes_node_id, options) => Some((brush_layer, BrushTarget::Existing { strokes_node_id, strokes })),
|
||||
_ => Some((brush_layer, new_group())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,10 +351,10 @@ impl BrushToolData {
|
||||
return false;
|
||||
};
|
||||
let value = |index: usize| node.inputs.get(index).and_then(|input| input.as_value());
|
||||
matches!(value(STROKES_COLOR_INPUT), Some(TaggedValue::Color(color)) if *color == options.active_color())
|
||||
&& matches!(value(STROKES_DIAMETER_INPUT), Some(TaggedValue::F64(diameter)) if *diameter == options.diameter)
|
||||
&& matches!(value(STROKES_HARDNESS_INPUT), Some(TaggedValue::F64(hardness)) if *hardness == options.hardness)
|
||||
&& matches!(value(STROKES_FLOW_INPUT), Some(TaggedValue::F64(flow)) if *flow == options.flow)
|
||||
matches!(value(brush_strokes::ColorInput::INDEX), Some(TaggedValue::Color(color)) if *color == options.active_color())
|
||||
&& matches!(value(brush_strokes::DiameterInput::INDEX), Some(TaggedValue::F64(diameter)) if *diameter == options.diameter)
|
||||
&& matches!(value(brush_strokes::HardnessInput::INDEX), Some(TaggedValue::F64(hardness)) if *hardness == options.hardness)
|
||||
&& matches!(value(brush_strokes::FlowInput::INDEX), Some(TaggedValue::F64(flow)) if *flow == options.flow)
|
||||
}
|
||||
|
||||
fn push_sample(&mut self, position: DVec2, pressure: Option<f64>, elapsed_milliseconds: f64) {
|
||||
@@ -376,7 +373,7 @@ impl BrushToolData {
|
||||
strokes.push(self.stroke.clone());
|
||||
responses.add(NodeGraphMessage::SetInputValue {
|
||||
node_id: stroke_node_id,
|
||||
input_index: 0,
|
||||
input_index: brush_strokes::StrokesInput::INDEX,
|
||||
value: TaggedValue::Strokes(strokes).into(),
|
||||
});
|
||||
}
|
||||
@@ -562,7 +559,11 @@ fn selected_strokes_node(document: &DocumentMessageHandler) -> Option<NodeId> {
|
||||
selected_layer.children(document.metadata()).next()?
|
||||
} else {
|
||||
let parent = selected_layer.parent(document.metadata()).filter(|&parent| parent != LayerNodeIdentifier::ROOT_PARENT)?;
|
||||
if !is_brush_layer(document, parent) {
|
||||
if !parent
|
||||
.ancestors(document.metadata())
|
||||
.take_while(|&ancestor| ancestor != LayerNodeIdentifier::ROOT_PARENT)
|
||||
.any(|ancestor| is_brush_layer(document, ancestor))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
selected_layer
|
||||
@@ -571,7 +572,7 @@ fn selected_strokes_node(document: &DocumentMessageHandler) -> Option<NodeId> {
|
||||
let OutputConnector::Node { node_id, .. } = document.network_interface.upstream_output_connector(&InputConnector::node_at_index(group.to_node(), 1), &[])? else {
|
||||
return None;
|
||||
};
|
||||
(document.network_interface.reference(&node_id, &[]) == Some(DefinitionIdentifier::ProtoNode(graphene_std::brush::brush_strokes::IDENTIFIER))).then_some(node_id)
|
||||
(document.network_interface.reference(&node_id, &[]) == Some(DefinitionIdentifier::ProtoNode(brush_strokes::IDENTIFIER))).then_some(node_id)
|
||||
}
|
||||
|
||||
fn is_brush_layer(document: &DocumentMessageHandler, candidate: LayerNodeIdentifier) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user