2025-12-01
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# SPDX-FileCopyrightText: 2021 Blender Studio Tools Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from typing import Any, Tuple, Generator, List
|
||||
from .. import constants
|
||||
import bpy
|
||||
|
||||
|
||||
####################################
|
||||
############# ID Stuff #############
|
||||
####################################
|
||||
|
||||
|
||||
def get_id_info() -> List[Tuple[type, str, str]]:
|
||||
"""Return a list of tuples with the python class, type identifier string, and bpy.data container name
|
||||
of each ID type present in the blend file.
|
||||
Eg. when called in a file containing meshes and objects, it will return at least:
|
||||
[
|
||||
(bpy.types.Object, 'OBJECT', "objects"),
|
||||
(bpy.types.Mesh, 'MESH', "meshes"),
|
||||
]
|
||||
"""
|
||||
bpy_prop_collection = type(bpy.data.objects)
|
||||
id_info = []
|
||||
for prop_name in dir(bpy.data):
|
||||
coll_prop = getattr(bpy.data, prop_name)
|
||||
if type(coll_prop) == bpy_prop_collection:
|
||||
if len(coll_prop) == 0:
|
||||
# We can't get full info about the ID type if there isn't at least one entry of it.
|
||||
# But we shouldn't need it, since we don't have any entries of it!
|
||||
continue
|
||||
|
||||
id_info.append((get_fundamental_id_type(coll_prop[0]), coll_prop[0].id_type, prop_name))
|
||||
return id_info
|
||||
|
||||
|
||||
def get_id_identifier_from_class(id_type: type):
|
||||
"""Return the string name of an ID type class.
|
||||
eg. bpy.types.Object -> 'OBJECT'
|
||||
"""
|
||||
id_info = get_id_info()
|
||||
for typ, typ_str, container_str in id_info:
|
||||
if id_type == typ:
|
||||
return typ_str
|
||||
|
||||
|
||||
def get_fundamental_id_type(datablock: bpy.types.ID) -> Any:
|
||||
"""Certain datablocks have very specific types, such as
|
||||
bpy.types.GeometryNodeTree instead of bpy.types.NodeTree.
|
||||
|
||||
This function should return their fundamental type, ie. parent class,
|
||||
by reaching into the python Method Resolution Order (MRO) to find its
|
||||
python class inheritance chain and then step back 4 steps:
|
||||
object->bpy_struct->bpy.types.ID->bpy.types.WhatWeNeed"""
|
||||
|
||||
return type(datablock).mro()[-4]
|
||||
|
||||
|
||||
def get_storage_of_id(datablock: bpy.types.ID) -> 'bpy_prop_collection':
|
||||
"""Return the storage collection property of the datablock.
|
||||
Eg. for an object, returns bpy.data.objects.
|
||||
"""
|
||||
|
||||
fundamental_type = get_fundamental_id_type(datablock)
|
||||
|
||||
id_info = get_id_info()
|
||||
for typ, _typ_str, container_str in id_info:
|
||||
if fundamental_type == typ:
|
||||
return getattr(bpy.data, container_str)
|
||||
assert False, "Failed to find the type of this ID: " + str(datablock) + "with fundamental type: " + str(fundamental_type)
|
||||
|
||||
|
||||
def traverse_collection_tree(
|
||||
collection: bpy.types.Collection,
|
||||
) -> Generator[bpy.types.Collection, None, None]:
|
||||
yield collection
|
||||
for child in collection.children:
|
||||
yield from traverse_collection_tree(child)
|
||||
|
||||
|
||||
def data_type_from_transfer_data_key(obj: bpy.types.Object, td_type: str):
|
||||
"""Returns the data on an object that is referred to by the Transferable Data type"""
|
||||
if td_type == constants.VERTEX_GROUP_KEY:
|
||||
return obj.vertex_groups
|
||||
if td_type == constants.MODIFIER_KEY:
|
||||
return obj.modifiers
|
||||
if td_type == constants.CONSTRAINT_KEY:
|
||||
return obj.constraints
|
||||
if td_type == constants.MATERIAL_SLOT_KEY:
|
||||
return obj.material_slots
|
||||
if td_type == constants.SHAPE_KEY_KEY:
|
||||
return obj.data.shape_keys.key_blocks
|
||||
if td_type == constants.ATTRIBUTE_KEY:
|
||||
return obj.data.attributes
|
||||
if td_type == constants.PARENT_KEY:
|
||||
return obj.parent
|
||||
Reference in New Issue
Block a user