Add Support for Geometry Node Cache #92890
5
.gitignore
vendored
5
.gitignore
vendored
@ -11,3 +11,8 @@ __pycache__
|
||||
/build/
|
||||
|
||||
/docs/_build
|
||||
|
||||
# envs
|
||||
|
||||
/.env
|
||||
/.venv
|
@ -127,9 +127,7 @@ 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]
|
||||
@ -352,6 +350,22 @@ class BlendFile:
|
||||
else:
|
||||
dna_size = dna_type.size * dna_name.array_size
|
||||
|
||||
if dna_name.name_only == b"bakes":
|
||||
array_count = 3 # Total elements in the array
|
||||
item_size = 48 # Size of each item in the array
|
||||
dna_size = (
|
||||
item_size * array_count
|
||||
) # Total size occupied by the array
|
||||
|
||||
# Create a single field for the entire array
|
||||
field = dna.Field(dna_type, dna_name, dna_size, dna_offset)
|
||||
dna_struct.append_field(field)
|
||||
dna_offset += (
|
||||
dna_size # Increment offset by the total size of the array
|
||||
)
|
||||
|
||||
else:
|
||||
# For other fields, proceed as usual
|
||||
field = dna.Field(dna_type, dna_name, dna_size, dna_offset)
|
||||
dna_struct.append_field(field)
|
||||
dna_offset += dna_size
|
||||
@ -796,6 +810,29 @@ class BlendFileBlock:
|
||||
continue
|
||||
yield dereferenced
|
||||
|
||||
def iter_bakes(self, array_size: int) -> typing.Iterator["BlendFileBlock"]:
|
||||
"""Iterate over an array of NodesModifierBake pointers with known size."""
|
||||
path = (
|
||||
b"bakes" # Assuming 'bakes' is the DNA field name for the array of pointers
|
||||
)
|
||||
if array_size == 0:
|
||||
return
|
||||
|
||||
array = self.get_pointer(path)
|
||||
assert array and array.code == b"DATA", "Expected DATA block, got {}".format(
|
||||
array.code.decode()
|
||||
)
|
||||
|
||||
file_offset = array.file_offset
|
||||
ps = self.bfile.header.pointer_size
|
||||
|
||||
for i in range(array_size):
|
||||
address = self.bfile.read_pointer_at(file_offset + ps * i)
|
||||
if address:
|
||||
dereferenced = self.bfile.dereference_pointer(address)
|
||||
if dereferenced:
|
||||
yield dereferenced
|
||||
|
||||
def __getitem__(self, path: dna.FieldPath):
|
||||
return self.get(path)
|
||||
|
||||
|
@ -22,12 +22,18 @@
|
||||
The modifier_xxx() functions all yield result.BlockUsage objects for external
|
||||
files used by the modifiers.
|
||||
"""
|
||||
|
||||
import struct
|
||||
import logging
|
||||
import typing
|
||||
from blender_asset_tracer.blendfile import iterators
|
||||
from blender_asset_tracer.blendfile.dna import Struct
|
||||
|
||||
from blender_asset_tracer import blendfile, bpathlib, cdefs
|
||||
from . import result
|
||||
|
||||
import ctypes
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
modifier_handlers = {} # type: typing.Dict[int, typing.Callable]
|
||||
|
||||
@ -317,3 +323,51 @@ def modifier_cloth(
|
||||
yield from _walk_point_cache(
|
||||
ctx, block_name, modifier.bfile, pointcache, cdefs.PTCACHE_EXT
|
||||
)
|
||||
|
||||
|
||||
def split_bytes_array(raw_data: bytes, item_size: int) -> typing.Iterator[bytes]:
|
||||
for i in range(0, len(raw_data), item_size):
|
||||
data_part = raw_data[i : i + item_size]
|
||||
yield data_part
|
||||
|
||||
|
||||
def bytes_to_struct(data_bytes: bytes, struct_type: Struct):
|
||||
"""Convert raw bytes into a struct based on the provided Struct definition."""
|
||||
struct_instance = {}
|
||||
|
||||
for field in struct_type.fields:
|
||||
start = field.offset
|
||||
end = start + field.size
|
||||
field_data = data_bytes[start:end]
|
||||
|
||||
value = field_data.hex()
|
||||
|
||||
struct_instance[field.name.name_only] = value
|
||||
|
||||
return struct_instance
|
||||
|
||||
|
||||
@mod_handler(cdefs.eModifierType_Nodes)
|
||||
def modifier_nodes(
|
||||
ctx: ModifierContext, modifier: blendfile.BlendFileBlock, block_name: bytes
|
||||
) -> typing.Iterator[result.BlockUsage]:
|
||||
bake_directory = modifier.get_pointer(b"simulation_bake_directory")
|
||||
# print(bake_directory)
|
||||
|
||||
bakes_ptr = modifier.get(b"bakes")
|
||||
bakes_num = modifier.get(b"bakes_num")
|
||||
bakes = modifier.get_pointer(b"bakes")
|
||||
raw_bakes = bakes.raw_data()
|
||||
|
||||
dna_type = bakes.dna_type
|
||||
print(list(bakes.values()))
|
||||
|
||||
bakes_split = split_bytes_array(raw_bakes, dna_type.size)
|
||||
|
||||
for bake_bytes in bakes_split:
|
||||
bake_struct = bytes_to_struct(bake_bytes, dna_type)
|
||||
print(bake_struct)
|
||||
|
||||
# yield bake_struct
|
||||
|
||||
quit()
|
||||
|
Loading…
Reference in New Issue
Block a user