Add Support for Geometry Node Cache #92890
@ -166,6 +166,7 @@ class BlendFile:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if block.code == b"DNA1":
|
if block.code == b"DNA1":
|
||||||
|
# for i in range(block.count):
|
||||||
self.decode_structs(block)
|
self.decode_structs(block)
|
||||||
else:
|
else:
|
||||||
self.fileobj.seek(block.size, os.SEEK_CUR)
|
self.fileobj.seek(block.size, os.SEEK_CUR)
|
||||||
@ -350,21 +351,6 @@ class BlendFile:
|
|||||||
else:
|
else:
|
||||||
dna_size = dna_type.size * dna_name.array_size
|
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
|
# For other fields, proceed as usual
|
||||||
field = dna.Field(dna_type, dna_name, dna_size, dna_offset)
|
field = dna.Field(dna_type, dna_name, dna_size, dna_offset)
|
||||||
dna_struct.append_field(field)
|
dna_struct.append_field(field)
|
||||||
@ -486,6 +472,12 @@ class BlendFileBlock:
|
|||||||
self.addr_old = blockheader[2]
|
self.addr_old = blockheader[2]
|
||||||
self.sdna_index = blockheader[3]
|
self.sdna_index = blockheader[3]
|
||||||
self.count = blockheader[4]
|
self.count = blockheader[4]
|
||||||
|
|
||||||
|
# if self.count > 1:
|
||||||
|
# self.size = self.size // self.count
|
||||||
|
# if self.count > 1:
|
||||||
|
# print(self.count)
|
||||||
|
# print("size is 144")
|
||||||
self.file_offset = bfile.fileobj.tell()
|
self.file_offset = bfile.fileobj.tell()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
@ -774,6 +766,35 @@ class BlendFileBlock:
|
|||||||
continue
|
continue
|
||||||
yield dereferenced
|
yield dereferenced
|
||||||
|
|
||||||
|
def iter_array_from_pointer(
|
||||||
|
self, path: dna.FieldPath, array_size: int
|
||||||
|
) -> typing.Iterator["BlendFileBlock"]:
|
||||||
|
"""Dereference pointers from an array field.
|
||||||
|
|
||||||
|
:param path: The array-of-pointers field.
|
||||||
|
:param array_size: Number of items in the array. If None, the
|
||||||
|
on-disk size of the DNA field is divided by the pointer size to
|
||||||
|
obtain the array size.
|
||||||
|
"""
|
||||||
|
if array_size == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
array = self.get_pointer(path)
|
||||||
|
array_ptr = self.get(path)
|
||||||
|
|
||||||
|
assert array_ptr is not None
|
||||||
|
|
||||||
|
item_size = array.size // array_size
|
||||||
|
|
||||||
|
for i in range(array_size):
|
||||||
|
print(i)
|
||||||
|
address = array_ptr + (item_size * i)
|
||||||
|
print(address)
|
||||||
|
if address == 0:
|
||||||
|
continue
|
||||||
|
dereferenced = self.bfile.dereference_pointer(address)
|
||||||
|
yield dereferenced
|
||||||
|
|
||||||
def iter_fixed_array_of_pointers(
|
def iter_fixed_array_of_pointers(
|
||||||
self, path: dna.FieldPath
|
self, path: dna.FieldPath
|
||||||
) -> typing.Iterator["BlendFileBlock"]:
|
) -> typing.Iterator["BlendFileBlock"]:
|
||||||
|
@ -27,7 +27,7 @@ import struct
|
|||||||
import logging
|
import logging
|
||||||
import typing
|
import typing
|
||||||
from blender_asset_tracer.blendfile import iterators
|
from blender_asset_tracer.blendfile import iterators
|
||||||
from blender_asset_tracer.blendfile.dna import Struct
|
from blender_asset_tracer.blendfile.dna import Struct, Field, Name
|
||||||
|
|
||||||
from blender_asset_tracer import blendfile, bpathlib, cdefs
|
from blender_asset_tracer import blendfile, bpathlib, cdefs
|
||||||
from . import result
|
from . import result
|
||||||
@ -325,13 +325,18 @@ def modifier_cloth(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def split_bytes_array(raw_data: bytes, item_size: int) -> typing.Iterator[bytes]:
|
def split_bytes_array(block: blendfile.BlendFileBlock) -> typing.Iterator[bytes]:
|
||||||
|
"""Split a bytes array into parts based on the Struct definition."""
|
||||||
|
raw_data = block.raw_data()
|
||||||
|
item_size = block.dna_type.size
|
||||||
for i in range(0, len(raw_data), item_size):
|
for i in range(0, len(raw_data), item_size):
|
||||||
data_part = raw_data[i : i + item_size]
|
data_part = raw_data[i : i + item_size]
|
||||||
yield data_part
|
yield data_part
|
||||||
|
|
||||||
|
|
||||||
def bytes_to_struct(data_bytes: bytes, struct_type: Struct):
|
def bytes_to_struct(
|
||||||
|
data_bytes: bytes, struct_type: Struct, block: blendfile.BlendFileBlock
|
||||||
|
) -> dict:
|
||||||
"""Convert raw bytes into a struct based on the provided Struct definition."""
|
"""Convert raw bytes into a struct based on the provided Struct definition."""
|
||||||
struct_instance = {}
|
struct_instance = {}
|
||||||
|
|
||||||
@ -340,9 +345,16 @@ def bytes_to_struct(data_bytes: bytes, struct_type: Struct):
|
|||||||
end = start + field.size
|
end = start + field.size
|
||||||
field_data = data_bytes[start:end]
|
field_data = data_bytes[start:end]
|
||||||
|
|
||||||
value = field_data.hex()
|
if field.name.name_only == b"directory":
|
||||||
|
directory_pointer = int.from_bytes(field_data, "little")
|
||||||
|
directory = block.bfile.dereference_pointer(directory_pointer).as_string()
|
||||||
|
struct_instance["directory"] = directory
|
||||||
|
|
||||||
struct_instance[field.name.name_only] = value
|
if field.name.name_only == b"flag":
|
||||||
|
flag_bin = bin(int.from_bytes(field_data, "little"))
|
||||||
|
flag_bin_padded = flag_bin[2:].zfill(2)
|
||||||
|
use_custom_directory = flag_bin_padded[0]
|
||||||
|
struct_instance["use_custom_directory"] = use_custom_directory
|
||||||
|
|
||||||
return struct_instance
|
return struct_instance
|
||||||
|
|
||||||
@ -352,22 +364,21 @@ def modifier_nodes(
|
|||||||
ctx: ModifierContext, modifier: blendfile.BlendFileBlock, block_name: bytes
|
ctx: ModifierContext, modifier: blendfile.BlendFileBlock, block_name: bytes
|
||||||
) -> typing.Iterator[result.BlockUsage]:
|
) -> typing.Iterator[result.BlockUsage]:
|
||||||
bake_directory = modifier.get_pointer(b"simulation_bake_directory")
|
bake_directory = modifier.get_pointer(b"simulation_bake_directory")
|
||||||
# print(bake_directory)
|
bake_directory = bake_directory.as_string()
|
||||||
|
|
||||||
bakes_ptr = modifier.get(b"bakes")
|
|
||||||
bakes_num = modifier.get(b"bakes_num")
|
|
||||||
bakes = modifier.get_pointer(b"bakes")
|
bakes = modifier.get_pointer(b"bakes")
|
||||||
raw_bakes = bakes.raw_data()
|
|
||||||
|
|
||||||
dna_type = bakes.dna_type
|
dna_type = bakes.dna_type
|
||||||
print(list(bakes.values()))
|
bakes_split = split_bytes_array(bakes)
|
||||||
|
|
||||||
bakes_split = split_bytes_array(raw_bakes, dna_type.size)
|
|
||||||
|
|
||||||
for bake_bytes in bakes_split:
|
for bake_bytes in bakes_split:
|
||||||
bake_struct = bytes_to_struct(bake_bytes, dna_type)
|
bake_struct = bytes_to_struct(bake_bytes, dna_type, modifier)
|
||||||
JonasDichelle marked this conversation as resolved
|
|||||||
print(bake_struct)
|
if bake_struct["use_custom_directory"] == "1":
|
||||||
|
directory = bake_struct["directory"]
|
||||||
|
else:
|
||||||
|
directory = bake_directory
|
||||||
|
|
||||||
# yield bake_struct
|
print(directory)
|
||||||
|
|
||||||
quit()
|
# yield from _walk_point_cache(
|
||||||
|
# ctx, block_name, modifier.bfile, pointcache, cdefs.PTCACHE_EXT
|
||||||
|
# )
|
||||||
|
Loading…
Reference in New Issue
Block a user
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: