diff options
author | Vilém Duha <vilda.novak@gmail.com> | 2021-05-01 20:09:09 +0300 |
---|---|---|
committer | Vilém Duha <vilda.novak@gmail.com> | 2021-05-01 20:09:09 +0300 |
commit | c12dc2b19968b3e222e5b0c41ea918a8a15c4ad0 (patch) | |
tree | efdaa80347c0927f09e8e75437a902093b0bbc47 | |
parent | 6dac52a35f3387720da6ca6fd04aa8160819c24e (diff) |
BlenderKit: minor tweaks to asset card layout
- some code cleanup
- labels with tooltips (an empty operator that enables this, drawing it non-emobssed)
-rw-r--r-- | blenderkit/autothumb.py | 2 | ||||
-rw-r--r-- | blenderkit/search.py | 22 | ||||
-rw-r--r-- | blenderkit/thumbnails/star_grey.png | bin | 0 -> 1733 bytes | |||
-rw-r--r-- | blenderkit/ui.py | 43 | ||||
-rw-r--r-- | blenderkit/ui_panels.py | 143 | ||||
-rw-r--r-- | blenderkit/utils.py | 7 |
6 files changed, 139 insertions, 78 deletions
diff --git a/blenderkit/autothumb.py b/blenderkit/autothumb.py index baf1a2ca..9be9039e 100644 --- a/blenderkit/autothumb.py +++ b/blenderkit/autothumb.py @@ -523,7 +523,7 @@ class GenerateMaterialThumbnailOperator(bpy.types.Operator): class ReGenerateMaterialThumbnailOperator(bpy.types.Operator): """ Generate default thumbnail with Cycles renderer and upload it. - Works also for assets from search results, without being downloaded before. + Works also for assets from search results, without being downloaded before """ bl_idname = "object.blenderkit_regenerate_material_thumbnail" bl_label = "BlenderKit Material Thumbnail Re-Generator" diff --git a/blenderkit/search.py b/blenderkit/search.py index 67a353ac..858f676b 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -990,10 +990,10 @@ def build_query_common(query, props): if props.search_keywords != '': query_common["query"] = props.search_keywords - if props.search_verification_status != 'ALL': + if props.search_verification_status != 'ALL' and utils.profile_is_validator(): query_common['verification_status'] = props.search_verification_status.lower() - if props.unrated_only: + if props.unrated_only and utils.profile_is_validator(): query["quality_count"] = 0 if props.search_file_size: @@ -1447,10 +1447,26 @@ class UrlOperator(Operator): bpy.ops.wm.url_open(url=self.url) return {'FINISHED'} +class TooltipLabelOperator(Operator): + """""" + bl_idname = "wm.blenderkit_tooltip" + bl_label = "" + bl_description = "Empty operator to be able to create tooltips on labels in UI" + bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} + + tooltip: bpy.props.StringProperty(default='Open a web page') + + @classmethod + def description(cls, context, properties): + return properties.tooltip + + def execute(self, context): + return {'FINISHED'} classes = [ SearchOperator, - UrlOperator + UrlOperator, + TooltipLabelOperator ] diff --git a/blenderkit/thumbnails/star_grey.png b/blenderkit/thumbnails/star_grey.png Binary files differnew file mode 100644 index 00000000..53c5bd05 --- /dev/null +++ b/blenderkit/thumbnails/star_grey.png diff --git a/blenderkit/ui.py b/blenderkit/ui.py index ba5855f7..644980de 100644 --- a/blenderkit/ui.py +++ b/blenderkit/ui.py @@ -231,11 +231,6 @@ def draw_ratings_bgl(): if rating_possible: # (not rated or ui_props.rating_menu_on): # print('rating is pssible', asset_data['name']) bkit_ratings = asset.bkit_ratings - bgcol = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.inner - textcol = (1, 1, 1, 1) - - r = bpy.context.region - font_size = int(ui.rating_ui_scale * 20) if ui.rating_button_on: # print('should draw button') @@ -261,7 +256,6 @@ def draw_ratings_bgl(): ui.rating_button_width, ui.rating_button_width, img, 1) - # ui_bgl.draw_text( 'rate asset %s' % asset_data['name'],r.width - rating_button_width + margin, margin, font_size) return @@ -278,7 +272,7 @@ def draw_text_block(x=0, y=0, width=40, font_size=10, line_height=15, text='', c ui_bgl.draw_text(l, x, ytext, font_size, color) -def draw_tooltip(x, y, name='', author='', img=None, gravatar=None): +def draw_tooltip(x, y, name='', author='', quality = '-', img=None, gravatar=None): region = bpy.context.region scale = bpy.context.preferences.view.ui_scale t = time.time() @@ -308,7 +302,7 @@ def draw_tooltip(x, y, name='', author='', img=None, gravatar=None): if gravatar is not None: overlay_height_base = 90 else: - overlay_height_base = 50 + overlay_height_base = 70 overlay_height = overlay_height_base * scale @@ -347,6 +341,12 @@ def draw_tooltip(x, y, name='', author='', img=None, gravatar=None): ttipmargin + overlay_height , background_overlay) + #draw name + name_x = x + textmargin + name_y = y - isizey + overlay_height - textmargin - name_height + ui_bgl.draw_text(name, name_x, name_y, name_height, textcol) + + # draw gravatar author_x_text = x + isizex - textmargin gravatar_size = overlay_height - 2 * textmargin @@ -357,13 +357,17 @@ def draw_tooltip(x, y, name='', author='', img=None, gravatar=None): gravatar_y, # + textmargin, gravatar_size, gravatar_size, gravatar, 1) - name_x = x + textmargin - name_y = y - isizey + overlay_height - textmargin - name_height - ui_bgl.draw_text(name, name_x, name_y, name_height, textcol) - + #draw author's name author_text_size = int(name_height * .7) ui_bgl.draw_text(author, author_x_text, gravatar_y, author_text_size, textcol, ralign=True) + # draw quality + quality_text_size = int(name_height * 1) + img = utils.get_thumbnail('star_grey.png') + ui_bgl.draw_image(name_x, gravatar_y, quality_text_size, quality_text_size, img, .6) + ui_bgl.draw_text(str(quality), name_x + quality_text_size + 5, gravatar_y, quality_text_size, textcol) + + def draw_tooltip_with_author(asset_data, x, y): # TODO move this lazy loading into a function and don't duplicate through the code @@ -377,13 +381,20 @@ def draw_tooltip_with_author(asset_data, x, y): if a.get('gravatarImg') is not None: gimg = utils.get_hidden_image(a['gravatarImg'], a['gravatarHash']) - # author_s = '' - # if not gimg: - # author_s = 'Author: ' aname = asset_data['displayName'] if len(aname)>36: aname = f"{aname[:33]}..." - draw_tooltip(x, y, name=aname, author=f"by {a['firstName']} {a['lastName']}", img=img, + + rc = asset_data.get('ratingsCount') + show_rating_threshold = 0 + rcount = 0 + quality = '-' + if rc: + rcount = min(rc['quality'], rc['workingHours']) + if rcount>show_rating_threshold: + quality = round(asset_data['ratingsAverage'].get('quality')) + + draw_tooltip(x, y, name=aname, author=f"by {a['firstName']} {a['lastName']}", quality= quality, img=img, gravatar=gimg) diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index 8d880fdd..daa374c1 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -1271,26 +1271,7 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False): profile = wm.get('bkit profile') if profile is not None: # validation - if utils.profile_is_validator(): - layout.label(text='Validation tools:') - layout.operator_context = 'EXEC_DEFAULT' - if asset_data['verificationStatus'] != 'uploaded': - op = layout.operator('object.blenderkit_change_status', text='set Uploaded') - op.asset_id = asset_data['id'] - op.state = 'uploaded' - if asset_data['verificationStatus'] != 'validated': - op = layout.operator('object.blenderkit_change_status', text='Validate') - op.asset_id = asset_data['id'] - op.state = 'validated' - if asset_data['verificationStatus'] != 'on_hold': - op = layout.operator('object.blenderkit_change_status', text='Put on Hold') - op.asset_id = asset_data['id'] - op.state = 'on_hold' - if asset_data['verificationStatus'] != 'rejected': - op = layout.operator('object.blenderkit_change_status', text='Reject') - op.asset_id = asset_data['id'] - op.state = 'rejected' if author_id == str(profile['user']['id']) or utils.profile_is_validator(): layout.label(text='Management tools:') @@ -1386,6 +1367,41 @@ def numeric_to_str(s): return s +def label_or_url(layout, text='', tooltip='', url='', icon_value=None, icon=None): + '''automatically switch between different layout options for linking or tooltips''' + layout.emboss = 'NONE' + if url != '': + if icon: + op = layout.operator('wm.blenderkit_url', text=text, icon=icon) + elif icon_value: + op = layout.operator('wm.blenderkit_url', text=text, icon_value=icon_value) + else: + op = layout.operator('wm.blenderkit_url', text=text) + op.url = url + op.tooltip = tooltip + layout.label(text='') + layout.label(text='') + + return + if tooltip != '': + if icon: + op = layout.operator('wm.blenderkit_tooltip', text=text, icon=icon) + elif icon_value: + op = layout.operator('wm.blenderkit_tooltip', text=text, icon_value=icon_value) + else: + op = layout.operator('wm.blenderkit_tooltip', text=text) + op.tooltip = tooltip + layout.label(text='') + layout.label(text='') + return + if icon: + layout.label(text=text, icon=icon) + elif icon_value: + layout.label(text=text, icon_value=icon_value) + else: + layout.label(text=text) + + class AssetPopupCard(bpy.types.Operator): """Generate Cycles thumbnail for model assets""" bl_idname = "wm.blenderkit_asset_popup" @@ -1510,32 +1526,20 @@ class AssetPopupCard(bpy.types.Operator): col = layout.column() draw_asset_context_menu(col, context, self.asset_data, from_panel=False) - def draw_property(self, layout, left, right, icon=None, icon_value=None, url=None, tooltip=''): + def draw_property(self, layout, left, right, icon=None, icon_value=None, url='', tooltip=''): right = str(right) row = layout.row() split = row.split(factor=0.4) split.alignment = 'RIGHT' split.label(text=left) split = split.split() - # if url: - # if icon_value: - # op = split.operator('wm.url_open', text=right, icon_value=icon_value) - # elif icon: - # op = split.operator('wm.url_open', text=right, icon=icon) - # else: - # op = split.operator('wm.url_open', text=right) - # op.url = url - # return - if url: - split = split.split(factor=0.9) - if icon_value: - split.label(text=right, icon_value=icon_value) - elif icon: - split.label(text=right, icon=icon) - - else: - split.label(text=right) - if url: + split.alignment = 'LEFT' + #split for questionmark: + if url!='': + split = split.split(factor=0.7) + label_or_url(split,text=right,tooltip=tooltip, url=url, icon_value=icon_value, icon=icon) + #additional questionmark icon where it's important? + if url!='': split = split.split() op = split.operator('wm.blenderkit_url', text='', icon='QUESTION') op.url = url @@ -1576,10 +1580,10 @@ class AssetPopupCard(bpy.types.Operator): self.draw_property(box, 'License:', t, - icon_value=icon.icon_id, + # icon_value=icon.icon_id, url="https://www.blenderkit.com/docs/licenses/", - tooltip='All BlenderKit assets are available for commercial use. ' - 'Click to read more about BlenderKit licenses online' + tooltip='All BlenderKit assets are available for commercial use. \n'\ + 'Click to read more about BlenderKit licenses on the website' ) if upload.can_edit_asset(asset_data=self.asset_data): @@ -1627,7 +1631,10 @@ class AssetPopupCard(bpy.types.Operator): resolution = utils.get_param(self.asset_data, 'textureResolutionMax') if resolution is not None: ress = f"{int(round(resolution / 1024, 0))}K" - self.draw_property(box, 'Resolution', ress) + self.draw_property(box, 'Resolution', ress, + tooltip='Maximal resolution of textures in this asset.\n'\ + 'Most texture asset have also lower resolutions generated.\n'\ + 'Go to BlenderKit add-on import settings to set default resolution') self.draw_asset_parameter(box, key='designer', pretext='Designer') self.draw_asset_parameter(box, key='manufacturer', pretext='Manufacturer') # TODO make them clickable! @@ -1650,17 +1657,28 @@ class AssetPopupCard(bpy.types.Operator): self.draw_property(box, 'Size:', t) # Free/Full plan or private Access + plans_tooltip = 'BlenderKit has 2 plans:\n'\ + ' * Free plan - more than 50% of all assets\n'\ + ' * Full plan - unlimited access to everything'\ + 'Click to go to subscriptions page.' + plans_link = 'https://www.blenderkit.com/plans/pricing/' if self.asset_data['isPrivate']: t = 'Private' self.draw_property(box, 'Access:', t, icon='LOCKED') elif self.asset_data['isFree']: t = 'Free plan' icon = pcoll['free'] - self.draw_property(box, 'Access:', t, icon_value=icon.icon_id) + self.draw_property(box, 'Access:', t, + icon_value=icon.icon_id, + tooltip = plans_tooltip, + url= plans_link) else: t = 'Full plan' icon = pcoll['full'] - self.draw_property(box, 'Access:', t, icon_value=icon.icon_id) + self.draw_property(box, 'Access:', t, + icon_value=icon.icon_id, + tooltip=plans_tooltip, + url=plans_link) def draw_author_area(self, context, layout, width=330): self.draw_author(context, layout, width=330) @@ -1716,7 +1734,7 @@ class AssetPopupCard(bpy.types.Operator): op = button_row.operator('wm.url_open', text=text) op.url = url - op = button_row.operator('view3d.blenderkit_search', text="Show Assets By Author") + op = button_row.operator('view3d.blenderkit_search', text="Find Assets By Author") op.keywords = '' op.author_id = self.asset_data['author']['id'] @@ -1724,12 +1742,8 @@ class AssetPopupCard(bpy.types.Operator): layout.emboss = 'NORMAL' box_thumbnail = layout.box() - # row = split_right.row() - # column_right = row.column() - box_thumbnail.scale_y = 0.5 - # row = box_thumbnail.row() - # row.scale_y = 20 + box_thumbnail.scale_y = .4 box_thumbnail.template_icon(icon_value=self.img.preview.icon_id, scale=34.0) # row = box_thumbnail.row() @@ -1738,8 +1752,11 @@ class AssetPopupCard(bpy.types.Operator): row = box_thumbnail.row() row.alignment = 'EXPAND' + + # display_ratings = can_display_ratings(self.asset_data) rc = self.asset_data.get('ratingsCount') - show_rating_threshold = 5 + show_rating_threshold = 0 + show_rating_prompt_threshold = 5 if rc: rcount = min(rc['quality'], rc['workingHours']) @@ -1755,13 +1772,25 @@ class AssetPopupCard(bpy.types.Operator): c = '-' pcoll = icons.icon_collections["main"] - row.label(text=str(s), icon_value=pcoll['trophy'].icon_id) - row.label(text=str(q), icon='SOLO_ON') - row.label(text=str(c), icon_value=pcoll['dumbbell'].icon_id) - if rcount <= show_rating_threshold: - box_thumbnail.alert = True + row.emboss = 'NONE' + op = row.operator('wm.blenderkit_tooltip', text=str(s), icon_value=pcoll['trophy'].icon_id) + op.tooltip = 'Asset score calculated from averaged user ratings. \n\n' \ + 'Score = quality × complexity × 10*\n\n *Happiness multiplier' + row.label(text=' ') + + tooltip_extension = f'.\n\nRatings results are shown for assets with more than {show_rating_threshold} ratings' + op = row.operator('wm.blenderkit_tooltip', text=str(q), icon='SOLO_ON') + op.tooltip = f"Quality, average from {rc['quality']} ratings" \ + f"{tooltip_extension if rcount <= show_rating_threshold else ''}" + row.label(text=' ') + op = row.operator('wm.blenderkit_tooltip', text=str(c), icon_value=pcoll['dumbbell'].icon_id) + op.tooltip = f"Complexity, average from {rc['workingHours']} ratings" \ + f"{tooltip_extension if rcount <= show_rating_threshold else ''}" + + if rcount <= show_rating_prompt_threshold: + box_thumbnail.alert = True box_thumbnail.label(text=f"") box_thumbnail.label(text=f"This asset has only {rcount} rating{'' if rcount == 1 else 's'} , please rate.") # box_thumbnail.label(text=f"Please rate this asset.") diff --git a/blenderkit/utils.py b/blenderkit/utils.py index f4302ac0..d0f52cb2 100644 --- a/blenderkit/utils.py +++ b/blenderkit/utils.py @@ -786,7 +786,12 @@ def profile_is_validator(): def guard_from_crash(): - '''Blender tends to crash when trying to run some functions with the addon going through unregistration process.''' + ''' + Blender tends to crash when trying to run some functions + with the addon going through unregistration process. + This function is used in these functions (like draw callbacks) + so these don't run during unregistration. + ''' if bpy.context.preferences.addons.get('blenderkit') is None: return False; if bpy.context.preferences.addons['blenderkit'].preferences is None: |