Merge branch 'master' into asset-browser-poselib

This commit is contained in:
Julian Eisel 2021-04-01 13:39:26 +02:00
commit c294704a0f
13 changed files with 228 additions and 82 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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')

View File

@ -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:

View File

@ -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": "",

View File

@ -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

View File

@ -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'}

View File

@ -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

View File

@ -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