diff options
| author | Kaalleen <36401965+kaalleen@users.noreply.github.com> | 2024-03-29 10:25:02 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-29 10:25:02 +0100 |
| commit | 2439adafa8592995d9acead47ef2802d5d95c373 (patch) | |
| tree | bfa10aaf017bc48cf6c166c7adeb9afd5dc12922 /lib/elements | |
| parent | fb1ecd0badf5eb142f17cc7f0f7e8b347151b002 (diff) | |
Add "the tartan universe" (#2782)
Diffstat (limited to 'lib/elements')
| -rw-r--r-- | lib/elements/element.py | 6 | ||||
| -rw-r--r-- | lib/elements/fill_stitch.py | 128 |
2 files changed, 124 insertions, 10 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py index 071f8a90..4ea909ac 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -22,7 +22,7 @@ from ..svg import (PIXELS_PER_MM, apply_transforms, convert_length, get_node_transform) from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS from ..utils import Point, cache -from ..utils.cache import get_stitch_plan_cache, CacheKeyGenerator +from ..utils.cache import CacheKeyGenerator, get_stitch_plan_cache class Param(object): @@ -557,6 +557,9 @@ class EmbroideryElement(object): gradient['styles'] = [(style['stop-color'], style['stop-opacity']) for style in self.gradient.stop_styles] return gradient + def _get_tartan_key_data(self): + return (self.node.get('inkstitch:tartan', None)) + def get_cache_key_data(self, previous_stitch): return [] @@ -572,6 +575,7 @@ class EmbroideryElement(object): cache_key_generator.update(self._get_patterns_cache_key_data()) cache_key_generator.update(self._get_guides_cache_key_data()) cache_key_generator.update(self.get_cache_key_data(previous_stitch)) + cache_key_generator.update(self._get_tartan_key_data()) cache_key = cache_key_generator.get_cache_key() debug.log(f"cache key for {self.node.get('id')} {self.node.get(INKSCAPE_LABEL)} {previous_stitch}: {cache_key}") diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 9ba649d7..cb1d5225 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -18,11 +18,13 @@ from ..i18n import _ from ..marker import get_marker_elements from ..stitch_plan import StitchGroup from ..stitches import (auto_fill, circular_fill, contour_fill, guided_fill, - legacy_fill, linear_gradient_fill, meander_fill) + legacy_fill, linear_gradient_fill, meander_fill, + tartan_fill) from ..stitches.linear_gradient_fill import gradient_angle from ..svg import PIXELS_PER_MM, get_node_transform from ..svg.clip import get_clip_path from ..svg.tags import INKSCAPE_LABEL +from ..tartan.utils import get_tartan_settings, get_tartan_stripes from ..utils import cache from ..utils.geometry import ensure_multi_polygon from ..utils.param import ParamOption @@ -112,6 +114,25 @@ class NoGradientWarning(ValidationWarning): ] +class NoTartanStripeWarning(ValidationWarning): + name = _("No stripes to render") + description = _("Tartan fill: There is no active fill stripe to render") + steps_to_solve = [ + _('Go to Extensions > Ink/Stitch > Fill Tools > Tartan and adjust stripe settings:'), + _('* Check if stripes are active'), + _('* Check the minimum stripe width setting and the scale factor') + ] + + +class DefaultTartanStripeWarning(ValidationWarning): + name = _("No customized pattern") + description = _("Tartan fill: Using default pattern") + steps_to_solve = [ + _('Go to Extensions > Ink/Stitch > Fill Tools > Tartan and adjust stripe settings:'), + _('* Customize your pattern') + ] + + class InvalidShapeError(ValidationError): name = _("This shape is invalid") description = _('Fill: This shape cannot be stitched out. Please try to repair it with the "Break Apart Fill Objects" extension.') @@ -129,11 +150,12 @@ class FillStitch(EmbroideryElement): return self.get_boolean_param('auto_fill', True) _fill_methods = [ParamOption('auto_fill', _("Auto Fill")), + ParamOption('circular_fill', _("Circular Fill")), ParamOption('contour_fill', _("Contour Fill")), ParamOption('guided_fill', _("Guided Fill")), - ParamOption('meander_fill', _("Meander Fill")), - ParamOption('circular_fill', _("Circular Fill")), ParamOption('linear_gradient_fill', _("Linear Gradient Fill")), + ParamOption('meander_fill', _("Meander Fill")), + ParamOption('tartan_fill', _("Tartan Fill")), ParamOption('legacy_fill', _("Legacy Fill"))] @property @@ -247,6 +269,7 @@ class FillStitch(EmbroideryElement): ('fill_method', 'guided_fill'), ('fill_method', 'meander_fill'), ('fill_method', 'circular_fill'), + ('fill_method', 'tartan_fill'), ('fill_method', 'linear_gradient_fill')]) def expand(self): return self.get_float_param('expand_mm', 0) @@ -265,6 +288,19 @@ class FillStitch(EmbroideryElement): return math.radians(self.get_float_param('angle', 0)) @property + @param('tartan_angle', + _('Angle of lines of stitches'), + tooltip=_('Relative to the tartan stripe direction.'), + unit='deg', + type='float', + sort_index=21, + select_items=[('fill_method', 'tartan_fill')], + default=45) + @cache + def tartan_angle(self): + return self.get_float_param('tartan_angle', -45) + + @property @param('max_stitch_length_mm', _('Maximum fill stitch length'), tooltip=_( @@ -276,6 +312,7 @@ class FillStitch(EmbroideryElement): ('fill_method', 'contour_fill'), ('fill_method', 'guided_fill'), ('fill_method', 'linear_gradient_fill'), + ('fill_method', 'tartan_fill'), ('fill_method', 'legacy_fill')], default=3.0) def max_stitch_length(self): @@ -293,6 +330,7 @@ class FillStitch(EmbroideryElement): ('fill_method', 'guided_fill'), ('fill_method', 'circular_fill'), ('fill_method', 'linear_gradient_fill'), + ('fill_method', 'tartan_fill'), ('fill_method', 'legacy_fill')], default=0.25) def row_spacing(self): @@ -323,6 +361,7 @@ class FillStitch(EmbroideryElement): select_items=[('fill_method', 'auto_fill'), ('fill_method', 'guided_fill'), ('fill_method', 'linear_gradient_fill'), + ('fill_method', 'tartan_fill'), ('fill_method', 'legacy_fill')], default=4) def staggers(self): @@ -359,6 +398,18 @@ class FillStitch(EmbroideryElement): @property @param( + 'reverse', + _('Reverse fill'), + tooltip=_('Reverses fill path.'), + type='boolean', + sort_index=28, + select_items=[('fill_method', 'legacy_fill')], + default=False) + def reverse(self): + return self.get_boolean_param("reverse", False) + + @property + @param( 'stop_at_ending_point', _('Stop at ending point'), tooltip=_('If this option is disabled, the ending point will only be used to define a general direction for ' @@ -396,7 +447,8 @@ class FillStitch(EmbroideryElement): ('fill_method', 'guided_fill'), ('fill_method', 'meander_fill'), ('fill_method', 'circular_fill'), - ('fill_method', 'linear_gradient_fill')], + ('fill_method', 'linear_gradient_fill'), + ('fill_method', 'tartan_fill')], sort_index=31) def running_stitch_length(self): return max(self.get_float_param("running_stitch_length_mm", 2.5), 0.01) @@ -434,7 +486,8 @@ class FillStitch(EmbroideryElement): 'A pattern with various repeats can be created with a list of values separated by a space.'), type='str', select_items=[('fill_method', 'meander_fill'), - ('fill_method', 'circular_fill')], + ('fill_method', 'circular_fill'), + ('fill_method', 'tartan_fill')], default=0, sort_index=34) def bean_stitch_repeats(self): @@ -467,6 +520,31 @@ class FillStitch(EmbroideryElement): return self.get_float_param("zigzag_width_mm", 3) @property + @param( + 'rows_per_thread', + _("Rows per tartan thread"), + tooltip=_("Consecutive rows of the same color"), + type='int', + default="2", + select_items=[('fill_method', 'tartan_fill')], + sort_index=35 + ) + def rows_per_thread(self): + return max(1, self.get_int_param("rows_per_thread", 2)) + + @property + @param('herringbone_width_mm', + _('Herringbone width'), + tooltip=_('Defines width of a herringbone pattern. Use 0 for regular rows.'), + unit='mm', + type='int', + default=0, + select_items=[('fill_method', 'tartan_fill')], + sort_index=36) + def herringbone_width(self): + return self.get_float_param('herringbone_width_mm', 0) + + @property def color(self): # SVG spec says the default fill is black return self.get_style("fill", "#000000") @@ -679,6 +757,15 @@ class FillStitch(EmbroideryElement): # they may used a fill on a straight line yield StrokeAndFillWarning(self.paths[0][0]) + # tartan fill + if self.fill_method == 'tartan_fill': + settings = get_tartan_settings(self.node) + warp, weft = get_tartan_stripes(settings) + if not (warp or weft): + yield NoTartanStripeWarning(self.shape.representative_point()) + if not self.node.get('inkstitch:tartan', ''): + yield DefaultTartanStripeWarning(self.shape.representative_point()) + for warning in super(FillStitch, self).validation_warnings(): yield warning @@ -778,19 +865,38 @@ class FillStitch(EmbroideryElement): stitch_groups.extend(self.do_circular_fill(fill_shape, previous_stitch_group, start, end)) elif self.fill_method == 'linear_gradient_fill': stitch_groups.extend(self.do_linear_gradient_fill(fill_shape, previous_stitch_group, start, end)) + elif self.fill_method == 'tartan_fill': + stitch_groups.extend(self.do_tartan_fill(fill_shape, previous_stitch_group, start, end)) else: # auto_fill stitch_groups.extend(self.do_auto_fill(fill_shape, previous_stitch_group, start, end)) if stitch_groups: previous_stitch_group = stitch_groups[-1] - # sort colors of linear gradient (if multiple shapes) - if self.fill_method == 'linear_gradient_fill': - colors = [stitch_group.color for stitch_group in stitch_groups] - stitch_groups.sort(key=lambda group: colors.index(group.color)) + # sort colors of linear gradient + if len(shapes) > 1 and self.fill_method == 'linear_gradient_fill': + self.color_sort(stitch_groups) + + # sort colors of tartan fill + if len(shapes) > 1 and self.fill_method == 'tartan_fill': + # while color sorting make sure stroke lines go still on top of the fills + fill_groups = [] + stroke_groups = [] + for stitch_group in stitch_groups: + if "tartan_run" in stitch_group.stitches[0].tags: + stroke_groups.append(stitch_group) + else: + fill_groups.append(stitch_group) + self.color_sort(fill_groups) + self.color_sort(stroke_groups) + stitch_groups = fill_groups + stroke_groups return stitch_groups + def color_sort(self, stitch_groups): + colors = [stitch_group.color for stitch_group in stitch_groups] + stitch_groups.sort(key=lambda group: colors.index(group.color)) + def do_legacy_fill(self): stitch_lists = legacy_fill( self.shape, @@ -799,6 +905,7 @@ class FillStitch(EmbroideryElement): self.end_row_spacing, self.max_stitch_length, self.flip, + self.reverse, self.staggers, self.skip_last ) @@ -996,3 +1103,6 @@ class FillStitch(EmbroideryElement): def do_linear_gradient_fill(self, shape, last_stitch_group, start, end): return linear_gradient_fill(self, shape, start, end) + + def do_tartan_fill(self, shape, last_stitch_group, start, end): + return tartan_fill(self, shape, start, end) |
