diff options
author | Vilém Duha <vilda.novak@gmail.com> | 2020-07-27 13:59:38 +0300 |
---|---|---|
committer | Vilém Duha <vilda.novak@gmail.com> | 2020-07-29 23:17:27 +0300 |
commit | 06181ee9947d558d5323471c9b5d9792267fdb66 (patch) | |
tree | 56fd77163c173a7cecfb9d5da1910ca5b8c391c6 | |
parent | 66bd6dea71862d8f55ede79879117d9e7de882a4 (diff) |
BlenderKit: Rating refactorings
This mainly paves a way for removing the old and clumsy bgl UI and enable faster rating for users.
-Rating Ui is now more responsive -it can be dragged over the stars widget.
-fast rating operator (f shortcut over assetbar)
-wip on new ratings panel(disabled by now)
-if author didn't provide his webpage, the link now leads to his profile on the BlenderKit site.
-upload was partially broken thanks to a small bug
-perpendicular snap - This limits angled snapping in a reasonable way, should help when placing foliage or items on sloped ceilings e.t.c.
-removed the first_run property, it's replaced with a poput that informs the user about connecting to the internet.
(cherry picked from commit 8f6903bc92531aa8e5d4c64a0a108c2904506a83)
-rw-r--r-- | blenderkit/__init__.py | 64 | ||||
-rw-r--r-- | blenderkit/paths.py | 3 | ||||
-rw-r--r-- | blenderkit/ratings.py | 269 | ||||
-rw-r--r-- | blenderkit/search.py | 10 | ||||
-rw-r--r-- | blenderkit/ui.py | 28 | ||||
-rw-r--r-- | blenderkit/ui_panels.py | 95 | ||||
-rw-r--r-- | blenderkit/upload.py | 2 |
7 files changed, 328 insertions, 143 deletions
diff --git a/blenderkit/__init__.py b/blenderkit/__init__.py index 23ee89c5..fba80a7e 100644 --- a/blenderkit/__init__.py +++ b/blenderkit/__init__.py @@ -250,6 +250,7 @@ def switch_search_results(self, context): s['search results orig'] = s.get('bkit brush search orig') search.load_previews() + def asset_type_callback(self, context): ''' Returns @@ -650,29 +651,6 @@ class BlenderKitCommonUploadProps(object): ) -def stars_enum_callback(self, context): - items = [] - for a in range(0, 10): - if self.rating_quality < a+1: - icon = 'SOLO_OFF' - else: - icon = 'SOLO_ON' - # has to have something before the number in the value, otherwise fails on registration. - items.append((f'{a+1}', f'{a+1}', '', icon, a+1)) - return items - - -def update_quality(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_quality_ui = '0' - self.rating_quality = int(self.rating_quality_ui) - - class BlenderKitRatingProps(PropertyGroup): rating_quality: IntProperty(name="Quality", description="quality of the material", @@ -680,19 +658,20 @@ class BlenderKitRatingProps(PropertyGroup): min=-1, max=10, update=ratings.update_ratings_quality) - #the following enum is only to ease interaction - enums support 'drag over' and enable to draw the stars easily. + # the following enum is only to ease interaction - enums support 'drag over' and enable to draw the stars easily. rating_quality_ui: EnumProperty(name='rating_quality_ui', - items=stars_enum_callback, - description='Rating stars 0 - 10', - default=None, - update=update_quality, - ) + items=ratings.stars_enum_callback, + description='Rating stars 0 - 10', + default=None, + update=ratings.update_quality_ui, + ) rating_work_hours: FloatProperty(name="Work Hours", description="How many hours did this work take?", default=0.00, min=0.0, max=1000, update=ratings.update_ratings_work_hours ) + # rating_complexity: IntProperty(name="Complexity", # description="Complexity is a number estimating how much work was spent on the asset.aaa", # default=0, min=0, max=10) @@ -1393,6 +1372,17 @@ class BlenderKitModelSearchProps(PropertyGroup, BlenderKitCommonSearchProps): max=180, subtype='ANGLE') + perpendicular_snap: BoolProperty(name='Perpendicular snap', + description="Limit snapping that is close to perpendicular angles to be perpendicular.", + default=True) + + perpendicular_snap_threshold: FloatProperty(name="Threshold", + description="Limit perpendicular snap to be below these values.", + default=.25, + min=0, + max=.5, + ) + class BlenderKitSceneSearchProps(PropertyGroup, BlenderKitCommonSearchProps): search_keywords: StringProperty( @@ -1586,12 +1576,13 @@ class BlenderKitAddonPreferences(AddonPreferences): min=0, max=20000) - first_run: BoolProperty( - name="First run", - description="Detects if addon was already registered/run.", - default=True, - update=utils.save_prefs - ) + # this is now made obsolete by the new popup upon registration -ensures the user knows about the first search. + # first_run: BoolProperty( + # name="First run", + # description="Detects if addon was already registered/run.", + # default=True, + # update=utils.save_prefs + # ) use_timers: BoolProperty( name="Use timers", @@ -1729,7 +1720,8 @@ def register(): for w in bpy.context.window_manager.windows: for a in w.screen.areas: if a.type == 'PREFERENCES': - tasks_queue.add_task((bpy.ops.wm.blenderkit_welcome,( 'INVOKE_DEFAULT',)),fake_context = True, fake_context_area = 'PREFERENCES') + tasks_queue.add_task((bpy.ops.wm.blenderkit_welcome, ('INVOKE_DEFAULT',)), fake_context=True, + fake_context_area='PREFERENCES') def unregister(): diff --git a/blenderkit/paths.py b/blenderkit/paths.py index b4210a85..399e7555 100644 --- a/blenderkit/paths.py +++ b/blenderkit/paths.py @@ -75,6 +75,9 @@ def get_api_url(): def get_oauth_landing_url(): return get_bkit_url() + BLENDERKIT_OAUTH_LANDING_URL +def get_author_gallery_url(author_id): + return f'{get_bkit_url()}/asset-gallery?query=author_id:{author_id}' + def default_global_dict(): from os.path import expanduser diff --git a/blenderkit/ratings.py b/blenderkit/ratings.py index 48c34a61..800749c8 100644 --- a/blenderkit/ratings.py +++ b/blenderkit/ratings.py @@ -94,7 +94,7 @@ def upload_review_thread(url, reviews, headers): def get_rating(asset_id): - #this function isn't used anywhere,should probably get removed. + # this function isn't used anywhere,should probably get removed. user_preferences = bpy.context.preferences.addons['blenderkit'].preferences api_key = user_preferences.api_key headers = utils.get_headers(api_key) @@ -114,8 +114,13 @@ def update_ratings_quality(self, context): headers = utils.get_headers(api_key) asset = self.id_data - bkit_ratings = asset.bkit_ratings - url = paths.get_api_url() + 'assets/' + asset['asset_data']['id'] + '/rating/' + if asset: + bkit_ratings = asset.bkit_ratings + url = paths.get_api_url() + 'assets/' + asset['asset_data']['id'] + '/rating/' + else: + # this part is for operator rating: + bkit_ratings = self + url = paths.get_api_url() + f'assets/{self.asset_id}/rating/' if bkit_ratings.rating_quality > 0.1: ratings = [('quality', bkit_ratings.rating_quality)] @@ -127,15 +132,19 @@ def update_ratings_work_hours(self, context): api_key = user_preferences.api_key headers = utils.get_headers(api_key) asset = self.id_data - bkit_ratings = asset.bkit_ratings - url = paths.get_api_url() + 'assets/' + asset['asset_data']['id'] + '/rating/' + if asset: + bkit_ratings = asset.bkit_ratings + url = paths.get_api_url() + 'assets/' + asset['asset_data']['id'] + '/rating/' + else: + # this part is for operator rating: + bkit_ratings = self + url = paths.get_api_url() + f'assets/{self.asset_id}/rating/' if bkit_ratings.rating_work_hours > 0.05: ratings = [('working_hours', round(bkit_ratings.rating_work_hours, 1))] tasks_queue.add_task((send_rating_to_thread_work_hours, (url, ratings, headers)), wait=1, only_last=True) - def upload_rating(asset): user_preferences = bpy.context.preferences.addons['blenderkit'].preferences api_key = user_preferences.api_key @@ -173,6 +182,7 @@ def upload_rating(asset): if bkit_ratings.rating_quality > 0.1 and bkit_ratings.rating_work_hours > 0.1: s['assets rated'][asset['asset_data']['assetBaseId']] = True + def get_assets_for_rating(): ''' gets assets from scene that could/should be rated by the user. @@ -191,26 +201,6 @@ def get_assets_for_rating(): assets.append(b) return assets -# class StarRatingOperator(bpy.types.Operator): -# """Tooltip""" -# bl_idname = "object.blenderkit_rating" -# bl_label = "Rate the Asset Quality" -# bl_options = {'REGISTER', 'INTERNAL'} -# -# property_name: StringProperty( -# name="Rating Property", -# description="Property that is rated", -# default="", -# ) -# -# rating: IntProperty(name="Rating", description="rating value", default=1, min=1, max=10) -# -# def execute(self, context): -# asset = utils.get_active_asset() -# props = asset.bkit_ratings -# props.rating_quality = self.rating -# return {'FINISHED'} - asset_types = ( ('MODEL', 'Model', 'set of objects'), @@ -254,43 +244,212 @@ class UploadRatingOperator(bpy.types.Operator): return wm.invoke_props_dialog(self) +def stars_enum_callback(self, context): + '''regenerates the enum property used to display rating stars, so that there are filled/empty stars correctly.''' + items = [] + for a in range(0, 10): + if self.rating_quality < a + 1: + icon = 'SOLO_OFF' + else: + icon = 'SOLO_ON' + # has to have something before the number in the value, otherwise fails on registration. + items.append((f'{a + 1}', f'{a + 1}', '', icon, a + 1)) + return items + -def draw_rating(layout, props, prop_name, name): - # layout.label(name) - - row = layout.row(align=True) - # test method - 10 booleans. - # propsx = bpy.context.active_object.bkit_ratings - # for a in range(0, 10): - # pn = f'rq{str(a+1).zfill(2)}' - # if eval('propsx.' + pn) == False: - # icon = 'SOLO_OFF' - # else: - # icon = 'SOLO_ON' - # row.prop(propsx, pn, icon=icon, icon_only=True) - # print(dir(props)) - # new best method - enum with an items callback. ('animates' the stars as item icons) - row.prop(props, 'rating_quality_ui', expand=True, icon_only=True, emboss = False) - # original (operator) method: - # row = layout.row(align=True) - # for a in range(0, 10): - # if eval('props.' + prop_name) < a + 1: - # icon = 'SOLO_OFF' - # else: - # icon = 'SOLO_ON' - # - # op = row.operator('object.blenderkit_rating', icon=icon, emboss=False, text='') - # op.property_name = prop_name - # op.rating = a + 1 +def update_quality_ui(self, context): + '''Converts the _ui the enum into actual quality number.''' + 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_quality_ui = '0' + self.rating_quality = int(self.rating_quality_ui) +def update_ratings_work_hours_ui(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 = '0' + self.rating_work_hours = float(self.rating_work_hours_ui) + +def update_ratings_work_hours_ui_1_5(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.update_ratings_work_hours_ui_1_5 = '0' + self.rating_work_hours = float(self.update_ratings_work_hours_ui_1_5) + + + +class FastRateMenu(Operator): + """Fast rating of the assets directly in the asset bar - without need to download assets.""" + bl_idname = "wm.blenderkit_menu_rating_upload" + bl_label = "Send Rating" + bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} + + message: StringProperty( + name="message", + description="message", + default="Rating asset") + + asset_id: StringProperty( + name="Asset Base Id", + description="Unique name of the asset (hidden)", + default="") + + asset_type: StringProperty( + name="Asset type", + description="asset type", + default="") + + rating_quality: IntProperty(name="Quality", + description="quality of the material", + default=0, + min=-1, max=10, + update=update_ratings_quality) + + # the following enum is only to ease interaction - enums support 'drag over' and enable to draw the stars easily. + rating_quality_ui: EnumProperty(name='rating_quality_ui', + items=stars_enum_callback, + description='Rating stars 0 - 10', + default=None, + update=update_quality_ui, + ) + + rating_work_hours: FloatProperty(name="Work Hours", + description="How many hours did this work take?", + default=0.00, + min=0.0, max=1000, update=update_ratings_work_hours + ) + + rating_work_hours_ui: EnumProperty(name="Work Hours", + description="How many hours did this work take?", + items=[('0', '0', ''), + ('.5', '0.5', ''), + ('1', '1', ''), + ('2', '2', ''), + ('3', '3', ''), + ('4', '4', ''), + ('5', '5', ''), + ('10', '10', ''), + ('15', '15', ''), + ('20', '20', ''), + ('50', '50', ''), + ('100', '100', ''), + ], + default='0', update=update_ratings_work_hours_ui + ) + + rating_work_hours_ui_1_5: EnumProperty(name="Work Hours", + description="How many hours did this work take?", + items=[('0', '0', ''), + ('.2', '0.2', ''), + ('.5', '0.5', ''), + ('1', '1', ''), + ('2', '2', ''), + ('3', '3', ''), + ('4', '4', ''), + ('5', '5', '') + ], + default='0', update=update_ratings_work_hours_ui_1_5 + ) + + @classmethod + def poll(cls, context): + scene = bpy.context.scene + ui_props = scene.blenderkitUI + return ui_props.active_index > -1 + + def draw(self, context): + layout = self.layout + col = layout.column() + + # layout.template_icon_view(bkit_ratings, property, show_labels=False, scale=6.0, scale_popup=5.0) + col.label(text=self.message) + row = col.row() + row.prop(self, 'rating_quality_ui', expand=True, icon_only=True, emboss=False) + col.separator() + col.prop(self, 'rating_work_hours') + row = col.row() + if self.asset_type == 'model': + row.prop(self, 'rating_work_hours_ui', expand=True, icon_only=False, emboss=True) + else: + row.prop(self, 'rating_work_hours_ui_1_5', expand=True, icon_only=False, emboss=True) + + def execute(self, context): + user_preferences = bpy.context.preferences.addons['blenderkit'].preferences + api_key = user_preferences.api_key + headers = utils.get_headers(api_key) + + url = paths.get_api_url() + f'assets/{self.asset_id}/rating/' + + rtgs = [ + + ] + + self.rating_quality = int(self.rating_quality_ui) + + if self.rating_quality > 0.1: + rtgs.append(('quality', self.rating_quality)) + if self.rating_work_hours > 0.1: + rtgs.append(('working_hours', round(self.rating_work_hours, 1))) + + thread = threading.Thread(target=upload_rating_thread, args=(url, rtgs, headers)) + thread.start() + return {'FINISHED'} + + def invoke(self, context, event): + scene = bpy.context.scene + ui_props = scene.blenderkitUI + if ui_props.active_index > -1: + sr = bpy.context.scene['search results'] + asset_data = dict(sr[ui_props.active_index]) + self.asset_id = asset_data['id'] + self.asset_type = asset_data['assetType'] + self.message = f"Rate asset {asset_data['name']}" + wm = context.window_manager + return wm.invoke_props_dialog(self) + + +def rating_menu_draw(self, context): + layout = self.layout + + ui_props = context.scene.blenderkitUI + sr = bpy.context.scene['search results orig'] + + asset_search_index = ui_props.active_index + if asset_search_index > -1: + asset_data = dict(sr['results'][asset_search_index]) + + col = layout.column() + layout.label(text='Admin rating Tools:') + col.operator_context = 'INVOKE_DEFAULT' + + op = col.operator('wm.blenderkit_menu_rating_upload', text='Fast rate') + op.asset_id = asset_data['id'] + op.asset_type = asset_data['assetType'] + def register_ratings(): - pass; - # bpy.utils.register_class(StarRatingOperator) bpy.utils.register_class(UploadRatingOperator) + bpy.utils.register_class(FastRateMenu) + # bpy.types.OBJECT_MT_blenderkit_asset_menu.append(rating_menu_draw) def unregister_ratings(): pass; # bpy.utils.unregister_class(StarRatingOperator) bpy.utils.unregister_class(UploadRatingOperator) + bpy.utils.unregister_class(FastRateMenu) diff --git a/blenderkit/search.py b/blenderkit/search.py index cee0b14b..6c8d16e2 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -280,7 +280,7 @@ def timer_update(): # TODO here it should check if there are some results, and only open assetbar if this is the case, not search. # if bpy.context.scene.get('search results') is None: search() - preferences.first_run = False + # preferences.first_run = False if preferences.tips_on_start: utils.get_largest_area() ui.update_ui_size(ui.active_area, ui.active_region) @@ -1161,14 +1161,6 @@ def search(category='', get_next=False, author_id=''): scene = bpy.context.scene ui_props = scene.blenderkitUI - ### updating of search categories was moved here, due to the reason that BlenderKit created the blenderkit_data - # folder upon registration of BlenderKit, which wasn't a favourite option for some users (devs running tests). - # user_preferences = bpy.context.preferences.addons['blenderkit'].preferences - # if not user_preferences.first_run: - # api_key = user_preferences.api_key - # if bpy.context.window_manager.get('bkit_categories') is None: - # categories.fetch_categories_thread(api_key) - if ui_props.asset_type == 'MODEL': if not hasattr(scene, 'blenderkit'): return; diff --git a/blenderkit/ui.py b/blenderkit/ui.py index 30195168..7935363d 100644 --- a/blenderkit/ui.py +++ b/blenderkit/ui.py @@ -876,7 +876,8 @@ def draw_callback_2d_search(self, context): else: iname = utils.previmg_name(ui_props.active_index) img = bpy.data.images.get(iname) - img.colorspace_settings.name = 'sRGB' + if img: + img.colorspace_settings.name = 'sRGB' gimg = None atip = '' @@ -931,9 +932,21 @@ def mouse_raycast(context, mx, my): # rote = mathutils.Euler((0, 0, math.pi)) randoffset = math.pi if has_hit: - snapped_rotation = snapped_normal.to_track_quat('Z', 'Y').to_euler() - up = Vector((0, 0, 1)) props = bpy.context.scene.blenderkit_models + up = Vector((0, 0, 1)) + + if props.perpendicular_snap: + if snapped_normal.z > 1 - props.perpendicular_snap_threshold: + snapped_normal = Vector((0, 0, 1)) + elif snapped_normal.z < -1 + props.perpendicular_snap_threshold: + snapped_normal = Vector((0, 0, -1)) + elif abs(snapped_normal.z) < props.perpendicular_snap_threshold: + snapped_normal.z = 0 + snapped_normal.normalize() + + snapped_rotation = snapped_normal.to_track_quat('Z', 'Y').to_euler() + + if props.randomize_rotation and snapped_normal.angle(up) < math.radians(10.0): randoffset = props.offset_rotation_amount + math.pi + ( random.random() - 0.5) * props.randomize_rotation_amount @@ -1668,6 +1681,7 @@ class AssetBarOperator(bpy.types.Operator): utils.p('author:', a) search.search(author_id=a) return {'RUNNING_MODAL'} + if event.type == 'X' and ui_props.active_index > -1: # delete downloaded files for this asset sr = bpy.context.scene['search results'] @@ -1845,13 +1859,15 @@ def register_ui(): if not wm.keyconfigs.addon: return km = wm.keyconfigs.addon.keymaps.new(name="Window", space_type='EMPTY') + #asset bar shortcut kmi = km.keymap_items.new(AssetBarOperator.bl_idname, 'SEMI_COLON', 'PRESS', ctrl=False, shift=False) kmi.properties.keep_running = False kmi.properties.do_search = False addon_keymapitems.append(kmi) - # auto open after searching: - kmi = km.keymap_items.new(RunAssetBarWithContext.bl_idname, 'SEMI_COLON', 'PRESS', \ - ctrl=True, shift=True, alt=True) + #fast rating shortcut + wm = bpy.context.window_manager + km = wm.keyconfigs.addon.keymaps['Window'] + kmi = km.keymap_items.new(ratings.FastRateMenu.bl_idname, 'F', 'PRESS', ctrl=False, shift=False) addon_keymapitems.append(kmi) diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index d067afa0..89646862 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -47,7 +47,6 @@ import os import random - # this was moved to separate interface: def draw_ratings(layout, context, asset): @@ -63,9 +62,8 @@ def draw_ratings(layout, context, asset): # layout.template_icon_view(bkit_ratings, property, show_labels=False, scale=6.0, scale_popup=5.0) row = col.row() - row.prop(bkit_ratings , 'rating_quality_ui', expand=True, icon_only=True, emboss=False) - #ratings.draw_rating(col, bkit_ratings, 'rating_quality', 'Quality') - if bkit_ratings.rating_quality>0: + row.prop(bkit_ratings, 'rating_quality_ui', expand=True, icon_only=True, emboss=False) + if bkit_ratings.rating_quality > 0: col.separator() col.prop(bkit_ratings, 'rating_work_hours') # w = context.region.width @@ -81,7 +79,7 @@ def draw_ratings(layout, context, asset): # re-enable layout if included in longer panel -def draw_not_logged_in(source, message = 'Please Login/Signup to use this feature' ): +def draw_not_logged_in(source, message='Please Login/Signup to use this feature'): title = "You aren't logged in" def draw_message(source, context): @@ -104,7 +102,7 @@ def draw_upload_common(layout, props, asset_type, context): row = layout.row(align=True) if props.upload_state != '': - utils.label_multiline(layout, text=props.upload_state, width=context.region.width) + utils.label_multiline(layout, text=props.upload_state, width=context.region.width) if props.uploading: op = layout.operator('object.kill_bg_process', text="", icon='CANCEL') op.process_source = asset_type @@ -193,7 +191,7 @@ def draw_panel_model_upload(self, context): op.process_source = 'MODEL' op.process_type = 'THUMBNAILER' elif props.thumbnail_generating_state != '': - utils.label_multiline(layout, text=props.thumbnail_generating_state) + utils.label_multiline(layout, text=props.thumbnail_generating_state) layout.prop(props, 'description') layout.prop(props, 'tags') @@ -359,7 +357,8 @@ class VIEW3D_PT_blenderkit_model_properties(Panel): o = utils.get_active_model() # o = bpy.context.active_object if o.get('asset_data') is None: - utils.label_multiline(layout, text='To upload this asset to BlenderKit, go to the Find and Upload Assets panel.') + utils.label_multiline(layout, + text='To upload this asset to BlenderKit, go to the Find and Upload Assets panel.') layout.prop(o, 'name') if o.get('asset_data') is not None: @@ -383,12 +382,14 @@ class VIEW3D_PT_blenderkit_model_properties(Panel): # fun override project, not finished # layout.operator('object.blenderkit_color_corrector') -def draw_rating_asset(self,context,asset): + +def draw_rating_asset(self, context, asset): layout = self.layout col = layout.box() # split = layout.split(factor=0.5) # col1 = split.column() # col2 = split.column() + # print('%s_search' % asset['asset_data']['assetType']) directory = paths.get_temp_dir('%s_search' % asset['asset_data']['assetType']) tpath = os.path.join(directory, asset['asset_data']['thumbnail_small']) for image in bpy.data.images: @@ -401,8 +402,6 @@ def draw_rating_asset(self,context,asset): draw_ratings(col, context, asset=asset) - - class VIEW3D_PT_blenderkit_ratings(Panel): bl_category = "BlenderKit" bl_idname = "VIEW3D_PT_blenderkit_ratings" @@ -418,16 +417,17 @@ class VIEW3D_PT_blenderkit_ratings(Panel): return p def draw(self, context): - #TODO make a list of assets inside asset appending code, to happen only when assets are added to the scene. + # TODO make a list of assets inside asset appending code, to happen only when assets are added to the scene. # draw asset properties here layout = self.layout assets = ratings.get_assets_for_rating() - if len(assets)>0: - layout.label(text = 'Help BlenderKit community') - layout.label(text = 'by rating these assets:') + if len(assets) > 0: + layout.label(text='Help BlenderKit community') + layout.label(text='by rating these assets:') for a in assets: - draw_rating_asset(self, context, asset = a) + draw_rating_asset(self, context, asset=a) + def draw_login_progress(layout): layout.label(text='Login through browser') @@ -520,7 +520,7 @@ def draw_panel_model_rating(self, context): # o = bpy.context.active_object o = utils.get_active_model() # print('ratings active',o) - draw_ratings(self.layout, context, asset = o) # , props) + draw_ratings(self.layout, context, asset=o) # , props) # op.asset_type = 'MODEL' @@ -564,7 +564,7 @@ def draw_panel_material_upload(self, context): op.process_source = 'MATERIAL' op.process_type = 'THUMBNAILER' elif props.thumbnail_generating_state != '': - utils.label_multiline(layout, text=props.thumbnail_generating_state) + utils.label_multiline(layout, text=props.thumbnail_generating_state) if bpy.context.scene.render.engine in ('CYCLES', 'BLENDER_EEVEE'): layout.operator("object.blenderkit_material_thumbnail", text='Render thumbnail with Cycles', icon='EXPORT') @@ -634,12 +634,12 @@ def draw_panel_brush_search(self, context): def draw_panel_brush_ratings(self, context): # props = utils.get_brush_props(context) brush = utils.get_active_brush() - draw_ratings(self.layout, context, asset = brush) # , props) + draw_ratings(self.layout, context, asset=brush) # , props) # # op.asset_type = 'BRUSH' -def draw_login_buttons(layout, invoke = False): +def draw_login_buttons(layout, invoke=False): user_preferences = bpy.context.preferences.addons['blenderkit'].preferences if user_preferences.login_attempt: @@ -782,7 +782,7 @@ class VIEW3D_PT_blenderkit_categories(Panel): s = context.scene ui_props = s.blenderkitUI mode = True - if ui_props.asset_type == 'BRUSH' and not (context.sculpt_object or context.image_paint_object): + if ui_props.asset_type == 'BRUSH' and not (context.sculpt_object or context.image_paint_object): mode = False return ui_props.down_up == 'SEARCH' and mode @@ -820,6 +820,10 @@ class VIEW3D_PT_blenderkit_import_settings(Panel): layout.prop(props, 'randomize_rotation') if props.randomize_rotation: layout.prop(props, 'randomize_rotation_amount') + layout.prop(props, 'perpendicular_snap') + if props.perpendicular_snap: + layout.prop(props,'perpendicular_snap_threshold') + if ui_props.asset_type == 'MATERIAL': props = s.blenderkit_mat layout.prop(props, 'automap') @@ -924,7 +928,7 @@ class VIEW3D_PT_blenderkit_unified(Panel): return; if ui_props.asset_type == 'MODEL': - #utils.label_multiline(layout, "Uploaded models won't be available in b2.79", icon='ERROR') + # utils.label_multiline(layout, "Uploaded models won't be available in b2.79", icon='ERROR') if bpy.context.view_layer.objects.active is not None: draw_panel_model_upload(self, context) else: @@ -933,12 +937,12 @@ class VIEW3D_PT_blenderkit_unified(Panel): draw_panel_scene_upload(self, context) elif ui_props.asset_type == 'MATERIAL': - #utils.label_multiline(layout, "Uploaded materials won't be available in b2.79", icon='ERROR') + # utils.label_multiline(layout, "Uploaded materials won't be available in b2.79", icon='ERROR') if bpy.context.view_layer.objects.active is not None and bpy.context.active_object.active_material is not None: draw_panel_material_upload(self, context) else: - utils.label_multiline(layout, text='select object with material to upload materials', width=w) + utils.label_multiline(layout, text='select object with material to upload materials', width=w) elif ui_props.asset_type == 'BRUSH': if context.sculpt_object or context.image_paint_object: @@ -972,6 +976,7 @@ class VIEW3D_PT_blenderkit_unified(Panel): if ui_props.asset_type == 'TEXTURE': layout.label(text='not yet implemented') + class BlenderKitWelcomeOperator(bpy.types.Operator): """Login online on BlenderKit webpage""" @@ -993,27 +998,36 @@ class BlenderKitWelcomeOperator(bpy.types.Operator): def draw(self, context): layout = self.layout if self.step == 0: - message = "BlenderKit is an addon that connects to the internet to search and upload for models, materials, and brushes. \n\n Let's start by searching for some cool materials?" + user_preferences = bpy.context.preferences.addons['blenderkit'].preferences + + message = "BlenderKit connects from Blender to an online, " \ + "community built shared library of models, " \ + "materials, and brushes. " \ + "Use addon preferences to set up where files will be saved in the Global directory setting." + + utils.label_multiline(layout, text=message, width=300) + utils.label_multiline(layout, text="\n Let's start by searching for some cool materials?", width=300) else: - message = "This shouldn't be here at all" - utils.label_multiline(layout, text= message, width = 300) + message = "Operator Tutorial called with invalid step" def execute(self, context): if self.step == 0: - #move mouse: - #bpy.context.window_manager.windows[0].cursor_warp(1000, 1000) - #show n-key sidebar (spaces[index] has to be found for view3d too: + # move mouse: + # bpy.context.window_manager.windows[0].cursor_warp(1000, 1000) + # show n-key sidebar (spaces[index] has to be found for view3d too: # bpy.context.window_manager.windows[0].screen.areas[5].spaces[0].show_region_ui = False print('running search no') ui_props = bpy.context.scene.blenderkitUI ui_props.asset_type = 'MATERIAL' - search.search() + bpy.context.scene.blenderkit_mat.search_keywords = 'ice' + # search.search() return {'FINISHED'} def invoke(self, context, event): wm = bpy.context.window_manager return wm.invoke_props_dialog(self) + def draw_asset_context_menu(self, context, asset_data): layout = self.layout ui_props = context.scene.blenderkitUI @@ -1024,10 +1038,11 @@ def draw_asset_context_menu(self, context, asset_data): a = bpy.context.window_manager['bkit authors'].get(author_id) if a is not None: # utils.p('author:', a) + op = layout.operator('wm.url_open', text="Open Author's Website") if a.get('aboutMeUrl') is not None: - op = layout.operator('wm.url_open', text="Open Author's Website") op.url = a['aboutMeUrl'] - + else: + op.url = paths.get_author_gallery_url(a['id']) op = layout.operator('view3d.blenderkit_search', text="Show Assets By Author") op.keywords = '' op.author_id = author_id @@ -1080,6 +1095,8 @@ def draw_asset_context_menu(self, context, asset_data): op.asset_id = asset_data['id'] op.state = 'rejected' + + if author_id == str(profile['user']['id']): layout.label(text='Management tools:') row = layout.row() @@ -1087,9 +1104,13 @@ def draw_asset_context_menu(self, context, asset_data): 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) + + if utils.profile_is_validator(): + layout.label(text='Admin rating Tools:') + + op = layout.operator('wm.blenderkit_menu_rating_upload', text='Fast rate') + op.asset_id = asset_data['id'] + op.asset_type = asset_data['assetType'] class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu): @@ -1104,6 +1125,7 @@ class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu): asset_data = sr[ui_props.active_index] draw_asset_context_menu(self, context, asset_data) + class OBJECT_MT_blenderkit_login_menu(bpy.types.Menu): bl_label = "BlenderKit login/signup:" bl_idname = "OBJECT_MT_blenderkit_login_menu" @@ -1188,6 +1210,7 @@ class UrlPopupDialog(bpy.types.Operator): return wm.invoke_props_dialog(self) + class LoginPopupDialog(bpy.types.Operator): """Generate Cycles thumbnail for model assets""" bl_idname = "wm.blenderkit_url_dialog" diff --git a/blenderkit/upload.py b/blenderkit/upload.py index 18e43b8a..14fbe6db 100644 --- a/blenderkit/upload.py +++ b/blenderkit/upload.py @@ -767,7 +767,7 @@ class UploadOperator(Operator): layout.label(text="For updates of thumbnail or model use reupload.") if props.is_private == 'PUBLIC': - ui_panels.label_multiline(layout, text='public assets are validated several hours' + utils.label_multiline(layout, text='public assets are validated several hours' ' or days after upload. Remember always to ' 'test download your asset to a clean file' ' to see if it uploaded correctly.' |