Skip to content

Commit

Permalink
Code review
Browse files Browse the repository at this point in the history
  • Loading branch information
Keavon committed Feb 12, 2025
1 parent 3538f06 commit 2c6c13e
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 138 deletions.
114 changes: 49 additions & 65 deletions editor/src/messages/portfolio/document/overlays/utility_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerSta
use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler};

use graphene_core::vector::ManipulatorPointId;
use graphene_std::vector::{PointId, SegmentId};

use bezier_rs::Bezier;
use bezier_rs::{Bezier, BezierHandles};
use glam::{DAffine2, DVec2};
use graphene_std::vector::{PointId, SegmentId};
use wasm_bindgen::JsCast;

pub fn overlay_canvas_element() -> Option<web_sys::HtmlCanvasElement> {
Expand All @@ -25,159 +25,143 @@ pub fn overlay_canvas_context() -> web_sys::CanvasRenderingContext2d {
create_context().expect("Failed to get canvas context")
}

pub fn get_selected_segments(document: &DocumentMessageHandler, shape_editor: &mut ShapeState) -> Vec<SegmentId> {
pub fn selected_segments(document: &DocumentMessageHandler, shape_editor: &mut ShapeState) -> Vec<SegmentId> {
let selected_points = shape_editor.selected_points();
let selected_anchors: Vec<PointId> = selected_points
let selected_anchors = selected_points
.filter_map(|point_id| if let ManipulatorPointId::Anchor(p) = point_id { Some(*p) } else { None })
.collect();
//Collect the segments whose handles are selected
let mut selected_segments: Vec<SegmentId> = shape_editor
.collect::<Vec<_>>();

// Collect the segments whose handles are selected
let mut selected_segments = shape_editor
.selected_points()
.filter_map(|point_id| {
if let ManipulatorPointId::EndHandle(segment_id) = point_id {
Some(*segment_id)
} else if let ManipulatorPointId::PrimaryHandle(segment_id) = point_id {
Some(*segment_id)
} else {
None
}
.filter_map(|point_id| match point_id {
ManipulatorPointId::PrimaryHandle(segment_id) | ManipulatorPointId::EndHandle(segment_id) => Some(*segment_id),
ManipulatorPointId::Anchor(_) => None,
})
.collect();
.collect::<Vec<_>>();

//TODO: Currently if there are two duplicate layers, both of their segments get overlays
// TODO: Currently if there are two duplicate layers, both of their segments get overlays
// Adding segments which are are connected to selected anchors
for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
continue;
};
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };

for (segment_id, _bezier, start, end) in vector_data.segment_bezier_iter() {
if selected_anchors.contains(&start) || selected_anchors.contains(&end) {
selected_segments.push(segment_id);
}
}
}

selected_segments
}

fn overlay_bezier_handles(
segment_id: SegmentId,
bezier: Bezier,
transform: DAffine2,
overlay_context: &mut OverlayContext,
selected: Option<&SelectedLayerState>,
is_selected: impl Fn(Option<&SelectedLayerState>, ManipulatorPointId) -> bool,
) {
fn overlay_bezier_handles(bezier: Bezier, segment_id: SegmentId, transform: DAffine2, is_selected: impl Fn(ManipulatorPointId) -> bool, overlay_context: &mut OverlayContext) {
let bezier = bezier.apply_transformation(|point| transform.transform_point2(point));
let not_under_anchor = |position: DVec2, anchor: DVec2| position.distance_squared(anchor) >= HIDE_HANDLE_DISTANCE * HIDE_HANDLE_DISTANCE;

match bezier.handles {
bezier_rs::BezierHandles::Quadratic { handle } if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) => {
BezierHandles::Quadratic { handle } if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) => {
overlay_context.line(handle, bezier.start, None);
overlay_context.line(handle, bezier.end, None);
overlay_context.manipulator_handle(handle, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None);
overlay_context.manipulator_handle(handle, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None);
}
bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => {
BezierHandles::Cubic { handle_start, handle_end } => {
if not_under_anchor(handle_start, bezier.start) {
overlay_context.line(handle_start, bezier.start, None);
overlay_context.manipulator_handle(handle_start, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None);
overlay_context.manipulator_handle(handle_start, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None);
}
if not_under_anchor(handle_end, bezier.end) {
overlay_context.line(handle_end, bezier.end, None);
overlay_context.manipulator_handle(handle_end, is_selected(selected, ManipulatorPointId::EndHandle(segment_id)), None);
overlay_context.manipulator_handle(handle_end, is_selected(ManipulatorPointId::EndHandle(segment_id)), None);
}
}
_ => {}
}
}

pub fn overlay_bezier_handle_specific_point(
segment_id: SegmentId,
bezier: Bezier,
start: PointId,
end: PointId,
segment_id: SegmentId,
(start, end): (PointId, PointId),
point_to_render: PointId,
transform: DAffine2,
is_selected: impl Fn(ManipulatorPointId) -> bool,
overlay_context: &mut OverlayContext,
selected: Option<&SelectedLayerState>,
is_selected: impl Fn(Option<&SelectedLayerState>, ManipulatorPointId) -> bool,
point_to_render: PointId,
) {
let bezier = bezier.apply_transformation(|point| transform.transform_point2(point));
let not_under_anchor = |position: DVec2, anchor: DVec2| position.distance_squared(anchor) >= HIDE_HANDLE_DISTANCE * HIDE_HANDLE_DISTANCE;

match bezier.handles {
bezier_rs::BezierHandles::Quadratic { handle } if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) => {
if start == point_to_render {
//review this
overlay_context.line(handle, bezier.start, None);
} else {
overlay_context.line(handle, bezier.end, None);
BezierHandles::Quadratic { handle } => {
if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) {
let end = if start == point_to_render { bezier.start } else { bezier.end };
overlay_context.line(handle, end, None);
overlay_context.manipulator_handle(handle, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None);
}
overlay_context.manipulator_handle(handle, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None);
}
bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => {
BezierHandles::Cubic { handle_start, handle_end } => {
if not_under_anchor(handle_start, bezier.start) && (point_to_render == start) {
overlay_context.line(handle_start, bezier.start, None);
overlay_context.manipulator_handle(handle_start, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None);
overlay_context.manipulator_handle(handle_start, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None);
}
if not_under_anchor(handle_end, bezier.end) && (point_to_render == end) {
overlay_context.line(handle_end, bezier.end, None);
overlay_context.manipulator_handle(handle_end, is_selected(selected, ManipulatorPointId::EndHandle(segment_id)), None);
overlay_context.manipulator_handle(handle_end, is_selected(ManipulatorPointId::EndHandle(segment_id)), None);
}
}
_ => {}
}
}

pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext, draw_handles: DrawHandles) {
pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandles, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext) {
for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
continue;
};
//let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let transform = document.metadata().transform_to_viewport(layer);
let selected = shape_editor.selected_shape_state.get(&layer);
let is_selected = |selected: Option<&SelectedLayerState>, point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_selected(point));
overlay_context.outline_vector(&vector_data, transform);

let opposite_handles_data: Vec<(PointId, SegmentId)> = shape_editor.selected_points().filter_map(|point_id| vector_data.get_adjacent_segment(point_id)).collect();
let selected = shape_editor.selected_shape_state.get(&layer);
let is_selected = |point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_selected(point));

let opposite_handles_data: Vec<(PointId, SegmentId)> = shape_editor.selected_points().filter_map(|point_id| vector_data.adjacent_segment(point_id)).collect();

match draw_handles {
DrawHandles::All => {
vector_data.segment_bezier_iter().for_each(|(segment_id, bezier, _start, _end)| {
overlay_bezier_handles(segment_id, bezier, transform, overlay_context, selected, is_selected);
overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context);
});
}
DrawHandles::SelectedAnchors(ref selected_segments) => {
vector_data
.segment_bezier_iter()
.filter(|(segment_id, ..)| selected_segments.contains(segment_id))
.for_each(|(segment_id, bezier, _start, _end)| {
overlay_bezier_handles(segment_id, bezier, transform, overlay_context, selected, is_selected);
overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context);
});

for (segment_id, bezier, start, end) in vector_data.segment_bezier_iter() {
if let Some((corresponding_anchor, _)) = opposite_handles_data.iter().find(|(_, adj_segment_id)| adj_segment_id == &segment_id) {
overlay_bezier_handle_specific_point(segment_id, bezier, start, end, transform, overlay_context, selected, is_selected, *corresponding_anchor);
overlay_bezier_handle_specific_point(bezier, segment_id, (start, end), *corresponding_anchor, transform, is_selected, overlay_context);
}
}
}

DrawHandles::FrontierHandles(ref segment_endpoints) => {
vector_data
.segment_bezier_iter()
.filter(|(segment_id, ..)| segment_endpoints.contains_key(&segment_id))
.filter(|(segment_id, ..)| segment_endpoints.contains_key(segment_id))
.for_each(|(segment_id, bezier, start, end)| {
if segment_endpoints.get(&segment_id).unwrap().len() == 1 {
let point_to_render = segment_endpoints.get(&segment_id).unwrap()[0];
overlay_bezier_handle_specific_point(segment_id, bezier, start, end, transform, overlay_context, selected, is_selected, point_to_render);
overlay_bezier_handle_specific_point(bezier, segment_id, (start, end), point_to_render, transform, is_selected, overlay_context);
} else {
overlay_bezier_handles(segment_id, bezier, transform, overlay_context, selected, is_selected);
overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context);
}
});
}
DrawHandles::None => {}
}

for (&id, &position) in vector_data.point_domain.ids().iter().zip(vector_data.point_domain.positions()) {
overlay_context.manipulator_anchor(transform.transform_point2(position), is_selected(selected, ManipulatorPointId::Anchor(id)), None);
overlay_context.manipulator_anchor(transform.transform_point2(position), is_selected(ManipulatorPointId::Anchor(id)), None);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::collections::HashMap;

use super::utility_functions::overlay_canvas_context;
use crate::consts::{
COLOR_OVERLAY_BLUE, COLOR_OVERLAY_TRANSPARENT, COLOR_OVERLAY_WHITE, COLOR_OVERLAY_YELLOW, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER,
Expand All @@ -13,6 +11,7 @@ use graphene_std::vector::{PointId, SegmentId, VectorData};
use core::borrow::Borrow;
use core::f64::consts::TAU;
use glam::{DAffine2, DVec2};
use std::collections::HashMap;
use wasm_bindgen::JsValue;

pub type OverlayProvider = fn(OverlayContext) -> Message;
Expand Down
Loading

0 comments on commit 2c6c13e

Please sign in to comment.