mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
Disable the Brush tool by default and add it to preferences under experimental
This commit is contained in:
parent
68a9bbced0
commit
90c91db550
7 changed files with 114 additions and 58 deletions
|
|
@ -89,7 +89,6 @@ impl PreferencesDialogMessageHandler {
|
|||
.tooltip_label("Zoom with Scroll")
|
||||
.tooltip_description(zoom_with_scroll_description)
|
||||
.for_checkbox(checkbox_id)
|
||||
.table_align(true)
|
||||
.widget_instance(),
|
||||
];
|
||||
|
||||
|
|
@ -102,7 +101,10 @@ impl PreferencesDialogMessageHandler {
|
|||
let selection_label = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
TextLabel::new("Selection").widget_instance(),
|
||||
TextLabel::new("Selection")
|
||||
.tooltip_label("Selection")
|
||||
.tooltip_description("Choose how targets are selected within dragged rectangular and lasso areas.")
|
||||
.widget_instance(),
|
||||
];
|
||||
|
||||
let selection_mode = RadioInput::new(vec![
|
||||
|
|
@ -151,7 +153,7 @@ impl PreferencesDialogMessageHandler {
|
|||
|
||||
let experimental_header = vec![TextLabel::new("Experimental").italic(true).widget_instance()];
|
||||
|
||||
let node_graph_section_description = "Appearance of the wires running between node connections in the graph.";
|
||||
let node_graph_section_description = "Configure the appearance of the wires running between node connections in the graph.";
|
||||
let node_graph_wires_label = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
|
|
@ -181,13 +183,18 @@ impl PreferencesDialogMessageHandler {
|
|||
];
|
||||
|
||||
let checkbox_id = CheckboxId::new();
|
||||
let vello_description = "Use the experimental Vello renderer. (Your browser must support WebGPU).";
|
||||
let vello_description = "Use the experimental Vello renderer instead of SVG-based rendering.".to_string();
|
||||
#[cfg(target_family = "wasm")]
|
||||
let mut vello_description = vello_description;
|
||||
#[cfg(target_family = "wasm")]
|
||||
vello_description.push_str("\n\n(Your browser must support WebGPU.)");
|
||||
|
||||
let use_vello = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
CheckboxInput::new(preferences.use_vello && preferences.supports_wgpu())
|
||||
.tooltip_label("Vello Renderer")
|
||||
.tooltip_description(vello_description)
|
||||
.tooltip_description(vello_description.clone())
|
||||
.disabled(!preferences.supports_wgpu())
|
||||
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::UseVello { use_vello: checkbox_input.checked }.into())
|
||||
.for_label(checkbox_id)
|
||||
|
|
@ -197,14 +204,14 @@ impl PreferencesDialogMessageHandler {
|
|||
.tooltip_description(vello_description)
|
||||
.disabled(!preferences.supports_wgpu())
|
||||
.for_checkbox(checkbox_id)
|
||||
.table_align(true)
|
||||
.widget_instance(),
|
||||
];
|
||||
|
||||
let checkbox_id = CheckboxId::new();
|
||||
let vector_mesh_description = "
|
||||
Allow tools to produce vector meshes, where more than two segments can connect to an anchor point.\n\
|
||||
Currently this does not properly handle stroke joins and fills.
|
||||
Allow the Pen tool to produce branching geometry, where more than two segments may be connected to one anchor point.\n\
|
||||
\n\
|
||||
Currently, vector meshes do not properly render strokes (branching joins) and fills (multiple regions).
|
||||
"
|
||||
.trim();
|
||||
let vector_meshes = vec![
|
||||
|
|
@ -220,23 +227,58 @@ impl PreferencesDialogMessageHandler {
|
|||
.tooltip_label("Vector Meshes")
|
||||
.tooltip_description(vector_mesh_description)
|
||||
.for_checkbox(checkbox_id)
|
||||
.table_align(true)
|
||||
.widget_instance(),
|
||||
];
|
||||
|
||||
let checkbox_id = CheckboxId::new();
|
||||
let brush_tool_description = "
|
||||
Enable the Brush tool to support basic raster-based layer painting.\n\
|
||||
\n\
|
||||
This legacy tool has performance and quality limitations and is slated for replacement in future versions of Graphite that will focus on raster graphics editing.
|
||||
"
|
||||
.trim();
|
||||
let brush_tool = vec![
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
||||
CheckboxInput::new(preferences.brush_tool)
|
||||
.tooltip_label("Brush Tool")
|
||||
.tooltip_description(brush_tool_description)
|
||||
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::BrushTool { enabled: checkbox_input.checked }.into())
|
||||
.for_label(checkbox_id)
|
||||
.widget_instance(),
|
||||
TextLabel::new("Brush Tool")
|
||||
.tooltip_label("Brush Tool")
|
||||
.tooltip_description(brush_tool_description)
|
||||
.for_checkbox(checkbox_id)
|
||||
.widget_instance(),
|
||||
];
|
||||
|
||||
Layout(vec![
|
||||
// NAVIGATION
|
||||
LayoutGroup::Row { widgets: navigation_header },
|
||||
// Navigation: Zoom Rate
|
||||
LayoutGroup::Row { widgets: zoom_rate_label },
|
||||
LayoutGroup::Row { widgets: zoom_rate },
|
||||
// Navigation: Zoom with Scroll
|
||||
LayoutGroup::Row { widgets: zoom_with_scroll },
|
||||
//
|
||||
// EDITING
|
||||
LayoutGroup::Row { widgets: editing_header },
|
||||
// Editing: Selection
|
||||
LayoutGroup::Row { widgets: selection_label },
|
||||
LayoutGroup::Row { widgets: selection_mode },
|
||||
//
|
||||
// EXPERIMENTAL
|
||||
LayoutGroup::Row { widgets: experimental_header },
|
||||
// Experimental: Node Graph Wires
|
||||
LayoutGroup::Row { widgets: node_graph_wires_label },
|
||||
LayoutGroup::Row { widgets: graph_wire_style },
|
||||
// Experimental: Vello Renderer
|
||||
LayoutGroup::Row { widgets: use_vello },
|
||||
// Experimental: Vector Meshes
|
||||
LayoutGroup::Row { widgets: vector_meshes },
|
||||
// Experimental: Brush Tool
|
||||
LayoutGroup::Row { widgets: brush_tool },
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub enum PreferencesMessage {
|
|||
UseVello { use_vello: bool },
|
||||
SelectionMode { selection_mode: SelectionMode },
|
||||
VectorMeshes { enabled: bool },
|
||||
BrushTool { enabled: bool },
|
||||
ModifyLayout { zoom_with_scroll: bool },
|
||||
GraphWireStyle { style: GraphWireStyle },
|
||||
ViewportZoomWheelRate { rate: f64 },
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ pub struct PreferencesMessageHandler {
|
|||
pub zoom_with_scroll: bool,
|
||||
pub use_vello: bool,
|
||||
pub vector_meshes: bool,
|
||||
pub brush_tool: bool,
|
||||
pub graph_wire_style: GraphWireStyle,
|
||||
pub viewport_zoom_wheel_rate: f64,
|
||||
}
|
||||
|
|
@ -38,6 +39,7 @@ impl Default for PreferencesMessageHandler {
|
|||
zoom_with_scroll: matches!(MappingVariant::default(), MappingVariant::ZoomWithScroll),
|
||||
use_vello: EditorPreferences::default().use_vello,
|
||||
vector_meshes: false,
|
||||
brush_tool: false,
|
||||
graph_wire_style: GraphWireStyle::default(),
|
||||
viewport_zoom_wheel_rate: VIEWPORT_ZOOM_WHEEL_RATE,
|
||||
}
|
||||
|
|
@ -76,6 +78,10 @@ impl MessageHandler<PreferencesMessage, ()> for PreferencesMessageHandler {
|
|||
PreferencesMessage::VectorMeshes { enabled } => {
|
||||
self.vector_meshes = enabled;
|
||||
}
|
||||
PreferencesMessage::BrushTool { enabled } => {
|
||||
self.brush_tool = enabled;
|
||||
responses.add(ToolMessage::RefreshToolShelf);
|
||||
}
|
||||
PreferencesMessage::ModifyLayout { zoom_with_scroll } => {
|
||||
self.zoom_with_scroll = zoom_with_scroll;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ pub enum ToolMessage {
|
|||
PreUndo,
|
||||
Redo,
|
||||
RefreshToolOptions,
|
||||
RefreshToolShelf,
|
||||
ResetColors,
|
||||
SelectWorkingColor {
|
||||
color: Color,
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ impl MessageHandler<ToolMessage, ToolMessageContext<'_>> for ToolMessageHandler
|
|||
let tool_type = tool_type.get_tool();
|
||||
|
||||
responses.add(ToolMessage::RefreshToolOptions);
|
||||
tool_data.send_layout(responses, LayoutTarget::ToolShelf);
|
||||
responses.add(ToolMessage::RefreshToolShelf);
|
||||
|
||||
// Do nothing if switching to the same tool
|
||||
if self.tool_is_active && tool_type == old_tool {
|
||||
|
|
@ -176,7 +176,7 @@ impl MessageHandler<ToolMessage, ToolMessageContext<'_>> for ToolMessageHandler
|
|||
responses.add(ToolMessage::RefreshToolOptions);
|
||||
|
||||
// Notify the frontend about the new active tool to be displayed
|
||||
tool_data.send_layout(responses, LayoutTarget::ToolShelf);
|
||||
responses.add(ToolMessage::RefreshToolShelf);
|
||||
}
|
||||
ToolMessage::DeactivateTools => {
|
||||
let tool_data = &mut self.tool_state.tool_data;
|
||||
|
|
@ -220,7 +220,7 @@ impl MessageHandler<ToolMessage, ToolMessageContext<'_>> for ToolMessageHandler
|
|||
tool_data.tools.get(active_tool).unwrap().send_layout(responses, LayoutTarget::ToolOptions);
|
||||
|
||||
// Notify the frontend about the initial active tool
|
||||
tool_data.send_layout(responses, LayoutTarget::ToolShelf);
|
||||
tool_data.send_layout(responses, LayoutTarget::ToolShelf, preferences.brush_tool);
|
||||
|
||||
// Notify the frontend about the initial working colors
|
||||
document_data.update_working_colors(responses);
|
||||
|
|
@ -259,6 +259,10 @@ impl MessageHandler<ToolMessage, ToolMessageContext<'_>> for ToolMessageHandler
|
|||
let tool_data = &mut self.tool_state.tool_data;
|
||||
tool_data.tools.get(&tool_data.active_tool_type).unwrap().send_layout(responses, LayoutTarget::ToolOptions);
|
||||
}
|
||||
ToolMessage::RefreshToolShelf => {
|
||||
let tool_data = &mut self.tool_state.tool_data;
|
||||
tool_data.send_layout(responses, LayoutTarget::ToolShelf, preferences.brush_tool);
|
||||
}
|
||||
ToolMessage::ResetColors => {
|
||||
let document_data = &mut self.tool_state.document_tool_data;
|
||||
|
||||
|
|
|
|||
|
|
@ -231,8 +231,15 @@ impl ToolData {
|
|||
}
|
||||
}
|
||||
|
||||
impl LayoutHolder for ToolData {
|
||||
fn layout(&self) -> Layout {
|
||||
impl ToolData {
|
||||
pub fn send_layout(&self, responses: &mut VecDeque<Message>, layout_target: LayoutTarget, brush_tool: bool) {
|
||||
responses.add(LayoutMessage::SendLayout {
|
||||
layout: self.layout(brush_tool),
|
||||
layout_target,
|
||||
});
|
||||
}
|
||||
|
||||
fn layout(&self, brush_tool: bool) -> Layout {
|
||||
let active_tool = self.active_shape_type.unwrap_or(self.active_tool_type);
|
||||
|
||||
let tool_groups_layout = list_tools_in_groups()
|
||||
|
|
@ -240,22 +247,26 @@ impl LayoutHolder for ToolData {
|
|||
.map(|tool_group|
|
||||
tool_group
|
||||
.iter()
|
||||
.map(|tool_availability| {
|
||||
match tool_availability {
|
||||
ToolAvailability::Available(tool) =>
|
||||
.filter_map(|tool_availability| {
|
||||
if !brush_tool && let ToolRole::Normal(tool) = tool_availability && tool.tool_type() == ToolType::Brush {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(match tool_availability {
|
||||
ToolRole::Normal(tool) =>
|
||||
ToolEntry::new(tool.tool_type(), tool.icon_name())
|
||||
.tooltip_label(tool.tooltip_label())
|
||||
.tooltip_shortcut(action_shortcut!(tool_type_to_activate_tool_message(tool.tool_type()))),
|
||||
ToolAvailability::AvailableAsShape(shape) =>
|
||||
ToolRole::Shape(shape) =>
|
||||
ToolEntry::new(shape.tool_type(), shape.icon_name())
|
||||
.tooltip_label(shape.tooltip_label())
|
||||
.tooltip_description(shape.tooltip_description())
|
||||
.tooltip_shortcut(action_shortcut!(tool_type_to_activate_tool_message(shape.tool_type()))),
|
||||
// ToolAvailability::ComingSoon(tool) => tool.clone(),
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
.filter(|group| !group.is_empty())
|
||||
.flat_map(|group| {
|
||||
let separator = std::iter::once(Separator::new(SeparatorType::Section).direction(SeparatorDirection::Vertical).widget_instance());
|
||||
let buttons = group.into_iter().map(|ToolEntry { tooltip_label, tooltip_description, tooltip_shortcut, tool_type, icon_name }| {
|
||||
|
|
@ -319,9 +330,8 @@ impl Default for ToolFsmState {
|
|||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(|tool| match tool {
|
||||
ToolAvailability::Available(tool) => Some((tool.tool_type(), tool)),
|
||||
ToolAvailability::AvailableAsShape(_) => None,
|
||||
// ToolAvailability::ComingSoon(_) => None,
|
||||
ToolRole::Normal(tool) => Some((tool.tool_type(), tool)),
|
||||
ToolRole::Shape(_) => None,
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
|
|
@ -369,7 +379,6 @@ pub enum ToolType {
|
|||
Patch,
|
||||
Detail,
|
||||
Relight,
|
||||
Frame,
|
||||
}
|
||||
|
||||
impl ToolType {
|
||||
|
|
@ -385,58 +394,57 @@ impl ToolType {
|
|||
}
|
||||
}
|
||||
|
||||
enum ToolAvailability {
|
||||
Available(Box<Tool>),
|
||||
AvailableAsShape(ShapeType),
|
||||
// ComingSoon(ToolEntry),
|
||||
enum ToolRole {
|
||||
Normal(Box<Tool>),
|
||||
Shape(ShapeType),
|
||||
}
|
||||
|
||||
/// List of all the tools in their conventional ordering and grouping.
|
||||
fn list_tools_in_groups() -> Vec<Vec<ToolAvailability>> {
|
||||
fn list_tools_in_groups() -> Vec<Vec<ToolRole>> {
|
||||
vec![
|
||||
vec![
|
||||
// General tool group
|
||||
ToolAvailability::Available(Box::<select_tool::SelectTool>::default()),
|
||||
ToolAvailability::Available(Box::<artboard_tool::ArtboardTool>::default()),
|
||||
ToolAvailability::Available(Box::<navigate_tool::NavigateTool>::default()),
|
||||
ToolAvailability::Available(Box::<eyedropper_tool::EyedropperTool>::default()),
|
||||
ToolAvailability::Available(Box::<fill_tool::FillTool>::default()),
|
||||
ToolAvailability::Available(Box::<gradient_tool::GradientTool>::default()),
|
||||
ToolRole::Normal(Box::<select_tool::SelectTool>::default()),
|
||||
ToolRole::Normal(Box::<artboard_tool::ArtboardTool>::default()),
|
||||
ToolRole::Normal(Box::<navigate_tool::NavigateTool>::default()),
|
||||
ToolRole::Normal(Box::<eyedropper_tool::EyedropperTool>::default()),
|
||||
ToolRole::Normal(Box::<fill_tool::FillTool>::default()),
|
||||
ToolRole::Normal(Box::<gradient_tool::GradientTool>::default()),
|
||||
],
|
||||
vec![
|
||||
// Vector tool group
|
||||
ToolAvailability::Available(Box::<path_tool::PathTool>::default()),
|
||||
ToolAvailability::Available(Box::<pen_tool::PenTool>::default()),
|
||||
ToolAvailability::Available(Box::<freehand_tool::FreehandTool>::default()),
|
||||
ToolAvailability::Available(Box::<spline_tool::SplineTool>::default()),
|
||||
ToolAvailability::AvailableAsShape(ShapeType::Line),
|
||||
ToolAvailability::AvailableAsShape(ShapeType::Rectangle),
|
||||
ToolAvailability::AvailableAsShape(ShapeType::Ellipse),
|
||||
ToolAvailability::Available(Box::<shape_tool::ShapeTool>::default()),
|
||||
ToolAvailability::Available(Box::<text_tool::TextTool>::default()),
|
||||
ToolRole::Normal(Box::<path_tool::PathTool>::default()),
|
||||
ToolRole::Normal(Box::<pen_tool::PenTool>::default()),
|
||||
ToolRole::Normal(Box::<freehand_tool::FreehandTool>::default()),
|
||||
ToolRole::Normal(Box::<spline_tool::SplineTool>::default()),
|
||||
ToolRole::Shape(ShapeType::Line),
|
||||
ToolRole::Shape(ShapeType::Rectangle),
|
||||
ToolRole::Shape(ShapeType::Ellipse),
|
||||
ToolRole::Normal(Box::<shape_tool::ShapeTool>::default()),
|
||||
ToolRole::Normal(Box::<text_tool::TextTool>::default()),
|
||||
],
|
||||
vec![
|
||||
// Raster tool group
|
||||
ToolAvailability::Available(Box::<brush_tool::BrushTool>::default()),
|
||||
// ToolAvailability::ComingSoon(
|
||||
ToolRole::Normal(Box::<brush_tool::BrushTool>::default()),
|
||||
// ToolRole::Normal(
|
||||
// ToolEntry::new(ToolType::Heal, "RasterHealTool")
|
||||
// .tooltip_label("Heal Tool")
|
||||
// .tooltip_shortcut(action_shortcut_manual!(Key::KeyJ)),
|
||||
// ),
|
||||
// ToolAvailability::ComingSoon(
|
||||
// ToolRole::Normal(
|
||||
// ToolEntry::new(ToolType::Clone, "RasterCloneTool")
|
||||
// .tooltip_label("Clone Tool")
|
||||
// .tooltip_shortcut(action_shortcut_manual!(Key::KeyC)),
|
||||
// ),
|
||||
// ToolAvailability::ComingSoon(ToolEntry::new(ToolType::Patch, "RasterPatchTool")
|
||||
// ToolRole::Normal(ToolEntry::new(ToolType::Patch, "RasterPatchTool")
|
||||
// .tooltip_label("Patch Tool"),
|
||||
// ),
|
||||
// ToolAvailability::ComingSoon(
|
||||
// ToolRole::Normal(
|
||||
// ToolEntry::new(ToolType::Detail, "RasterDetailTool")
|
||||
// .tooltip_label("Detail Tool")
|
||||
// .tooltip_shortcut(action_shortcut_manual!(Key::KeyD)),
|
||||
// ),
|
||||
// ToolAvailability::ComingSoon(
|
||||
// ToolRole::Normal(
|
||||
// ToolEntry::new(ToolType::Relight, "RasterRelightTool")
|
||||
// .tooltip_label("Relight Tool")
|
||||
// .tooltip_shortcut(action_shortcut_manual!(Key::KeyO)),
|
||||
|
|
|
|||
|
|
@ -304,14 +304,8 @@
|
|||
if (cursor === "custom-rotate") {
|
||||
const svg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
|
||||
<path transform="translate(2 2)" fill="black" stroke="black" stroke-width="2px" d="
|
||||
M8,15.2C4,15.2,0.8,12,0.8,8C0.8,4,4,0.8,8,0.8c2,0,3.9,0.8,5.3,2.3l-1,1C11.2,2.9,9.6,2.2,8,2.2C4.8,2.2,2.2,4.8,2.2,8s2.6,5.8,5.8,5.8s5.8-2.6,5.8-5.8h1.4C15.2,12,12,15.2,8,15.2z
|
||||
" />
|
||||
<polygon transform="translate(2 2)" fill="black" stroke="black" stroke-width="2px" points="12.6,0 15.5,5 9.7,5" />
|
||||
<path transform="translate(2 2)" fill="white" d="
|
||||
M8,15.2C4,15.2,0.8,12,0.8,8C0.8,4,4,0.8,8,0.8c2,0,3.9,0.8,5.3,2.3l-1,1C11.2,2.9,9.6,2.2,8,2.2C4.8,2.2,2.2,4.8,2.2,8s2.6,5.8,5.8,5.8s5.8-2.6,5.8-5.8h1.4C15.2,12,12,15.2,8,15.2z
|
||||
" />
|
||||
<polygon transform="translate(2 2)" fill="white" points="12.6,0 15.5,5 9.7,5" />
|
||||
<path fill="none" stroke="black" stroke-width="2" d="M10,15.8c-3.2,0-5.8-2.6-5.8-5.8S6.8,4.2,10,4.2c0.999,0,1.999,0.273,2.877,0.771L11.7,7h5.8l-2.9-5l-1.013,1.746C12.5,3.125,11.271,2.8,10,2.8C6,2.8,2.8,6,2.8,10S6,17.2,10,17.2s7.2-3.2,7.2-7.2h-1.4C15.8,13.2,13.2,15.8,10,15.8z" />
|
||||
<path fill="white" d="M10,15.8c-3.2,0-5.8-2.6-5.8-5.8S6.8,4.2,10,4.2c0.999,0,1.999,0.273,2.877,0.771L11.7,7h5.8l-2.9-5l-1.013,1.746C12.5,3.125,11.271,2.8,10,2.8C6,2.8,2.8,6,2.8,10S6,17.2,10,17.2s7.2-3.2,7.2-7.2h-1.4C15.8,13.2,13.2,15.8,10,15.8z" />
|
||||
</svg>
|
||||
`
|
||||
.split("\n")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue