9fcddeca02
update amznchartools
196 lines
7.4 KiB
Python
196 lines
7.4 KiB
Python
import bpy
|
|
|
|
print("=== Custom Visibility Script Starting ===")
|
|
print(f"Blender version: {bpy.app.version_string}")
|
|
|
|
# Check if auto-execution is enabled for drivers
|
|
print(f"Auto-execution enabled: {bpy.context.preferences.filepaths.use_scripts_auto_execute}")
|
|
if not bpy.context.preferences.filepaths.use_scripts_auto_execute:
|
|
print("WARNING: Auto-execution is disabled - drivers may not work properly")
|
|
|
|
# Get the active object and selected objects
|
|
active_obj = bpy.context.active_object
|
|
selected_objects = bpy.context.selected_objects
|
|
|
|
if not active_obj:
|
|
print("✗ ERROR: No active object selected")
|
|
print("Please select an object and run the script again")
|
|
raise Exception("No active object - script aborted")
|
|
|
|
print(f"Found active object: {active_obj.name}")
|
|
print(f"Found {len(selected_objects)} selected object(s): {[obj.name for obj in selected_objects]}")
|
|
|
|
# Find the armature object in the scene
|
|
armature_obj = None
|
|
|
|
# First, check if the active object is an armature
|
|
if active_obj and active_obj.type == 'ARMATURE':
|
|
armature_obj = active_obj
|
|
print(f"Using active armature: {armature_obj.name}")
|
|
else:
|
|
# Look for an armature that has a Settings bone
|
|
print("Active object is not an armature, searching for armature with Settings bone...")
|
|
for obj in bpy.data.objects:
|
|
if obj.type == 'ARMATURE' and 'Settings' in obj.pose.bones:
|
|
armature_obj = obj
|
|
print(f"Found armature with Settings bone: {armature_obj.name}")
|
|
break
|
|
|
|
# If still no armature found, just use the first armature
|
|
if not armature_obj:
|
|
for obj in bpy.data.objects:
|
|
if obj.type == 'ARMATURE':
|
|
armature_obj = obj
|
|
print(f"Using first available armature: {armature_obj.name}")
|
|
break
|
|
|
|
if not armature_obj:
|
|
print("✗ ERROR: No armature object found in scene")
|
|
raise Exception("No armature object found - script aborted")
|
|
|
|
print(f"Selected armature object: {armature_obj.name}")
|
|
|
|
# Get the Settings pose bone
|
|
pose_bone = armature_obj.pose.bones.get('Settings')
|
|
if not pose_bone:
|
|
print("✗ ERROR: Settings pose bone not found in armature")
|
|
print("Available bones:", [bone.name for bone in armature_obj.pose.bones])
|
|
raise Exception("Settings pose bone not found - script aborted")
|
|
|
|
print("✓ Settings pose bone found")
|
|
|
|
# Create property name based on active object name
|
|
property_name = active_obj.name
|
|
print(f"Creating visibility property: {property_name}")
|
|
|
|
# Remove any existing property with this name to avoid duplication
|
|
if property_name in pose_bone:
|
|
del pose_bone[property_name]
|
|
print(f"Removed existing {property_name} property")
|
|
|
|
# Create custom property as boolean (default to visible)
|
|
pose_bone[property_name] = True
|
|
|
|
# Set up the property UI
|
|
ui_data = pose_bone.id_properties_ui(property_name)
|
|
ui_data.update(
|
|
description=f"Toggle {active_obj.name} visibility",
|
|
default=True
|
|
)
|
|
|
|
# Make the property overridable for linked rigs
|
|
try:
|
|
# Try the newer Blender 4.x API first
|
|
if hasattr(pose_bone, 'property_overridable_library_set'):
|
|
pose_bone.property_overridable_library_set(f'["{property_name}"]', True)
|
|
print(f"✓ Set {property_name} property as library overridable")
|
|
else:
|
|
print(f"Note: Library override API not available in this Blender version")
|
|
except Exception as e:
|
|
print(f"Note: Could not set library override: {e}")
|
|
|
|
print(f"✓ Created '{property_name}' custom property with library override support")
|
|
|
|
# Set up drivers for object visibility
|
|
print(f"Setting up drivers for {active_obj.name} object...")
|
|
|
|
try:
|
|
# Set up drivers for all selected objects
|
|
for obj in selected_objects:
|
|
print(f" Setting up drivers for {obj.name}...")
|
|
|
|
# Clear any existing drivers
|
|
try:
|
|
obj.driver_remove('hide_render')
|
|
print(f" Removed existing hide_render driver")
|
|
except:
|
|
print(" No existing hide_render driver to remove")
|
|
|
|
try:
|
|
obj.driver_remove('hide_viewport')
|
|
print(" Removed existing hide_viewport driver")
|
|
except:
|
|
print(" No existing hide_viewport driver to remove")
|
|
|
|
# Create hide_render driver (hide when property = False, show when property = True)
|
|
driver_fcurve = obj.driver_add('hide_render')
|
|
driver = driver_fcurve.driver
|
|
driver.type = 'SUM'
|
|
|
|
var = driver.variables.new()
|
|
var.name = 'vis_val'
|
|
var.type = 'SINGLE_PROP'
|
|
var.targets[0].id_type = 'OBJECT'
|
|
var.targets[0].id = armature_obj
|
|
var.targets[0].data_path = f'pose.bones["Settings"]["{property_name}"]'
|
|
|
|
# Use polynomial modifier to invert: hide_render = 1 - vis_val
|
|
mod = driver_fcurve.modifiers.new('GENERATOR')
|
|
mod.mode = 'POLYNOMIAL'
|
|
mod.poly_order = 1
|
|
mod.coefficients = (1.0, -1.0) # 1 - x
|
|
|
|
print(f" ✓ Created hide_render driver for {obj.name}")
|
|
|
|
# Create hide_viewport driver (same logic)
|
|
driver_fcurve = obj.driver_add('hide_viewport')
|
|
driver = driver_fcurve.driver
|
|
driver.type = 'SUM'
|
|
|
|
var = driver.variables.new()
|
|
var.name = 'vis_val'
|
|
var.type = 'SINGLE_PROP'
|
|
var.targets[0].id_type = 'OBJECT'
|
|
var.targets[0].id = armature_obj
|
|
var.targets[0].data_path = f'pose.bones["Settings"]["{property_name}"]'
|
|
|
|
# Use polynomial modifier to invert: hide_viewport = 1 - vis_val
|
|
mod = driver_fcurve.modifiers.new('GENERATOR')
|
|
mod.mode = 'POLYNOMIAL'
|
|
mod.poly_order = 1
|
|
mod.coefficients = (1.0, -1.0) # 1 - x
|
|
|
|
print(f" ✓ Created hide_viewport driver for {obj.name}")
|
|
|
|
except Exception as e:
|
|
print(f" Error creating drivers: {e}")
|
|
|
|
print("✓ Driver setup complete")
|
|
|
|
# Test the toggle functionality
|
|
print(f"\n=== Testing {property_name} visibility functionality ===")
|
|
|
|
# Force update to make sure drivers are working
|
|
bpy.context.view_layer.update()
|
|
bpy.context.evaluated_depsgraph_get().update()
|
|
|
|
# Initial state (should be visible)
|
|
print(f"Current state: {property_name} = {pose_bone[property_name]} (True=visible, False=hidden)")
|
|
for obj in selected_objects:
|
|
print(f" {obj.name}: hide_render={obj.hide_render}, hide_viewport={obj.hide_viewport}")
|
|
|
|
# Test toggle to False (objects hidden)
|
|
print(f"\nToggling to False (objects hidden)...")
|
|
pose_bone[property_name] = False
|
|
bpy.context.view_layer.update()
|
|
bpy.context.evaluated_depsgraph_get().update()
|
|
|
|
print(f"New state: {property_name} = {pose_bone[property_name]}")
|
|
for obj in selected_objects:
|
|
print(f" {obj.name}: hide_render={obj.hide_render}, hide_viewport={obj.hide_viewport}")
|
|
|
|
# Test toggle back to True (objects visible)
|
|
print(f"\nToggling to True (objects visible)...")
|
|
pose_bone[property_name] = True
|
|
bpy.context.view_layer.update()
|
|
bpy.context.evaluated_depsgraph_get().update()
|
|
|
|
print(f"Final state: {property_name} = {pose_bone[property_name]}")
|
|
for obj in selected_objects:
|
|
print(f" {obj.name}: hide_render={obj.hide_render}, hide_viewport={obj.hide_viewport}")
|
|
|
|
print("\n✓ Custom Visibility script completed successfully!")
|
|
print(f"The '{property_name}' property is now available on the Settings bone as a checkbox")
|
|
print(f"Use checkbox to toggle visibility of {len(selected_objects)} selected object(s): {[obj.name for obj in selected_objects]}")
|
|
print(f" - {property_name} ON (checked): Shows all selected objects")
|
|
print(f" - {property_name} OFF (unchecked): Hides all selected objects") |