BlendFileBlock.get to support accessing different items in the file-block (#92898)
Add an `array_index` parameter to `block.get(property_name)` to get a specific item from an array. Example: ```python verts = self.bf.block_from_addr[verts_ptr] assert verts.get(b"co") == [-1.0, -1.0, -1.0] # index 0 assert verts.get(b"co", array_index=1) == [-1.0, -1.0, 1.0] ``` Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92898
This commit is contained in:
parent
b1c4f5e116
commit
c69612b264
@ -596,6 +596,7 @@ class BlendFileBlock:
|
|||||||
null_terminated=True,
|
null_terminated=True,
|
||||||
as_str=False,
|
as_str=False,
|
||||||
return_field=False,
|
return_field=False,
|
||||||
|
array_index=0,
|
||||||
) -> typing.Any:
|
) -> typing.Any:
|
||||||
"""Read a property and return the value.
|
"""Read a property and return the value.
|
||||||
|
|
||||||
@ -612,8 +613,20 @@ class BlendFileBlock:
|
|||||||
(assumes UTF-8 encoding).
|
(assumes UTF-8 encoding).
|
||||||
:param return_field: When True, returns tuple (dna.Field, value).
|
:param return_field: When True, returns tuple (dna.Field, value).
|
||||||
Otherwise just returns the value.
|
Otherwise just returns the value.
|
||||||
|
:param array_index: If the property is an array, this determines the
|
||||||
|
index of the returned item from that array. Also see
|
||||||
|
`blendfile.iterators.dynamic_array()` for iterating such arrays.
|
||||||
"""
|
"""
|
||||||
self.bfile.fileobj.seek(self.file_offset, os.SEEK_SET)
|
file_offset = self.file_offset
|
||||||
|
if array_index:
|
||||||
|
if not (0 <= array_index < self.count):
|
||||||
|
raise IndexError(
|
||||||
|
"Invalid 'array_index' for file-block. "
|
||||||
|
f"Expected int value in range 0-{self.count - 1}, got {array_index}."
|
||||||
|
)
|
||||||
|
file_offset += array_index * self.dna_type.size
|
||||||
|
|
||||||
|
self.bfile.fileobj.seek(file_offset, os.SEEK_SET)
|
||||||
|
|
||||||
dna_struct = self.bfile.structs[self.sdna_index]
|
dna_struct = self.bfile.structs[self.sdna_index]
|
||||||
field, value = dna_struct.field_get(
|
field, value = dna_struct.field_get(
|
||||||
|
|||||||
@ -81,6 +81,9 @@ def dynamic_array(block: BlendFileBlock) -> typing.Iterator[BlendFileBlock]:
|
|||||||
pointer. BAT interprets these as a single data block, making it hard to
|
pointer. BAT interprets these as a single data block, making it hard to
|
||||||
access individual elements. This function divides the array into individual
|
access individual elements. This function divides the array into individual
|
||||||
blocks by creating modified copies of the original block.
|
blocks by creating modified copies of the original block.
|
||||||
|
|
||||||
|
See `some_block.get(b'name', array_index)` if you want to access elements by
|
||||||
|
index (instead of iterating).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
element_size = block.dna_type.size
|
element_size = block.dna_type.size
|
||||||
|
|||||||
@ -46,6 +46,12 @@ class BlendFileBlockTest(AbstractBlendFileTest):
|
|||||||
mname = mesh.get((b"id", b"name"), as_str=True)
|
mname = mesh.get((b"id", b"name"), as_str=True)
|
||||||
self.assertEqual("MECube³", mname)
|
self.assertEqual("MECube³", mname)
|
||||||
|
|
||||||
|
# Try to access different file-block items.
|
||||||
|
verts_ptr = mesh.get(b"mvert")
|
||||||
|
verts = self.bf.block_from_addr[verts_ptr]
|
||||||
|
assert verts.get(b"co") == [-1.0, -1.0, -1.0]
|
||||||
|
assert verts.get(b"co", array_index=1) == [-1.0, -1.0, 1.0]
|
||||||
|
|
||||||
def test_get_recursive_iter(self):
|
def test_get_recursive_iter(self):
|
||||||
ob = self.bf.code_index[b"OB"][0]
|
ob = self.bf.code_index[b"OB"][0]
|
||||||
assert isinstance(ob, blendfile.BlendFileBlock)
|
assert isinstance(ob, blendfile.BlendFileBlock)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user