From c5b6e7a4c89828227c6c11aa00b679cef994c30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vil=C3=A9m=20Duha?= Date: Fri, 16 Aug 2019 22:33:33 +0200 Subject: BlenderKit: Right click menu -Open authors webpage -Search assets by author -basic 'search similar' . -fix some tooltips -deleting of assets from online lib (disabled by now) - possibility to validate , not yet supported on server. scroll wheel now scrolls rows instead of single items if there are more rows enabled. --- blenderkit/autothumb.py | 2 +- blenderkit/search.py | 21 +++++++++++++---- blenderkit/ui.py | 27 +++++++++++++++++---- blenderkit/ui_panels.py | 63 ++++++++++++++++++++++++++++++++++++++++++------- blenderkit/upload.py | 62 ++++++++++++++++++++++++++++++++++++------------ 5 files changed, 142 insertions(+), 33 deletions(-) diff --git a/blenderkit/autothumb.py b/blenderkit/autothumb.py index b5f659aa..2e5eb710 100644 --- a/blenderkit/autothumb.py +++ b/blenderkit/autothumb.py @@ -253,7 +253,7 @@ def start_material_thumbnailer(self, context): class GenerateThumbnailOperator(bpy.types.Operator): - """Tooltip""" + """Generate Cycles thumbnail for model assets""" bl_idname = "object.blenderkit_generate_thumbnail" bl_label = "BlenderKit Thumbnail Generator" diff --git a/blenderkit/search.py b/blenderkit/search.py index e81e456e..56c8b526 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -597,7 +597,7 @@ def fetch_author(a_id, api_key): f.write(r.content) adata['gravatarImg'] = gravatar_path elif r.status_code == '404': - adata['gravatarHash']= None + adata['gravatarHash'] = None except Exception as e: utils.p(e) utils.p('finish fetch') @@ -723,7 +723,6 @@ class Searcher(threading.Thread): else: requeststring += '+order:_score' - requeststring += '&addon_version=%s' % params['addon_version'] if params.get('scene_uuid') is not None: requeststring += '&scene_uuid=%s' % params['scene_uuid'] @@ -1101,6 +1100,7 @@ class SearchOperator(Operator): own: BoolProperty(name="own assets only", description="Find all own assets", default=False) + category: StringProperty( name="category", description="search only subtree of this category", @@ -1115,13 +1115,26 @@ class SearchOperator(Operator): description="get next page from previous search", default=False) + keywords = StringProperty( + name="Keywords", + description="Keywords", + default="") + @classmethod def poll(cls, context): return True def execute(self, context): - search(own=self.own, category=self.category, get_next=self.get_next, author_id=self.author_id) - bpy.ops.view3d.blenderkit_asset_bar() + # TODO ; this should all get transferred to properties of the search operator, so sprops don't have to be fetched here at all. + sprops = utils.get_search_props() + if self.author_id != '': + sprops.search_keywords = '' + if self.keywords != '': + sprops.search_keywords = self.keywords + + + search(category=self.category, get_next=self.get_next, author_id=self.author_id) + #bpy.ops.view3d.blenderkit_asset_bar() return {'FINISHED'} diff --git a/blenderkit/ui.py b/blenderkit/ui.py index d33c124f..bd30d152 100644 --- a/blenderkit/ui.py +++ b/blenderkit/ui.py @@ -1323,11 +1323,23 @@ class AssetBarOperator(bpy.types.Operator): # if event.type == 'TRACKPADPAN' : # print(dir(event)) # print(event.value, event.oskey, event.) - if (event.type == 'WHEELDOWNMOUSE') and len(sr) - ui_props.scrolloffset > ui_props.wcount: - ui_props.scrolloffset += 1 + if (event.type == 'WHEELDOWNMOUSE') and len(sr) - ui_props.scrolloffset > ( + ui_props.wcount * ui_props.hcount): + if ui_props.hcount > 1: + ui_props.scrolloffset += ui_props.wcount + else: + ui_props.scrolloffset += 1 + if len(sr) - ui_props.scrolloffset < (ui_props.wcount * ui_props.hcount): + ui_props.scrolloffset = len(sr) - (ui_props.wcount * ui_props.hcount) if event.type == 'WHEELUPMOUSE' and ui_props.scrolloffset > 0: - ui_props.scrolloffset -= 1 + if ui_props.hcount > 1: + ui_props.scrolloffset -= ui_props.wcount + else: + ui_props.scrolloffset -= 1 + if ui_props.scrolloffset < 0: + ui_props.scrolloffset = 0 + return {'RUNNING_MODAL'} if event.type == 'MOUSEMOVE': # Apply @@ -1358,7 +1370,6 @@ class AssetBarOperator(bpy.types.Operator): ui_props.draw_snapped_bounds = False ui_props.draw_tooltip = False bpy.context.window.cursor_set("DEFAULT") - print('out of region') return {'PASS_THROUGH'} sr = bpy.context.scene['search results'] @@ -1412,6 +1423,14 @@ class AssetBarOperator(bpy.types.Operator): ui_props.draw_drag_image = True return {'RUNNING_MODAL'} + if event.type == 'RIGHTMOUSE': + mx = event.mouse_x - r.x + my = event.mouse_y - r.y + + if event.value == 'PRESS' and mouse_in_asset_bar(mx, my): + bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_asset_menu') + return {'RUNNING_MODAL'} + if event.type == 'LEFTMOUSE': r = self.region diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index 9175bed4..d17fe040 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -114,18 +114,16 @@ def draw_upload_common(layout, props, asset_type, context): op.asset_type = asset_type if props.asset_base_id != '': - op = layout.operator("object.blenderkit_upload", text='Reupload asset', icon='EXPORT') op.asset_type = asset_type op.reupload = True - op = layout.operator("object.blenderkit_upload", text='Upload as new asset', icon='EXPORT') op.asset_type = asset_type op.reupload = False # layout.label(text = 'asset id, overwrite only for reuploading') - layout.label(text = 'asset has a version online.') + layout.label(text='asset has a version online.') # row = layout.row() # row.enabled = False # row.prop(props, 'asset_base_id', icon='FILE_TICK') @@ -387,11 +385,13 @@ class VIEW3D_PT_blenderkit_model_properties(Panel): layout.operator('object.blenderkit_bring_to_scene', text='Bring to scene') # layout.operator('object.blenderkit_color_corrector') + def draw_login_progress(layout): layout.label(text='Login through browser') layout.label(text='in progress.') layout.operator("wm.blenderkit_login_cancel", text="Cancel", icon='CANCEL') + class VIEW3D_PT_blenderkit_profile(Panel): bl_category = "BlenderKit" bl_idname = "VIEW3D_PT_blenderkit_profile" @@ -416,7 +416,6 @@ class VIEW3D_PT_blenderkit_profile(Panel): if user_preferences.enable_oauth: draw_login_buttons(layout) - if user_preferences.api_key != '': me = bpy.context.window_manager.get('bkit profile') if me is not None: @@ -429,7 +428,7 @@ class VIEW3D_PT_blenderkit_profile(Panel): layout.label(text='Private assets: %i MiB' % (me['sumPrivateAssetFilesSize'])) if me.get('remainingPrivateQuota') is not None: layout.label(text='Remaining private storage: %i MiB' % (me['remainingPrivateQuota'])) - + layout.operator("wm.url_open", text="See my uploads", icon='URL').url = paths.BLENDERKIT_USER_ASSETS @@ -561,13 +560,11 @@ def draw_login_buttons(layout): else: layout.operator("wm.blenderkit_login", text="Login as someone else", - icon='URL').signup = False + icon='URL').signup = False layout.operator("wm.blenderkit_logout", text="Logout", icon='URL') - - class VIEW3D_PT_blenderkit_unified(Panel): bl_category = "BlenderKit" bl_idname = "VIEW3D_PT_blenderkit_unified" @@ -721,6 +718,53 @@ class VIEW3D_PT_blenderkit_unified(Panel): layout.label(text='not yet implemented') +class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu): + bl_label = "Asset options:" + bl_idname = "OBJECT_MT_blenderkit_asset_menu" + + def draw(self, context): + layout = self.layout + ui_props = context.scene.blenderkitUI + + sr = bpy.context.scene['search results'] + sr = bpy.context.scene['search results orig']['results'] + asset_data = sr[ui_props.active_index] + author_id = str(asset_data['author']['id']) + a = bpy.context.window_manager['bkit authors'].get(author_id) + if a is not None: + # utils.p('author:', a) + if a.get('aboutMeUrl') is not None: + op = layout.operator('wm.url_open', text="Open author's website") + op.url = a['aboutMeUrl'] + op = layout.operator('view3d.blenderkit_search', text='search assets by same author') + op.author_id = author_id + + op = layout.operator('view3d.blenderkit_search', text='search similar') + print(dir(asset_data)) + op.keywords = asset_data['name'] + ' ' + asset_data['description'] + ' ' + ''.join(asset_data['tags']) + + wm = bpy.context.window_manager + profile = wm.get('bkit profile') + if profile is not None: + # validation by admin + if profile['user']['id'] == 2: + if asset_data['verificationStatus'] != 'validated': + op = layout.operator('object.blenderkit_change_status', text='Validate') + op.asset_id = asset_data['id'] + op.state = 'validated' + + if author_id == str(profile['user']['id']): + layout.label(text='Management tools:') + row = layout.row() + row.operator_context = 'INVOKE_DEFAULT' + op = row.operator('object.blenderkit_change_status', text='Delete') + op.asset_id = asset_data['id'] + op.state = 'deleted' + # else: + # #not an author - can rate + # draw_ratings(layout, context) + + class SetCategoryOperator(bpy.types.Operator): """Visit subcategory""" bl_idname = "view3d.blenderkit_set_category" @@ -838,7 +882,8 @@ classess = ( VIEW3D_PT_blenderkit_unified, VIEW3D_PT_blenderkit_model_properties, VIEW3D_PT_blenderkit_downloads, - VIEW3D_PT_blenderkit_profile + VIEW3D_PT_blenderkit_profile, + OBJECT_MT_blenderkit_asset_menu ) diff --git a/blenderkit/upload.py b/blenderkit/upload.py index 6f2fad45..3616beb0 100644 --- a/blenderkit/upload.py +++ b/blenderkit/upload.py @@ -45,6 +45,7 @@ BLENDERKIT_EXPORT_DATA_FILE = "data.json" from bpy.props import ( # TODO only keep the ones actually used when cleaning EnumProperty, BoolProperty, + StringProperty, ) from bpy.types import ( Operator, @@ -464,27 +465,19 @@ def get_upload_data(self, context, asset_type): return export_data, upload_data, eval_path_computing, eval_path_state, eval_path, props -def mark_for_validation(self, context, asset_type): - props = utils.get_upload_props() - props.upload_state = 'marking for validation' +def verification_status_change(self, context, asset_id, state): user_preferences = bpy.context.preferences.addons['blenderkit'].preferences - upload_data = { - "verificationStatus": "ready" + "verificationStatus": state } - - url = paths.get_api_url() + 'assets/' - + url = paths.get_api_url() + 'assets/' + str(asset_id) + '/' headers = utils.get_headers(user_preferences.api_key) - - url += props.id + '/' - try: r = requests.patch(url, json=upload_data, headers=headers, verify=True) # files = files, - props.upload_state = 'marked for validation' + #print('changed status ') + #print(r.text) except requests.exceptions.RequestException as e: - props.upload_state = str(e) - props.uploading = False + print(e) return {'CANCELLED'} return {'FINISHED'} @@ -644,7 +637,7 @@ def start_upload(self, context, asset_type, reupload, upload_set): # props.upload_state = 'step 1' if upload_set == ['METADATA']: props.uploading = False - + props.upload_state = 'upload finished successfully' return {'FINISHED'} try: rj = r.json() @@ -798,9 +791,48 @@ class UploadOperator(Operator): return self.execute(context) + +class AssetVerificationStatusChange(Operator): + """Change verification status""" + bl_idname = "object.blenderkit_change_status" + bl_description = "Change asset ststus" + bl_label = "Change verification status" + + # type of upload - model, material, textures, e.t.c. + asset_id: StringProperty( + name="asset id", + ) + + state: StringProperty( + name="verification_status", + default = 'uploaded' + ) + @classmethod + def poll(cls, context): + return True + + def draw(self, context): + layout = self.layout + #if self.state == 'deleted': + layout.label(text='Really delete asset from BlenderKit online storage?') + # layout.prop(self, 'state') + + def execute(self, context): + result = verification_status_change(self, context, self.asset_id, self.state) + return result + + def invoke(self, context, event): + print(self.state) + if self.state =='deleted': + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def register_upload(): bpy.utils.register_class(UploadOperator) + bpy.utils.register_class(AssetVerificationStatusChange) def unregister_upload(): bpy.utils.unregister_class(UploadOperator) + bpy.utils.unregister_class(AssetVerificationStatusChange) -- cgit v1.2.3