shelves folder init

master
Cosmin P 2022-03-04 11:54:16 +00:00
parent 10afe009fb
commit 515c363c4a
13 changed files with 0 additions and 1419 deletions

View File

@ -1,103 +0,0 @@
info = {
'icon': 'RECOVER_LAST',
'description': 'Duplicate current low as mid',
}
import bpy
from pathlib import Path
import re
# make a proxy through python
### / unused, just because it's interesting (but relinking break hide statement)
## https://blender.stackexchange.com/questions/157562/sorting-collections-alphabetically-in-the-outliner
def sort_collection(collection, case = False):
if collection.children is None: return
children = sorted (
collection.children,
key = lambda c: c.name if case else c.name.lower()
)
for child in children:
collection.children.unlink(child)
collection.children.link(child)
sort_collection(child)
def sort_all_collection():
# case_sensitive sort, (default is False)
case_sensitive = True
for scene in bpy.data.scenes:
sort_collection(scene.collection, case_sensitive)
### unused /
def set_collection(ob, collection, unlink=True) :
''' link an object in a collection and create it if necessary, if unlink object is removed from other collections'''
scn = bpy.context.scene
col = None
visible = False
linked = False
# check if collection exist or create it
for c in bpy.data.collections :
if c.name == collection : col = c
if not col : col = bpy.data.collections.new(name=collection)
# link the collection to the scene's collection if necessary
for c in scn.collection.children :
if c.name == col.name : visible = True
if not visible : scn.collection.children.link(col)
# check if the object is already in the collection and link it if necessary
for o in col.objects :
if o == ob : linked = True
if not linked : col.objects.link(ob)
# remove object from scene's collection
for o in scn.collection.objects :
if o == ob : scn.collection.objects.unlink(ob)
# if unlink flag we remove the object from other collections
if unlink :
for c in ob.users_collection :
if c.name != collection : c.objects.unlink(ob)
return col
# mid = None
# low = None
# for c in bpy.data.collections:
# if re.search(r'vetement.*_mid', c.name, re.I):
# mid = c
# if re.search(r'vetement.*_low', c.name, re.I):
# low = c
def backup_low_to_mid():
low = mid = None
for o in bpy.context.scene.objects:
if re.search(r'vetements?_mid', o.name, re.I):
mid = o
if re.search(r'vetements?_low', o.name, re.I):
low = o
if not low:
print('ERROR', 'low not found')
return
if not mid and low:
#create mid by duplicating low
mid = low.copy()
mid.name = low.name.replace('_low', '_mid')
mid.data = low.data.copy()# also copy data !
mid.data.name = low.data.name.replace('_low', '_mid')
col = set_collection(mid, mid.name)
# hide viewport
col.hide_viewport = True
else:
print('ERROR', 'mid already exists')
return
backup_low_to_mid()

View File

@ -1,27 +0,0 @@
info = {
'icon': 'SYNTAX_OFF',
'description': 'rename all lowercase (a bit dangerous, check if any break)',
}
import bpy
for c in bpy.data.collections:
new = c.name.lower()
if bpy.data.collections.get(new):
print(f'{new} exists!')
else:
c.name = new
for o in bpy.data.meshes:
new = o.name.lower()
if bpy.data.meshes.get(new):
print(f'{new} exists!')
else:
o.name = new
for o in bpy.data.objects:
new = o.name.lower()
if bpy.data.objects.get(new):
print(f'{new} exists!')
else:
o.name = new

View File

@ -1,90 +0,0 @@
info = {
'icon': 'MOD_CLOTH',
'description': 'Decimate cloth',
}
import bpy
from pathlib import Path
import re
def set_panel(panel):
'''take a panel name and apply it to properties zone'''
for area in bpy.context.screen.areas:
if area.type == 'PROPERTIES':
for space in area.spaces:
if space.type == 'PROPERTIES':
space.context = panel
return (1)
return (0)
def get_panel():
'''return active panel name of the properties zone'''
for area in bpy.context.screen.areas:
if area.type == 'PROPERTIES':
for space in area.spaces:
if space.type == 'PROPERTIES':
return(space.context)
return (0)
def get_override():
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in screen.areas:
if area.type == 'PROPERTIES':
#for region in area.regions:
# if region.type == 'WINDOW':
return {'window': window, 'screen': screen, 'area': area}
def simplify_cloth(poly_target):
if not get_override():
print('ERROR', f'Need a properties windows editor open !')
return
obj = bpy.context.object
mods = obj.modifiers
polycount = len(obj.data.polygons)
if polycount < poly_target:
print('ERROR', f'Already lowpoly ({polycount} polygons)')
return
target_ratio = poly_target / polycount
print('target_ratio: ', target_ratio)
sdef = None
for m in mods:
if m.type == 'SURFACE_DEFORM':
sdef = m
break
if not sdef:
print('ERROR', 'no surface deform found')
return
set_panel('MODIFIER')
properties_override = get_override()
if sdef.is_bound:
bpy.ops.object.surfacedeform_bind(properties_override, modifier="SurfaceDeform")
# create decimate and move to top
decim = obj.modifiers.new('Decimate', 'DECIMATE')
bpy.ops.object.modifier_move_to_index(modifier="Decimate", index=0)
# use target ratio
decim.ratio = target_ratio
# apply
bpy.ops.object.modifier_apply(modifier="Decimate")
# rebind
bpy.ops.object.surfacedeform_bind(properties_override, modifier="SurfaceDeform")
simplify_cloth(15000)

View File

@ -1,275 +0,0 @@
info = {
'icon' : 'PHYSICS',
'description' : 'Copy dynamic physics object from selected instance_collection',
}
import bpy
from os.path import abspath, relpath, dirname, basename, join
from time import time
C = bpy.context
D = bpy.data
scene = C.scene
def set_collection(ob, collection, unlink=True) :
''' link an object in a collection and create it if necessary, if unlink object is removed from other collections'''
scn = bpy.context.scene
col = None
visible = False
linked = False
# check if collection exist or create it
for c in bpy.data.collections :
if c.name == collection : col = c
if not col : col = bpy.data.collections.new(name=collection)
# link the collection to the scene's collection if necessary
for c in scn.collection.children :
if c.name == col.name : visible = True
if not visible : scn.collection.children.link(col)
# check if the object is already in the collection and link it if necessary
for o in col.objects :
if o == ob : linked = True
if not linked : col.objects.link(ob)
# remove object from scene's collection
for o in scn.collection.objects :
if o == ob : scn.collection.objects.unlink(ob)
# if unlink flag we remove the object from other collections
if unlink :
for c in ob.users_collection :
if c.name != collection : c.objects.unlink(ob)
def append_stuff(blendfile, section, obj):
filepath = blendfile
directory = join(blendfile, section)#join(blendfile, section)
filename = obj
print('Append')
print('filepath: ', filepath)
print('directory: ', directory)
print('filename: ', filename)
print(f'''using:
bpy.ops.wm.append(
filepath='{filepath}',
filename='{filename}',
directory='{directory}',
active_collection=True,
)
''')
bpy.ops.wm.append(
filepath=filepath,
filename=filename,
directory=directory,
filter_blender=True, filter_backup=False, filter_image=False, filter_movie=False,
filter_python=False, filter_font=False, filter_sound=False, filter_text=False,
filter_archive=False, filter_btx=False, filter_collada=False, filter_alembic=False,
filter_folder=True, filter_blenlib=True, filemode=1, display_type='DEFAULT', sort_method='FILE_SORT_ALPHA',
link=False, autoselect=True, active_collection=True,#default -> active_collection=True
instance_collections=False, set_fake=False,
use_recursive=True
)
#return {'finished'}
## data way (not working as is...)
'''
with bpy.data.libraries.load(filepath, link=False) as (data_from, data_to):
data_to.objects = [o for o in data_from.objects if o == obj]
#link object to current scene
for obj in data_to.objects:
if obj is not None:
C.scene.collection.objects.link(obj)
'''
def set_soft_body(ob, mod, bake=False):
if bake:
print(f'baking {ob.name} > {mod.name}')
ptc = mod.point_cache
name = ptc.name
override = {'scene': bpy.context.scene,
'active_object': ob,#no sure of this line.. .
'point_cache': ptc}
if bake:
if name:#kill point cache related to point cache name
# delete_point_cache(name)
bpy.ops.ptcache.free_bake(override)
## bpy.ops.ptcache.free_bake_all(override)
#ptc.is_outdated = True # read-only
ptc.frame_start = scene.frame_start
ptc.frame_end = scene.frame_end
# ptc.filepath = join(dirname(D.filepath), splitext(basename)[0]+'_cache')
if not ptc.use_disk_cache:
ptc.use_disk_cache = True
print('enabling use disk cache')
if bake:
print('>>> baking')
start = time()
#bpy.ops.ptcache.bake(override, bake=False)# bake to current frame
bpy.ops.ptcache.bake(override, bake=True)
print(f'Done {time()-start:.3f}')
def set_particle_system(ob, mod, bake=False):
if bake:
print(f'baking {ob.name} > {mod.name}')
ptc = mod.particle_system.point_cache
ptc.frame_start = scene.frame_start
ptc.frame_end = scene.frame_end
# ptc.filepath = join(dirname(D.filepath), splitext(basename)[0]+'_cache')
if not ptc.use_disk_cache:
ptc.use_disk_cache = True
print('enabling use disk cache')
if bake:
override = {'scene': bpy.context.scene,
'active_object': ob,#no sure of this line.. .
'point_cache': ptc}
print('>>> baking')
start = time()
#bpy.ops.ptcache.bake(override, bake=False)# bake to current frame
bpy.ops.ptcache.bake(override, bake=True)
print(f'Done {time()-start:.3f}')
def bake_mods(ob, bake=False):
for mod in ob.modifiers:
if mod.type == 'SOFT_BODY':
set_soft_body(ob, mod, bake)
if mod.type == 'PARTICLE_SYSTEM':
set_particle_system(ob, mod, bake)
def clear_obj_driver(ob):
'''delete visibility driver if any'''
print('clearing driver', ob.name)
ob.driver_remove('hide_viewport')
ob.driver_remove('hide_render')
ob.hide_viewport = False
ob.hide_render = False
def append_physics_obj(selected=True, purge=False, bake=False):
'''On selection or all scene'''
current_active_col = C.view_layer.active_layer_collection
if selected:
obpool = C.selected_objects
else:
obpool = bpy.context.scene.objects
pool = [o for o in obpool if o.type == 'EMPTY' and o.instance_collection]#PARTICLE_SYSTEM
if selected:
for proxyarm in [o for o in obpool if o.type == 'ARMATURE' and o.name.endswith('_proxy')]:
inst = proxyarm.proxy_collection
if inst not in pool: pool.append(inst)
linked = []
#[m for m in o.modifiers if m.type == 'SOFT_BODY']
for instance in pool:
print("instance", instance.name)#Dbg
for ob in instance.instance_collection.all_objects:
# print("ob", ob.name)#Dbg
if ob.type in ('MESH', 'CURVE'):
for mod in ob.modifiers:
if mod.type in ('SOFT_BODY', 'PARTICLE_SYSTEM'):
print(f'{ob.name} > {mod.name} ({mod.type})')
## check if object already exists in object base.
dynob_name = ob.name + '_DYN'
phycol = D.collections.get('Physics_sim')#Dynamic_physics
theob = None
if phycol: theob = phycol.objects.get(dynob_name)
if theob:
print(f'{dynob_name} already as object in scene')
continue
'''
if purge:#delete whats in physics collection, crashy as hell..
print(f'--> purge: deleting {dynob_name}')
D.objects.remove(theob)
else:
continue
'''
## get library path
libpath = abspath(bpy.path.abspath(instance.instance_collection.library.filepath))
print('libpath: ', libpath)
#libpath = instance.instance_collection.library.filepath
#objpath = join(libpath, 'Object', ob.name)
if not phycol:
phycol = D.collections.new('Physics_sim')
C.scene.collection.children.link(phycol)
## make it active
C.view_layer.active_layer_collection = C.view_layer.layer_collection.children['Physics_sim']
## Append individual object, (physics object with a different name from the blend file, else it 'links' to the one withi instance_collection)
#append_stuff(libpath, 'Object', ob.name)
## test copy from existing object
newob = ob.copy()
#newob.make_local()
#newob.data.make_local()
set_collection(newob, 'Physics_sim')
linked.append(newob)
# newob.name = newob.name + '_DYN'
#clear_obj_driver(newob)##crash when clearing driver of the copied object immediately. Do it later
'''
## get the newly appended object
newob = phycol.objects.get(ob.name)#not rename currently
if not newob:
print(f'problem, did not found "{dynob_name}" in physics collection')
continue
linked.append(newob)
'''
# setup proxy visibility...
if instance.name == 'jenny':
proxy = C.scene.objects.get('jenny_proxy')
hairdyn = proxy.pose.bones['root']['_RNA_UI'].get('hair_dynamic')
if hairdyn:
if hairdyn['max'] < 2:
#setmax
proxy.pose.bones['root']['_RNA_UI']['hair_dynamic']['max'] = 2
proxy.pose.bones['root']['_RNA_UI']['hair_dynamic']['soft_max'] = 2
#set val
proxy.pose.bones['root']['hair_dynamic'] = 2
if instance.name == 'boom':
proxy = C.scene.objects.get('boom_proxy')
hairdyn = proxy.pose.bones['root']['_RNA_UI'].get('hair_placeholder')
if hairdyn:
if hairdyn['max'] < 3:
#setmax
proxy.pose.bones['root']['_RNA_UI']['hair_placeholder']['max'] = 3
proxy.pose.bones['root']['_RNA_UI']['hair_placeholder']['soft_max'] = 3
#set val
proxy.pose.bones['root']['hair_placeholder'] = 3
for o in linked:#linked
print(f'-- linked: {o.name}')
# o.make_local()#localize then modify, usually no need to make local if appended
o.name = o.name + '_DYN'
clear_obj_driver(o)
print(o.name)
#set_collection(o, 'Physics_sim')
bake_mods(o, bake=False)
#reset active collection
C.view_layer.active_layer_collection = current_active_col
print()
append_physics_obj(selected=True, purge=False, bake=False)#purge bugged

View File

@ -1,143 +0,0 @@
info = {
'icon' : 'ACTION_TWEAK',
'description' : 'Bake action of selected objects',
'selection' : True
}
import bpy
from os.path import abspath, relpath, dirname, basename, join
from time import time
C = bpy.context
D = bpy.data
scene = C.scene
def set_collection(ob, collection, unlink=True) :
''' link an object in a collection and create it if necessary, if unlink object is removed from other collections'''
scn = bpy.context.scene
col = None
visible = False
linked = False
# check if collection exist or create it
for c in bpy.data.collections :
if c.name == collection : col = c
if not col : col = bpy.data.collections.new(name=collection)
# link the collection to the scene's collection if necessary
for c in scn.collection.children :
if c.name == col.name : visible = True
if not visible : scn.collection.children.link(col)
# check if the object is already in the collection and link it if necessary
for o in col.objects :
if o == ob : linked = True
if not linked : col.objects.link(ob)
# remove object from scene's collection
for o in scn.collection.objects :
if o == ob : scn.collection.objects.unlink(ob)
# if unlink flag we remove the object from other collections
if unlink :
for c in ob.users_collection :
if c.name != collection : c.objects.unlink(ob)
def set_soft_body(ob, mod, bake=False):
if bake:
print(f'baking {ob.name} > {mod.name}')
ptc = mod.point_cache
name = ptc.name
override = {'scene': bpy.context.scene,
'active_object': ob,#no sure of this line.. .
'point_cache': ptc}
if bake:
if name:#kill point cache related to point cache name
bpy.ops.ptcache.free_bake(override)
## bpy.ops.ptcache.free_bake_all(override)
#ptc.is_outdated = True # read-only
ptc.frame_start = scene.frame_start
ptc.frame_end = scene.frame_end
if not ptc.use_disk_cache:
ptc.use_disk_cache = True
print('enabling use disk cache')
if bake:
print('>>> baking')
start = time()
#bpy.ops.ptcache.bake(override, bake=False)# bake to current frame
bpy.ops.ptcache.bake(override, bake=True)
print(f'Done {time()-start:.3f}')
def set_particle_system(ob, mod, bake=False):
if bake:
print(f'baking {ob.name} > {mod.name}')
ptc = mod.particle_system.point_cache
ptc.frame_start = scene.frame_start
ptc.frame_end = scene.frame_end
# ptc.filepath = join(dirname(D.filepath), splitext(basename)[0]+'_cache')
if not ptc.use_disk_cache:
ptc.use_disk_cache = True
print('enabling use disk cache')
if bake:
override = {'scene': bpy.context.scene,
'active_object': ob,#no sure of this line.. .
'point_cache': ptc}
print('>>> baking')
start = time()
#bpy.ops.ptcache.bake(override, bake=False)# bake to current frame
bpy.ops.ptcache.bake(override, bake=True)
print(f'Done {time()-start:.3f}')
def bake_mods(ob, bake=False):
for mod in ob.modifiers:
if mod.type == 'SOFT_BODY':
set_soft_body(ob, mod, bake)
if mod.type == 'PARTICLE_SYSTEM':
set_particle_system(ob, mod, bake)
def bake_action(selected=True):
if selected:
pool = []
for o in C.selected_objects:
if o.animation_data.action:
print(f'{o.name} already has an action')
o.select_set(False)
continue
else:
pool.append(o)
if not pool:
print('no object ready for action bake')
return
else:#go in physics ob collection
phycol = D.collections.get('Physics_sim')
if not phycol:
print('No physics collection')
return
pool = [o for o in phycol.all_objects if not o.hide_viewport and not o.animation_data.action]
#redefine selection
bpy.ops.object.select_all(action='DESELECT')
for o in pool:
o.select_set(True)
C.view_layer.objects.active = o
# get viewport override ? (no need if launched from custom shelf)
print('Baking action...')
# launch action baking
bpy.ops.nla.bake(frame_start=scene.frame_start, frame_end=scene.frame_end, only_selected=False, visual_keying=True, clear_constraints=True, clear_parents=True, bake_types={'OBJECT'})
bake_action(selected=info['selection'])
print('EOF')

View File

@ -1,100 +0,0 @@
info = {
'icon' : 'PHYSICS',
'description' : 'Bake modifier cache of selected objects',
'selection' : True
}
import bpy
from os.path import abspath, relpath, dirname, basename, join
from time import time
C = bpy.context
D = bpy.data
scene = C.scene
def set_soft_body(ob, mod, bake=False):
if bake:
print(f'baking {ob.name} > {mod.name}')
ptc = mod.point_cache
name = ptc.name
override = {'scene': bpy.context.scene,
'active_object': ob,#no sure of this line.. .
'point_cache': ptc}
if bake:
if name:#kill point cache related to point cache name
bpy.ops.ptcache.free_bake(override)
## bpy.ops.ptcache.free_bake_all(override)
#ptc.is_outdated = True # read-only
ptc.frame_start = scene.frame_start
ptc.frame_end = scene.frame_end
if not ptc.use_disk_cache:
ptc.use_disk_cache = True
print('enabling use disk cache')
if bake:
print('>>> baking')
start = time()
#bpy.ops.ptcache.bake(override, bake=False)# bake to current frame
bpy.ops.ptcache.bake(override, bake=True)
print(f'Done {time()-start:.3f}')
def set_particle_system(ob, mod, bake=False):
if bake:
print(f'baking {ob.name} > {mod.name}')
ptc = mod.particle_system.point_cache
ptc.frame_start = scene.frame_start
ptc.frame_end = scene.frame_end
# ptc.filepath = join(dirname(D.filepath), splitext(basename)[0]+'_cache')
if not ptc.use_disk_cache:
ptc.use_disk_cache = True
print('enabling use disk cache')
if bake:
override = {'scene': bpy.context.scene,
'active_object': ob,#no sure of this line.. .
'point_cache': ptc}
print('>>> baking')
start = time()
#bpy.ops.ptcache.bake(override, bake=False)# bake to current frame
bpy.ops.ptcache.bake(override, bake=True)
print(f'Done {time()-start:.3f}')
def bake_mods(ob, bake=False):
for mod in ob.modifiers:
if mod.type == 'SOFT_BODY':
set_soft_body(ob, mod, bake)
if mod.type == 'PARTICLE_SYSTEM':
set_particle_system(ob, mod, bake)
def bake_mod_cache(selected=True):
phycol = D.collections.get('Physics_sim')
if not phycol:
print('No physics collection')
return
if selected:
pool = []
for o in C.selected_objects:
if not phycol in o.users_collection:
print(f'{o.name} is not in Physics_sim collection' )
continue
pool.append(o)
if not pool:
print('no object ready for cache baking')
return
else:#go in physics ob collection
pool = [o for o in phycol.all_objects if not o.hide_viewport and not o.animation_data.action]
#automate preroll ?
for o in pool:
bake_mods(o, bake=True)
bake_mod_cache(selected=info['selection'])
print('EOF')

View File

@ -1,19 +0,0 @@
info = {
'icon' : 'X',
'description' : 'Delete everything in collection Physics_sim',
}
import bpy
from os.path import abspath, relpath, dirname, basename, join
from time import time
C = bpy.context
D = bpy.data
scene = C.scene
phycol = D.collections.get('Physics_sim')#Dynamic_physics
if phycol:
for ob in phycol.all_objects:
D.objects.remove(ob)
D.collections.remove(phycol)

View File

@ -1,144 +0,0 @@
import bpy
from mathutils import Vector, Matrix
from math import radians, degrees
from random import uniform
import bmesh
C = bpy.context
# Assumes we have a mesh object selected in OBJECT mode
def transfer_value(Value, OldMin, OldMax, NewMin, NewMax):
'''map a value from a range to another (transfer/translate value)'''
return (((Value - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
ob = C.object
M = ob.matrix_world
# Get the active mesh
me = ob.data
## get active group
#C.vertex_groups.active_index
if ob.type != 'MESH':
print('ERROR : not a mesh')
mode = bpy.context.mode
if mode == 'EDIT_MESH':
#me = bpy.context.edit_object.data
bm = bmesh.from_edit_mesh(me) #get Bmesh from edit
elif mode == 'OBJECT':
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()
#deselect everything first
for f in bm.edges:f.select = False
for e in bm.edges:e.select = False
for v in bm.verts:v.select = False
# Modify the BMesh, can do anything here...
chunks = []
sc = 1
ec = 0
for v in bm.verts:
v.select_set(False)
#v.co.x += 1.0
if len(v.link_edges) == 1:#vertices chain tip
#sc+=1
#if sc == 2:
# sc = 0
chunks.append(v.index)
if len(chunks)%2 != 0:
print("list not pair")
for i in chunks:
bm.verts[i].select_set(True)
n = 2
pairs = [chunks[i:i + n] for i in range(0, len(chunks), n)]
#print("pairs", pairs)#Dbg
vlists = []
cursorloc = bpy.context.scene.cursor.location
for p in pairs:
vlen = p[1] - p[0]#number of vertices in chunk
#get_closest to 3d cursor
if (cursorloc - M @ bm.verts[p[0]].co).length < (cursorloc - M @ bm.verts[p[1]].co).length:
print(f'{p[0]} to {p[1]}')
bm.verts[p[1]].select = False
vlists.append( [i for i in range(p[0], p[1]+1)] )
else:# Last point is closer to cursor (so invert direction)
print(f'{p[1]} to {p[0]}')
bm.verts[p[0]].select = False
vlists.append( [i for i in reversed(range(p[0], p[1]+1))] )
if mode == 'EDIT_MESH':
bmesh.update_edit_mesh(me, True)
elif mode == 'OBJECT':
bm.to_mesh(me)
bm.free()
# tweak vertex group (need to be in object mode)
'''
## classic progressive
for vl in vlists:
vnum = len(vl)
for i, vid in enumerate(vl):
weight = i/vnum# progressive
weight = abs(weight-1)# reverse
weight = transfer_value(weight, 0, 1, 0.8, 1)# clamp between two value
C.object.vertex_groups.active.add([vid], weight, "REPLACE")
'''
## with a divider to limit
## ex with 5 points:
## divider 2 : 0, 0, 0 , 0.5, 1.0
## divider 3 : 0, 0, 0.33 , 0.66, 1.0
percentage = 0.4 #(0 for full progressive)
#divider = 3
for vl in vlists:
vnum = len(vl)
# limit = int(vnum/divider)
limit = int(vnum*percentage)
rest = vnum - limit
mini = uniform(0.86, 0.96)#random minimum
for i, vid in enumerate(vl):
#weight = i/vnum
w = weight = (i - limit)/(vnum-limit-1)
if weight < 0: weight=0
weight = abs(weight-1)#reverse
# mini = 0.9
weight = transfer_value(weight, 0, 1, mini, 1)# clamp between two last value
print(i, w, "->", weight)#Dbg
C.object.vertex_groups.active.add([vid], weight, "REPLACE")
print("vnum", vnum)#Dbg
print("random minimum", mini)#Dbg
print("limit", limit)#Dbg
print("rest", rest)#Dbg
print("full", rest + limit)#Dbg
#too smooth with 0.8 on fast movements
## transfer_value(weight, 0, 1, 0.8, 1)

View File

@ -1,132 +0,0 @@
## create visibility on objects or armature selection from a bone of a rig ##
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 = 'name_of_the_rig'
## write the name of the propertie to attach
prop_name = "hide_something"#'hide_headband'
## prop_bone (bone holding the propertie), 'root' if left string empty.
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)

View File

@ -1,32 +0,0 @@
# coding: utf-8
import bpy
import bmesh
ob = bpy.context.object
me = ob.data
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()
#deselect everything first
for f in bm.edges:f.select = False
for e in bm.edges:e.select = False
for v in bm.verts:v.select = False
#Checker deselect on each separate mesh portion
ct = 0
for v in bm.verts:
ct+=1
if len(v.link_edges) == 1:#star/end of chain
# v.select_set(False)#already deselected
ct = 0#reset ct for next
else:
print(v.index, 'select', ct%2)
v.select_set(ct%2)
bm.to_mesh(me)
bm.free()

View File

@ -1,286 +0,0 @@
bl_info = {
"name": "FTP sync",
"author": "Christophe Seux",
"version": (1, 0),
"blender": (2, 81, 0),
"warning": "",
"wiki_url": "",
"category": "User",
}
import bpy
from bpy.types import Operator, AddonPreferences
from bpy.props import FloatVectorProperty
import os
from os.path import *
import re
### EXCLUSIONS
EXCLUSIONS = ['.*','*.db','*.blend1','*~','*sync-conflict*','*.DS_Store']
'''
TO DO
Accepts empty folders, option for type of sync (override etc)
'''
class Preferences(AddonPreferences):
bl_idname = __name__
domain : bpy.props.StringProperty(name="FTP Domain")
login : bpy.props.StringProperty(name="FTP Login")
password : bpy.props.StringProperty(name="FTP Password",subtype='PASSWORD')
ftp_folder : bpy.props.StringProperty(name="FTP folder", default = '/')
local_folder : bpy.props.StringProperty(name="Local Folder", subtype='DIR_PATH')
active_connection : bpy.props.BoolProperty(name="Active Connection", default = True)
sync_type : bpy.props.EnumProperty(
name="Sync Type",
items = [(i,i.title(),"") for i in ("ONLY_NEW", "OVERRIDE", "MORE_RECENT")],
default = "ONLY_NEW")
def draw(self, context):
layout = self.layout
layout.prop(self, "domain")
layout.prop(self, "login")
layout.prop(self, "password")
layout.prop(self, "ftp_folder")
layout.prop(self, "active_connection")
layout.prop(self, "local_folder")
def connect_to_ftp(domain, login, passwd, active = True) :
from ftplib import FTP
ftp = FTP(domain,timeout = 10)
ftp.login(user = login, passwd = passwd)
ftp.set_pasv(active)
return ftp
def is_exclude(name, patterns) :
from fnmatch import fnmatch
if not isinstance(patterns, (list,tuple)) :
patterns = [patterns]
return any([fnmatch(name, p) for p in patterns])
def get_ftp_files(ftp, root, exclusions) :
files = []
ftp.cwd(root)
for k,v in ftp.mlsd() :
if is_exclude(k, exclusions) : continue
path = '/'.join([root,k])
if v['type'] == 'file' :
files.append(path)
elif v['type'] == 'dir' :
files+= get_ftp_files(ftp, path, exclusions)
return sorted(files)
def get_files(root, exclusions) :
'''Recursively get files in passed directory if not in exclusion list'''
files = []
for f in os.scandir(root) :
if is_exclude(f.path, exclusions) : continue
if f.is_file() :
files.append(f.path)
elif f.is_dir() :
files+= get_files(f.path, exclusions)
return sorted(files)
def createDirs(ftp, dirpath):
from ftplib import error_perm
"""
Create dir with subdirs (progressive dir creation).
:param ftp: connected FTP
:param dirpath: path (like 'test/test1/test2')
:type ftp: FTP
:type dirpath: str
:rtype: None
"""
dirpath = dirpath.replace('\\', '/')
tmp = dirpath.split('/')
dirs = []
for _ in tmp:
if len(dirs) == 0:
dirs.append(_)
continue
dirs.append(dirs[-1] + '/' + _)
for _ in dirs:
try:
ftp.mkd(_)
except error_perm as e:
e_str = str(e)
if '550' in e_str and 'File exists' in e_str:
continue
def exist_ftp_file(ftp, filepath) :
filepath = filepath.replace('\\', '/')
#ftp.cwd('/')
if filepath.startswith('/') : filepath = filepath[1:]
split_path = filepath.split('/')
for i,path in enumerate(split_path) :
list_dir = {k:v['type'] for k,v in ftp.mlsd()}
#print(i,path, list(list_dir.keys()))
if path in list_dir.keys() :
if i == len(split_path)-1 :
return True
elif list_dir[path] == 'dir' :
ftp.cwd(path)
else :
return False
else :
return False
class SendToFtp(Operator):
"""Send To FTP"""
bl_idname = "ftpsync.send"
bl_label = "Send to FTP"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
prefs = context.preferences.addons[__name__].preferences
ftp = connect_to_ftp(prefs.domain, prefs.login, prefs.password, prefs.active_connection)
print('\nStart Uploading to the FTP')
print('Source Folder :', prefs.local_folder)
ftp_folder = prefs.ftp_folder.replace('\\','/').strip('/')
if not ftp_folder.startswith('/') : ftp_folder = '/'+ftp_folder
local_folder = prefs.local_folder.replace('\\','/')
for f in get_files(local_folder, EXCLUSIONS) :
'''recursively get files in directory if not in exclusion list'''
ftp.cwd(ftp_folder)
dst_file = re.sub(local_folder, '', f.replace('\\','/')).strip('/')
if prefs.sync_type == 'ONLY_NEW' and exist_ftp_file(ftp,dst_file) :
continue
ftp.cwd(ftp_folder)
createDirs(ftp,dirname(dst_file))
try :
with open(f, 'rb') as fp:
ftp.storbinary('STOR '+dst_file, fp)
print('New file :', dst_file)
except :
print('Impossible to copy %s'%fp)
ftp.close()
return {'FINISHED'}
class GetFromFtp(Operator,):
"""Create a new Mesh Object"""
bl_idname = "ftpsync.get"
bl_label = "Get from FTP"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
prefs = context.preferences.addons[__name__].preferences
ftp = connect_to_ftp(prefs.domain, prefs.login, prefs.password, prefs.active_connection)
if not prefs.local_folder :
print('You have to set the local folder in your prefs')
return {'FINISHED'}
print('\nStart Downloading from FTP')
print('Destination Folder :', prefs.local_folder)
ftp_folder = prefs.ftp_folder.replace('\\','/').strip('/')
if not ftp_folder.startswith('/') : ftp_folder = '/'+ftp_folder
local_folder = prefs.local_folder.replace('\\','/')
for f in get_ftp_files(ftp, ftp_folder, EXCLUSIONS) :
dst_file = join(local_folder, re.sub(ftp_folder,'',f.replace('\\','/')).strip('/'))
if prefs.sync_type == 'ONLY_NEW' and exists(dst_file) :
continue
if not exists(dirname(dst_file)) :
os.makedirs(dirname(dst_file))
with open(dst_file, 'wb') as fp:
ftp.retrbinary('RETR '+f, fp.write)
print('New file :', dst_file)
ftp.close()
return {'FINISHED'}
class Menu(bpy.types.Menu):
bl_label = "ADM"
bl_idname = "ADM_MT_menu"
def draw(self, context):
layout = self.layout
prefs = context.preferences.addons[__name__].preferences
layout.operator("ftpsync.get", icon='IMPORT')
layout.operator("ftpsync.send", icon='EXPORT')
layout.prop(prefs, "sync_type", text = '')
def menu_draw(self,context):
self.layout.menu("ADM_MT_menu")
cls = [Preferences, SendToFtp, GetFromFtp,Menu]
def register():
bpy.types.TOPBAR_MT_editor_menus.append(menu_draw)
for c in cls :
bpy.utils.register_class(c)
def unregister():
bpy.types.TOPBAR_MT_editor_menus.remove(menu_draw)
for c in cls :
bpy.utils.unregister_class(c)
if __name__ == "__main__":
register()

View File

@ -1,51 +0,0 @@
# coding: utf-8
import bpy
import bmesh
from math import degrees, radians
ob = bpy.context.object
me = ob.data
if ob.type != 'MESH':
print('ERROR : not a mesh')
mode = bpy.context.mode
if mode == 'EDIT_MESH':
#me = bpy.context.edit_object.data
bm = bmesh.from_edit_mesh(me) #get Bmesh from edit
elif mode == 'OBJECT':
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()
#deselect everything first
for f in bm.edges:f.select = False
for e in bm.edges:e.select = False
for v in bm.verts:v.select = False
#keep vertex that mark angle above this degree tolerance
degree_tolerance = 20
tol = radians(degree_tolerance)
#Checker
ct = 0
for v in bm.verts:
if len(v.link_edges) == 2:#star/end of chain
if v.calc_edge_angle() < tol:
#v.select_set(True)#full select
v.select_set(ct%2)#checker select
else:
ct = 0#reset counter
ct+=1
if mode == 'EDIT_MESH':
bmesh.update_edit_mesh(me, True)
elif mode == 'OBJECT':
bm.to_mesh(me)
bm.free()

View File

@ -1,17 +0,0 @@
vl = [10,11,12,13,14,15,16,17,18,19,20,21,22,23]
vl = [10,11,12,13,14]
print()
divider = 0.8
vnum = len(vl)
#limit = int(vnum/divider)
limit = int(vnum*divider)
rest = vnum - limit
print("vnum", vnum)#Dbg
print("limit", limit)#Dbg
print("rest", rest)#Dbg
for i, vid in enumerate(vl):
total = (vnum-limit-1)
w = (i - limit)/total
print(i, f'{w:.2f}')#Dbg