Merge branch 'master' into asset-browser-poselib
This commit is contained in:
commit
c294704a0f
|
@ -56,6 +56,7 @@ if "bpy" in locals():
|
|||
ui_bgl = reload(ui_bgl)
|
||||
ui_panels = reload(ui_panels)
|
||||
upload = reload(upload)
|
||||
upload_bg = reload(upload_bg)
|
||||
utils = reload(utils)
|
||||
|
||||
bl_ui_label = reload(bl_ui_label)
|
||||
|
@ -90,6 +91,7 @@ else:
|
|||
from blenderkit import ui_bgl
|
||||
from blenderkit import ui_panels
|
||||
from blenderkit import upload
|
||||
from blenderkit import upload_bg
|
||||
from blenderkit import utils
|
||||
|
||||
from blenderkit.bl_ui_widgets import bl_ui_label
|
||||
|
|
|
@ -632,7 +632,8 @@ def timer_update():
|
|||
l.reload()
|
||||
|
||||
if tcom.passargs.get('replace_resolution'):
|
||||
# try to relink first.
|
||||
# try to relink
|
||||
# HDRs are always swapped, so their swapping is handled without the replace_resolution option
|
||||
|
||||
ain, resolution = asset_in_scene(asset_data)
|
||||
|
||||
|
@ -809,6 +810,7 @@ class Downloader(threading.Thread):
|
|||
t = '%iKB' % fskb
|
||||
else:
|
||||
t = ' %iMB' % fsmb
|
||||
|
||||
tcom.report = f'Downloading {t} {self.resolution}'
|
||||
|
||||
dl = 0
|
||||
|
|
|
@ -293,6 +293,19 @@ def update_ratings_work_hours_ui_1_5(self, context):
|
|||
# print(float(self.rating_work_hours_ui_1_5))
|
||||
self.rating_work_hours = float(self.rating_work_hours_ui_1_5)
|
||||
|
||||
def update_ratings_work_hours_ui_1_10(self, context):
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if user_preferences.api_key == '':
|
||||
# ui_panels.draw_not_logged_in(self, message='Please login/signup to rate assets.')
|
||||
# bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_login_menu')
|
||||
# return
|
||||
bpy.ops.wm.blenderkit_login('INVOKE_DEFAULT',
|
||||
message='Please login/signup to rate assets. Clicking OK takes you to web login.')
|
||||
# self.rating_work_hours_ui_1_5 = '0'
|
||||
# print('updating 1-5')
|
||||
# print(float(self.rating_work_hours_ui_1_5))
|
||||
self.rating_work_hours = float(self.rating_work_hours_ui_1_10)
|
||||
|
||||
|
||||
class FastRateMenu(Operator):
|
||||
"""Rating of the assets , also directly from the asset bar - without need to download assets"""
|
||||
|
@ -390,11 +403,30 @@ class FastRateMenu(Operator):
|
|||
options = {'SKIP_SAVE'}
|
||||
)
|
||||
|
||||
rating_work_hours_ui_1_10: EnumProperty(name="Work Hours",
|
||||
description="How many hours did this work take?",
|
||||
items=[('0', '0', ''),
|
||||
('1', '1', ''),
|
||||
('2', '2', ''),
|
||||
('3', '3', ''),
|
||||
('4', '4', ''),
|
||||
('5', '5', ''),
|
||||
('6', '6', ''),
|
||||
('7', '7', ''),
|
||||
('8', '8', ''),
|
||||
('9', '9', ''),
|
||||
('10', '10', '')
|
||||
],
|
||||
default='0',
|
||||
update=update_ratings_work_hours_ui_1_10,
|
||||
options={'SKIP_SAVE'}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# scene = bpy.context.scene
|
||||
# ui_props = scene.blenderkitUI
|
||||
return True # ui_props.active_index > -1
|
||||
scene = bpy.context.scene
|
||||
ui_props = scene.blenderkitUI
|
||||
return ui_props.active_index > -1
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -426,9 +458,10 @@ class FastRateMenu(Operator):
|
|||
text=f"\nThat's a lot! please be sure to give such rating only to amazing {self.asset_type}s.\n",
|
||||
width=500)
|
||||
|
||||
elif self.asset_type == 'hdr':
|
||||
row = layout.row()
|
||||
row.prop(self, 'rating_work_hours_ui_1_10', expand=True, icon_only=False, emboss=True)
|
||||
else:
|
||||
|
||||
|
||||
row = layout.row()
|
||||
row.prop(self, 'rating_work_hours_ui_1_5', expand=True, icon_only=False, emboss=True)
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ def generate_lower_resolutions_hdr(asset_data, fpath):
|
|||
fn_strip, ext = os.path.splitext(fpath)
|
||||
ext = '.exr'
|
||||
if i>0:
|
||||
downscale(hdr)
|
||||
image_utils.downscale(hdr)
|
||||
|
||||
|
||||
hdr_resolution_filepath = fn_strip + paths.resolution_suffix[p2res] + ext
|
||||
|
@ -379,7 +379,7 @@ def generate_lower_resolutions(data):
|
|||
else:
|
||||
p2res = rkeys[rkeys.index(p2res) - 1]
|
||||
print('uploading resolution files')
|
||||
#upload_resolutions(files, data['asset_data'])
|
||||
upload_resolutions(files, data['asset_data'])
|
||||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
patch_asset_empty(data['asset_data']['id'], preferences.api_key)
|
||||
return
|
||||
|
|
|
@ -243,21 +243,37 @@ def parse_result(r):
|
|||
r['available_resolutions'] = []
|
||||
allthumbs = []
|
||||
durl, tname, small_tname = '', '', ''
|
||||
for f in r['files']:
|
||||
if f['fileType'] == 'thumbnail':
|
||||
tname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
small_tname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
allthumbs.append(tname) # TODO just first thumb is used now.
|
||||
|
||||
tdict = {}
|
||||
for i, t in enumerate(allthumbs):
|
||||
tdict['thumbnail_%i'] = t
|
||||
if r['assetType'] == 'hdr':
|
||||
tname = paths.extract_filename_from_url(r['thumbnailMiddleUrlNonsquared'])
|
||||
else:
|
||||
tname = paths.extract_filename_from_url(r['thumbnailMiddleUrl'])
|
||||
small_tname = paths.extract_filename_from_url(r['thumbnailSmallUrl'])
|
||||
allthumbs.append(tname) # TODO just first thumb is used now.
|
||||
# if r['fileType'] == 'thumbnail':
|
||||
# tname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
# small_tname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
# allthumbs.append(tname) # TODO just first thumb is used now.
|
||||
|
||||
for f in r['files']:
|
||||
# if f['fileType'] == 'thumbnail':
|
||||
# tname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
# small_tname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
# allthumbs.append(tname) # TODO just first thumb is used now.
|
||||
|
||||
|
||||
if f['fileType'] == 'blend':
|
||||
durl = f['downloadUrl'].split('?')[0]
|
||||
# fname = paths.extract_filename_from_url(f['filePath'])
|
||||
|
||||
if f['fileType'].find('resolution') > -1:
|
||||
r['available_resolutions'].append(resolutions.resolutions[f['fileType']])
|
||||
|
||||
#code for more thumbnails
|
||||
# tdict = {}
|
||||
# for i, t in enumerate(allthumbs):
|
||||
# tdict['thumbnail_%i'] = t
|
||||
|
||||
r['max_resolution'] = 0
|
||||
if r['available_resolutions']: # should check only for non-empty sequences
|
||||
r['max_resolution'] = max(r['available_resolutions'])
|
||||
|
@ -311,7 +327,7 @@ def parse_result(r):
|
|||
if asset_type == 'material':
|
||||
asset_data['texture_size_meters'] = params.get('textureSizeMeters', 1.0)
|
||||
|
||||
asset_data.update(tdict)
|
||||
# asset_data.update(tdict)
|
||||
|
||||
au = scene.get('assets used', {})
|
||||
if au == {}:
|
||||
|
@ -1019,25 +1035,44 @@ class Searcher(threading.Thread):
|
|||
thumb_full_filepaths = []
|
||||
# END OF PARSING
|
||||
for d in rdata.get('results', []):
|
||||
thumb_small_urls.append(d["thumbnailSmallUrl"])
|
||||
imgname = paths.extract_filename_from_url(d['thumbnailSmallUrl'])
|
||||
imgpath = os.path.join(self.tempdir, imgname)
|
||||
thumb_small_filepaths.append(imgpath)
|
||||
|
||||
for f in d['files']:
|
||||
# TODO move validation of published assets to server, too manmy checks here.
|
||||
if f['fileType'] == 'thumbnail' and f['fileThumbnail'] != None and f['fileThumbnailLarge'] != None:
|
||||
if f['fileThumbnail'] == None:
|
||||
f['fileThumbnail'] = 'NONE'
|
||||
if f['fileThumbnailLarge'] == None:
|
||||
f['fileThumbnailLarge'] = 'NONE'
|
||||
|
||||
thumb_small_urls.append(f['fileThumbnail'])
|
||||
thumb_full_urls.append(f['fileThumbnailLarge'])
|
||||
|
||||
imgname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
imgpath = os.path.join(self.tempdir, imgname)
|
||||
thumb_small_filepaths.append(imgpath)
|
||||
if d["assetType"] == 'hdr':
|
||||
larege_thumb_url = d['thumbnailMiddleUrlNonsquared']
|
||||
|
||||
imgname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
imgpath = os.path.join(self.tempdir, imgname)
|
||||
thumb_full_filepaths.append(imgpath)
|
||||
else:
|
||||
larege_thumb_url = d['thumbnailMiddleUrl']
|
||||
|
||||
thumb_full_urls.append(larege_thumb_url)
|
||||
imgname = paths.extract_filename_from_url(larege_thumb_url)
|
||||
imgpath = os.path.join(self.tempdir, imgname)
|
||||
thumb_full_filepaths.append(imgpath)
|
||||
|
||||
|
||||
|
||||
# for f in d['files']:
|
||||
# # TODO move validation of published assets to server, too manmy checks here.
|
||||
# if f['fileType'] == 'thumbnail' and f['fileThumbnail'] != None and f['fileThumbnailLarge'] != None:
|
||||
# if f['fileThumbnail'] == None:
|
||||
# f['fileThumbnail'] = 'NONE'
|
||||
# if f['fileThumbnailLarge'] == None:
|
||||
# f['fileThumbnailLarge'] = 'NONE'
|
||||
#
|
||||
# thumb_small_urls.append(f['fileThumbnail'])
|
||||
# thumb_full_urls.append(f['fileThumbnailLarge'])
|
||||
#
|
||||
# imgname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
# imgpath = os.path.join(self.tempdir, imgname)
|
||||
# thumb_small_filepaths.append(imgpath)
|
||||
#
|
||||
# imgname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
# imgpath = os.path.join(self.tempdir, imgname)
|
||||
# thumb_full_filepaths.append(imgpath)
|
||||
|
||||
sml_thbs = zip(thumb_small_filepaths, thumb_small_urls)
|
||||
full_thbs = zip(thumb_full_filepaths, thumb_full_urls)
|
||||
|
|
|
@ -390,7 +390,7 @@ def draw_tooltip(x, y, text='', author='', img=None, gravatar=None):
|
|||
xtext += int(isizex / ncolumns)
|
||||
|
||||
column_lines = 1
|
||||
i=0
|
||||
i = 0
|
||||
for l in alines:
|
||||
if gravatar is not None:
|
||||
if column_lines == 1:
|
||||
|
@ -399,20 +399,20 @@ def draw_tooltip(x, y, text='', author='', img=None, gravatar=None):
|
|||
xtext -= gsize + textmargin
|
||||
|
||||
ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth
|
||||
if False:#i == 0:
|
||||
if False: # i == 0:
|
||||
ytext = y - name_height + 5 - isizey + texth - textmargin
|
||||
elif i == len(lines) - 1:
|
||||
ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth
|
||||
tcol = textcol
|
||||
tsize = font_height
|
||||
if (i> 0 and alines[i-1][:7] == 'Author:'):
|
||||
if (i > 0 and alines[i - 1][:7] == 'Author:'):
|
||||
tcol = textcol_strong
|
||||
fsize = font_height + 2
|
||||
else:
|
||||
fsize = font_height
|
||||
tcol = textcol
|
||||
|
||||
if l[:4] == 'Tip:' or l[:11] == 'Please rate' :
|
||||
if l[:4] == 'Tip:' or l[:11] == 'Please rate':
|
||||
tcol = textcol_strong
|
||||
fsize = font_height + 1
|
||||
|
||||
|
@ -710,6 +710,8 @@ def get_large_thumbnail_image(asset_data):
|
|||
iname = utils.previmg_name(ui_props.active_index, fullsize=True)
|
||||
directory = paths.get_temp_dir('%s_search' % mappingdict[ui_props.asset_type])
|
||||
tpath = os.path.join(directory, asset_data['thumbnail'])
|
||||
if asset_data['assetType'] == 'hdr':
|
||||
tpath = os.path.join(directory, asset_data['thumbnail'])
|
||||
if not asset_data['thumbnail']:
|
||||
tpath = paths.get_addon_thumbnail_path('thumbnail_not_available.jpg')
|
||||
|
||||
|
@ -890,15 +892,16 @@ def draw_callback_3d(self, context):
|
|||
if ui.draw_snapped_bounds:
|
||||
draw_bbox(ui.snapped_location, ui.snapped_rotation, ui.snapped_bbox_min, ui.snapped_bbox_max)
|
||||
|
||||
|
||||
def object_in_particle_collection(o):
|
||||
'''checks if an object is in a particle system as instance, to not snap to it and not to try to attach material.'''
|
||||
for p in bpy.data.particles:
|
||||
if p.render_type =='COLLECTION':
|
||||
if p.render_type == 'COLLECTION':
|
||||
if p.instance_collection:
|
||||
for o1 in p.instance_collection.objects:
|
||||
if o1 == o:
|
||||
return True
|
||||
if p.render_type =='COLLECTION':
|
||||
if p.render_type == 'COLLECTION':
|
||||
if p.instance_object == o:
|
||||
return True
|
||||
return False
|
||||
|
@ -921,12 +924,14 @@ def deep_ray_cast(depsgraph, ray_origin, vec):
|
|||
try_has_hit, try_snapped_location, try_snapped_normal, try_face_index, try_object, try_matrix = bpy.context.scene.ray_cast(
|
||||
depsgraph, ray_origin, vec)
|
||||
if try_has_hit:
|
||||
#this way only good hits are returned, otherwise
|
||||
# this way only good hits are returned, otherwise
|
||||
has_hit, snapped_location, snapped_normal, face_index, object, matrix = try_has_hit, try_snapped_location, try_snapped_normal, try_face_index, try_object, try_matrix
|
||||
if not (object.display_type == 'BOUNDS' or object_in_particle_collection(try_object)):# or not object.visible_get()):
|
||||
if not (object.display_type == 'BOUNDS' or object_in_particle_collection(
|
||||
try_object)): # or not object.visible_get()):
|
||||
return has_hit, snapped_location, snapped_normal, face_index, object, matrix
|
||||
return empty_set
|
||||
|
||||
|
||||
def mouse_raycast(context, mx, my):
|
||||
r = context.region
|
||||
rv3d = context.region_data
|
||||
|
@ -938,7 +943,7 @@ def mouse_raycast(context, mx, my):
|
|||
view_position = rv3d.view_matrix.inverted().translation
|
||||
ray_origin = view3d_utils.region_2d_to_location_3d(r, rv3d, coord, depth_location=view_position)
|
||||
else:
|
||||
ray_origin = view3d_utils.region_2d_to_origin_3d(r, rv3d, coord, clamp = 1.0)
|
||||
ray_origin = view3d_utils.region_2d_to_origin_3d(r, rv3d, coord, clamp=1.0)
|
||||
|
||||
ray_target = ray_origin + (view_vector * 1000000000)
|
||||
|
||||
|
@ -947,8 +952,8 @@ def mouse_raycast(context, mx, my):
|
|||
has_hit, snapped_location, snapped_normal, face_index, object, matrix = deep_ray_cast(
|
||||
bpy.context.view_layer.depsgraph, ray_origin, vec)
|
||||
|
||||
#backface snapping inversion
|
||||
if view_vector.angle(snapped_normal)<math.pi/2:
|
||||
# backface snapping inversion
|
||||
if view_vector.angle(snapped_normal) < math.pi / 2:
|
||||
snapped_normal = -snapped_normal
|
||||
# print(has_hit, snapped_location, snapped_normal, face_index, object, matrix)
|
||||
# rote = mathutils.Euler((0, 0, math.pi))
|
||||
|
@ -1102,7 +1107,6 @@ def mouse_in_area(mx, my, x, y, w, h):
|
|||
|
||||
|
||||
def mouse_in_asset_bar(mx, my):
|
||||
|
||||
ui_props = bpy.context.scene.blenderkitUI
|
||||
# search_results = bpy.context.window_manager.get('search results')
|
||||
# if search_results == None:
|
||||
|
@ -1220,6 +1224,7 @@ class ParticlesDropDialog(bpy.types.Operator):
|
|||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self, width=400)
|
||||
|
||||
|
||||
# class MaterialDropDialog(bpy.types.Operator):
|
||||
# """Tooltip"""
|
||||
# bl_idname = "object.blenderkit_material_drop"
|
||||
|
@ -1624,7 +1629,7 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
return {'RUNNING_MODAL'}
|
||||
|
||||
# Drag-drop interaction
|
||||
if ui_props.dragging and mouse_in_region(r, mx, my):# and ui_props.drag_length>10:
|
||||
if ui_props.dragging and mouse_in_region(r, mx, my): # and ui_props.drag_length>10:
|
||||
asset_search_index = ui_props.active_index
|
||||
# raycast here
|
||||
ui_props.active_index = -3
|
||||
|
@ -1727,7 +1732,8 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
model_location=loc,
|
||||
model_rotation=rotation,
|
||||
target_object=target_object,
|
||||
material_target_slot=target_slot)
|
||||
material_target_slot=target_slot,
|
||||
)
|
||||
|
||||
|
||||
elif ui_props.asset_type == 'MODEL':
|
||||
|
@ -1752,9 +1758,17 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
model_rotation=rotation,
|
||||
target_object=target_object)
|
||||
|
||||
elif ui_props.asset_type == 'HDR':
|
||||
bpy.ops.scene.blenderkit_download('INVOKE_DEFAULT',
|
||||
asset_index=asset_search_index,
|
||||
# replace_resolution=True,
|
||||
invoke_resolution=True,
|
||||
max_resolution = asset_data.get('max_resolution', 0)
|
||||
)
|
||||
else:
|
||||
bpy.ops.scene.blenderkit_download( # asset_type=ui_props.asset_type,
|
||||
asset_index=asset_search_index)
|
||||
asset_index=asset_search_index,
|
||||
)
|
||||
|
||||
ui_props.dragging = False
|
||||
return {'RUNNING_MODAL'}
|
||||
|
@ -1927,6 +1941,7 @@ def draw_callback_3d_dragging(self, context):
|
|||
if self.has_hit:
|
||||
draw_bbox(self.snapped_location, self.snapped_rotation, self.snapped_bbox_min, self.snapped_bbox_max)
|
||||
|
||||
|
||||
def find_and_activate_instancers(object):
|
||||
for ob in bpy.context.visible_objects:
|
||||
if ob.instance_type == 'COLLECTION' and ob.instance_collection and object.name in ob.instance_collection.objects:
|
||||
|
@ -1978,10 +1993,10 @@ class AssetDragOperator(bpy.types.Operator):
|
|||
# action
|
||||
else:
|
||||
if object.is_library_indirect:
|
||||
ui_panels.ui_message(title = 'This object is linked from outer file',
|
||||
message = "Please select the model,"
|
||||
"go to the 'Selected Model' panel "
|
||||
"in BlenderKit and hit 'Bring to Scene' first.")
|
||||
ui_panels.ui_message(title='This object is linked from outer file',
|
||||
message="Please select the model,"
|
||||
"go to the 'Selected Model' panel "
|
||||
"in BlenderKit and hit 'Bring to Scene' first.")
|
||||
|
||||
self.report({'WARNING'}, "Invalid or library object as input:")
|
||||
target_object = ''
|
||||
|
@ -2037,11 +2052,11 @@ class AssetDragOperator(bpy.types.Operator):
|
|||
target_object=target_object)
|
||||
|
||||
else:
|
||||
if ui_props.asset_type =='SCENE':
|
||||
ui_panels.ui_message(title = 'Scene will be appended after download',
|
||||
message = 'After the scene is appended, you have to switch to it manually.'
|
||||
'If you want to switch to scenes automatically after appending,'
|
||||
' you can set it in import settings.')
|
||||
if ui_props.asset_type == 'SCENE':
|
||||
ui_panels.ui_message(title='Scene will be appended after download',
|
||||
message='After the scene is appended, you have to switch to it manually.'
|
||||
'If you want to switch to scenes automatically after appending,'
|
||||
' you can set it in import settings.')
|
||||
bpy.ops.scene.blenderkit_download( # asset_type=ui_props.asset_type,
|
||||
asset_index=self.asset_search_index)
|
||||
|
||||
|
|
|
@ -1227,7 +1227,8 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
|
|||
op.max_resolution = asset_data.get('max_resolution',
|
||||
0) # str(utils.get_param(asset_data, 'textureResolutionMax'))
|
||||
|
||||
elif asset_data['assetBaseId'] in s['assets used'].keys():
|
||||
elif asset_data['assetBaseId'] in s['assets used'].keys() and asset_data['assetType'] != 'hdr':
|
||||
#HDRs are excluded from replacement, since they are always replaced.
|
||||
# called from asset bar:
|
||||
print('context menu')
|
||||
op = col.operator('scene.blenderkit_download', text='Replace asset resolution')
|
||||
|
|
|
@ -569,7 +569,7 @@ def update_free_full(self, context):
|
|||
|
||||
|
||||
def can_edit_asset(active_index=-1, asset_data=None):
|
||||
if active_index == -1 and not asset_data:
|
||||
if active_index < 0 and not asset_data:
|
||||
return False
|
||||
profile = bpy.context.window_manager.get('bkit profile')
|
||||
if profile is None:
|
||||
|
|
|
@ -21,7 +21,7 @@ bl_info = {
|
|||
"name": "Grease Pencil Tools",
|
||||
"description": "Extra tools for Grease Pencil",
|
||||
"author": "Samuel Bernou, Antonio Vazquez, Daniel Martinez Lara, Matias Mendiola",
|
||||
"version": (1, 4, 0),
|
||||
"version": (1, 4, 2),
|
||||
"blender": (2, 91, 0),
|
||||
"location": "Sidebar > Grease Pencil > Grease Pencil Tools",
|
||||
"warning": "",
|
||||
|
|
|
@ -530,10 +530,10 @@ valid:Spacebar/Enter, cancel:Del/Backspace/Tab/Ctrl+T"
|
|||
print('Deleted remaining lattice object')
|
||||
delete_cage(phantom_obj)
|
||||
|
||||
if [m for m in self.gp_obj.grease_pencil_modifiers if m.type == 'GP_LATTICE']:
|
||||
self.report({'ERROR'}, "Grease pencil object already has a lattice modifier (can only have one)")
|
||||
return {'CANCELLED'}
|
||||
|
||||
if bpy.app.version < (2,93,0):
|
||||
if [m for m in self.gp_obj.grease_pencil_modifiers if m.type == 'GP_LATTICE']:
|
||||
self.report({'ERROR'}, "Grease pencil object already has a lattice modifier (multi-lattices are enabled in blender 2.93+)")
|
||||
return {'CANCELLED'}
|
||||
|
||||
self.gp_mode = context.mode#store mode for restore
|
||||
|
||||
|
|
|
@ -233,6 +233,12 @@ class GPTS_OT_time_scrub(bpy.types.Operator):
|
|||
|
||||
self.hud = prefs.use_hud
|
||||
if not self.hud:
|
||||
## Same as end settings when HUD is On
|
||||
if self.lock_range:
|
||||
self.pos = [i for i in self.pos if self.f_start <= i <= self.f_end]
|
||||
self.pos = np.asarray(self.pos)
|
||||
if self.rolling_mode:
|
||||
context.scene.frame_current = self.new_frame
|
||||
context.window_manager.modal_handler_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ bl_info = {
|
|||
"name": "Collection Manager",
|
||||
"description": "Manage collections and their objects",
|
||||
"author": "Ryan Inch",
|
||||
"version": (2, 21, 0),
|
||||
"version": (2, 21, 1),
|
||||
"blender": (2, 80, 0),
|
||||
"location": "View3D - Object Mode (Shortcut - M)",
|
||||
"warning": '', # used for warning icon and text in addons panel
|
||||
|
|
|
@ -173,30 +173,52 @@ class CollectionManager(Operator):
|
|||
# set selection
|
||||
setsel = name_row.row(align=True)
|
||||
icon = 'DOT'
|
||||
some_selected = False
|
||||
|
||||
if any((laycol["ptr"].exclude,
|
||||
collection.hide_select,
|
||||
collection.hide_viewport,
|
||||
laycol["ptr"].hide_viewport,
|
||||
not collection.objects,)):
|
||||
# objects cannot be selected
|
||||
if not collection.objects:
|
||||
icon = 'BLANK1'
|
||||
setsel.active = False
|
||||
|
||||
else:
|
||||
all_selected = None
|
||||
all_unreachable = None
|
||||
|
||||
for obj in collection.objects:
|
||||
if not obj.visible_get() or obj.hide_select:
|
||||
if all_unreachable != False:
|
||||
all_unreachable = True
|
||||
|
||||
else:
|
||||
all_unreachable = False
|
||||
|
||||
if obj.select_get() == False:
|
||||
# some objects remain unselected
|
||||
icon = 'LAYER_USED'
|
||||
break
|
||||
icon = 'KEYFRAME'
|
||||
all_selected = False
|
||||
|
||||
if icon != 'LAYER_USED':
|
||||
else:
|
||||
some_selected = True
|
||||
|
||||
if all_selected == False:
|
||||
break
|
||||
|
||||
all_selected = True
|
||||
|
||||
|
||||
if all_selected:
|
||||
# all objects are selected
|
||||
icon = 'LAYER_ACTIVE'
|
||||
icon = 'KEYFRAME_HLT'
|
||||
|
||||
if all_unreachable:
|
||||
if collection.objects:
|
||||
icon = 'DOT'
|
||||
|
||||
setsel.active = False
|
||||
|
||||
prop = setsel.operator("view3d.select_collection_objects",
|
||||
text="",
|
||||
icon=icon,
|
||||
depress=bool(icon == 'LAYER_ACTIVE')
|
||||
depress=some_selected,
|
||||
)
|
||||
prop.is_master_collection = True
|
||||
prop.collection_name = 'Master Collection'
|
||||
|
@ -607,30 +629,60 @@ class CM_UL_items(UIList):
|
|||
# set selection
|
||||
setsel = c_name.row(align=True)
|
||||
icon = 'DOT'
|
||||
some_selected = False
|
||||
|
||||
if not collection.objects:
|
||||
icon = 'BLANK1'
|
||||
setsel.active = False
|
||||
|
||||
if any((laycol["ptr"].exclude,
|
||||
collection.hide_select,
|
||||
collection.hide_viewport,
|
||||
laycol["ptr"].hide_viewport,
|
||||
not collection.objects,)):
|
||||
laycol["ptr"].hide_viewport,)):
|
||||
# objects cannot be selected
|
||||
setsel.active = False
|
||||
|
||||
else:
|
||||
all_selected = None
|
||||
all_unreachable = None
|
||||
|
||||
for obj in collection.objects:
|
||||
if not obj.visible_get() or obj.hide_select:
|
||||
if all_unreachable != False:
|
||||
all_unreachable = True
|
||||
|
||||
else:
|
||||
all_unreachable = False
|
||||
|
||||
if obj.select_get() == False:
|
||||
# some objects remain unselected
|
||||
icon = 'LAYER_USED'
|
||||
break
|
||||
icon = 'KEYFRAME'
|
||||
all_selected = False
|
||||
|
||||
if icon != 'LAYER_USED':
|
||||
else:
|
||||
some_selected = True
|
||||
|
||||
if all_selected == False:
|
||||
break
|
||||
|
||||
all_selected = True
|
||||
|
||||
|
||||
if all_selected:
|
||||
# all objects are selected
|
||||
icon = 'LAYER_ACTIVE'
|
||||
icon = 'KEYFRAME_HLT'
|
||||
|
||||
if all_unreachable:
|
||||
if collection.objects:
|
||||
icon = 'DOT'
|
||||
|
||||
setsel.active = False
|
||||
|
||||
|
||||
prop = setsel.operator("view3d.select_collection_objects",
|
||||
text="",
|
||||
icon=icon,
|
||||
depress=bool(icon == 'LAYER_ACTIVE')
|
||||
depress=some_selected
|
||||
)
|
||||
prop.is_master_collection = False
|
||||
prop.collection_name = item.name
|
||||
|
|
Loading…
Reference in New Issue