196 lines
7.3 KiB
Python
196 lines
7.3 KiB
Python
import bpy
|
|
import math
|
|
import os
|
|
|
|
try:
|
|
from ..utils import get_addon_preferences
|
|
except (ImportError, ValueError):
|
|
# Fallback if import fails (e.g., when run as script)
|
|
def get_addon_preferences():
|
|
test_names = ["bl_ext.vscode_development.AmazonCharacterTools", "amzncharactertools", "AmazonCharacterTools"]
|
|
for addon_name in test_names:
|
|
addon_prefs = bpy.context.preferences.addons.get(addon_name)
|
|
if addon_prefs and hasattr(addon_prefs, 'preferences') and hasattr(addon_prefs.preferences, 'amzn_bsdf_materials_path'):
|
|
return addon_prefs.preferences
|
|
# Search all addons
|
|
for addon_name in bpy.context.preferences.addons.keys():
|
|
addon_prefs = bpy.context.preferences.addons.get(addon_name)
|
|
if addon_prefs and hasattr(addon_prefs, 'preferences') and hasattr(addon_prefs.preferences, 'amzn_bsdf_materials_path'):
|
|
return addon_prefs.preferences
|
|
return None
|
|
|
|
def append_and_parent_device():
|
|
# Get path from addon preferences
|
|
prefs = get_addon_preferences()
|
|
if not prefs:
|
|
print("Error: Could not access addon preferences")
|
|
return
|
|
|
|
device_blend_path = prefs.amzn_device_path
|
|
|
|
if not device_blend_path or not os.path.exists(device_blend_path):
|
|
print(f"Error: Device library path not set or file not found: {device_blend_path}")
|
|
return
|
|
|
|
# Append the Device object
|
|
with bpy.data.libraries.load(device_blend_path, link=False) as (data_from, data_to):
|
|
if 'Device' in data_from.objects:
|
|
data_to.objects = ['Device']
|
|
|
|
# Link the Device to the current scene
|
|
if 'Device' in bpy.data.objects:
|
|
device_obj = bpy.data.objects['Device']
|
|
bpy.context.collection.objects.link(device_obj)
|
|
|
|
# Make it no longer an asset
|
|
device_obj.asset_clear()
|
|
|
|
print("Successfully appended Device")
|
|
else:
|
|
print("Error: Device not found in blend file")
|
|
return
|
|
|
|
# Set transforms before parenting
|
|
device_obj.location = (-0.030083, 0.002195, -0.000632)
|
|
device_obj.rotation_euler = (
|
|
math.radians(-89.493),
|
|
math.radians(0.63873),
|
|
math.radians(85.309)
|
|
)
|
|
|
|
# Get the active armature
|
|
active_armature = bpy.context.active_object
|
|
if not active_armature or active_armature.type != 'ARMATURE':
|
|
print("Error: No active armature selected")
|
|
return
|
|
|
|
# Find the DEF-forearm.L bone
|
|
forearm_bone = active_armature.data.bones.get('DEF-forearm.L')
|
|
if not forearm_bone:
|
|
print("Error: Bone 'DEF-forearm.L' not found in active armature")
|
|
return
|
|
|
|
# Parent the device to the armature and the specific bone
|
|
device_obj.parent = active_armature
|
|
device_obj.parent_type = 'BONE'
|
|
device_obj.parent_bone = 'DEF-forearm.L'
|
|
|
|
print(f"Successfully parented 'Device' to {active_armature.name} bone 'DEF-forearm.L'")
|
|
|
|
def append_and_parent_finger_scanner():
|
|
# Get path from addon preferences
|
|
prefs = get_addon_preferences()
|
|
if not prefs:
|
|
print("Error: Could not access addon preferences")
|
|
return
|
|
|
|
scanner_blend_path = prefs.amzn_scanner_assets_path
|
|
|
|
if not scanner_blend_path or not os.path.exists(scanner_blend_path):
|
|
print(f"Error: Scanner assets library path not set or file not found: {scanner_blend_path}")
|
|
return
|
|
|
|
# Append the Finger-Scanner object
|
|
with bpy.data.libraries.load(scanner_blend_path, link=False) as (data_from, data_to):
|
|
if 'Finger-Scanner' in data_from.objects:
|
|
data_to.objects = ['Finger-Scanner']
|
|
|
|
# Link the Finger-Scanner to the current scene
|
|
if 'Finger-Scanner' in bpy.data.objects:
|
|
scanner_obj = bpy.data.objects['Finger-Scanner']
|
|
bpy.context.collection.objects.link(scanner_obj)
|
|
|
|
# Make it no longer an asset
|
|
scanner_obj.asset_clear()
|
|
|
|
print("Successfully appended Finger-Scanner")
|
|
else:
|
|
print("Error: Finger-Scanner not found in blend file")
|
|
return
|
|
|
|
# Set transforms before parenting (from latest screenshot)
|
|
scanner_obj.location = (0.000367, -0.012914, 0.002702)
|
|
scanner_obj.rotation_euler = (
|
|
math.radians(0),
|
|
math.radians(-185),
|
|
math.radians(-180)
|
|
)
|
|
scanner_obj.scale = (0.493, 0.493, 0.493)
|
|
|
|
# Get the active armature
|
|
active_armature = bpy.context.active_object
|
|
if not active_armature or active_armature.type != 'ARMATURE':
|
|
print("Error: No active armature selected")
|
|
return
|
|
|
|
# Find the DEF-f_index.01.R bone
|
|
finger_bone = active_armature.data.bones.get('DEF-f_index.01.R')
|
|
if not finger_bone:
|
|
print("Error: Bone 'DEF-f_index.01.R' not found in active armature")
|
|
return
|
|
|
|
# Parent the finger scanner to the armature and the specific bone
|
|
scanner_obj.parent = active_armature
|
|
scanner_obj.parent_type = 'BONE'
|
|
scanner_obj.parent_bone = 'DEF-f_index.01.R'
|
|
|
|
print(f"Successfully parented 'Finger-Scanner' to {active_armature.name} bone 'DEF-f_index.01.R'")
|
|
|
|
def rename_device_band():
|
|
# Find and rename arm-band or armband to device-band
|
|
band_variants = ['arm-band', 'armband', 'Arm-band', 'Armband', 'ARM-BAND', 'ARMBAND']
|
|
|
|
for variant in band_variants:
|
|
obj = bpy.data.objects.get(variant)
|
|
if obj:
|
|
print(f"Found {variant}, renaming to device-band")
|
|
obj.name = 'device-band'
|
|
return True
|
|
|
|
print("No arm-band or armband object found to rename")
|
|
return False
|
|
|
|
def rename_geometry_data():
|
|
# Select all geometry objects (meshes, curves, etc.)
|
|
bpy.ops.object.select_all(action='DESELECT')
|
|
|
|
renamed_count = 0
|
|
skipped_count = 0
|
|
not_in_view_layer_count = 0
|
|
|
|
for obj in bpy.data.objects:
|
|
if obj.type in ['MESH', 'CURVE', 'SURFACE', 'META']:
|
|
# Check if object is in current view layer before selecting
|
|
if obj.name in bpy.context.view_layer.objects:
|
|
obj.select_set(True)
|
|
else:
|
|
not_in_view_layer_count += 1
|
|
skipped_count += 1
|
|
# Try to rename the data directly
|
|
try:
|
|
if obj.data and obj.data.name != obj.name:
|
|
# Check if data is shared with other objects
|
|
data_users = [o for o in bpy.data.objects if o.data == obj.data]
|
|
if len(data_users) == 1:
|
|
# Only one user, safe to rename
|
|
obj.data.name = obj.name
|
|
renamed_count += 1
|
|
else:
|
|
skipped_count += 1
|
|
except AttributeError:
|
|
skipped_count += 1
|
|
|
|
# Set the first selected object as active (for any remaining operations)
|
|
selected_objects = [obj for obj in bpy.data.objects if obj.select_get()]
|
|
if selected_objects:
|
|
bpy.context.view_layer.objects.active = selected_objects[0]
|
|
# Now run the operator on the selection
|
|
bpy.ops.renaming.data_name_from_obj()
|
|
|
|
print(f"Renamed {renamed_count} objects, skipped {skipped_count} objects (not in view layer: {not_in_view_layer_count})")
|
|
|
|
# Execute all operations
|
|
append_and_parent_device()
|
|
append_and_parent_finger_scanner()
|
|
rename_device_band()
|
|
rename_geometry_data() |