From 850e316688fe48b2ac60dd9de0b94ca98b85fb0e Mon Sep 17 00:00:00 2001 From: Falk David Date: Tue, 20 Aug 2024 11:11:53 +0200 Subject: [PATCH] Refactor: Move Grease Pencil helper classes to `_bpy_internal` This moves the helper python classes from `scripts/modules/grease_pencil_python.py` to `scripts/modules/_bpy_internal/grease_pencil.py`. It also cleans up the code a bit more. No functional changes. Pull Request: https://projects.blender.org/blender/blender/pulls/126403 --- .../_bpy_internal/grease_pencil/__init__.py | 3 + .../grease_pencil/stroke.py} | 137 +++++++++--------- scripts/modules/bpy_types.py | 2 +- 3 files changed, 70 insertions(+), 72 deletions(-) create mode 100644 scripts/modules/_bpy_internal/grease_pencil/__init__.py rename scripts/modules/{grease_pencil_python.py => _bpy_internal/grease_pencil/stroke.py} (80%) diff --git a/scripts/modules/_bpy_internal/grease_pencil/__init__.py b/scripts/modules/_bpy_internal/grease_pencil/__init__.py new file mode 100644 index 00000000000..e566929148e --- /dev/null +++ b/scripts/modules/_bpy_internal/grease_pencil/__init__.py @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: 2024 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later diff --git a/scripts/modules/grease_pencil_python.py b/scripts/modules/_bpy_internal/grease_pencil/stroke.py similarity index 80% rename from scripts/modules/grease_pencil_python.py rename to scripts/modules/_bpy_internal/grease_pencil/stroke.py index aa2bbc62f32..d1fb6cbc577 100644 --- a/scripts/modules/grease_pencil_python.py +++ b/scripts/modules/_bpy_internal/grease_pencil/stroke.py @@ -38,6 +38,50 @@ class AttributeGetterSetter: raise Exception("Could not create attribute {:s} of type {!r}".format(name, type)) +class SliceHelper: + """ + Helper class to handle custom slicing. + """ + + def __init__(self, start: int, stop: int): + self._start = start + self._stop = stop + self._size = stop - start + + def __len__(self): + return self._size + + def _is_valid_index(self, key: int): + if self._size <= 0: + return False + if key < 0: + # Support indexing from the end. + return abs(key) <= self._size + return abs(key) < self._size + + def _getitem_helper(self, key): + if isinstance(key, int): + if not self._is_valid_index(key): + raise IndexError("Key {:d} is out of range".format(key)) + # Turn the key into an index. + return self._start + (key % self._size) + elif isinstance(key, slice): + if key.step is not None and key.step != 1: + raise ValueError("Step values != 1 not supported") + # Default to 0 and size for the start and stop values. + start = key.start if key.start is not None else 0 + stop = key.stop if key.stop is not None else self._size + # Wrap negative indices. + start = self._size + start if start < 0 else start + stop = self._size + stop if stop < 0 else stop + # Clamp start and stop. + start = max(0, min(start, self._size)) + stop = max(0, min(stop, self._size)) + return (self._start + start, self._start + stop) + else: + raise TypeError("Unexpected index of type {!r}".format(type(key))) + + def def_prop_for_attribute(attr_name, type, default, doc): """ Creates a property that can read and write an attribute. @@ -50,6 +94,7 @@ def def_prop_for_attribute(attr_name, type, default, doc): def fset(self, value): # Define `setter` callback for property. self._set_attribute(attr_name, type, value) + prop = property(fget=fget, fset=fset, doc=doc) return prop @@ -88,50 +133,25 @@ class GreasePencilStrokePoint(AttributeGetterSetter): super().__init__(drawing.attributes, point_index, 'POINT') -class GreasePencilStrokePointSlice: +class GreasePencilStrokePointSlice(SliceHelper): """ A helper class that represents a slice of GreasePencilStrokePoint's. """ - def __init__(self, drawing, start, stop): + def __init__(self, drawing, start: int, stop: int): + super().__init__(start, stop) self._drawing = drawing - self._start = start - self._stop = stop - self._size = stop - start def __len__(self): - return self._size - - def _is_valid_index(self, key): - if self._size <= 0: - return False - if key < 0: - # Support indexing from the end. - return abs(key) <= self._size - return abs(key) < self._size + return super().__len__() def __getitem__(self, key): + key = super()._getitem_helper(key) if isinstance(key, int): - if not self._is_valid_index(key): - raise IndexError("Key {:d} is out of range".format(key)) - # Turn the key into an index. - point_i = self._start + (key % self._size) - return GreasePencilStrokePoint(self._drawing, point_i) - elif isinstance(key, slice): - if key.step is not None and key.step != 1: - raise ValueError("Step values != 1 not supported") - # Default to 0 and size for the start and stop values. - start = key.start if key.start is not None else 0 - stop = key.stop if key.stop is not None else self._size - # Wrap negative indices. - start = self._size + start if start < 0 else start - stop = self._size + stop if stop < 0 else stop - # Clamp start and stop. - start = max(0, min(start, self._size)) - stop = max(0, min(stop, self._size)) - return GreasePencilStrokePointSlice(self._drawing, self._start + start, self._start + stop) - else: - raise TypeError("Unexpected index of type {!r}".format(type(key))) + return GreasePencilStrokePoint(self._drawing, key) + elif isinstance(key, tuple): + start, stop = key + return GreasePencilStrokePointSlice(self._drawing, start, stop) # Define the list of attributes that should be exposed as read/write properties on the class. @@ -154,7 +174,7 @@ class GreasePencilStroke(AttributeGetterSetter): A helper class to get access to stroke data. """ - def __init__(self, drawing, curve_index, points_start_index, points_end_index): + def __init__(self, drawing, curve_index: int, points_start_index: int, points_end_index: int): super().__init__(drawing.attributes, curve_index, 'CURVE') self._drawing = drawing self._curve_index = curve_index @@ -168,7 +188,7 @@ class GreasePencilStroke(AttributeGetterSetter): """ return GreasePencilStrokePointSlice(self._drawing, self._points_start_index, self._points_end_index) - def add_points(self, count): + def add_points(self, count: int): """ Add new points at the end of the stroke and returns the new points as a list. """ @@ -178,7 +198,7 @@ class GreasePencilStroke(AttributeGetterSetter): self._points_end_index = self._points_start_index + new_size return GreasePencilStrokePointSlice(self._drawing, previous_end, self._points_end_index) - def remove_points(self, count): + def remove_points(self, count: int): """ Remove points at the end of the stroke. """ @@ -190,49 +210,24 @@ class GreasePencilStroke(AttributeGetterSetter): self._points_end_index = self._points_start_index + new_size -class GreasePencilStrokeSlice: +class GreasePencilStrokeSlice(SliceHelper): """ A helper class that represents a slice of GreasePencilStroke's. """ - def __init__(self, drawing, start, stop): + def __init__(self, drawing, start: int, stop: int): + super().__init__(start, stop) self._drawing = drawing self._curve_offsets = drawing.curve_offsets - self._start = start - self._stop = stop - self._size = stop - start def __len__(self): - return self._size - - def _is_valid_index(self, key): - if self._size <= 0: - return False - if key < 0: - # Support indexing from the end. - return abs(key) <= self._size - return abs(key) < self._size + return super().__len__() def __getitem__(self, key): + key = super()._getitem_helper(key) if isinstance(key, int): - if not self._is_valid_index(key): - raise IndexError("Key {:d} is out of range".format(key)) - # Turn the key into an index. - curve_i = self._start + (key % self._size) offsets = self._curve_offsets - return GreasePencilStroke(self._drawing, curve_i, offsets[curve_i].value, offsets[curve_i + 1].value) - elif isinstance(key, slice): - if key.step is not None and key.step != 1: - raise ValueError("Step values != 1 not supported") - # Default to 0 and size for the start and stop values. - start = key.start if key.start is not None else 0 - stop = key.stop if key.stop is not None else self._size - # Wrap negative indices. - start = self._size + start if start < 0 else start - stop = self._size + stop if stop < 0 else stop - # Clamp start and stop. - start = max(0, min(start, self._size)) - stop = max(0, min(stop, self._size)) - return GreasePencilStrokeSlice(self._drawing, self._start + start, self._start + stop) - else: - raise TypeError("Unexpected index of type {!r}".format(type(key))) + return GreasePencilStroke(self._drawing, key, offsets[key].value, offsets[key + 1].value) + elif isinstance(key, tuple): + start, stop = key + return GreasePencilStrokeSlice(self._drawing, start, stop) diff --git a/scripts/modules/bpy_types.py b/scripts/modules/bpy_types.py index 1bbffd46d37..014ae7e9107 100644 --- a/scripts/modules/bpy_types.py +++ b/scripts/modules/bpy_types.py @@ -1410,7 +1410,7 @@ class GreasePencilDrawing(StructRNA): This API should *not* be used for performance critical operations. Use the :class:`GreasePencilDrawing.attributes` API instead. """ - from grease_pencil_python import GreasePencilStrokeSlice + from _bpy_internal.grease_pencil.stroke import GreasePencilStrokeSlice num_strokes = self.attributes.domain_size('CURVE') if num_strokes > 0: return GreasePencilStrokeSlice(self, 0, num_strokes)