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
|
||||||
JonasDichelle marked this conversation as resolved
Outdated
|
|||||||
|
|
||||||
|
/.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]
|
||||||
JonasDichelle marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Please keep formatting changes out of this PR. There is no direct need for this PR to modify this file. Of course non-functional improvements like this are always welcome, but shouldn't be part of the same PR as functional changes. Please keep formatting changes out of this PR. There is no direct need for this PR to modify this file.
Of course non-functional improvements like this are always welcome, but shouldn't be part of the same PR as functional changes.
|
|||||||
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
The use of these directories is quite personal, and differs from developer to developer. Please put those into your
.git/info/exclude
file. That behaves like an extra.gitignore
but isn't tracked by Git.