Skip to content

make pen/pencil/spline stroke weight match shape tools and fix stroke weight change behaviour during transformation#3894

Open
krVatsal wants to merge 1 commit intoGraphiteEditor:masterfrom
krVatsal:fix-stroke-weight-inconsistency-in-pen-pencil-spline-clean
Open

make pen/pencil/spline stroke weight match shape tools and fix stroke weight change behaviour during transformation#3894
krVatsal wants to merge 1 commit intoGraphiteEditor:masterfrom
krVatsal:fix-stroke-weight-inconsistency-in-pen-pencil-spline-clean

Conversation

@krVatsal
Copy link
Contributor

Fixes #3893
-Insert Transform before Stroke when creating pen, pencil, and spline layers
-Prevent post stroke transform insertion from changing apparent stroke width
-Fix moved value ownership issue in spline/path node construction

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request standardizes the stroke weight behavior across various drawing tools, specifically pen, pencil, and spline, to ensure they behave consistently with other shape tools. The core change involves reordering graph nodes to apply transformations correctly before stroke rendering, which resolves issues where stroke weights would appear to change unexpectedly during scaling or other transformations. This enhancement improves the predictability and reliability of drawing operations.

Highlights

  • Stroke Weight Consistency: Ensured that the stroke weight for pen, pencil, and spline tools now matches the behavior of shape tools, providing a more consistent user experience.
  • Transformation Behavior Fix: Addressed an issue where changing stroke weight during transformations would lead to incorrect visual results, now ensuring stable stroke appearance.
  • Graph Node Order: Implemented the insertion of a 'Transform' node before the 'Stroke' node in the graph for pen, pencil, and spline layers, which is crucial for the stroke weight fixes.
  • Ownership Issue Resolution: Fixed a moved value ownership problem encountered during the construction of spline and path nodes, improving stability.
Changelog
  • editor/src/messages/tool/tool_messages/freehand_tool.rs
    • Imported NodeInput for use in graph node construction.
    • Modified the creation of new freehand layers to include a Transform node that processes the Path node, ensuring transformations are applied correctly before stroke rendering.
  • editor/src/messages/tool/tool_messages/pen_tool.rs
    • Imported NodeInput for use in graph node construction.
    • Modified the creation of new pen layers to include a Transform node that processes the Path node, aligning with the new stroke weight consistency requirements.
  • editor/src/messages/tool/tool_messages/spline_tool.rs
    • Refactored the creation of new spline layers to introduce a Transform node after the Spline node, which itself takes input from a Path node. This ensures proper transformation handling for spline strokes.
    • Adjusted internal NodeId assignments to reflect the new sequence of graph nodes.
Activity
  • No specific activity (comments, reviews, or progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly adds a Transform node when creating layers with the pen, pencil, and spline tools. This change makes the stroke weight behavior consistent with the shape tools. The implementation is solid, and I've added a few minor suggestions to improve code conciseness and consistency across the modified files.

Comment on lines 295 to +298
let node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let node = node_type.default_node_template();
let nodes = vec![(NodeId(0), node)];
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![(NodeId(1), node), (NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]))];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with other tools and to improve conciseness, you can define the nodes vector directly without creating an intermediate node variable. Renaming node_type to path_node_type would also improve clarity.

Suggested change
let node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let node = node_type.default_node_template();
let nodes = vec![(NodeId(0), node)];
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![(NodeId(1), node), (NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]))];
let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![(NodeId(1), path_node_type.default_node_template()),
(NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]))];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense +1

Comment on lines 1289 to +1294
let node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let nodes = vec![(NodeId(0), node_type.default_node_template())];
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![
(NodeId(1), node_type.default_node_template()),
(NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))])),
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For clarity and consistency with other tools, consider renaming node_type to path_node_type.

Suggested change
let node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let nodes = vec![(NodeId(0), node_type.default_node_template())];
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![
(NodeId(1), node_type.default_node_template()),
(NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))])),
];
let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![
(NodeId(1), path_node_type.default_node_template()),
(NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))])),
];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above , + 1

Comment on lines 396 to +402
let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let path_node = path_node_type.default_node_template();
let spline_node_type = resolve_proto_node_type(graphene_std::vector::spline::IDENTIFIER).expect("Spline node does not exist");
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(1), path_node), (NodeId(0), spline_node)];
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(2), 0))]);
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let transform_node = transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(2), path_node), (NodeId(1), spline_node), (NodeId(0), transform_node)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve conciseness and consistency with other tools, you can define the nodes vector directly without creating intermediate variables for each node template.

Suggested change
let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let path_node = path_node_type.default_node_template();
let spline_node_type = resolve_proto_node_type(graphene_std::vector::spline::IDENTIFIER).expect("Spline node does not exist");
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(1), path_node), (NodeId(0), spline_node)];
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(2), 0))]);
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let transform_node = transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(2), path_node), (NodeId(1), spline_node), (NodeId(0), transform_node)];
let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let spline_node_type = resolve_proto_node_type(graphene_std::vector::spline::IDENTIFIER).expect("Spline node does not exist");
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![
(NodeId(2), path_node_type.default_node_template()),
(NodeId(1), spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(2), 0))])),
(NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]))];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Annonnymmousss

This comment was marked as outdated.

Annonnymmousss

This comment was marked as outdated.

@krVatsal
Copy link
Contributor Author

It reversed the changes which was desired. Ignore the approval.

can you please explain what desired change are you talking about?

Comment on lines 295 to +298
let node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let node = node_type.default_node_template();
let nodes = vec![(NodeId(0), node)];
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![(NodeId(1), node), (NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]))];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense +1

Comment on lines 1289 to +1294
let node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let nodes = vec![(NodeId(0), node_type.default_node_template())];
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let nodes = vec![
(NodeId(1), node_type.default_node_template()),
(NodeId(0), transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))])),
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above , + 1

Comment on lines 396 to +402
let path_node_type = resolve_network_node_type("Path").expect("Path node does not exist");
let path_node = path_node_type.default_node_template();
let spline_node_type = resolve_proto_node_type(graphene_std::vector::spline::IDENTIFIER).expect("Spline node does not exist");
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(1), path_node), (NodeId(0), spline_node)];
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(2), 0))]);
let transform_node_type = resolve_network_node_type("Transform").expect("Transform node does not exist");
let transform_node = transform_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(2), path_node), (NodeId(1), spline_node), (NodeId(0), transform_node)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@krVatsal
Copy link
Contributor Author

was only able to find this bug , let me know when you fix it. I'll review again, thanks

Screen.Recording.2026-03-13.at.11.17.32.PM.mov

Fixed, as it doesn't exist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stroke weight inconsistency between Shape tools and pen/pencil/spline tool

3 participants