From 2afbdc806e23fbd0ee8aedddafab6eb84b3cccb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vil=C3=A9m=20Duha?= <vilda.novak@gmail.com> Date: Thu, 28 Jan 2021 13:59:29 +0100 Subject: [PATCH] BlederKit: fix snapping with particles Now the snap also ignores particles. Also fix a case if user didn't fill a name in profile, now it draws at least users email. --- blenderkit/__init__.py | 23 +++------ blenderkit/asset_bar_op.py | 1 + blenderkit/autothumb.py | 11 ++--- blenderkit/resolutions.py | 2 +- blenderkit/search.py | 7 +-- blenderkit/ui.py | 99 +++++++++++++++++++++++++++++++++----- blenderkit/ui_panels.py | 22 +++++++-- blenderkit/upload.py | 1 - 8 files changed, 122 insertions(+), 44 deletions(-) diff --git a/blenderkit/__init__.py b/blenderkit/__init__.py index 90a50e6e7..1a8c3cef9 100644 --- a/blenderkit/__init__.py +++ b/blenderkit/__init__.py @@ -582,16 +582,11 @@ def name_update(self, context): def update_free(self, context): if self.is_free == False: self.is_free = True - title = "All BlenderKit materials are free" - message = "Any material uploaded to BlenderKit is free." \ + ui_panels.ui_message(title = "All BlenderKit materials are free", + message = "Any material uploaded to BlenderKit is free." \ " However, it can still earn money for the author," \ " based on our fair share system. " \ - "Part of subscription is sent to artists based on usage by paying users." - - def draw_message(self, context): - utils.label_multiline(self.layout, text=message, icon='NONE', width=-1) - - bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO') + "Part of subscription is sent to artists based on usage by paying users.") class BlenderKitCommonUploadProps(object): @@ -1517,15 +1512,11 @@ def fix_subdir(self, context): if self.project_subdir != pp: self.project_subdir = pp - title = "Fixed to relative path" - message = "This path should be always realative.\n" \ - " It's a directory BlenderKit creates where your .blend is \n " \ - "and uses it for storing assets." - - def draw_message(self, context): - utils.label_multiline(self.layout, text=message, icon='NONE', width=400) + ui_panels.ui_message(title = "Fixed to relative path", + message = "This path should be always realative.\n" \ + " It's a directory BlenderKit creates where your .blend is \n " \ + "and uses it for storing assets.") - bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO') class BlenderKitAddonPreferences(AddonPreferences): diff --git a/blenderkit/asset_bar_op.py b/blenderkit/asset_bar_op.py index 2c445ad4b..f0092960c 100644 --- a/blenderkit/asset_bar_op.py +++ b/blenderkit/asset_bar_op.py @@ -516,6 +516,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): sro = bpy.context.window_manager.get('search results orig') if sro is not None and sro.get('next') is not None: blenderkit.search.search(get_next=True) + def update_images(self): sr = bpy.context.window_manager['search results'] diff --git a/blenderkit/autothumb.py b/blenderkit/autothumb.py index da6e6d29d..2a649427e 100644 --- a/blenderkit/autothumb.py +++ b/blenderkit/autothumb.py @@ -17,7 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### -from blenderkit import paths, utils, bg_blender +from blenderkit import paths, utils, bg_blender, ui_panels import tempfile, os, subprocess, json, sys @@ -262,13 +262,10 @@ class GenerateThumbnailOperator(bpy.types.Operator): def invoke(self, context, event): wm = context.window_manager if bpy.data.filepath == '': - title = "Can't render thumbnail" - message = "please save your file first" + ui_panels.ui_message( + title = "Can't render thumbnail", + message = "please save your file first") - def draw_message(self, context): - self.layout.label(text=message) - - bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO') return {'FINISHED'} return wm.invoke_props_dialog(self) diff --git a/blenderkit/resolutions.py b/blenderkit/resolutions.py index a5b5d7230..018889e79 100644 --- a/blenderkit/resolutions.py +++ b/blenderkit/resolutions.py @@ -601,7 +601,7 @@ def assets_db_path(): def get_assets_search(): - bpy.app.debug_value = 2 + # bpy.app.debug_value = 2 results = [] preferences = bpy.context.preferences.addons['blenderkit'].preferences diff --git a/blenderkit/search.py b/blenderkit/search.py index d37b00455..c902104c7 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -237,7 +237,7 @@ def parse_result(r): # except: # utils.p('asset with no files-size') asset_type = r['assetType'] - if len(r['files']) > 0: + if len(r['files']) > 0:#TODO remove this condition so all assets are parsed. r['available_resolutions'] = [] allthumbs = [] durl, tname, small_tname = '', '', '' @@ -403,7 +403,6 @@ def timer_update(): result_field = [] ok, error = check_errors(rdata) if ok: - bpy.ops.object.run_assetbar_fix_context() for r in rdata['results']: asset_data = parse_result(r) @@ -1278,7 +1277,6 @@ def add_search_process(query, params, orig_result): old_thread[0].stop() # TODO CARE HERE FOR ALSO KILLING THE Thumbnail THREADS.? # AT LEAST NOW SEARCH DONE FIRST WON'T REWRITE AN OLDER ONE - tempdir = paths.get_temp_dir('%s_search' % query['asset_type']) thread = Searcher(query, params, orig_result) thread.start() @@ -1343,7 +1341,6 @@ def search(category='', get_next=False, author_id=''): ''' initialize searching''' global search_start_time user_preferences = bpy.context.preferences.addons['blenderkit'].preferences - search_start_time = time.time() # mt('start') scene = bpy.context.scene @@ -1418,7 +1415,7 @@ def search(category='', get_next=False, author_id=''): # if free_only: # query['keywords'] += '+is_free:true' - orig_results = scene.get(f'bkit {ui_props.asset_type.lower()} search orig', {}) + orig_results = bpy.context.window_manager.get(f'bkit {ui_props.asset_type.lower()} search orig', {}) if orig_results != {}: # ensure it's a copy in dict for what we are passing to thread: orig_results = orig_results.to_dict() diff --git a/blenderkit/ui.py b/blenderkit/ui.py index 6d797f733..72d0ad7e0 100644 --- a/blenderkit/ui.py +++ b/blenderkit/ui.py @@ -883,6 +883,19 @@ 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.instance_collection: + for o1 in p.instance_collection.objects: + if o1 == o: + return True + if p.render_type =='COLLECTION': + if p.instance_object == o: + return True + return False + def deep_ray_cast(depsgraph, ray_origin, vec): # this allows to ignore some objects, like objects with bounding box draw style or particle objects @@ -890,19 +903,22 @@ def deep_ray_cast(depsgraph, ray_origin, vec): # while object is None or object.draw has_hit, snapped_location, snapped_normal, face_index, object, matrix = bpy.context.scene.ray_cast( depsgraph, ray_origin, vec) + empty_set = False, Vector((0, 0, 0)), Vector((0, 0, 1)), None, None, None if not object: - return False, Vector((0, 0, 0)), Vector((0, 0, 1)), None, None, None + return empty_set try_object = object - while try_object and try_object.display_type == 'BOUNDS': + + while try_object and (try_object.display_type == 'BOUNDS' or object_in_particle_collection(try_object)): ray_origin = snapped_location + vec.normalized() * 0.0003 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 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 - - return has_hit, snapped_location, snapped_normal, face_index, object, matrix - + 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 @@ -1197,6 +1213,67 @@ 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" +# bl_label = "BlenderKit material drop on linked objects" +# bl_options = {'REGISTER', 'INTERNAL'} +# +# asset_search_index: IntProperty(name="Asset index", +# description="Index of the asset in asset bar", +# default=0, +# ) +# +# model_location: FloatVectorProperty(name="Location", +# default=(0, 0, 0)) +# +# model_rotation: FloatVectorProperty(name="Rotation", +# default=(0, 0, 0), +# subtype='QUATERNION') +# +# target_object: StringProperty( +# name="Target object", +# description="The object to which the particles will get applied", +# default="", options={'SKIP_SAVE'}) +# +# target_material_slot: IntProperty(name="Target material slot", +# description="Index of the material on the object to be changed", +# default=0, +# ) +# +# @classmethod +# def poll(cls, context): +# return True +# +# def draw(self, context): +# layout = self.layout +# message = "This asset is linked to the scene from an external file and cannot have material appended." \ +# " Do you want to bring it into Blender Scene?" +# utils.label_multiline(layout, text=message, width=400) +# +# def execute(self, context): +# for c in bpy.data.collections: +# for o in c.objects: +# if o.name != self.target_object: +# continue; +# for empty in bpy.context.visible_objects: +# if not(empty.instance_type == 'COLLECTION' and empty.instance_collection == c): +# continue; +# utils.activate(empty) +# break; +# bpy.ops.object.blenderkit_bring_to_scene() +# bpy.ops.scene.blenderkit_download(True, +# # asset_type=ui_props.asset_type, +# asset_index=self.asset_search_index, +# model_location=self.model_rotation, +# model_rotation=self.model_rotation, +# target_object=self.target_object, +# material_target_slot = self.target_slot) +# return {'FINISHED'} +# +# def invoke(self, context, event): +# wm = context.window_manager +# return wm.invoke_props_dialog(self, width=400) class AssetBarOperator(bpy.types.Operator): '''runs search and displays the asset bar at the same time''' @@ -1707,7 +1784,7 @@ class AssetBarOperator(bpy.types.Operator): ui_props = context.scene.blenderkitUI sr = bpy.context.window_manager.get('search results') - if self.do_search or sr is None: + if self.do_search: # we erase search keywords for cateogry search now, since these combinations usually return nothing now. # when the db gets bigger, this can be deleted. if self.category != '': @@ -1715,11 +1792,8 @@ class AssetBarOperator(bpy.types.Operator): sprops.search_keywords = '' search.search(category=self.category) - if sr is None: - bpy.context.window_manager['search results'] = [] - if ui_props.assetbar_on: - # we don't want to run the assetbar many times, that's why it has a switch on/off behaviour, + # we don't want to run the assetbar more than once, that's why it has a switch on/off behaviour, # unless being called with 'keep_running' prop. if not self.keep_running: # this sends message to the originally running operator, so it quits, and then it ends this one too. @@ -1738,7 +1812,8 @@ class AssetBarOperator(bpy.types.Operator): ui_props.assetbar_on = True ui_props.turn_off = False - + if sr is None: + bpy.context.window_manager['search results'] = [] if context.area.type != 'VIEW_3D': self.report({'WARNING'}, "View3D not found, cannot run operator") @@ -1875,6 +1950,8 @@ class AssetDragOperator(bpy.types.Operator): temp_mesh = object_eval.to_mesh() target_slot = temp_mesh.polygons[self.face_index].material_index object_eval.to_mesh_clear() + # elif object.is_library_indirect:#case for bring to scene objects, will be solved through prefs and direct + # action else: self.report({'WARNING'}, "Invalid or library object as input:") target_object = '' diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index deb3c0bb0..91abd4460 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -546,7 +546,10 @@ class VIEW3D_PT_blenderkit_profile(Panel): if me is not None: me = me['user'] # user name - layout.label(text='Me: %s %s' % (me['firstName'], me['lastName'])) + if len(me['firstName'])>0 or len(me['lastName'])>0: + layout.label(text=f"Me: {me['firstName']} {me['lastName']}") + else: + layout.label(text=f"Me: {me['email']}") # layout.label(text='Email: %s' % (me['email'])) # plan information @@ -1520,10 +1523,18 @@ class UrlPopupDialog(bpy.types.Operator): def draw(self, context): layout = self.layout - utils.label_multiline(layout, text=self.message) + utils.label_multiline(layout, text=self.message, width = 300) layout.active_default = True op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION') + if not utils.user_logged_in(): + utils.label_multiline(layout, + text='Already subscribed? You need to login to access your Full Plan.', + width = 300) + + layout.operator_context = 'EXEC_DEFAULT' + layout.operator("wm.blenderkit_login", text="Login", + icon='URL').signup = False op.url = self.url def execute(self, context): @@ -1533,7 +1544,7 @@ class UrlPopupDialog(bpy.types.Operator): def invoke(self, context, event): wm = context.window_manager - return wm.invoke_props_dialog(self) + return wm.invoke_props_dialog(self,width = 300) class LoginPopupDialog(bpy.types.Operator): @@ -1688,7 +1699,12 @@ def header_search_draw(self, context): layout.prop(props, "search_keywords", text="", icon='VIEWZOOM') draw_assetbar_show_hide(layout, props) +def ui_message(title, message): + def draw_message(self, context): + layout = self.layout + utils.label_multiline(layout, text=message) + bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO') # We can store multiple preview collections here, # however in this example we only store "main" preview_collections = {} diff --git a/blenderkit/upload.py b/blenderkit/upload.py index 8a905cecc..1901d92cc 100644 --- a/blenderkit/upload.py +++ b/blenderkit/upload.py @@ -673,7 +673,6 @@ class FastMetadata(bpy.types.Operator): except Exception as e: print(e) self.message = f"Fast edit metadata of {asset_data['name']}" - self.message = str(cat_path) self.name = asset_data['displayName'] self.description = asset_data['description'] self.tags = ','.join(asset_data['tags']) -- GitLab