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 8f6903bc92)
This commit is contained in:
Vilém Duha 2020-07-27 12:59:38 +02:00
parent 66bd6dea71
commit 06181ee994
7 changed files with 327 additions and 142 deletions

View File

@ -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():

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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"

View File

@ -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.'