Clean-up of clone code (#2851)

pull/2872/head
capellancitizen 2024-04-23 18:09:32 -04:00 zatwierdzone przez GitHub
rodzic 275843c2b2
commit cca25ba679
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
2 zmienionych plików z 26 dodań i 19 usunięć

Wyświetl plik

@ -4,11 +4,10 @@
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from math import degrees
from copy import deepcopy
from contextlib import contextmanager
from typing import Generator, List
from inkex import Transform, BaseElement, Style
from inkex import Transform, BaseElement
from shapely import MultiLineString
from ..stitch_plan.stitch_group import StitchGroup
@ -43,7 +42,7 @@ class Clone(EmbroideryElement):
@property
@param('clone', _("Clone"), type='toggle', inverse=False, default=True)
def clone(self):
return self.get_boolean_param("clone")
return self.get_boolean_param("clone", True)
@property
@param('angle',
@ -81,6 +80,9 @@ class Clone(EmbroideryElement):
return elements
def to_stitch_groups(self, last_stitch_group=None) -> List[StitchGroup]:
if not self.clone:
return []
with self.clone_elements() as elements:
stitch_groups = []
@ -123,22 +125,18 @@ class Clone(EmbroideryElement):
parent: BaseElement = self.node.getparent()
source_node: BaseElement = self.node.href
source_parent: BaseElement = source_node.getparent()
cloned_node = deepcopy(source_node)
cloned_node = source_node.copy()
if recursive:
# Recursively resolve all clones as if the clone was in the same place as its source
source_parent.add(cloned_node)
if is_clone(cloned_node):
resolved_cloned_node = Clone(cloned_node).resolve_clone()
cloned_node.getparent().remove(cloned_node)
# Replace the cloned_node with its resolved version
cloned_node = resolved_cloned_node
cloned_node = cloned_node.replace_with(Clone(cloned_node).resolve_clone())
else:
clones: List[BaseElement] = [n for n in cloned_node.iterdescendants() if is_clone(n)]
for clone in clones:
Clone(clone).resolve_clone()
clone.getparent().remove(clone)
clone.replace_with(Clone(clone).resolve_clone())
source_parent.remove(cloned_node)
@ -146,14 +144,10 @@ class Clone(EmbroideryElement):
parent.add(cloned_node)
# The transform of a resolved clone is based on the clone's transform as well as the source element's transform.
# This makes intuitive sense: The clone of a scaled item is also scaled, the clone of a rotated item is also rotated, etc.
cloned_node.set('transform', Transform(self.node.get('transform')) @ Transform(cloned_node.get('transform')))
cloned_node.transform = self.node.transform @ cloned_node.transform
# Merge the style, if any: Note that the source node's style applies on top of the use's, not the other way around.
clone_style = self.node.get('style')
if clone_style:
merged_style = Style(clone_style)
merged_style.update(cloned_node.get('style'))
cloned_node.set('style', merged_style)
cloned_node.style = self.node.style + cloned_node.style
# Compute angle transform:
# Effectively, this is (local clone transform) * (to parent space) * (from clone's parent space)
@ -174,7 +168,6 @@ class Clone(EmbroideryElement):
# Otherwise we'd have to calculate the transform of (0,0) and subtract it from the transform of (1,0)
angle_transform = Transform((transform.a, transform.b, transform.c, transform.d, 0.0, 0.0))
elements = self.clone_to_elements(cloned_node)
for node in cloned_node.iter():
# Only need to adjust angles on embroiderable nodes
if node.tag not in EMBROIDERABLE_TAGS:
@ -195,8 +188,6 @@ class Clone(EmbroideryElement):
node.set(INKSTITCH_ATTRIBS['angle'], round(element_angle, 6))
return elements
@property
def shape(self):
path = self.node.get_path()

Wyświetl plik

@ -34,6 +34,22 @@ class CloneElementTest(TestCase):
stitch_groups = clone.to_stitch_groups(None)
self.assertEqual(len(stitch_groups), 0)
def test_not_clone(self):
root: SvgDocumentElement = svg()
rect = root.add(Rectangle(attrib={
"width": "10",
"height": "10",
INKSTITCH_ATTRIBS["angle"]: "30"
}))
use = root.add(Use(attrib={
INKSTITCH_ATTRIBS["clone"]: "false"
}))
use.href = rect
clone = Clone(use)
stitch_groups = clone.to_stitch_groups(None)
self.assertEqual(len(stitch_groups), 0)
# These tests make sure the element cloning works as expected, using the `clone_elements` method.
def test_basic(self):