Move operators and preferences out of __init__.py into dedicated modules.
Fix cyclic import by using proper AddonPreferences pattern. Replace
implicit .zip extension detection in CLI with explicit -z/--zip flag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
As addresses typically represented everywhere as hex values.
Before:
```
Biggest ARegion-DATA block is 304 B at address 1585888006560
Finding what points there
<BlendFileBlock.ScrArea (DATA), size=184 at 0x1713e4acd60> (b'regionbase', b'first')
<BlendFileBlock.ARegion (DATA), size=304 at 0x1713e4a9020> b'prev'
```
After:
```
Biggest ARegion-DATA block is 304 B at address 0x1713e4a91a0
Finding what points there
<BlendFileBlock.ScrArea (DATA), size=184 at 0x1713e4acd60> (b'regionbase', b'first')
<BlendFileBlock.ARegion (DATA), size=304 at 0x1713e4a9020> b'prev'
```
Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92900
Extend `Struct.field_set()` so that the `path` type can be a
`dna.FieldPath`, to mirror `Struct.field_get`'s `path` type, and allow
users to set file-block's subproperties. For example this allows
setting `object_block[(b'id', 'name')]`.
Also, along the way, added a test for getting subproperty value.
Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92899
Add an `array_index` parameter to `block.get(property_name)` to get a
specific item from an array.
Example:
```python
verts = self.bf.block_from_addr[verts_ptr]
assert verts.get(b"co") == [-1.0, -1.0, -1.0] # index 0
assert verts.get(b"co", array_index=1) == [-1.0, -1.0, 1.0]
```
Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92898
Add support for geometry node simulation cache files.
This also adds support for dealing with dynamic arrays in Blender's
DNA, because `modifier.bakes` is a pointer to such an array.
Co-authored-by: Sybren A. Stüvel <sybren@blender.org>
Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92890
BlendFileBlock attributes:
Explicit annotation on BlendFileBlock are needed because otherwise
e.g. `block.add_old` type was imprecisely inferred from the
assignments as `int | Any`, where `Any` comes from `.unpack` returning
`tuple[Any, ...]`.
Ideally unpack should be somehow connected to the returned types, but
this solution should work for now just to avoid typing errors.
dna_io - add some missing annotations:
Some annotations were needed to ensure `block.code` will be inferred
as `bytes` and not `bytes | Unknown`.
Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92897
Reviewed-by: Sybren A. Stüvel <sybren@blender.org>
This is mostly the same as blender/blender!140195. The header parsing code has
been updated to be able to read old and new .blend file headers.
There is a new test file which is the same as the existing `basic_file.blend`,
but saved with the new header format. A new unit test has been added to check
that this file is read correctly as well.
Pull Request: https://projects.blender.org/blender/blender-asset-tracer/pulls/92893
Add support for the Dynamic Paint modifier point cache.
I added a walker to iterate through all surfaces on a canvas to get each surface's point cache.
Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92889
Reviewed-by: Sybren A. Stüvel <sybren@blender.org>
When an asset is represented as directory in Blender (for example fluid
simulation caches), that directory is traced and each file is considered
an asset.
This makes it considerably easier for Shaman clients, as they need to
compute the SHA256 checksum of each file. The logic to transform a
directory path to a list of the contained files is now in BAT itself.
Add functions to interpret the data in a `BlendFileBlock` as either `bytes`
or `string`. This is used to obtain the contents of a `char*` (instead
of an embedded `char[N]` array).
Previously the `callback.trace_blendfile()` callback was called just before
tracing its dependencies would start, i.e. after opening it. This is now
changed to before opening it, because that can take a long time (to load
SDNA). this will make any UI (like the Flamenco add-on) report the right
filename when waiting for big files, instead of lingering on the
last-opened (potentially very small) blend file.
In some unexpected situations BAT would just show that the
`bfile_pp is not None` assertion failed. Now it also shows which file is
the one causing this issue, aiding in debugging the situation.
---
The blendfile module within BAT supports reading data from structs, such
as the Count property on an array modifier. However, blendfile only
supports modifying structs with type "char". This patch adds support for
writing structs of more types in blendfile blocks. Now, writing is
supported for ushort, short, uint, int, float, and ulong types.
The use case that inspired this patch was an instance where a file had
several array modifiers that prevented the file from being opened in
Blender on machines without large amounts of RAM. A solution using the
blendfile module may look like:
```
from blender_asset_tracer import blendfile
from pathlib import Path
b = blendfile.open_cached(Path('flag.blend'), mode='rb+')
for block in b.blocks:
if 'ArrayModifierData' in block.__str__():
try:
print('previous:', block.get(b'count'))
block.set(b'count', 1)
print('current:', block.get(b'count'))
except KeyError:
continue
b.close()
```
This would fail with the exception
`blender_asset_tracer.blendfile.exceptions.NoWriterImplemented: Setting
type Struct(b'int') is not supported for ArrayModifierData.count`. With
this patch, the above code succeeds and the count struct can be set to
a lower number that allows the file to be opened.
This solution implements missing functionality without adding any new
interfaces. A few details are:
* When deciding what type to write to the struct, the value is inferred
from what is given by the caller. If the caller gives a Python int, the
exact type is inferred from the DNA type ID. If they give a float, a
float is written. Otherwise, the existing logic is used to determine
whether to write a string or byte sequence.
* A \_write method was added to dna\_io.py that takes a Python struct
object and a value to write a byte sequence to the file object. This
method is used by public methods appropriately named to indicate what
type they will write.
* The check for whether the caller is trying to write an unsupported
type is left in place, but it has been changed to include types which
are now supported.
* Tests have been added that provide a mock file object, call the new
methods, and confirm that the correct bytes were written.
Reviewed By: sybren
Differential Revision: https://developer.blender.org/D14374
Decided to *not* support the Shaman API of Flamenco 3.x in BAT. The
support for that protocol will be implemented in the Flamenco 3.x add-on
for Blender, and not in BAT itself.
A future version of BAT will remove the Shaman API support altogether.
Avoiding late imports helps to isolate Blender add-ons bundling BAT from
each other.
There was one late/lazy import to avoid a dependency cycle. This was
solved by simply copying that one tiny function.