Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion desktop/src/render/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl RenderState {
return;
};
let size = glam::UVec2::new(viewport_texture.width(), viewport_texture.height());
let result = futures::executor::block_on(self.executor.render_vello_scene_to_target_texture(&scene, size, &Default::default(), None, &mut self.overlays_texture));
let result = futures::executor::block_on(self.executor.render_vello_scene_to_target_texture(&scene, size, &Default::default(), &mut self.overlays_texture));
if let Err(e) = result {
tracing::error!("Error rendering overlays: {:?}", e);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::messages::prelude::*;
pub enum ExportDialogMessage {
FileType { file_type: FileType },
ScaleFactor { factor: f64 },
TransparentBackground { transparent: bool },
ExportBounds { bounds: ExportBounds },

Submit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub struct ExportDialogMessageHandler {
pub file_type: FileType,
pub scale_factor: f64,
pub bounds: ExportBounds,
pub transparent_background: bool,
pub artboards: HashMap<LayerNodeIdentifier, String>,
pub has_selection: bool,
}
Expand All @@ -25,7 +24,6 @@ impl Default for ExportDialogMessageHandler {
file_type: Default::default(),
scale_factor: 1.,
bounds: Default::default(),
transparent_background: false,
artboards: Default::default(),
has_selection: false,
}
Expand All @@ -40,20 +38,25 @@ impl MessageHandler<ExportDialogMessage, ExportDialogMessageContext<'_>> for Exp
match message {
ExportDialogMessage::FileType { file_type } => self.file_type = file_type,
ExportDialogMessage::ScaleFactor { factor } => self.scale_factor = factor,
ExportDialogMessage::TransparentBackground { transparent } => self.transparent_background = transparent,
ExportDialogMessage::ExportBounds { bounds } => self.bounds = bounds,

ExportDialogMessage::Submit => {
let artboard_name = match self.bounds {
// Fall back to "All Artwork" if "Selection" was chosen but nothing is currently selected
let bounds = if !self.has_selection && self.bounds == ExportBounds::Selection {
ExportBounds::AllArtwork
} else {
self.bounds
};

let artboard_name = match bounds {
ExportBounds::Artboard(layer) => self.artboards.get(&layer).cloned(),
_ => None,
};
responses.add_front(PortfolioMessage::SubmitDocumentExport {
name: portfolio.active_document().map(|document| document.name.clone()).unwrap_or_default(),
file_type: self.file_type,
scale_factor: self.scale_factor,
bounds: self.bounds,
transparent_background: self.file_type != FileType::Jpg && self.transparent_background,
bounds,
artboard_name,
artboard_count: self.artboards.len(),
})
Expand Down Expand Up @@ -127,6 +130,7 @@ impl LayoutHolder for ExportDialogMessageHandler {
let artboards = self.artboards.iter().map(|(&layer, name)| (ExportBounds::Artboard(layer), name.to_string(), false)).collect();
let choices = [standard_bounds, artboards];

// Fall back to "All Artwork" if "Selection" was chosen but nothing is currently selected
let current_bounds = if !self.has_selection && self.bounds == ExportBounds::Selection {
ExportBounds::AllArtwork
} else {
Expand Down Expand Up @@ -159,22 +163,6 @@ impl LayoutHolder for ExportDialogMessageHandler {
DropdownInput::new(entries).selected_index(Some(index as u32)).widget_instance(),
];

let checkbox_id = CheckboxId::new();
let transparent_background = vec![
TextLabel::new("Transparency").table_align(true).min_width(100).for_checkbox(checkbox_id).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
CheckboxInput::new(self.transparent_background)
.disabled(self.file_type == FileType::Jpg)
.on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground { transparent: value.checked }.into())
.for_label(checkbox_id)
.widget_instance(),
];

Layout(vec![
LayoutGroup::row(export_type),
LayoutGroup::row(resolution),
LayoutGroup::row(export_area),
LayoutGroup::row(transparent_background),
])
Layout(vec![LayoutGroup::row(export_type), LayoutGroup::row(resolution), LayoutGroup::row(export_area)])
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*;
use glam::{IVec2, UVec2};
use graph_craft::document::NodeId;
use graphene_std::Color;

/// A dialog to allow users to set some initial options about a new document.
#[derive(Debug, Clone, Default, ExtractField)]
Expand Down Expand Up @@ -29,19 +31,32 @@ impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHa
artboard: graphene_std::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()),
});
responses.add(NavigationMessage::CanvasPan { delta: self.dimensions.as_dvec2() });
responses.add(NodeGraphMessage::RunDocumentGraph);

responses.add(ViewportMessage::RepropagateUpdate);

responses.add(DeferMessage::AfterNavigationReady {
messages: vec![
DocumentMessage::ZoomCanvasToFitAll.into(),
DocumentMessage::DeselectAllLayers.into(),
PortfolioMessage::AutoSaveActiveDocument.into(),
],
} else {
let node_id = NodeId::new();
responses.add(GraphOperationMessage::NewColorFillLayer {
node_id,
color: Color::WHITE,
parent: LayerNodeIdentifier::ROOT_PARENT,
insert_index: 0,
});
responses.add(NodeGraphMessage::SetDisplayNameImpl {
node_id,
alias: "Background".to_string(),
});
responses.add(NodeGraphMessage::SetLocked { node_id, locked: true });
}

responses.add(NodeGraphMessage::RunDocumentGraph);
responses.add(ViewportMessage::RepropagateUpdate);

responses.add(DeferMessage::AfterNavigationReady {
messages: vec![
DocumentMessage::ZoomCanvasToFitAll.into(),
DocumentMessage::DeselectAllLayers.into(),
PortfolioMessage::AutoSaveActiveDocument.into(),
],
});

responses.add(DocumentMessage::MarkAsSaved);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1400,8 +1400,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
let node_layer_id = LayerNodeIdentifier::new_unchecked(node_id);
let new_artboard_node = document_node_definitions::resolve_network_node_type("Artboard")
.expect("Failed to create artboard node")
// Enable clipping by default (input index 5) so imported content is masked to the artboard bounds
.node_template_input_override([None, None, None, None, None, Some(NodeInput::value(TaggedValue::Bool(true), false))]);
.default_node_template();
responses.add(NodeGraphMessage::InsertNode {
node_id,
node_template: Box::new(new_artboard_node),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::messages::portfolio::document::utility_types::network_interface::Node
use crate::messages::prelude::*;
use glam::{DAffine2, IVec2};
use graph_craft::document::NodeId;
use graphene_std::Artboard;
use graphene_std::brush::brush_stroke::BrushStroke;
use graphene_std::raster::BlendMode;
use graphene_std::raster_types::{CPU, Raster};
Expand All @@ -14,6 +13,7 @@ use graphene_std::text::{Font, TypesettingConfig};
use graphene_std::vector::PointId;
use graphene_std::vector::VectorModificationType;
use graphene_std::vector::style::{Fill, Stroke};
use graphene_std::{Artboard, Color};

#[impl_message(Message, DocumentMessage, GraphOperation)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
Expand Down Expand Up @@ -97,6 +97,12 @@ pub enum GraphOperationMessage {
parent: LayerNodeIdentifier,
insert_index: usize,
},
NewColorFillLayer {
node_id: NodeId,
color: Color,
parent: LayerNodeIdentifier,
insert_index: usize,
},
NewVectorLayer {
id: NodeId,
subpaths: Vec<Subpath<PointId>>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
responses.add(NodeGraphMessage::MoveLayerToStack { layer, parent, insert_index });
responses.add(NodeGraphMessage::RunDocumentGraph);
}
GraphOperationMessage::NewColorFillLayer { node_id, color, parent, insert_index } => {
let mut modify_inputs = ModifyInputsContext::new(network_interface, responses);
let layer = modify_inputs.create_layer(node_id);
modify_inputs.insert_color_value(color, layer);
network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
responses.add(NodeGraphMessage::RunDocumentGraph);
}
GraphOperationMessage::NewVectorLayer { id, subpaths, parent, insert_index } => {
let mut modify_inputs = ModifyInputsContext::new(network_interface, responses);
let layer = modify_inputs.create_layer(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use glam::{DAffine2, IVec2};
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput};
use graph_craft::{ProtoNodeIdentifier, concrete};
use graphene_std::Artboard;
use graphene_std::brush::brush_stroke::BrushStroke;
use graphene_std::raster::BlendMode;
use graphene_std::raster_types::{CPU, Raster};
Expand All @@ -17,7 +16,7 @@ use graphene_std::text::{Font, TypesettingConfig};
use graphene_std::vector::Vector;
use graphene_std::vector::style::{Fill, Stroke};
use graphene_std::vector::{PointId, VectorModificationType};
use graphene_std::{Graphic, NodeInputDecleration};
use graphene_std::{Artboard, Color, Graphic, NodeInputDecleration};

#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
pub enum TransformIn {
Expand Down Expand Up @@ -289,6 +288,19 @@ impl<'a> ModifyInputsContext<'a> {
self.network_interface.move_node_to_chain_start(&fill_id, layer, &[], self.import);
}

pub fn insert_color_value(&mut self, color: Color, layer: LayerNodeIdentifier) {
let color_value = resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER)
.expect("Color Value node does not exist")
.node_template_input_override([
Some(NodeInput::value(TaggedValue::None, false)),
Some(NodeInput::value(TaggedValue::Color(Table::new_from_element(color)), false)),
]);

let color_value_id = NodeId::new();
self.network_interface.insert_node(color_value_id, color_value, &[]);
self.network_interface.move_node_to_chain_start(&color_value_id, layer, &[], self.import);
}

pub fn insert_image_data(&mut self, image_frame: Table<Raster<CPU>>, layer: LayerNodeIdentifier) {
let transform = resolve_network_node_type("Transform").expect("Transform node does not exist").default_node_template();
let image = resolve_proto_node_type(graphene_std::raster_nodes::std_nodes::image_value::IDENTIFIER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false),
NodeInput::value(TaggedValue::DVec2(DVec2::new(1920., 1080.)), false),
NodeInput::value(TaggedValue::Color(Table::new_from_element(Color::WHITE)), false),
NodeInput::value(TaggedValue::Bool(false), false),
NodeInput::value(TaggedValue::Bool(true), false),
],
..Default::default()
},
Expand Down
1 change: 0 additions & 1 deletion editor/src/messages/portfolio/portfolio_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ pub enum PortfolioMessage {
file_type: FileType,
scale_factor: f64,
bounds: ExportBounds,
transparent_background: bool,
artboard_name: Option<String>,
artboard_count: usize,
},
Expand Down
2 changes: 0 additions & 2 deletions editor/src/messages/portfolio/portfolio_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1382,7 +1382,6 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
file_type,
scale_factor,
bounds,
transparent_background,
artboard_name,
artboard_count,
} => {
Expand All @@ -1392,7 +1391,6 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
file_type,
scale_factor,
bounds,
transparent_background,
artboard_name,
artboard_count,
..Default::default()
Expand Down
2 changes: 1 addition & 1 deletion editor/src/messages/tool/tool_messages/artboard_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ impl Fsm for ArtboardToolFsmState {
location: start.min(end).round().as_ivec2(),
dimensions: (start.round() - end.round()).abs().as_ivec2(),
background: graphene_std::Color::WHITE,
clip: false,
clip: true,
},
})
}
Expand Down
19 changes: 12 additions & 7 deletions editor/src/node_graph_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ impl NodeGraphExecutor {
pointer,
export_format: graphene_std::application_io::ExportFormat::Raster,
render_mode: document.render_mode,
hide_artboards: false,
for_export: false,
for_eyedropper: false,
};
Expand Down Expand Up @@ -218,7 +217,6 @@ impl NodeGraphExecutor {
pointer,
export_format: graphene_std::application_io::ExportFormat::Raster,
render_mode,
hide_artboards: false,
for_export: false,
for_eyedropper: true,
};
Expand All @@ -241,10 +239,10 @@ impl NodeGraphExecutor {
graphene_std::application_io::ExportFormat::Raster
};

// Calculate the bounding box of the region to be exported
// Calculate the bounding box of the region to be exported (artboard bounds always contribute)
let bounds = match export_config.bounds {
ExportBounds::AllArtwork => document.network_interface.document_bounds_document_space(!export_config.transparent_background),
ExportBounds::Selection => document.network_interface.selected_bounds_document_space(!export_config.transparent_background, &[]),
ExportBounds::AllArtwork => document.network_interface.document_bounds_document_space(true),
ExportBounds::Selection => document.network_interface.selected_bounds_document_space(true, &[]),
ExportBounds::Artboard(id) => document.metadata().bounding_box_document(id),
}
.ok_or_else(|| "No bounding box".to_string())?;
Expand All @@ -266,7 +264,6 @@ impl NodeGraphExecutor {
pointer: DVec2::ZERO,
export_format,
render_mode: document.render_mode,
hide_artboards: export_config.transparent_background,
for_export: true,
for_eyedropper: false,
};
Expand Down Expand Up @@ -481,7 +478,7 @@ impl NodeGraphExecutor {
use image::buffer::ConvertBuffer;
use image::{ImageFormat, RgbImage, RgbaImage};

let Some(image) = RgbaImage::from_raw(width, height, data) else {
let Some(mut image) = RgbaImage::from_raw(width, height, data) else {
return Err("Failed to create image buffer for export".to_string());
};

Expand All @@ -496,6 +493,14 @@ impl NodeGraphExecutor {
}
}
FileType::Jpg => {
// Composite onto a white background since JPG doesn't support transparency
for pixel in image.pixels_mut() {
let [r, g, b, a] = pixel.0;
let alpha = a as f32 / 255.;
let blend = |channel: u8| (channel as f32 * alpha + 255. * (1. - alpha)).round() as u8;
*pixel = image::Rgba([blend(r), blend(g), blend(b), 255]);
}

let image: RgbImage = image.convert();
let result = image.write_to(&mut cursor, ImageFormat::Jpeg);
if let Err(err) = result {
Expand Down
1 change: 0 additions & 1 deletion editor/src/node_graph_executor/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ pub struct ExportConfig {
pub file_type: FileType,
pub scale_factor: f64,
pub bounds: ExportBounds,
pub transparent_background: bool,
pub size: UVec2,
pub artboard_name: Option<String>,
pub artboard_count: usize,
Expand Down
1 change: 0 additions & 1 deletion node-graph/libraries/application-io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ pub struct RenderConfig {
#[serde(alias = "view_mode")]
pub render_mode: RenderMode,
pub export_format: ExportFormat,
pub hide_artboards: bool,
pub for_export: bool,
pub for_eyedropper: bool,
}
Expand Down
2 changes: 1 addition & 1 deletion node-graph/libraries/graphic-types/src/artboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Artboard {
location: location.min(location + dimensions),
dimensions: dimensions.abs(),
background: Color::WHITE,
clip: false,
clip: true,
}
}
}
Expand Down
Loading
Loading