192 lines
7.4 KiB
Python
192 lines
7.4 KiB
Python
# SPDX-FileCopyrightText: 2025 Blender Studio Tools Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import bpy
|
|
from bpy.props import StringProperty
|
|
from .names import get_blender_number_suffix
|
|
from ..id_types import get_id
|
|
|
|
|
|
def get_desired_override_name(id):
|
|
override = id.override_library
|
|
if not override:
|
|
return id.name
|
|
suffix = get_blender_number_suffix(override.hierarchy_root.name)
|
|
return override.reference.name + suffix
|
|
|
|
|
|
class BLENLOG_OT_report_library_overrides(bpy.types.Operator):
|
|
"""Report various issues relating to library overrides"""
|
|
|
|
bl_idname = "blenlog.report_library_overrides"
|
|
bl_label = "Report Library Overrides"
|
|
bl_options = {'INTERNAL', 'REGISTER', 'UNDO'}
|
|
|
|
def execute(self, context):
|
|
blenlog = context.scene.blender_log
|
|
|
|
leftovers = report_leftover_overrides(context)
|
|
if leftovers:
|
|
self.report(
|
|
{'WARNING'}, f"There are override leftover collections in the file: {leftovers}"
|
|
)
|
|
|
|
cat_name_taken = "Override Name Occupied"
|
|
blenlog.clear_category(cat_name_taken)
|
|
|
|
cat_name_wrong = "Override Name Mismatch"
|
|
blenlog.clear_category(cat_name_wrong)
|
|
|
|
cat_name_conflict = "Override Name Conflict"
|
|
blenlog.clear_category(cat_name_conflict)
|
|
|
|
objects = [obj for obj in bpy.data.objects if obj.override_library]
|
|
collections = [coll for coll in bpy.data.collections if coll.override_library]
|
|
iter_stuff = [
|
|
('OBJECT', bpy.data.objects, objects),
|
|
('COLLECTION', bpy.data.collections, collections),
|
|
]
|
|
counter = 0
|
|
for id_type, propcoll, ids in iter_stuff:
|
|
for id in ids:
|
|
desired_name = get_desired_override_name(id)
|
|
if id.name == desired_name:
|
|
continue
|
|
counter += 1
|
|
occupied = propcoll.get((desired_name, None))
|
|
if occupied:
|
|
if get_desired_override_name(occupied) == occupied.name:
|
|
blenlog.add(
|
|
description=f"Inherent override name conflict! {id.name} should be named {desired_name}, which is already taken by an object that is named correctly. This issue cannot be fixed locally. The number suffix in the name must be removed in the original library ({id.override_library.reference.library.filepath}), or one of the overridden objects must be deleted.",
|
|
icon='LIBRARY_DATA_OVERRIDE',
|
|
name=id.name,
|
|
category=cat_name_conflict,
|
|
)
|
|
else:
|
|
blenlog.add(
|
|
description=f"Desired overridden {id_type} name '{desired_name}' is already taken from {id.name}. All names should be fixed recursively such that each ID is named after its reference library ID, plus the number suffix of the override hierarchy root.",
|
|
icon='LIBRARY_DATA_OVERRIDE',
|
|
name=id.name,
|
|
category=cat_name_taken,
|
|
operator=BLENLOG_OT_recursive_override_name_fix.bl_idname,
|
|
op_kwargs={'id_name': id.name, 'id_type': id_type},
|
|
)
|
|
else:
|
|
blenlog.add(
|
|
description=f"Overridden object name doesn't match referenced library object name.",
|
|
icon='LIBRARY_DATA_OVERRIDE',
|
|
name=id.name,
|
|
category=cat_name_wrong,
|
|
operator='blenlog.rename_id',
|
|
op_kwargs={
|
|
'id_name': id.name,
|
|
'id_type': id_type,
|
|
'new_name': desired_name,
|
|
},
|
|
)
|
|
|
|
if counter > 0:
|
|
self.report({'WARNING'}, f"Found {counter} wrong override names.")
|
|
else:
|
|
self.report({'INFO'}, f"All overrides are named correctly.")
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
def report_leftover_overrides(context):
|
|
blenlog = context.scene.blender_log
|
|
category = 'Leftover Overrides'
|
|
blenlog.clear_category(category)
|
|
leftovers = [
|
|
c
|
|
for c in bpy.data.collections
|
|
if c.name in {'OVERRIDE_RESYNC_LEFTOVERS', 'OVERRIDE_HIDDEN'}
|
|
]
|
|
for leftover in leftovers:
|
|
blenlog.add(
|
|
description=f"Override Resync Leftovers are left behind when an override data hierarchy became ambiguous. This should be extremely rare. Check your overrides for any issues, then you can delete these leftovers.",
|
|
icon='LIBRARY_DATA_OVERRIDE',
|
|
name=leftover.name,
|
|
category=category,
|
|
operator=BLENLOG_OT_delete_collection_hierarchy.bl_idname,
|
|
op_kwargs={
|
|
'coll_name': leftover.name,
|
|
},
|
|
)
|
|
return leftovers
|
|
|
|
|
|
class BLENLOG_OT_delete_collection_hierarchy(bpy.types.Operator):
|
|
"""Delete a collection hierarchy"""
|
|
|
|
bl_idname = "blenlog.delete_collection_hierarchy"
|
|
bl_label = "Delete Collection Hierarchy"
|
|
bl_options = {'INTERNAL', 'REGISTER', 'UNDO'}
|
|
|
|
coll_name: StringProperty()
|
|
|
|
def execute(self, context):
|
|
coll = bpy.data.objects.get((self.coll_name, None))
|
|
if not coll:
|
|
self.report({'INFO'}, f'Collection "{self.coll_name}" had already been removed.')
|
|
return {'CANCELLED'}
|
|
|
|
bpy.data.collections.remove(coll)
|
|
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=False, do_recursive=True)
|
|
|
|
self.report(
|
|
{'INFO'},
|
|
f"Removed collection {self.coll_name} and purged the blend file of any unused datablocks.",
|
|
)
|
|
|
|
logs = context.scene.blender_log
|
|
logs.remove(logs.active_log)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class BLENLOG_OT_recursive_override_name_fix(bpy.types.Operator):
|
|
"""Recursively rename override object names that occupy each other's names, to the correct suffixes. Useful when the object names of duplicated overrides get tangled up"""
|
|
|
|
bl_idname = "blenlog.recursive_override_name_fix"
|
|
bl_label = "Recursive Override Name Fix"
|
|
bl_options = {'INTERNAL', 'REGISTER', 'UNDO'}
|
|
|
|
id_name: StringProperty()
|
|
id_type: StringProperty()
|
|
|
|
def execute(self, context):
|
|
blenlog = context.scene.blender_log
|
|
|
|
id = get_id(self.id_name, self.id_type)
|
|
if not id:
|
|
self.report({'ERROR'}, f"{self.id_type} '{self.id_name}' no longer exists.")
|
|
blenlog.remove_active()
|
|
return {'CANCELLED'}
|
|
|
|
override_recursive_rename(id)
|
|
blenlog.remove_active()
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
def override_recursive_rename(override_id):
|
|
"""Try to rename an override object to its desired name, which is the name of its
|
|
referenced link ID, plus this override's root hierarchy number suffix, if any."""
|
|
desired_name = get_desired_override_name(override_id)
|
|
if desired_name == override_id.name:
|
|
return
|
|
occupying = get_id(desired_name, override_id.id_type)
|
|
if occupying:
|
|
override_recursive_rename(occupying)
|
|
print("Renaming ", override_id.name, "to", desired_name)
|
|
override_id.name = desired_name
|
|
|
|
|
|
registry = [
|
|
BLENLOG_OT_report_library_overrides,
|
|
BLENLOG_OT_delete_collection_hierarchy,
|
|
BLENLOG_OT_recursive_override_name_fix,
|
|
]
|