Store click targets in Arc (#3726)

This commit is contained in:
Dennis Kobert
2026-02-06 13:35:32 +01:00
committed by GitHub
parent 1a9f0a543c
commit 5efa81df85
5 changed files with 29 additions and 18 deletions

View File

@@ -1,4 +1,5 @@
use std::path::PathBuf;
use std::sync::Arc;
use super::utility_types::misc::{GroupFolderType, SnappingState};
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
@@ -203,7 +204,7 @@ pub enum DocumentMessage {
first_element_source_id: HashMap<NodeId, Option<NodeId>>,
},
UpdateClickTargets {
click_targets: HashMap<NodeId, Vec<ClickTarget>>,
click_targets: HashMap<NodeId, Vec<Arc<ClickTarget>>>,
},
UpdateClipTargets {
clip_targets: HashSet<NodeId>,

View File

@@ -42,6 +42,7 @@ use graphene_std::vector::misc::{dvec2_to_point, point_to_dvec2};
use graphene_std::vector::style::RenderMode;
use kurbo::{Affine, CubicBez, Line, ParamCurve, PathSeg, QuadBez};
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
#[derive(ExtractField)]
@@ -3071,7 +3072,14 @@ impl<'a> ClickXRayIter<'a> {
}
/// Handles the checking of the layer where the target is a rect or path
fn check_layer_area_target(&mut self, click_targets: Option<&Vec<ClickTarget>>, clip: bool, layer: LayerNodeIdentifier, path: Vec<path_bool_lib::PathSegment>, transform: DAffine2) -> XRayResult {
fn check_layer_area_target(
&mut self,
click_targets: Option<&[Arc<ClickTarget>]>,
clip: bool,
layer: LayerNodeIdentifier,
path: Vec<path_bool_lib::PathSegment>,
transform: DAffine2,
) -> XRayResult {
// Convert back to Kurbo types for intersections
let segment = |bezier: &path_bool_lib::PathSegment| match *bezier {
path_bool_lib::PathSegment::Line(start, end) => PathSeg::Line(Line::new(dvec2_to_point(start), dvec2_to_point(end))),
@@ -3088,7 +3096,7 @@ impl<'a> ClickXRayIter<'a> {
// In the case of a clip path where the area partially intersects, it is necessary to do a boolean operation.
// We do this on this using the target area to reduce computation (as the target area is usually very simple).
if clip && intersects {
let clip_path = click_targets_to_path_lib_segments(click_targets.iter().flat_map(|x| x.iter()), transform);
let clip_path = click_targets_to_path_lib_segments(click_targets.iter().flat_map(|x| x.iter()).map(|x| x.as_ref()), transform);
let subtracted = boolean_intersect(path, clip_path).into_iter().flatten().collect::<Vec<_>>();
if subtracted.is_empty() {
use_children = false;

View File

@@ -13,6 +13,7 @@ use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
use graphene_std::vector::{PointId, Vector};
use std::collections::{HashMap, HashSet};
use std::num::NonZeroU64;
use std::sync::Arc;
// ================
// DocumentMetadata
@@ -26,7 +27,7 @@ pub struct DocumentMetadata {
pub local_transforms: HashMap<NodeId, DAffine2>,
pub first_element_source_ids: HashMap<NodeId, Option<NodeId>>,
pub structure: HashMap<LayerNodeIdentifier, NodeRelations>,
pub click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>,
pub click_targets: HashMap<LayerNodeIdentifier, Vec<Arc<ClickTarget>>>,
pub clip_targets: HashSet<NodeId>,
pub vector_modify: HashMap<NodeId, Vector>,
/// Transform from document space to viewport space.
@@ -46,8 +47,8 @@ impl DocumentMetadata {
self.structure.contains_key(&layer)
}
pub fn click_targets(&self, layer: LayerNodeIdentifier) -> Option<&Vec<ClickTarget>> {
self.click_targets.get(&layer)
pub fn click_targets(&self, layer: LayerNodeIdentifier) -> Option<&[Arc<ClickTarget>]> {
self.click_targets.get(&layer).map(|x| x.as_slice())
}
/// Access the [`NodeRelations`] of a layer.
@@ -206,7 +207,7 @@ impl DocumentMetadata {
}
pub fn layer_outline(&self, layer: LayerNodeIdentifier) -> impl Iterator<Item = &subpath::Subpath<PointId>> {
static EMPTY: Vec<ClickTarget> = Vec::new();
static EMPTY: Vec<Arc<ClickTarget>> = Vec::new();
let click_targets = self.click_targets.get(&layer).unwrap_or(&EMPTY);
click_targets.iter().filter_map(|target| match target.target_type() {
ClickTargetType::Subpath(subpath) => Some(subpath),
@@ -215,7 +216,7 @@ impl DocumentMetadata {
}
pub fn layer_with_free_points_outline(&self, layer: LayerNodeIdentifier) -> impl Iterator<Item = &ClickTargetType> {
static EMPTY: Vec<ClickTarget> = Vec::new();
static EMPTY: Vec<Arc<ClickTarget>> = Vec::new();
let click_targets = self.click_targets.get(&layer).unwrap_or(&EMPTY);
click_targets.iter().map(|target| target.target_type())
}

View File

@@ -31,6 +31,7 @@ use serde_json::{Value, json};
use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::Hash;
use std::ops::Deref;
use std::sync::Arc;
/// All network modifications should be done through this API, so the fields cannot be public. However, all fields within this struct can be public since it it not possible to have a public mutable reference.
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
@@ -3078,7 +3079,7 @@ impl NodeNetworkInterface {
self.document_metadata
.click_targets
.get(&layer)
.map(|click| click.iter().map(ClickTarget::target_type))
.map(|click| click.iter().map(|x| x.target_type()))
.map(|target_types| Vector::from_target_types(target_types, true))
}
@@ -3180,7 +3181,7 @@ impl NodeNetworkInterface {
}
/// Update the cached click targets of the layers
pub fn update_click_targets(&mut self, new_click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>) {
pub fn update_click_targets(&mut self, new_click_targets: HashMap<LayerNodeIdentifier, Vec<Arc<ClickTarget>>>) {
self.document_metadata.click_targets = new_click_targets;
}