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.
This commit is contained in:
parent
4b6ee68c00
commit
2afbdc806e
|
@ -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."
|
||||
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.")
|
||||
|
||||
def draw_message(self, context):
|
||||
utils.label_multiline(self.layout, text=message, icon='NONE', width=400)
|
||||
|
||||
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
|
||||
|
||||
|
||||
class BlenderKitAddonPreferences(AddonPreferences):
|
||||
|
|
|
@ -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']
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 = ''
|
||||
|
|
|
@ -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 = {}
|
||||
|
|
|
@ -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'])
|
||||
|
|
Loading…
Reference in New Issue