Add Support for Geometry Node Cache #92890
5
.gitignore
vendored
5
.gitignore
vendored
@ -11,3 +11,8 @@ __pycache__
|
|||||||
/build/
|
/build/
|
||||||
|
|
||||||
/docs/_build
|
/docs/_build
|
||||||
|
|
||||||
|
# envs
|
||||||
|
|
||||||
|
/.env
|
||||||
|
/.venv
|
@ -127,9 +127,7 @@ class BlendFile:
|
|||||||
self.blocks = [] # type: BFBList
|
self.blocks = [] # type: BFBList
|
||||||
"""BlendFileBlocks of this file, in disk order."""
|
"""BlendFileBlocks of this file, in disk order."""
|
||||||
|
|
||||||
self.code_index = collections.defaultdict(
|
self.code_index = collections.defaultdict(list) # type: typing.Dict[bytes, BFBList]
|
||||||
list
|
|
||||||
) # type: typing.Dict[bytes, BFBList]
|
|
||||||
self.structs = [] # type: typing.List[dna.Struct]
|
self.structs = [] # type: typing.List[dna.Struct]
|
||||||
self.sdna_index_from_id = {} # type: typing.Dict[bytes, int]
|
self.sdna_index_from_id = {} # type: typing.Dict[bytes, int]
|
||||||
self.block_from_addr = {} # type: typing.Dict[int, BlendFileBlock]
|
self.block_from_addr = {} # type: typing.Dict[int, BlendFileBlock]
|
||||||
@ -352,9 +350,25 @@ class BlendFile:
|
|||||||
else:
|
else:
|
||||||
dna_size = dna_type.size * dna_name.array_size
|
dna_size = dna_type.size * dna_name.array_size
|
||||||
|
|
||||||
field = dna.Field(dna_type, dna_name, dna_size, dna_offset)
|
if dna_name.name_only == b"bakes":
|
||||||
dna_struct.append_field(field)
|
array_count = 3 # Total elements in the array
|
||||||
dna_offset += dna_size
|
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
|
||||||
|
|
||||||
def abspath(self, relpath: bpathlib.BlendPath) -> bpathlib.BlendPath:
|
def abspath(self, relpath: bpathlib.BlendPath) -> bpathlib.BlendPath:
|
||||||
"""Construct an absolute path from a blendfile-relative path."""
|
"""Construct an absolute path from a blendfile-relative path."""
|
||||||
@ -796,6 +810,29 @@ class BlendFileBlock:
|
|||||||
continue
|
continue
|
||||||
yield dereferenced
|
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):
|
def __getitem__(self, path: dna.FieldPath):
|
||||||
return self.get(path)
|
return self.get(path)
|
||||||
|
|
||||||
|
@ -22,12 +22,18 @@
|
|||||||
The modifier_xxx() functions all yield result.BlockUsage objects for external
|
The modifier_xxx() functions all yield result.BlockUsage objects for external
|
||||||
files used by the modifiers.
|
files used by the modifiers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import struct
|
||||||
import logging
|
import logging
|
||||||
import typing
|
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 blender_asset_tracer import blendfile, bpathlib, cdefs
|
||||||
from . import result
|
from . import result
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
modifier_handlers = {} # type: typing.Dict[int, typing.Callable]
|
modifier_handlers = {} # type: typing.Dict[int, typing.Callable]
|
||||||
|
|
||||||
@ -317,3 +323,51 @@ def modifier_cloth(
|
|||||||
yield from _walk_point_cache(
|
yield from _walk_point_cache(
|
||||||
ctx, block_name, modifier.bfile, pointcache, cdefs.PTCACHE_EXT
|
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