Fix regressions introduced in the vector nodes migration (#1100)

* Fix double click to enter path tool

* Fix error

* Fix transform bug

* Fix squaring scale on images

* Shift node position and refresh graph

* Downscale node seperate

* Fix mirror

* Remove duplicate transform

* Always show node graph

* Correctly set freehand and spline tool positions

* Run cargo format

* Maybe fix the scale

* Downscaled image is always smaller than origional

* Fix one crash

* Don't show node graph on welcome screen

* Reduce default graph panel height

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube 2023-03-31 21:15:49 +01:00 committed by Keavon Chambers
parent 92fe0bea50
commit d710285029
23 changed files with 105 additions and 118 deletions

View file

@ -230,9 +230,6 @@ pub enum FrontendMessage {
UpdateNodeGraphSelection {
selected: Vec<NodeId>,
},
UpdateNodeGraphVisibility {
visible: bool,
},
UpdateNodeTypes {
#[serde(rename = "nodeTypes")]
node_types: Vec<FrontendNodeType>,

View file

@ -589,10 +589,18 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
warn!("Image node should be in registry");
return;
};
let Some(transform_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Transform") else {
warn!("Transform node should be in registry");
return;
};
let Some(downscale_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Downscale") else {
warn!("Downscale node should be in registry");
return;
};
let path = vec![generate_uuid()];
let image_node_id = 100;
let mut network = crate::messages::portfolio::document::node_graph::new_image_network(32, image_node_id);
let [image_node_id, transform_node_id, downscale_node_id] = [100, 101, 102];
let mut network = crate::messages::portfolio::document::node_graph::new_image_network(32, downscale_node_id);
// Transform of parent folder
let to_parent_folder = self.document_legacy.generate_transform_across_scope(&path[..path.len() - 1], None).unwrap_or_default();
@ -612,16 +620,30 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
responses.push_back(DocumentMessage::StartTransaction.into());
let mut pos = 8;
let mut next_pos = || {
pos += 8;
graph_craft::document::DocumentNodeMetadata::position((pos, 4))
};
network.nodes.insert(
image_node_id,
image_node_type.to_document_node(
[graph_craft::document::NodeInput::value(
graph_craft::document::value::TaggedValue::ImageFrame(ImageFrame { image, transform }),
graph_craft::document::value::TaggedValue::ImageFrame(ImageFrame { image, transform: DAffine2::IDENTITY }),
false,
)],
graph_craft::document::DocumentNodeMetadata::position((20, 4)),
next_pos(),
),
);
network.nodes.insert(
transform_node_id,
transform_node_type.to_document_node_default_inputs([Some(graph_craft::document::NodeInput::node(image_node_id, 0))], next_pos()),
);
network.nodes.insert(
downscale_node_id,
downscale_node_type.to_document_node_default_inputs([Some(graph_craft::document::NodeInput::node(transform_node_id, 0))], next_pos()),
);
responses.push_back(
DocumentOperation::AddNodeGraphFrame {

View file

@ -22,7 +22,7 @@ pub enum GraphOperationMessage {
Vector { layer: LayerIdentifier, modification: VectorDataModification },
}
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
pub enum TransformIn {
Local,
Scope { scope: DAffine2 },

View file

@ -49,6 +49,8 @@ impl<'a> ModifyInputsContext<'a> {
let metadata = output_node.metadata.clone();
let new_input = output_node.inputs[0].clone();
let node_id = generate_uuid();
output_node.metadata.position.x += 8;
output_node.inputs[0] = NodeInput::node(node_id, 0);
let Some(node_type) = resolve_document_node_type(name) else {
@ -62,8 +64,8 @@ impl<'a> ModifyInputsContext<'a> {
/// Changes the inputs of a specific node
fn modify_inputs(&mut self, name: &'static str, update_input: impl FnOnce(&mut Vec<NodeInput>)) {
let node_id = self.network.primary_flow().find(|(node, _)| node.name == name).map(|(_, id)| id);
if let Some(node_id) = node_id {
let existing_node_id = self.network.primary_flow().find(|(node, _)| node.name == name).map(|(_, id)| id);
if let Some(node_id) = existing_node_id {
self.modify_existing_node_inputs(node_id, update_input);
} else {
self.modify_new_node(name, update_input);
@ -73,6 +75,10 @@ impl<'a> ModifyInputsContext<'a> {
self.responses.add(PropertiesPanelMessage::ResendActiveProperties);
let layer_path = self.layer.to_vec();
self.responses.add(DocumentMessage::NodeGraphFrameGenerate { layer_path });
if existing_node_id.is_none() {
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
}
}
fn fill_set(&mut self, fill: Fill) {
@ -117,8 +123,8 @@ impl<'a> ModifyInputsContext<'a> {
TransformIn::Scope { scope } => scope * parent_transform,
TransformIn::Viewport => parent_transform,
};
let pivot = DAffine2::from_translation(bounds.local_pivot(transform_utils::get_current_normalized_pivot(inputs)));
let transform = to.inverse() * pivot.inverse() * transform * pivot * to * layer_transform;
let pivot = DAffine2::from_translation(bounds.layerspace_pivot(transform_utils::get_current_normalized_pivot(inputs)));
let transform = to.inverse() * transform * to * layer_transform;
transform_utils::update_transform(inputs, transform);
});
}
@ -130,8 +136,8 @@ impl<'a> ModifyInputsContext<'a> {
TransformIn::Scope { scope } => scope * parent_transform,
TransformIn::Viewport => parent_transform,
};
let pivot = DAffine2::from_translation(bounds.local_pivot(transform_utils::get_current_normalized_pivot(inputs)));
let transform = to.inverse() * pivot.inverse() * transform * pivot;
let pivot = DAffine2::from_translation(bounds.layerspace_pivot(transform_utils::get_current_normalized_pivot(inputs)));
let transform = to.inverse() * transform * pivot;
transform_utils::update_transform(inputs, transform);
});
}
@ -141,7 +147,7 @@ impl<'a> ModifyInputsContext<'a> {
let layer_transform = transform_utils::get_current_transform(inputs);
let old_pivot_transform = DAffine2::from_translation(bounds.local_pivot(transform_utils::get_current_normalized_pivot(inputs)));
let new_pivot_transform = DAffine2::from_translation(bounds.local_pivot(new_pivot));
let transform = new_pivot_transform.inverse() * old_pivot_transform * layer_transform * old_pivot_transform.inverse() * new_pivot_transform;
let transform = layer_transform * old_pivot_transform.inverse() * new_pivot_transform;
transform_utils::update_transform(inputs, transform);
inputs[5] = NodeInput::value(TaggedValue::DVec2(new_pivot), false);
});
@ -184,7 +190,7 @@ impl<'a> ModifyInputsContext<'a> {
let new_pivot_transform = DAffine2::from_translation(new_layerspace_pivot);
let old_pivot_transform = DAffine2::from_translation(old_layerspace_pivot);
let transform = new_pivot_transform.inverse() * old_pivot_transform * layer_transform * old_pivot_transform.inverse() * new_pivot_transform;
let transform = layer_transform * old_pivot_transform.inverse() * new_pivot_transform;
transform_utils::update_transform(inputs, transform);
});
}
@ -231,17 +237,16 @@ impl MessageHandler<GraphOperationMessage, (&mut Document, &mut NodeGraphMessage
let bounds = LayerBounds::new(document, &layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new(&layer, document, node_graph, responses) {
modify_inputs.transform_set(transform, transform_in, parent_transform, bounds);
} else {
let transform = transform.to_cols_array();
responses.add(match transform_in {
TransformIn::Local => Operation::SetLayerTransform { path: layer, transform },
TransformIn::Scope { scope } => {
let scope = scope.to_cols_array();
Operation::SetLayerTransformInScope { path: layer, transform, scope }
}
TransformIn::Viewport => Operation::SetLayerTransformInViewport { path: layer, transform },
});
}
let transform = transform.to_cols_array();
responses.add(match transform_in {
TransformIn::Local => Operation::SetLayerTransform { path: layer, transform },
TransformIn::Scope { scope } => {
let scope = scope.to_cols_array();
Operation::SetLayerTransformInScope { path: layer, transform, scope }
}
TransformIn::Viewport => Operation::SetLayerTransformInViewport { path: layer, transform },
});
}
GraphOperationMessage::TransformSetPivot { layer, pivot } => {
let bounds = LayerBounds::new(document, &layer);

View file

@ -65,9 +65,6 @@ pub enum NodeGraphMessage {
SendGraph {
should_rerender: bool,
},
SetDrawing {
new_drawing: bool,
},
SetInputValue {
node_id: NodeId,
input_index: usize,

View file

@ -115,9 +115,6 @@ pub struct NodeGraphMessageHandler {
pub selected_nodes: Vec<graph_craft::document::NodeId>,
#[serde(skip)]
pub widgets: [LayoutGroup; 2],
/// Do not allow the node graph window to open or close whilst the user is drawing a node graph frame
#[serde(skip)]
pub is_drawing_node_graph_frame: bool,
}
impl NodeGraphMessageHandler {
@ -395,6 +392,15 @@ impl NodeGraphMessageHandler {
.filter_map(|(&id, &new)| network.nodes.get(&id).map(|node| (new, node.clone())))
.map(move |(new, node)| (new, node.map_ids(Self::default_node_input, new_ids)))
}
fn clear_graph(responses: &mut VecDeque<Message>) {
let nodes = Vec::new();
let links = Vec::new();
responses.add(FrontendMessage::UpdateNodeGraph { nodes, links });
responses.add(LayoutMessage::SendLayout {
layout: Layout::WidgetLayout(WidgetLayout::new(Vec::new())),
layout_target: crate::messages::layout::utility_types::misc::LayoutTarget::NodeGraphBar,
});
}
}
impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &[LayerId]>)> for NodeGraphMessageHandler {
@ -403,13 +409,8 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &
#[remain::sorted]
match message {
NodeGraphMessage::CloseNodeGraph => {
// Don't close when drawing a node graph frame
if self.is_drawing_node_graph_frame {
return;
}
if let Some(_old_layer_path) = self.layer_path.take() {
responses.push_back(FrontendMessage::UpdateNodeGraphVisibility { visible: false }.into());
Self::clear_graph(responses);
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
}
}
@ -622,16 +623,10 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &
Self::send_graph(network, responses);
}
NodeGraphMessage::OpenNodeGraph { layer_path } => {
// Don't open when drawing a node graph frame
if self.is_drawing_node_graph_frame {
return;
}
self.layer_path = Some(layer_path);
if let Some(network) = self.get_active_network(document) {
self.selected_nodes.clear();
responses.push_back(FrontendMessage::UpdateNodeGraphVisibility { visible: true }.into());
Self::send_graph(network, responses);
@ -700,25 +695,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &
}
}
}
NodeGraphMessage::SetDrawing { new_drawing } => {
let selected: Vec<_> = selected.collect();
// Check if we stopped drawing a node graph frame
if self.is_drawing_node_graph_frame && !new_drawing {
// Check if we should open or close the node graph
if selected.len() == 1
&& document
.layer(selected[0])
.ok()
.filter(|layer| LayerDataTypeDiscriminant::from(&layer.data) == LayerDataTypeDiscriminant::NodeGraphFrame)
.is_some()
{
responses.push_back(NodeGraphMessage::OpenNodeGraph { layer_path: selected[0].to_vec() }.into());
} else {
responses.push_back(NodeGraphMessage::CloseNodeGraph.into());
}
}
self.is_drawing_node_graph_frame = new_drawing
}
NodeGraphMessage::SetInputValue { node_id, input_index, value } => {
if let Some(network) = self.get_active_network(document) {
if let Some(node) = network.nodes.get(&node_id) {

View file

@ -105,7 +105,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
properties: |_document_node, _node_id, _context| node_properties::string_properties("The identity node simply returns the input"),
},
DocumentNodeType {
name: "Image",
name: "Downscale",
category: "Ignore",
identifier: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0],
@ -138,7 +138,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
}),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: |_document_node, _node_id, _context| node_properties::string_properties("A bitmap image embedded in this node"),
properties: |_document_node, _node_id, _context| node_properties::string_properties("Downscale the image to a lower resolution"),
},
// DocumentNodeType {
// name: "Input",
@ -473,6 +473,14 @@ fn static_nodes() -> Vec<DocumentNodeType> {
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: node_properties::no_properties,
},
DocumentNodeType {
name: "Image",
category: "Ignore",
identifier: NodeImplementation::proto("graphene_core::ops::IdNode"),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: |_document_node, _node_id, _context| node_properties::string_properties("A bitmap image embedded in this node"),
},
#[cfg(feature = "gpu")]
DocumentNodeType {
name: "GpuImage",

View file

@ -941,7 +941,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
// Create the input to the graph using an empty image
let image_frame = std::borrow::Cow::Owned(graphene_core::raster::ImageFrame {
image: graphene_core::raster::Image::empty(),
transform,
transform: glam::DAffine2::IDENTITY,
});
// Compute the transform input to the node graph frame
let image_frame: graphene_core::raster::ImageFrame = context.executor.compute_input(context.network, &imaginate_node, 0, image_frame).unwrap_or_default();

View file

@ -320,7 +320,7 @@ pub fn register_artwork_layer_properties(
]
}
LayerDataType::NodeGraphFrame(node_graph_frame) => {
let mut properties_sections = vec![node_section_transform(layer, persistent_data)];
let mut properties_sections = Vec::new();
let mut context = crate::messages::portfolio::document::node_graph::NodePropertiesContext {
persistent_data,

View file

@ -130,9 +130,6 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, u64, &InputPreprocess
// Notify the frontend about the new active tool to be displayed
tool_data.register_properties(responses, LayoutTarget::ToolShelf);
// Ensure the node graph drawing state is reset
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
}
ToolMessage::DeactivateTools => {
let tool_data = &mut self.tool_state.tool_data;

View file

@ -11,7 +11,7 @@ use document_legacy::LayerId;
use document_legacy::Operation;
use graphene_core::vector::style::Stroke;
use glam::DVec2;
use glam::{DAffine2, DVec2};
use serde::{Deserialize, Serialize};
#[derive(Default)]
@ -219,10 +219,16 @@ fn remove_preview(data: &FreehandToolData) -> Message {
fn add_polyline(data: &FreehandToolData, tool_data: &DocumentToolData, responses: &mut VecDeque<Message>) {
let layer_path = data.path.clone().unwrap();
let subpath = bezier_rs::Subpath::from_anchors(data.points.iter().copied(), false);
let position = subpath.bounding_box().unwrap_or_default().into_iter().sum::<DVec2>() / 2.;
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
responses.add(GraphOperationMessage::StrokeSet {
layer: layer_path,
layer: layer_path.clone(),
stroke: Stroke::new(tool_data.primary_color, data.weight),
});
responses.add(GraphOperationMessage::TransformSet {
layer: layer_path,
transform: DAffine2::from_translation(position),
transform_in: TransformIn::Local,
});
}

View file

@ -114,7 +114,6 @@ impl Fsm for ImaginateToolFsmState {
(Ready, DragStart) => {
shape_data.start(responses, document, input, render_data);
responses.push_back(DocumentMessage::StartTransaction.into());
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: true }.into());
shape_data.path = Some(document.get_path_for_new_layer());
responses.push_back(DocumentMessage::DeselectAllLayers.into());
@ -153,7 +152,6 @@ impl Fsm for ImaginateToolFsmState {
}
(Drawing, DragStop) => {
input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses);
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
shape_data.cleanup(responses);
Ready
@ -161,8 +159,6 @@ impl Fsm for ImaginateToolFsmState {
(Drawing, Abort) => {
responses.push_back(DocumentMessage::AbortTransaction.into());
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
shape_data.cleanup(responses);
Ready

View file

@ -114,7 +114,6 @@ impl Fsm for NodeGraphToolFsmState {
(Ready, DragStart) => {
shape_data.start(responses, document, input, render_data);
responses.push_back(DocumentMessage::StartTransaction.into());
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: true }.into());
shape_data.path = Some(document.get_path_for_new_layer());
responses.push_back(DocumentMessage::DeselectAllLayers.into());
@ -141,14 +140,12 @@ impl Fsm for NodeGraphToolFsmState {
}
(Drawing, DragStop) => {
input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses);
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
shape_data.cleanup(responses);
Ready
}
(Drawing, Abort) => {
responses.push_back(DocumentMessage::AbortTransaction.into());
responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: false }.into());
shape_data.cleanup(responses);

View file

@ -1202,7 +1202,7 @@ fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, interse
}
fn edit_layer_deepest_manipulation(intersect: &Layer, intersect_layer_path: &Vec<u64>, responses: &mut VecDeque<Message>) {
match intersect.data {
match &intersect.data {
LayerDataType::Text(_) => {
responses.push_front(ToolMessage::ActivateTool { tool_type: ToolType::Text }.into());
responses.push_back(TextToolMessage::Interact.into());
@ -1210,11 +1210,8 @@ fn edit_layer_deepest_manipulation(intersect: &Layer, intersect_layer_path: &Vec
LayerDataType::Shape(_) => {
responses.push_front(ToolMessage::ActivateTool { tool_type: ToolType::Path }.into());
}
LayerDataType::NodeGraphFrame(_) => {
let replacement_selected_layers = vec![intersect_layer_path.clone()];
let layer_path = intersect_layer_path.clone();
responses.push_back(DocumentMessage::SetSelectedLayers { replacement_selected_layers }.into());
responses.push_back(NodeGraphMessage::OpenNodeGraph { layer_path }.into());
LayerDataType::NodeGraphFrame(frame) if frame.vector_data.is_some() => {
responses.push_front(ToolMessage::ActivateTool { tool_type: ToolType::Path }.into());
}
_ => {}
}

View file

@ -262,6 +262,7 @@ fn add_spline(tool_data: &SplineToolData, global_tool_data: &DocumentToolData, s
}
let subpath = bezier_rs::Subpath::new_cubic_spline(points);
let position = subpath.bounding_box().unwrap_or_default().into_iter().sum::<DVec2>() / 2.;
let layer_path = tool_data.path.clone().unwrap();
graph_modification_utils::new_vector_layer(vec![subpath], layer_path.clone(), responses);
@ -269,4 +270,9 @@ fn add_spline(tool_data: &SplineToolData, global_tool_data: &DocumentToolData, s
layer: layer_path.clone(),
stroke: Stroke::new(global_tool_data.primary_color, tool_data.weight),
});
responses.add(GraphOperationMessage::TransformSet {
layer: layer_path,
transform: glam::DAffine2::from_translation(position),
transform_in: TransformIn::Local,
})
}

View file

@ -59,6 +59,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
*mouse_position = ipp.mouse.position;
*start_mouse = ipp.mouse.position;
selected.original_transforms.clear();
};
#[remain::sorted]
@ -87,7 +88,6 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::Grabbing(Default::default());
responses.push_back(BroadcastEvent::DocumentIsDirty.into());
self.original_transforms.clear();
}
BeginRotate => {
if let TransformOperation::Rotating(_) = self.transform_operation {
@ -104,7 +104,6 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
self.transform_operation = TransformOperation::Rotating(Default::default());
responses.push_back(BroadcastEvent::DocumentIsDirty.into());
self.original_transforms.clear();
}
BeginScale => {
if let TransformOperation::Scaling(_) = self.transform_operation {
@ -119,10 +118,8 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
begin_operation(self.transform_operation, &mut self.typing, &mut self.mouse_position, &mut self.start_mouse);
self.transform_operation = TransformOperation::Scaling(Default::default());
self.transform_operation.apply_transform_operation(&mut selected, self.snap, Axis::Both);
responses.push_back(BroadcastEvent::DocumentIsDirty.into());
self.original_transforms.clear();
}
CancelTransformOperation => {
selected.revert_operation();

View file

@ -15,7 +15,6 @@ impl MessageHandler<WorkspaceMessage, ()> for WorkspaceMessageHandler {
// Messages
NodeGraphToggleVisibility => {
self.node_graph_visible = !self.node_graph_visible;
responses.push_back(FrontendMessage::UpdateNodeGraphVisibility { visible: self.node_graph_visible }.into());
}
}
}

View file

@ -236,7 +236,7 @@ impl NodeGraphExecutor {
let layer = document.document_legacy.layer(&layer_path).map_err(|e| format!("No layer: {e:?}"))?;
// Construct the input image frame
let transform = layer.transform;
let transform = DAffine2::IDENTITY;
let image_frame = ImageFrame { image, transform };
let node_graph_frame = match &layer.data {

View file

@ -14,8 +14,8 @@
const PANEL_SIZES = {
/**/ root: 100,
/* ├── */ content: 80,
/* │ ├── */ document: 60,
/* │ └── */ graph: 40,
/* │ ├── */ document: 80,
/* │ └── */ graph: 20,
/* └── */ details: 20,
/* ├── */ properties: 45,
/* └── */ layers: 55,
@ -111,7 +111,7 @@
bind:this={documentPanel}
/>
</LayoutRow>
{#if $workspace.nodeGraphVisible}
{#if $portfolio.documents.length > 0}
<LayoutRow class="workspace-grid-resize-gutter" data-gutter-vertical on:pointerdown={resizePanel} />
<LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["graph"] }} data-subdivision-name="graph">
<Panel panelType="NodeGraph" tabLabels={[{ name: "Node Graph" }]} tabActiveIndex={0} />

View file

@ -1,28 +1,15 @@
/* eslint-disable max-classes-per-file */
import {tick} from "svelte";
import {writable} from "svelte/store";
import { type Editor } from "@graphite/wasm-communication/editor";
import { UpdateNodeGraphVisibility } from "@graphite/wasm-communication/messages";
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function createWorkspaceState(editor: Editor) {
const { subscribe, update } = writable({
nodeGraphVisible: false,
});
const { subscribe, update } = writable({});
// Set up message subscriptions on creation
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphVisibility, async (updateNodeGraphVisibility) => {
update((state) => {
state.nodeGraphVisible = updateNodeGraphVisibility.visible;
return state;
});
// Update the viewport bounds
await tick();
window.dispatchEvent(new Event("resize"));
});
return {
subscribe,

View file

@ -44,9 +44,6 @@ export class UpdateNodeGraphSelection extends JsMessage {
readonly selected!: bigint[];
}
export class UpdateNodeGraphVisibility extends JsMessage {
readonly visible!: boolean;
}
export class UpdateOpenDocumentsList extends JsMessage {
@Type(() => FrontendDocumentDetails)
@ -1432,7 +1429,6 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateNodeGraphBarLayout,
UpdateNodeGraphSelection,
UpdateNodeTypes,
UpdateNodeGraphVisibility,
UpdateOpenDocumentsList,
UpdatePropertyPanelOptionsLayout,
UpdatePropertyPanelSectionsLayout,

View file

@ -19,7 +19,7 @@ pub struct TransformNode<Translation, Rotation, Scale, Shear, Pivot> {
pub(crate) fn transform_vector_data(mut vector_data: VectorData, translate: DVec2, rotate: f64, scale: DVec2, shear: DVec2, pivot: DVec2) -> VectorData {
let pivot = DAffine2::from_translation(vector_data.local_pivot(pivot));
let modification = pivot * DAffine2::from_scale_angle_translation(scale, rotate, translate) * DAffine2::from_cols_array(&[1., shear.y, shear.x, 1., 0., 0.]) * pivot.inverse();
let modification = DAffine2::from_scale_angle_translation(scale, rotate, translate) * DAffine2::from_cols_array(&[1., shear.y, shear.x, 1., 0., 0.]) * pivot.inverse();
vector_data.transform = modification * vector_data.transform;
vector_data
@ -40,9 +40,12 @@ where
let rotate = self.rotate.eval(());
let scale = self.scale.eval(());
let shear = self.shear.eval(());
let pivot = self.pivot.eval(());
let pivot = DAffine2::from_translation(pivot);
let modification = pivot * DAffine2::from_scale_angle_translation(scale, rotate, translate) * DAffine2::from_cols_array(&[1., shear.y, shear.x, 1., 0., 0.]) * pivot.inverse();
image_frame.transform = modification * image_frame.transform;
let transform = generate_transform(shear, &image_frame.transform, scale, rotate, translate);
image_frame.transform = transform * image_frame.transform;
image_frame
}
}

View file

@ -94,8 +94,8 @@ pub struct DownscaleNode;
#[node_macro::node_fn(DownscaleNode)]
fn downscale(image_frame: ImageFrame) -> ImageFrame {
let target_width = image_frame.transform.transform_vector2((1., 0.).into()).length() as usize;
let target_height = image_frame.transform.transform_vector2((0., 1.).into()).length() as usize;
let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize);
let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize);
let mut image = Image {
width: target_width as u32,