io_scene_3ds: Update for Blender 3.x #104511
@ -4,7 +4,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
'name': 'glTF 2.0 format',
|
'name': 'glTF 2.0 format',
|
||||||
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
|
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
|
||||||
"version": (3, 6, 6),
|
"version": (3, 6, 10),
|
||||||
'blender': (3, 5, 0),
|
'blender': (3, 5, 0),
|
||||||
'location': 'File > Import-Export',
|
'location': 'File > Import-Export',
|
||||||
'description': 'Import-Export as glTF 2.0',
|
'description': 'Import-Export as glTF 2.0',
|
||||||
|
@ -14,7 +14,6 @@ def get_mesh_cache_key(blender_mesh,
|
|||||||
blender_object,
|
blender_object,
|
||||||
vertex_groups,
|
vertex_groups,
|
||||||
modifiers,
|
modifiers,
|
||||||
skip_filter,
|
|
||||||
materials,
|
materials,
|
||||||
original_mesh,
|
original_mesh,
|
||||||
export_settings):
|
export_settings):
|
||||||
@ -34,21 +33,19 @@ def get_mesh_cache_key(blender_mesh,
|
|||||||
return (
|
return (
|
||||||
(id(mesh_to_id_cache),),
|
(id(mesh_to_id_cache),),
|
||||||
(modifiers,),
|
(modifiers,),
|
||||||
(skip_filter,), #TODO to check if still needed
|
|
||||||
mats
|
mats
|
||||||
)
|
)
|
||||||
|
|
||||||
@cached_by_key(key=get_mesh_cache_key)
|
@cached_by_key(key=get_mesh_cache_key)
|
||||||
def gather_mesh(blender_mesh: bpy.types.Mesh,
|
def gather_mesh(blender_mesh: bpy.types.Mesh,
|
||||||
uuid_for_skined_data,
|
uuid_for_skined_data,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
skip_filter: bool,
|
|
||||||
materials: Tuple[bpy.types.Material],
|
materials: Tuple[bpy.types.Material],
|
||||||
original_mesh: bpy.types.Mesh,
|
original_mesh: bpy.types.Mesh,
|
||||||
export_settings
|
export_settings
|
||||||
) -> Optional[gltf2_io.Mesh]:
|
) -> Optional[gltf2_io.Mesh]:
|
||||||
if not skip_filter and not __filter_mesh(blender_mesh, vertex_groups, modifiers, export_settings):
|
if not __filter_mesh(blender_mesh, vertex_groups, modifiers, export_settings):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
mesh = gltf2_io.Mesh(
|
mesh = gltf2_io.Mesh(
|
||||||
@ -75,25 +72,21 @@ def gather_mesh(blender_mesh: bpy.types.Mesh,
|
|||||||
blender_object,
|
blender_object,
|
||||||
vertex_groups,
|
vertex_groups,
|
||||||
modifiers,
|
modifiers,
|
||||||
skip_filter,
|
|
||||||
materials)
|
materials)
|
||||||
|
|
||||||
return mesh
|
return mesh
|
||||||
|
|
||||||
|
|
||||||
def __filter_mesh(blender_mesh: bpy.types.Mesh,
|
def __filter_mesh(blender_mesh: bpy.types.Mesh,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
export_settings
|
export_settings
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
if blender_mesh.users == 0:
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def __gather_extensions(blender_mesh: bpy.types.Mesh,
|
def __gather_extensions(blender_mesh: bpy.types.Mesh,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
export_settings
|
export_settings
|
||||||
) -> Any:
|
) -> Any:
|
||||||
@ -101,7 +94,7 @@ def __gather_extensions(blender_mesh: bpy.types.Mesh,
|
|||||||
|
|
||||||
|
|
||||||
def __gather_extras(blender_mesh: bpy.types.Mesh,
|
def __gather_extras(blender_mesh: bpy.types.Mesh,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
export_settings
|
export_settings
|
||||||
) -> Optional[Dict[Any, Any]]:
|
) -> Optional[Dict[Any, Any]]:
|
||||||
@ -128,7 +121,7 @@ def __gather_extras(blender_mesh: bpy.types.Mesh,
|
|||||||
|
|
||||||
|
|
||||||
def __gather_name(blender_mesh: bpy.types.Mesh,
|
def __gather_name(blender_mesh: bpy.types.Mesh,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
export_settings
|
export_settings
|
||||||
) -> str:
|
) -> str:
|
||||||
@ -137,7 +130,7 @@ def __gather_name(blender_mesh: bpy.types.Mesh,
|
|||||||
|
|
||||||
def __gather_primitives(blender_mesh: bpy.types.Mesh,
|
def __gather_primitives(blender_mesh: bpy.types.Mesh,
|
||||||
uuid_for_skined_data,
|
uuid_for_skined_data,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
materials: Tuple[bpy.types.Material],
|
materials: Tuple[bpy.types.Material],
|
||||||
export_settings
|
export_settings
|
||||||
@ -151,7 +144,7 @@ def __gather_primitives(blender_mesh: bpy.types.Mesh,
|
|||||||
|
|
||||||
|
|
||||||
def __gather_weights(blender_mesh: bpy.types.Mesh,
|
def __gather_weights(blender_mesh: bpy.types.Mesh,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
export_settings
|
export_settings
|
||||||
) -> Optional[List[float]]:
|
) -> Optional[List[float]]:
|
||||||
|
@ -182,11 +182,7 @@ def __gather_mesh(vnode, blender_object, export_settings):
|
|||||||
# Be sure that object is valid (no NaN for example)
|
# Be sure that object is valid (no NaN for example)
|
||||||
blender_object.data.validate()
|
blender_object.data.validate()
|
||||||
|
|
||||||
# If not using vertex group, they are irrelevant for caching --> ensure that they do not trigger a cache miss
|
|
||||||
vertex_groups = blender_object.vertex_groups
|
|
||||||
modifiers = blender_object.modifiers
|
modifiers = blender_object.modifiers
|
||||||
if len(vertex_groups) == 0:
|
|
||||||
vertex_groups = None
|
|
||||||
if len(modifiers) == 0:
|
if len(modifiers) == 0:
|
||||||
modifiers = None
|
modifiers = None
|
||||||
|
|
||||||
@ -194,7 +190,6 @@ def __gather_mesh(vnode, blender_object, export_settings):
|
|||||||
if export_settings['gltf_apply']:
|
if export_settings['gltf_apply']:
|
||||||
if modifiers is None: # If no modifier, use original mesh, it will instance all shared mesh in a single glTF mesh
|
if modifiers is None: # If no modifier, use original mesh, it will instance all shared mesh in a single glTF mesh
|
||||||
blender_mesh = blender_object.data
|
blender_mesh = blender_object.data
|
||||||
skip_filter = False
|
|
||||||
else:
|
else:
|
||||||
armature_modifiers = {}
|
armature_modifiers = {}
|
||||||
if export_settings['gltf_skins']:
|
if export_settings['gltf_skins']:
|
||||||
@ -209,7 +204,6 @@ def __gather_mesh(vnode, blender_object, export_settings):
|
|||||||
blender_mesh = blender_mesh_owner.to_mesh(preserve_all_data_layers=True, depsgraph=depsgraph)
|
blender_mesh = blender_mesh_owner.to_mesh(preserve_all_data_layers=True, depsgraph=depsgraph)
|
||||||
for prop in blender_object.data.keys():
|
for prop in blender_object.data.keys():
|
||||||
blender_mesh[prop] = blender_object.data[prop]
|
blender_mesh[prop] = blender_object.data[prop]
|
||||||
skip_filter = True
|
|
||||||
|
|
||||||
if export_settings['gltf_skins']:
|
if export_settings['gltf_skins']:
|
||||||
# restore Armature modifiers
|
# restore Armature modifiers
|
||||||
@ -217,15 +211,12 @@ def __gather_mesh(vnode, blender_object, export_settings):
|
|||||||
blender_object.modifiers[idx].show_viewport = show_viewport
|
blender_object.modifiers[idx].show_viewport = show_viewport
|
||||||
else:
|
else:
|
||||||
blender_mesh = blender_object.data
|
blender_mesh = blender_object.data
|
||||||
skip_filter = False
|
|
||||||
# If no skin are exported, no need to have vertex group, this will create a cache miss
|
# If no skin are exported, no need to have vertex group, this will create a cache miss
|
||||||
if not export_settings['gltf_skins']:
|
if not export_settings['gltf_skins']:
|
||||||
vertex_groups = None
|
|
||||||
modifiers = None
|
modifiers = None
|
||||||
else:
|
else:
|
||||||
# Check if there is an armature modidier
|
# Check if there is an armature modidier
|
||||||
if len([mod for mod in blender_object.modifiers if mod.type == "ARMATURE"]) == 0:
|
if len([mod for mod in blender_object.modifiers if mod.type == "ARMATURE"]) == 0:
|
||||||
vertex_groups = None # Not needed if no armature, avoid a cache miss
|
|
||||||
modifiers = None
|
modifiers = None
|
||||||
|
|
||||||
materials = tuple(ms.material for ms in blender_object.material_slots)
|
materials = tuple(ms.material for ms in blender_object.material_slots)
|
||||||
@ -241,9 +232,8 @@ def __gather_mesh(vnode, blender_object, export_settings):
|
|||||||
|
|
||||||
result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh,
|
result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh,
|
||||||
uuid_for_skined_data,
|
uuid_for_skined_data,
|
||||||
vertex_groups,
|
blender_object.vertex_groups,
|
||||||
modifiers,
|
modifiers,
|
||||||
skip_filter,
|
|
||||||
materials,
|
materials,
|
||||||
None,
|
None,
|
||||||
export_settings)
|
export_settings)
|
||||||
@ -279,17 +269,14 @@ def __gather_mesh_from_nonmesh(blender_object, export_settings):
|
|||||||
|
|
||||||
needs_to_mesh_clear = True
|
needs_to_mesh_clear = True
|
||||||
|
|
||||||
skip_filter = True
|
|
||||||
materials = tuple([ms.material for ms in blender_object.material_slots if ms.material is not None])
|
materials = tuple([ms.material for ms in blender_object.material_slots if ms.material is not None])
|
||||||
vertex_groups = None
|
|
||||||
modifiers = None
|
modifiers = None
|
||||||
blender_object_for_skined_data = None
|
blender_object_for_skined_data = None
|
||||||
|
|
||||||
result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh,
|
result = gltf2_blender_gather_mesh.gather_mesh(blender_mesh,
|
||||||
blender_object_for_skined_data,
|
blender_object_for_skined_data,
|
||||||
vertex_groups,
|
blender_object.vertex_groups,
|
||||||
modifiers,
|
modifiers,
|
||||||
skip_filter,
|
|
||||||
materials,
|
materials,
|
||||||
blender_object.data,
|
blender_object.data,
|
||||||
export_settings)
|
export_settings)
|
||||||
@ -361,8 +348,7 @@ def gather_skin(vnode, export_settings):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# no skin needed when the modifier is linked without having a vertex group
|
# no skin needed when the modifier is linked without having a vertex group
|
||||||
vertex_groups = blender_object.vertex_groups
|
if len(blender_object.vertex_groups) == 0:
|
||||||
if len(vertex_groups) == 0:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# check if any vertices in the mesh are part of a vertex group
|
# check if any vertices in the mesh are part of a vertex group
|
||||||
|
@ -15,9 +15,9 @@ from .material import gltf2_blender_gather_materials
|
|||||||
from .material.extensions import gltf2_blender_gather_materials_variants
|
from .material.extensions import gltf2_blender_gather_materials_variants
|
||||||
|
|
||||||
@cached
|
@cached
|
||||||
def get_primitive_cache_key(
|
def gather_primitive_cache_key(
|
||||||
blender_mesh,
|
blender_mesh,
|
||||||
blender_object,
|
uuid_for_skined_data,
|
||||||
vertex_groups,
|
vertex_groups,
|
||||||
modifiers,
|
modifiers,
|
||||||
materials,
|
materials,
|
||||||
@ -36,11 +36,11 @@ def get_primitive_cache_key(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@cached_by_key(key=get_primitive_cache_key)
|
@cached_by_key(key=gather_primitive_cache_key)
|
||||||
def gather_primitives(
|
def gather_primitives(
|
||||||
blender_mesh: bpy.types.Mesh,
|
blender_mesh: bpy.types.Mesh,
|
||||||
uuid_for_skined_data,
|
uuid_for_skined_data,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
materials: Tuple[bpy.types.Material],
|
materials: Tuple[bpy.types.Material],
|
||||||
export_settings
|
export_settings
|
||||||
@ -92,11 +92,33 @@ def gather_primitives(
|
|||||||
|
|
||||||
return primitives
|
return primitives
|
||||||
|
|
||||||
|
|
||||||
@cached
|
@cached
|
||||||
|
def get_primitive_cache_key(
|
||||||
|
blender_mesh,
|
||||||
|
uuid_for_skined_data,
|
||||||
|
vertex_groups,
|
||||||
|
modifiers,
|
||||||
|
export_settings):
|
||||||
|
|
||||||
|
# Use id of mesh
|
||||||
|
# Do not use bpy.types that can be unhashable
|
||||||
|
# Do not use mesh name, that can be not unique (when linked)
|
||||||
|
# Do not use materials here
|
||||||
|
|
||||||
|
# TODO check what is really needed for modifiers
|
||||||
|
|
||||||
|
return (
|
||||||
|
(id(blender_mesh),),
|
||||||
|
(modifiers,)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cached_by_key(key=get_primitive_cache_key)
|
||||||
def __gather_cache_primitives(
|
def __gather_cache_primitives(
|
||||||
blender_mesh: bpy.types.Mesh,
|
blender_mesh: bpy.types.Mesh,
|
||||||
uuid_for_skined_data,
|
uuid_for_skined_data,
|
||||||
vertex_groups: Optional[bpy.types.VertexGroups],
|
vertex_groups: bpy.types.VertexGroups,
|
||||||
modifiers: Optional[bpy.types.ObjectModifiers],
|
modifiers: Optional[bpy.types.ObjectModifiers],
|
||||||
export_settings
|
export_settings
|
||||||
) -> List[dict]:
|
) -> List[dict]:
|
||||||
|
@ -85,7 +85,7 @@ class PrimitiveCreator:
|
|||||||
# Check if we have to export skin
|
# Check if we have to export skin
|
||||||
self.armature = None
|
self.armature = None
|
||||||
self.skin = None
|
self.skin = None
|
||||||
if self.blender_vertex_groups and self.export_settings['gltf_skins']:
|
if self.export_settings['gltf_skins']:
|
||||||
if self.modifiers is not None:
|
if self.modifiers is not None:
|
||||||
modifiers_dict = {m.type: m for m in self.modifiers}
|
modifiers_dict = {m.type: m for m in self.modifiers}
|
||||||
if "ARMATURE" in modifiers_dict:
|
if "ARMATURE" in modifiers_dict:
|
||||||
@ -197,15 +197,6 @@ class PrimitiveCreator:
|
|||||||
attr['skip_getting_to_dots'] = True
|
attr['skip_getting_to_dots'] = True
|
||||||
self.blender_attributes.append(attr)
|
self.blender_attributes.append(attr)
|
||||||
|
|
||||||
# Manage uvs TEX_COORD_x
|
|
||||||
for tex_coord_i in range(self.tex_coord_max):
|
|
||||||
attr = {}
|
|
||||||
attr['blender_data_type'] = 'FLOAT2'
|
|
||||||
attr['blender_domain'] = 'CORNER'
|
|
||||||
attr['gltf_attribute_name'] = 'TEXCOORD_' + str(tex_coord_i)
|
|
||||||
attr['get'] = self.get_function()
|
|
||||||
self.blender_attributes.append(attr)
|
|
||||||
|
|
||||||
# Manage NORMALS
|
# Manage NORMALS
|
||||||
if self.use_normals:
|
if self.use_normals:
|
||||||
attr = {}
|
attr = {}
|
||||||
@ -216,6 +207,15 @@ class PrimitiveCreator:
|
|||||||
attr['get'] = self.get_function()
|
attr['get'] = self.get_function()
|
||||||
self.blender_attributes.append(attr)
|
self.blender_attributes.append(attr)
|
||||||
|
|
||||||
|
# Manage uvs TEX_COORD_x
|
||||||
|
for tex_coord_i in range(self.tex_coord_max):
|
||||||
|
attr = {}
|
||||||
|
attr['blender_data_type'] = 'FLOAT2'
|
||||||
|
attr['blender_domain'] = 'CORNER'
|
||||||
|
attr['gltf_attribute_name'] = 'TEXCOORD_' + str(tex_coord_i)
|
||||||
|
attr['get'] = self.get_function()
|
||||||
|
self.blender_attributes.append(attr)
|
||||||
|
|
||||||
# Manage TANGENT
|
# Manage TANGENT
|
||||||
if self.use_tangents:
|
if self.use_tangents:
|
||||||
attr = {}
|
attr = {}
|
||||||
@ -269,6 +269,13 @@ class PrimitiveCreator:
|
|||||||
attr['len'] = gltf2_blender_conversion.get_data_length(attr['blender_data_type'])
|
attr['len'] = gltf2_blender_conversion.get_data_length(attr['blender_data_type'])
|
||||||
attr['type'] = gltf2_blender_conversion.get_numpy_type(attr['blender_data_type'])
|
attr['type'] = gltf2_blender_conversion.get_numpy_type(attr['blender_data_type'])
|
||||||
|
|
||||||
|
|
||||||
|
# Now we have all attribtues, we can change order if we want
|
||||||
|
# Note that the glTF specification doesn't say anything about order
|
||||||
|
# Attributes are defined only by name
|
||||||
|
# But if user want it in a particular order, he can use this hook to perform it
|
||||||
|
export_user_extensions('gather_attributes_change', self.export_settings, self.blender_attributes)
|
||||||
|
|
||||||
def create_dots_data_structure(self):
|
def create_dots_data_structure(self):
|
||||||
# Now that we get all attributes that are going to be exported, create numpy array that will store them
|
# Now that we get all attributes that are going to be exported, create numpy array that will store them
|
||||||
dot_fields = [('vertex_index', np.uint32)]
|
dot_fields = [('vertex_index', np.uint32)]
|
||||||
@ -698,6 +705,8 @@ class PrimitiveCreator:
|
|||||||
self.normals = self.normals.reshape(len(self.blender_mesh.loops), 3)
|
self.normals = self.normals.reshape(len(self.blender_mesh.loops), 3)
|
||||||
|
|
||||||
self.normals = np.round(self.normals, NORMALS_ROUNDING_DIGIT)
|
self.normals = np.round(self.normals, NORMALS_ROUNDING_DIGIT)
|
||||||
|
# Force normalization of normals in case some normals are not (why ?)
|
||||||
|
PrimitiveCreator.normalize_vecs(self.normals)
|
||||||
|
|
||||||
self.morph_normals = []
|
self.morph_normals = []
|
||||||
for key_block in key_blocks:
|
for key_block in key_blocks:
|
||||||
|
@ -596,7 +596,22 @@ def skin_into_bind_pose(gltf, skin_idx, vert_joints, vert_weights, locs, vert_no
|
|||||||
for i in range(4):
|
for i in range(4):
|
||||||
skinning_mats += ws[:, i].reshape(len(ws), 1, 1) * joint_mats[js[:, i]]
|
skinning_mats += ws[:, i].reshape(len(ws), 1, 1) * joint_mats[js[:, i]]
|
||||||
weight_sums += ws[:, i]
|
weight_sums += ws[:, i]
|
||||||
# Normalize weights to one; necessary for old files / quantized weights
|
|
||||||
|
# Some invalid files have 0 weight sum.
|
||||||
|
# To avoid to have this vertices at 0.0 / 0.0 / 0.0
|
||||||
|
# We set all weight ( aka 1.0 ) to the first bone
|
||||||
|
zeros_indices = np.where(weight_sums == 0)[0]
|
||||||
|
if zeros_indices.shape[0] > 0:
|
||||||
|
print_console('ERROR', 'File is invalid: Some vertices are not assigned to bone(s) ')
|
||||||
|
vert_weights[0][:, 0][zeros_indices] = 1.0 # Assign to first bone with all weight
|
||||||
|
|
||||||
|
# Reprocess IBM for these vertices
|
||||||
|
skinning_mats[zeros_indices] = np.zeros((4, 4), dtype=np.float32)
|
||||||
|
for js, ws in zip(vert_joints, vert_weights):
|
||||||
|
for i in range(4):
|
||||||
|
skinning_mats[zeros_indices] += ws[:, i][zeros_indices].reshape(len(ws[zeros_indices]), 1, 1) * joint_mats[js[:, i][zeros_indices]]
|
||||||
|
weight_sums[zeros_indices] += ws[:, i][zeros_indices]
|
||||||
|
|
||||||
skinning_mats /= weight_sums.reshape(num_verts, 1, 1)
|
skinning_mats /= weight_sums.reshape(num_verts, 1, 1)
|
||||||
|
|
||||||
skinning_mats_3x3 = skinning_mats[:, :3, :3]
|
skinning_mats_3x3 = skinning_mats[:, :3, :3]
|
||||||
|
@ -62,7 +62,7 @@ def pose_library_list_item_context_menu(self: UIList, context: Context) -> None:
|
|||||||
list = getattr(context, "ui_list", None)
|
list = getattr(context, "ui_list", None)
|
||||||
if not list or list.bl_idname != "UI_UL_asset_view" or list.list_id != "pose_assets":
|
if not list or list.bl_idname != "UI_UL_asset_view" or list.list_id != "pose_assets":
|
||||||
return False
|
return False
|
||||||
if not context.asset_handle:
|
if not context.active_file:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user