When point/curves count of a `GreasePencilDrawing` is changed, prior stroke
slices are no longer valid. This is not obvious when using the `stroke()`
call since it is meant to provide a easier access to the drawing data and
did not represent the actual data layout in the drawing, hence we need an
additional note in the document to tell users to be more careful.
Pull Request: https://projects.blender.org/blender/blender/pulls/126815
Writing to the `curve_type` attribute directly is not allowed as there are other
updates needed and otherwise will result in a crash.
The fix makes sure the `curve_type` is read-only. To change the curve type,
the `grease_pencil.set_curve_type` operator has to be used for now.
With layered actions, the bake action wasn't working.
More specifically it failed to create a slot on the action
and link that slot on the animation data.
The fix is to create the slot.
Pull Request: https://projects.blender.org/blender/blender/pulls/126546
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
This extends the `GreasePencilDrawing` rna type using python.
The goal is to add an API that allows developers to transition to
the new grease pencil API a bit more smoothly.
Adds the following endpoints to the `GreasePencilDrawing`:
* `drawing.strokes`: Returns a list/slice of `GreasePencilStroke`s in the drawing.
Adds a python class `GreasePencilStroke`:
* `stroke.points`: Returns a list/slice of `GreasePencilStrokePoint`s.
* Getters/Setters of attributes for this stroke:
* `stroke.cyclic`
* `stroke.material_index`
* `stroke.select`
* `stroke.softness` (used to be `hardness`)
* `stroke.start_cap`
* `stroke.end_cap`
* `stroke.curve_type`: The type of curve: `POLY`,`BEZIER`,`CATMULL_ROM`,`NURBS`.
* `stroke.aspect_ratio`
* `stroke.fill_opacity`
* `stroke.fill_color`
* `stroke.time_start`
* High-level functions:
* `stroke.add_points(count)`: Adds `count` points at the end of the stroke.
* `stroke.remove_points(count)`: Removes `count` points from the end of the stroke. Note that this will not remove the stroke if the count is greater than the number of points in the stroke. A stroke has at least 1 point. Removing strokes can be done from the drawing.
Adds a python class `GreasePencilStrokePoint`:
* Getters/Setters of attributes for this point:
* `position`
* `radius`
* `opacity`
* `select`
* `vertex_color`
* `rotation`
* `delta_time`
Note that `GreasePencilStroke` and `GreasePencilStrokePoint` are not stored in the file and don't have an RNA API. This means that they are not compatible with e.g. `layout.prop`.
This API should not be used for performance critical code. It's likely
even slower than the python API from 4.2.
There will be migration documentation for addon developers here:
https://developer.blender.org/docs/release_notes/4.3/grease_pencil/#python-api-changes
Pull Request: https://projects.blender.org/blender/blender/pulls/125599
The lazy-connect feature of node wrangler uses the built-in `connect_sockets`
function which automatically handles virtual sockets in group input and output
nodes already. However, it does not handle virtual sockets in other nodes.
The fix is to generalize this behavior. For that, a new `handle_dynamic_sockets`
boolean input is added to `tree.links.new`. When enabled, virtual sockets are
handled properly by internally calling the `bNodeType.insert_link` methods.
The new behavior is turned of by default for compatibility reasons.
Pull Request: https://projects.blender.org/blender/blender/pulls/126282
- Paths of C++-parsed files were not properly 'unixified' on Windows.
This was bad both for changes noisyness in PO files, and broke on
the un-escaping of `\n` and `\t` sequences.
- The `ProcessPoolExecutor` starts sub-processes differently on Linux
than on Windows or OSX. While Linux's `fork` keeps the same
environment (i.e. all Blender stuff remains available in workers
subprocesses), the 'spawn' used on Windows (and reportedly OSX) starts
a new bare python interpreter. This means that code executed by these
needs to be Blender-agnostic to be portable.
The only thing that is currently known broken on non-Linux platforms is
the RTL processing of some languages like Arabic or Hebrew.
When deleting files on WIN32, open files cannot be removed.
This is especially a problem for compiled Python modules which
remain open once imported.
Previously it was not as common for add-ons to include compiled Python
modules however with extensions supporting Python-wheels,
it's increasingly likely users run into this.
Workaround the problem by:
- Scheduling the files for removal next time Blender starts.
- Rename paths that cannot be removed to avoid collisions when
the paths is reused (re-installing for example).
This is supported for:
- Extensions.
- Python wheels.
- Legacy user add-ons.
- App-templates.
Details:
- On startup, a file exists that indicates cleanup is needed.
In the common case the file doesn't exist.
Otherwise module paths are scanned for files to remove.
- Since errors resolving paths to remove could result in user data loss,
ensure the paths are always within the (extension/addon/app-template)
directory.
- File locking isn't used, if multiple Blender instances start at the
same time and try to remove the same files, this won't cause errors.
Even so, remove the checking file immediately avoid unnecessary
file-system access overhead for other Blender instances.
Also resolves#125049.
Expose arguments to use when creating a Python sub-process.
Python could fail to start when loaded in a customized environment,
with PYTHONPATH set for e.g. Blender ignores these and loads but a
Python sub-process attempts to use these environment variables which
may point to incompatible Python versions.
Resolve the root cause of #124731.
As each extension has it's own package, any modules it includes must be
imported as sub-modules. Warn if extensions are including themselves
in the sys.path as this breaks name-spacing of extensions.
Show these warnings in the add-on & extensions UI.
When the extensions add-on module was loaded before the add-on was
enabled, the module was detected as having changed since it had no
`__time__` member. Loading the add-on would then reload the module.
Resolve by setting the __time__ when first importing.
This is the main merge commit of the brush assets project. The previous
commits did some preparing changes, more tweaks are in the following commits.
Also, a lot of the more general work was already merged into the main branch
over the last two years.
With the new design, quite some things can be removed/replaced:
- There's a unified "Brush" tool now, brush based tools and all special
handling is removed.
- Old tool and brush icons are unsed now, and their initialization code
removed here. That means they draw as blank now, and the icon files can be
removed in a follow up.
- Creation of default brushes is unnecessary since brushes are now bundled in
the Essentials asset library. Icons/previews are handled as standard asset
previews.
- Grease pencil eraser options are replaced by a general default eraser brush
that can be set by the user.
More changes are planned still, see task list issue below.
Main Authors: Bastien Montagne, Brecht Van Lommel, Hans Goudey, Julian Eisel
Additionally involved on the design: Dalai Felinto, Julien Kaspar
Blog Post: https://code.blender.org/2024/07/brush-assets-is-out/
Tasks:
https://projects.blender.org/blender/blender/issues/116337
Reviewed incrementally as part of the brush assets project, see:
https://projects.blender.org/blender/blender/pulls/106303
When a registered class has a non-registered superclass,
rna_info.BuildRNAInfo entered an eternal loop.
The while loop in `rna_info.get_py_class_from_rna` was not mutating the
variables within the loop nor the variable in its condition, meaning it
would loop infinitely if the loop didn't exit in its first iteration.
When yielding registered classes in `subclasses_recurse`, the function
was erroneously checking if the class' superclass was registered rather
than checking the class itself, causing registered classes to be skipped
if their superclass was not also registered. If the class to be found
was skipped, the while loop would not exit in its first iteration and
would thus loop infinitely.
The while loop has been modified to iterate through each base rna type
until there is no further base type.
The `subclasses_recurse` function now correctly checks whether the
subclass is registered, not its superclass, when determining if the
subclass should be yielded.
Besides the fix, no functional changes are expected, the generated
Python API docs remain unchanged.
Ref: !108256
Previously add-ons were sorted by category & name, remove the category
only sorting by name since the category is no longer displayed and
isn't part of extension meta-data. Now the add-ons are sorted by name
(case insensitive).
Details:
- Store add-ons modules sorted to avoid having to sort on every redraw.
- addon_utils.modules() now returns an iterator.
Changes to an extensions manifest weren't accounted for.
This was particularly a problem for "System" extensions which aren't
intended to be managed inside Blender however the problem existed for
any changes made outside of Blender.
Now enabled extensions are checked on startup to ensure:
- They are compatible with Blender.
- The Python wheels are synchronized.
Resolves#123645.
Details:
- Any extension incompatibilities prevent the add-on being enabled
with a message printing the reason for it being disabled.
- Incompatible add-ons are kept enabled in the preferences to avoid
loosing their own preferences and allow for an upgrade to restore
compatibility.
- To avoid slowing down Blender's startup:
- Checks are skipped when no extensions are enabled
(as is the case for `--factory-startup` & running tests).
- Compatibility data is cached so in common case,
the cache is loaded and all enabled extensions `stat` their
manifests to detect changes without having to parse them.
- The cache is re-generated if any extensions change or the
Blender/Python version changes.
- Compatibility data is updated:
- On startup (when needed).
- On an explicit "Refresh Local"
(mainly for developers who may edit the manifest).
- When refreshing extensions after install/uninstall etc.
since an incompatible extensions may become compatible
after an update.
- When reloading preferences.
- Additional info is shown when the `--debug-python` is enabled,
if there are ever issues with the extension compatibility cache
generation not working as expected.
- The behavior for Python wheels has changed so they are only setup
when the extension is enabled. This was done to simplify startup
checks and has the benefit that an installed but disabled extension
never runs code - as the ability to install wheels means it could
have been imported from other scripts. It also means users can disable
an extension to avoid wheel version conflicts.
This does add the complication however that enabling add-on which is
an extension must first ensure it's wheels are setup.
See `addon_utils.extensions_refresh(..)`.
See code-comments for further details.