mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 03:08:11 +08:00
* Dissolve Points from path * Add handling for removing the first anchor * Add function to turn handles into bez_paths * Created overlay manager, wip * WIP Refactor of VectorShape / Overlays / ShapeEditor * WIP stripping vector shape, anchor, point. * WIP Removed kurbo deps from vector shape, anchor, point * WIP Further work to make vector shapes / anchors / points more standalone. * WIP more pruning * WIP Progress on overlay_renderer * WIP more overlay_renderer work * WIP more pruning, cleared warnings * WIP decided ShapeRenderer wasn't an accurate name, ShapeAdapter now. Error squashing continues. * WIP squashed more errors, now need to decide if anchors should have unique IDs * WIP Errors squashed, now to actually make it work. * WIP Moved vector structs to graphene, beginning to remove bezpath from shape_layer * Refactoring: disentangle kurbo from apply_affine * Refactor internal shape and remove reliance on Kurbo (PR #617) - Disentangle Kurbo (#619) * Refactoring: disentangle kurbo from apply_affine * Broke boolean operations, refactor in state which compiles * "fixed" boolean operation refactor related errors * fixed apply_affine, which would not have applied any type of affine * Small Cleanup, readability * Fix issue with overlay styles no longer showing selection state. * Resolved error with point option * WIP, figuring out how to have one source of truth for VectorShape. Trying to avoid cloning. * WIP work on single source of truth vectorshapes * More steps toward single source of truth VectorShape * Continued wip on making VectorShapes mutably accessible without cloning * Wip using paths to reference vectorshapes instead, need to restructure ShapeEditor * Decided to allow temporary copies of vectorshapes. * Removed HashSet for selected shape indices * Added @TrueDoctor's id_storage.rs with some heavy modification. Added it to VectorShape. Isn't yet used for folders. * Integrated UniqueElements<T> with VectorShape to store VectorAnchors * Improved storage_id.rs perf and cleaned up it's interface * Iterator Implementations and fixes (#637) * Refactoring: disentangle kurbo from apply_affine * Broke boolean operations, refactor in state which compiles * "fixed" boolean operation refactor related errors * fixed apply_affine, which would not have applied any type of affine * implemented transforms for VectorAnchors implemented Not for VectorControlPointType * started adding Vector Shape implementations of shape prototypes * added several useful implemtations to UniqueElements * added another implemnation for UniqueElements to make working with iterators easier, fixed vector-shape errors * package-lock.json * clean up rebase, added back Layer paths * added deref implementation for VectorShape * unnecesary variable * simplify code by removing levels of indirection * fixed errors * merge cleanup * removed package-lock.json * Removed .selected from VectorShape, it isn't needed as layers are selected not shapes specifically. * Removed transform and layer_path from VectorShape * Auto-saving tentitively working. Work toward Overlay transform issues. * Overlays properly hiding and caching. Not clearing cache yet and some tool switching issues remain, but progress. * Putting layers in folders changes their unique ID. This is problematic. Assumed this was not the case. * Removed need for closed bool, changed VectorShape to a tuple struct. * WIP Switched to layer paths as opposed to VectorShapes. Next up add messages for changing VectorShapes. * Added initial messages to edit VectorShape points. * DeleteSelectedPoints messages implemented, selection isn't working currently though. * Selection messages arriving in document, but transform is wrong. * Selection, Deselection working, delete working for first point. * Working towards moving points again * Removed extra vec from UniqueElements, attempting to squash ordering bug. Still appears to occur though. * Delete more stable, clean up, renamed to HandleIn, HandleOut * Further vec_unique cleanup * Further cleanup * Removed Deref / DerefMut from VectorShape * Document version++, will likely revert before merge into master * Seleting / deleting handles tentitively working again. * Version number bump, fixed tests. * Fixed comment in VecUnique * Improved VecUnique descriptor comment * Renamed VecUnique to IdBackedVec to further clarify usage. * Resolved formatting. * WIP Fixing dragging points * Fixed an instance where an OverlayMessage could be sent to the main document incorrectly. * Deleting all of a shapes points now gracefully deletes the layer instead of crashing. * Fixed handle configurations that would panic on deletion * Single anchor dragging restored with multi-dragging next plus handles * sides.into() * Handle and Multi-point dragging working * WIP Handle symmetry working again * Handle mirroring functional again. * Cleaned up warnings * Fixed overlay outline not matching shape * Git branch fix of compatibility with new master * Fixed closed shape bug, replaced kurbo ellipse * Removed unused func, updated comments * Deleting points can undo, multiple shape selection deletes now working * Removed AddOverlay* operations * Partial fix for select drift, added helpers * Don't snap against dragging points * Properly cleanup path outline with multiple shapes * Clear all points in other selected shapes * Actually don't snap against dragging points * Fix path tool & add snap angle and break handle * Fix handle being set to NaN causing render issues * Fix cached overlays not showing line -> curve * Add operations for modifying paths * Remove kurbo from pen tool * Do not snap against handles when anchor selected * Fix overlays not being cleaned up on path tool * Fix handle position after dragging * Use `Anchor` for text & no kurbo in operations * Replace kurbo to_svg function * Ngon no longer center scales by default, still some weird behaviour when holding alt * Cleanup overlays * Fix render and bounding box doctests * Fix fun to_svg error * Fix compile error * Some code review * Remove legacy `SelectPoint` on doubleclick * Remove font from test document * Fix the pen tool selection changed * Reorder imports Co-authored-by: Dennis <dennis@kobert.dev> Co-authored-by: Caleb Dennis <caleb.dennis429@gmail.com> Co-authored-by: caleb <56044292+caleb-ad@users.noreply.github.com> Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: 0hypercube <0hypercube@gmail.com> Co-authored-by: 0HyperCube <78500760+0HyperCube@users.noreply.github.com>
173 lines
5.3 KiB
Rust
173 lines
5.3 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
/// Brief description: A vec that allows indexing elements by both index and an assigned unique ID
|
|
/// Goals of this Data Structure:
|
|
/// - Drop-in replacement for a Vec.
|
|
/// - Provide an auto-assigned Unique ID per element upon insertion.
|
|
/// - Add elements to the start or end.
|
|
/// - Insert element by Unique ID. Insert directly after an existing element by its Unique ID.
|
|
/// - Access data by providing Unique ID.
|
|
/// - Maintain ordering among the elements.
|
|
/// - Remove elements without changing Unique IDs.
|
|
/// This data structure is somewhat similar to a linked list in terms of invarients.
|
|
/// The downside is that currently it requires a lot of iteration.
|
|
|
|
type ElementId = u64;
|
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
|
pub struct IdBackedVec<T> {
|
|
/// Contained elements
|
|
elements: Vec<T>,
|
|
/// The IDs of the [Elements] contained within this
|
|
element_ids: Vec<ElementId>,
|
|
/// The ID that will be assigned to the next element that is added to this
|
|
#[serde(skip)]
|
|
next_id: ElementId,
|
|
}
|
|
|
|
impl<T> IdBackedVec<T> {
|
|
/// Push a new element to the start of the vector
|
|
pub fn push_front(&mut self, element: T) -> Option<ElementId> {
|
|
self.next_id += 1;
|
|
self.elements.insert(0, element);
|
|
self.element_ids.insert(0, self.next_id);
|
|
Some(self.next_id)
|
|
}
|
|
|
|
// Push an element to the end of the vector
|
|
pub fn push_end(&mut self, element: T) -> Option<ElementId> {
|
|
self.next_id += 1;
|
|
self.elements.push(element);
|
|
self.element_ids.push(self.next_id);
|
|
Some(self.next_id)
|
|
}
|
|
|
|
/// Insert an element adjacent to the given ID
|
|
pub fn insert(&mut self, element: T, id: ElementId) -> Option<ElementId> {
|
|
if let Some(index) = self.index_from_id(id) {
|
|
self.next_id += 1;
|
|
self.elements.insert(index, element);
|
|
self.element_ids.insert(index, self.next_id);
|
|
return Some(self.next_id);
|
|
}
|
|
None
|
|
}
|
|
|
|
/// Push an element to the end of the vector
|
|
/// Overriden from Vec, so adding values without creating an id cannot occur
|
|
pub fn push(&mut self, element: T) -> Option<ElementId> {
|
|
self.push_end(element)
|
|
}
|
|
|
|
/// Add a range of elements of elements to the end of this vector
|
|
pub fn push_range<I>(&mut self, elements: I) -> Vec<ElementId>
|
|
where
|
|
I: IntoIterator<Item = T>,
|
|
{
|
|
let mut ids = vec![];
|
|
for element in elements {
|
|
if let Some(id) = self.push_end(element) {
|
|
ids.push(id);
|
|
}
|
|
}
|
|
ids
|
|
}
|
|
|
|
/// Remove an element with a given element ID from the within this container.
|
|
/// This operation will return false if the element ID is not found.
|
|
/// Preserve unique ID lookup by using swap end and updating hashmap
|
|
pub fn remove(&mut self, to_remove_id: ElementId) -> Option<T> {
|
|
if let Some(index) = self.index_from_id(to_remove_id) {
|
|
self.element_ids.remove(index);
|
|
return Some(self.elements.remove(index));
|
|
}
|
|
None
|
|
}
|
|
|
|
/// Get a single element with a given element ID from the within this container.
|
|
pub fn by_id(&self, id: ElementId) -> Option<&T> {
|
|
let index = self.index_from_id(id)?;
|
|
Some(&self.elements[index])
|
|
}
|
|
|
|
/// Get a mutable reference to a single element with a given element ID from the within this container.
|
|
pub fn by_id_mut(&mut self, id: ElementId) -> Option<&mut T> {
|
|
let index = self.index_from_id(id)?;
|
|
Some(&mut self.elements[index])
|
|
}
|
|
|
|
/// Get an element based on its index
|
|
pub fn by_index(&self, index: usize) -> Option<&T> {
|
|
self.elements.get(index)
|
|
}
|
|
|
|
/// Get a mutable element based on its index
|
|
pub fn by_index_mut(&mut self, index: usize) -> Option<&mut T> {
|
|
self.elements.get_mut(index)
|
|
}
|
|
|
|
/// Clear the elements and unique ids
|
|
pub fn clear(&mut self) {
|
|
self.elements.clear();
|
|
self.element_ids.clear();
|
|
}
|
|
|
|
/// Enumerate the ids and elements in this container `(&ElementId, &T)`
|
|
pub fn enumerate(&self) -> impl Iterator<Item = (&ElementId, &T)> {
|
|
self.element_ids.iter().zip(self.elements.iter())
|
|
}
|
|
|
|
/// Mutably Enumerate the ids and elements in this container `(&ElementId, &mut T)`
|
|
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (&ElementId, &mut T)> {
|
|
self.element_ids.iter().zip(self.elements.iter_mut())
|
|
}
|
|
|
|
/// If this container contains an element with the given ID
|
|
pub fn contains(&self, id: ElementId) -> bool {
|
|
self.element_ids.contains(&id)
|
|
}
|
|
|
|
/// Get the index of an element with the given ID
|
|
pub fn index_from_id(&self, element_id: ElementId) -> Option<usize> {
|
|
// Though this is a linear traversal, it is still likely faster than using a hashmap
|
|
self.element_ids.iter().position(|&id| id == element_id)
|
|
}
|
|
}
|
|
|
|
impl<T> Default for IdBackedVec<T> {
|
|
fn default() -> Self {
|
|
IdBackedVec {
|
|
elements: vec![],
|
|
element_ids: vec![],
|
|
next_id: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Allows for usage of UniqueElements as a Vec<T>
|
|
impl<T> Deref for IdBackedVec<T> {
|
|
type Target = [T];
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.elements
|
|
}
|
|
}
|
|
|
|
// TODO Consider removing this, it could allow for ElementIds and Elements to get out of sync
|
|
/// Allows for mutable usage of UniqueElements as a Vec<T>
|
|
impl<T> DerefMut for IdBackedVec<T> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.elements
|
|
}
|
|
}
|
|
|
|
/// Allows use with iterators
|
|
/// Also allows constructing UniqueElements with collect
|
|
impl<A> FromIterator<A> for IdBackedVec<A> {
|
|
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
|
|
let mut new = IdBackedVec::default();
|
|
// Add to the end of the existing elements
|
|
new.push_range(iter);
|
|
new
|
|
}
|
|
}
|