shelves folder init
parent
10afe009fb
commit
515c363c4a
|
@ -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()
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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')
|
|
@ -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')
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
Loading…
Reference in New Issue