Add Support for Geometry Node Cache #92890

Open
Jonas Dichelle wants to merge 14 commits from JonasDichelle/blender-asset-tracer:geonodes_support into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 24 additions and 27 deletions
Showing only changes of commit 0f904d03c5 - Show all commits

5
.gitignore vendored
View File

@ -10,7 +10,4 @@ __pycache__
/dist/
/build/
/docs/_build
/.env
/.venv
/docs/_build

View File

@ -127,7 +127,9 @@ class BlendFile:
self.blocks = [] # type: BFBList
"""BlendFileBlocks of this file, in disk order."""
self.code_index = collections.defaultdict(list) # type: typing.Dict[bytes, BFBList]
self.code_index = collections.defaultdict(
list
) # type: typing.Dict[bytes, BFBList]
self.structs = [] # type: typing.List[dna.Struct]
self.sdna_index_from_id = {} # type: typing.Dict[bytes, int]
self.block_from_addr = {} # type: typing.Dict[int, BlendFileBlock]

View File

@ -20,6 +20,7 @@
# (c) 2014, Blender Foundation - Campbell Barton
# (c) 2018, Blender Foundation - Sybren A. Stüvel
import typing
import copy
from blender_asset_tracer import cdefs
from . import BlendFileBlock
@ -72,26 +73,22 @@ def modifiers(object_block: BlendFileBlock) -> typing.Iterator[BlendFileBlock]:
yield from listbase(mods, next_path=(b"modifier", b"next"))
JonasDichelle marked this conversation as resolved

I think it's fine to make this function a method on BlendFileBlock. It could then simply be named .clone() or .copy().

Then again, is there any reason to not use copy.copy() and avoid the need for this function altogether?

I think it's fine to make this function a method on `BlendFileBlock`. It could then simply be named `.clone()` or `.copy()`. Then again, is there any reason to not use [copy.copy()](https://docs.python.org/3/library/copy.html#copy.copy) and avoid the need for this function altogether?
Review

yes copy should work fine for this too.

yes copy should work fine for this too.
def copy_block(block: BlendFileBlock) -> BlendFileBlock:
"""Create a new BlendFileBlock instance with the same slot data as the provided block."""
if not isinstance(block, BlendFileBlock):
raise ValueError("The existing_block must be an instance of BlendFileBlock")
new_block = BlendFileBlock(block.bfile)
for slot in BlendFileBlock.__slots__:
setattr(new_block, slot, getattr(block, slot))
return new_block
def dynamic_array(block: BlendFileBlock) -> typing.Iterator[BlendFileBlock]:
"""Generator, yields all blocks in a block that is a dynamic array."""
"""
Generator that yields each element of a dynamic array as a separate block.
Dynamic arrays are multiple contiguous elements accessed via a single pointer.
BAT interprets these as a single data block, making it hard to access individual elements.
This function divides the array into individual blocks by creating modified copies of the original block.
"""
offset = block.file_offset
element_size = block.dna_type.size
for i in range(block.count):
new_block = copy_block(block)
new_block = copy.copy(block)
new_block.file_offset = offset
new_block.size = block.dna_type.size // block.count
new_block.size = element_size
yield new_block
offset += block.dna_type.size
offset += element_size

View File

@ -52,6 +52,9 @@ eModifierType_MeshSequenceCache = 52
eModifierType_Fluid = 56
eModifierType_Nodes = 57
# NodesModifierBakeFlag
NODES_MODIFIER_BAKE_CUSTOM_PATH = 1 << 1
# DNA_particle_types.h
PART_DRAW_OB = 7
PART_DRAW_GR = 8
@ -101,4 +104,4 @@ PTCACHE_PATH = b"blendcache_"
# BKE_node.h
SH_NODE_TEX_IMAGE = 143
CMP_NODE_R_LAYERS = 221
CMP_NODE_R_LAYERS = 221

View File

@ -369,9 +369,7 @@ def modifier_nodes(
)
flag = bake.get(b"flag")
flag_bin = bin(flag)
flag_bin_padded = flag_bin[2:].zfill(2)
use_custom_directory = flag_bin_padded[0] == "1"
use_custom_directory = bool(flag & cdefs.NODES_MODIFIER_BAKE_CUSTOM_PATH)
if use_custom_directory:
JonasDichelle marked this conversation as resolved

Please don't use string operations to get a single bit flag. Add a constant to cdefs.py with the name of the flag, then use something like:

use_custom_path = bool(flag & cdefs.NODES_MODIFIER_BAKE_CUSTOM_PATH)
Please don't use string operations to get a single bit flag. Add a constant to `cdefs.py` with the name of the flag, then use something like: ```python use_custom_path = bool(flag & cdefs.NODES_MODIFIER_BAKE_CUSTOM_PATH) ```
directory_ptr = bake_directory_ptr
@ -382,7 +380,7 @@ def modifier_nodes(
field = mod_directory_field
block = modifier
if directory_ptr == 0:
if not directory_ptr:
continue
directory = bake.bfile.dereference_pointer(directory_ptr)
JonasDichelle marked this conversation as resolved

I think it's slightly nicer to not compare to a concrete value, and just use if not directory_ptr:

I think it's slightly nicer to not compare to a concrete value, and just use `if not directory_ptr:`
if not directory: