custom_shelf initial commit

This commit is contained in:
Cos_Min
2022-03-04 12:28:53 +01:00
parent 705b6f2017
commit 232e5cc7f6
45 changed files with 4221 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
info = {
'icon' : 'FILE_TEXT',
'description' : 'explore API in console at datapath of the popup',
'data_path' : ''
}
import bpy, mathutils
exclude = (
### add lines here to exclude specific attribute
'bl_rna', 'identifier','name_property','rna_type','properties',#basic
## To avoid recursion/crash on direct object call (comment for API check on deeper props)
'data', 'edges', 'faces', 'edge_keys', 'polygons', 'loops', 'face_maps', 'original',
## Avoid some specific properties
#'matrix_local', 'matrix_parent_inverse', 'matrix_basis','location','rotation_euler', 'rotation_quaternion', 'rotation_axis_angle', 'scale', 'translation',
)
def list_attr(path, ct=0):
for attr in dir(eval(path)):
if not attr.startswith('__') and not attr in exclude:
try:
value = getattr(eval(path),attr)
except AttributeError:
value = None
if value != None:
if not callable(value):
if type(value) in ( type(0),type(0.0),type(True),type('str'),type(mathutils.Vector()),type(mathutils.Color()), type(mathutils.Matrix()) ):
print(ct*' ' + attr, value)
else:
print(ct*' ' + attr,value,type(value))
ct+=1
# print (ct*' ' + '>')
list_attr('%s.%s'%(path,attr), ct)#Comment this line to kill recursion
print('---')
# write datapath as string. ex : "bpy.data.objects['Cube'].modifiers['Softbody']"
dt = info['data_path']
if dt:
list_attr(dt)
print ('Done')
else:
print('no data path given')
+56
View File
@@ -0,0 +1,56 @@
info = {
'icon' : 'EVENT_X',
'description' : 'Delete all blend backup version (.blend1 and next backups) in passed directory',
'folderpath' : '',
'recursive' : True,
'test' : False,
}
# coding: utf-8
import bpy
import os
import re, fnmatch, glob
from pathlib import Path
import shutil
C = bpy.context
D = bpy.data
scene = C.scene
def kill_blend_backup_version(fp, recursive=True, test=False):
if not fp:
print('ERROR', 'no filepath given')
return
re_blendbackup = re.compile(r'\.blend\d+')
fpo = Path(fp)
if not fpo.exists():
print('ERROR', f'invalid path: {fp}')
return
ct = 0
print(f'Removing blend backup files in : {fpo}')
if recursive:
for root, dirs, files in os.walk(fp):
for name in files:
fo = Path(root) / name
if re_blendbackup.match(fo.suffix):
ct += 1
print(fo)
if not test:
fo.unlink()
else:
for f in os.listdir(fp):
fo = Path(fp) / f
if re_blendbackup.match(fo.suffix):
ct += 1
print(fo)
if not test:
fo.unlink()
if ct:
print('INFO', f'Deleted {ct} file(s)')
kill_blend_backup_version(info['folderpath'], recursive = info['recursive'], test = info['test'])
@@ -0,0 +1,71 @@
info = {
'icon' : 'LIBRARY_DATA_BROKEN',
'description' : 'Correct path (print in console, apply as option) when weirdly auto added unwanted parent directory (still break rotate order for armatures...)',
'apply' : False
}
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext, abspath
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
""" rel = D.libraries[0].filepath.replace('//','')
parent = rel.count('..')
print('parent: ', parent)
abspath(join(dirname(D.filepath), rel)) """
## relpath
def to_abs(rfp):
return abspath(bpy.path.abspath(rfp))
print('\n--- Cheking libraries filepath ---')
apply = False
apply = info['apply']#get it from info dic
folder = dirname(D.filepath)
for lib in D.libraries:
libfp = lib.filepath
if exists(to_abs(libfp)):
print('clean :', libfp)
else:
print('broken:', libfp)
pct = libfp.count('..')
for i in range(1, pct+1):
newrel = ('').join(libfp.split('../',i))
if exists(to_abs(newrel)):
print(f'found at -{i} parent folder')
print(f'-> {newrel}')
if apply:
lib.filepath = newrel
print()
break
if i == pct:
print(f'tested with {pct} folder up and nothing found')
print('Done.')
'''
## abspath technique
folder = dirname(D.filepath)
for lib in D.libraries:
curfp = abspath(bpy.path.abspath(lib.filepath))
if exists(curfp):
print('clean :', lib.filepath)
else:
print('broken:', lib.filepath)
pct = lib.filepath.count('..')
print('up folder: ', pct)
endlib = lib.filepath.lstrip(os.sep+'.')
for i in range(1, pct+1):
start = '/'.join(folder.split(os.sep)[:-i])
nfp = join(start, endlib)
if exists(nfp):
print(f'{i} parent folder VS {pct} in current')
'''
+60
View File
@@ -0,0 +1,60 @@
info = {
'icon' : 'ARMATURE_DATA',
'description' : 'run some check on proxys and armautre and print in console',
}
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = bpy.context.scene
print('\nCollection instance check -- ')
problems = []
for o in bpy.context.scene.objects:
if o.instance_collection:
for instob in o.instance_collection.objects:
badname = withproxy = withcolproxy = alert = ''
if instob.type == 'ARMATURE':
mess = f'{o.name} -> rig: {instob.name}'
arm = instob.data
# print("arm", arm.name)#Dbg
if instob.name != arm.name:
badname = 1
mess += f' != arm data: {arm.name}'
rigname = arm.name.replace('_rig','_proxy') if 'rig' in arm.name else arm.name + '_proxy'
proxy = bpy.context.scene.objects.get(rigname)
if proxy:
withproxy = 1
mess += ' ->> Proxy in scene'
if not proxy:
collec_proxy = instob.name.replace('_rig','_proxy') if 'rig' in instob.name else instob.name + '_proxy'
proxy = bpy.context.scene.objects.get(collec_proxy)
if proxy :
withcolproxy = 1
mess += ' ->> Proxy from colname in scene'
if proxy and proxy.animation_data and proxy.animation_data.action and len(proxy.animation_data.action.fcurves) > 0:
mess += ' (animated)'
if badname and withcolproxy:
alert = '!!!'
elif badname and withproxy:
alert = '!!'
elif badname:
alert = '!'
mess = f'{alert} {mess}'
if badname or withproxy or withcolproxy:
problems.append(mess)
print(mess)
print('Done')
@@ -0,0 +1,140 @@
info = {
'icon' : 'DRIVER',
'description' : 'create visibility on driver objects or armature selection from a bone of a rig',
'prop_rig' : 'name_of_the_rig'
'prop_name' : 'hide_something'
'prop_bone' : 'root'
}
import bpy
def add_driver(source, target, prop, dataPath, index = -1, negative = False, func = ''):
''' Add driver to source prop (at index), driven by target dataPath '''
source.driver_remove(prop, index)
if index != -1:
d = source.driver_add( prop, index ).driver
else:
d = source.driver_add( prop ).driver
v = d.variables.new()
v.targets[0].id = target
v.targets[0].data_path = dataPath
d.expression = func + "(" + v.name + ")" if func else v.name
d.expression = d.expression if not negative else "-1 * " + d.expression
def create_hide_custom_prop(src_object, prop_name, prop_bone = ''):
'''
add source propertie with boolean option
place the hide prop on src_object with name prop_name
'''
rig = bpy.data.objects.get(src_object)
if not rig:
print(f"No objects named {src_object}")
return 1
if rig.type != 'ARMATURE':
print(f"Not an armature : {src_object}")
return 1
#add target bone
if prop_bone:
holder = rig.pose.bones.get(prop_bone)
else:
holder = rig.pose.bones.get('root')
if not holder:
print(f'problem finding bone {prop_bone} (or root)')
return 1
# create
if not holder.get('_RNA_UI'):
holder['_RNA_UI'] = {}
if not prop_name in holder.keys() :
holder[prop_name] = 0
holder['_RNA_UI'][prop_name] = {"default": 0,"min":0,"max":1,"soft_min":0,"soft_max":1}
else:
print(f'{prop_name} : already exists on root key')
return
return 0
def drive_selection_visibility(rig, prop_name, prop_bone = ''):
# add driver on selection
prefixs = ('MCH','DEF','ORG', 'WGT')
rig = bpy.data.objects.get(src_object)
if not rig:
print(f"No objects named {src_object}")
return 1
if rig.type != 'ARMATURE':
print(f"Not an armature : {src_object}")
return 1
#add target bone
if not prop_bone:
prop_bone = 'root'
if not rig.pose.bones.get(prop_bone):
print(f'no bones {prop_bone} on rig {rig.name}')
return 1
meshes = [i for i in bpy.context.selected_objects if i.type in ('MESH','CURVE','TEXT') and not i.name.startswith(('WGT', 'WDGT'))]
armatures = [i for i in bpy.context.selected_objects if i.type == 'ARMATURE']
if bpy.context.mode == 'POSE':
obarm = bpy.context.active_object
for bone in bpy.context.selected_pose_bones_from_active_object:
prop = 'bones["%s"].hide'%bone.name
index = -1
layer = bone.bone.layers
protect_layer = rig.data.layers_protected
### dont check for protected, strictly use selection.
# if bone.name.startswith(prefixs) or any([i==j==1 for i,j in zip(layer,protect_layer)]) :
# print(f'Skipped : Prefixed or protected bone : {bone.name}')
# rig.data.driver_remove(prop, index)
# continue
print(f'New : Driver on bone {bone.name}')
add_driver(obarm.data, rig, prop, f'pose.bones["{prop_bone}"]["{prop_name}"]', index)
return
for ob in meshes :
print('Object : ', obarm.name)
add_driver(ob, rig, 'hide_viewport', f'pose.bones["{prop_bone}"]["{prop_name}"]', -1)
add_driver(ob, rig, 'hide_render', f'pose.bones["{prop_bone}"]["{prop_name}"]', -1)
for obarm in armatures:
print('Armature : ', obarm.name)
## mask armature object
## add_driver(obarm, rig, 'hide_viewport', f'pose.bones["{prop_bone}"]["{prop_name}"]', -1)
## bette mask pose bones since its a proxy...
for bone in obarm.pose.bones :
prop = 'bones["%s"].hide'%bone.name
index = -1
layer = bone.bone.layers
protect_layer = rig.data.layers_protected
if bone.name.startswith(prefixs) or any([i==j==1 for i,j in zip(layer,protect_layer)]) :
print(f'Skipped : Prefixed or protected bone : {bone.name}')
rig.data.driver_remove(prop, index)
else :
print(f'New : Driver on bone {bone.name}')
add_driver(obarm.data, rig, prop, f'pose.bones["{prop_bone}"]["{prop_name}"]', index)
### ----
## write the name of the rig source (will put the propertie on the root of this armature)
prop_rig = info['prop_rig']# name_of_the_rig
## write the name of the propertie to attach
prop_name = info["prop_name"]#'hide_headband'# hide_something
## prop_bone (bone holding the propertie), 'root' if left string empty.
prop_bone = info["prop_bone"]
create_hide_custom_prop(prop_rig, prop_name, prop_bone = prop_bone)
drive_selection_visibility(prop_rig, prop_name, prop_bone = prop_bone)
@@ -0,0 +1,27 @@
info = {
'icon' : 'ACTION_TWEAK',
'description' : 'Rename selected armature actions (with name of the rig, replacing "_rig" with "_act")',
}
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
for o in C.selected_objects:
if o.type == 'ARMATURE':
print(o.animation_data.action.name)
if '_rig' in o.name:
action = o.animation_data.action
if action.name.replace('_act','') != o.name.replace('_rig', ''):
newname = o.name.replace('_rig', '_act')
print(f'action rename {action.name} > {newname}')
action.name = newname
@@ -0,0 +1,21 @@
info = {
'icon' : 'HIDE_OFF',
'description' : 'Force viewport visibility ON for objects with hide_viewport prop animated',
}
# coding: utf-8
import bpy
import os
from os import listdir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from mathutils import Vector, Matrix
from math import radians, degrees
C = bpy.context
D = bpy.data
scene = C.scene
import bpy
for o in bpy.context.scene.objects:
if o.animation_data and o.animation_data.action and o.animation_data.action.fcurves.find('hide_viewport'):
o.hide_viewport = False
+22
View File
@@ -0,0 +1,22 @@
info = {
'icon' : 'OUTLINER_OB_ARMATURE',
'description' : 'Hide/Unhide all rigs',
}
import bpy
C = bpy.context
D = bpy.data
scene = C.scene
#hide armature
hide = True
arms = [o for o in C.scene.objects if o.type == 'ARMATURE']
if arms:
hide = not arms[0].hide_viewport
#invert of the state of the first armature found for all of them
for o in C.scene.objects:
if o.type == 'ARMATURE':
o.hide_viewport = hide
+5
View File
@@ -0,0 +1,5 @@
import bpy
from bpy import data as D
ob = D.objects['boom_hairs_group_ref']
ob.hide_viewport = not ob.hide_viewport