Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVilém Duha <vilda.novak@gmail.com>2020-07-12 19:07:45 +0300
committerVilém Duha <vilda.novak@gmail.com>2020-07-12 19:07:58 +0300
commit054ee2f41734049c9ba1386d9ec9eb3e85fc2e3f (patch)
treec0ca21ef9335b368b9785df3c7b9a86fb4200164
parent6f7c4230af8e404d9fa9687b80ee8e7f3f8eac1d (diff)
BlenderKit: fix rating interaction
-disabled layout didn't work(thanks to another blender layout bug that I reported) -replaced it with an enum, and also a popup that informs the user instead.
-rw-r--r--blenderkit/__init__.py76
-rw-r--r--blenderkit/bkit_oauth.py21
-rw-r--r--blenderkit/ratings.py98
-rw-r--r--blenderkit/rerequests.py2
-rw-r--r--blenderkit/search.py2
-rw-r--r--blenderkit/ui_panels.py195
-rw-r--r--blenderkit/upload.py2
-rw-r--r--blenderkit/utils.py38
8 files changed, 311 insertions, 123 deletions
diff --git a/blenderkit/__init__.py b/blenderkit/__init__.py
index 15dcaffb..a7e148ea 100644
--- a/blenderkit/__init__.py
+++ b/blenderkit/__init__.py
@@ -93,6 +93,7 @@ def scene_load(context):
preferences = bpy.context.preferences.addons['blenderkit'].preferences
preferences.login_attempt = False
+
@bpy.app.handlers.persistent
def check_timers_timer():
''' checks if all timers are registered regularly. Prevents possible bugs from stopping the addon.'''
@@ -249,17 +250,12 @@ def switch_search_results(self, context):
s['search results orig'] = s.get('bkit brush search orig')
search.load_previews()
-#define these static
-# asset_type_ui_items = (
-# ('MODEL', 'Models', 'Find upload models in the BlenderKit online database', 'OBJECT_DATAMODE',0),
-# # ('SCENE', 'SCENE', 'Browse scenes', 'SCENE_DATA', 1),
-# ('MATERIAL', 'Materials', 'Find or upload models in the BlenderKit online database', 'MATERIAL',2),
-# # ('TEXTURE', 'Texture', 'Browse textures', 'TEXTURE', 3),
-# ('BRUSH', 'Brushes', 'Find or upload models in the BlenderKit online database', 'BRUSH_DATA',3)
-# )
-
-#same as above, but dynamic.
def asset_type_callback(self, context):
+ '''
+ Returns
+ items for Enum property, depending on the down_up property - BlenderKit is either in search or in upload mode.
+
+ '''
if self.down_up == 'SEARCH':
items = (
('MODEL', 'Models', 'Find models in the BlenderKit online database', 'OBJECT_DATAMODE', 0),
@@ -533,7 +529,7 @@ def update_free(self, context):
"Part of subscription is sent to artists based on usage by paying users."
def draw_message(self, context):
- ui_panels.label_multiline(self.layout, text=message, icon='NONE', width=-1)
+ utils.label_multiline(self.layout, text=message, icon='NONE', width=-1)
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
@@ -654,6 +650,29 @@ 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",
@@ -661,17 +680,25 @@ 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.
+ rating_quality_ui: EnumProperty(name='rating_quality_ui',
+ items=stars_enum_callback,
+ description='Rating stars 0 - 10',
+ default=None,
+ update=update_quality,
+ )
+
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)
- rating_virtual_price: FloatProperty(name="Virtual Price",
- description="How much would you pay for this object if buing it?",
- default=0, min=0, max=10000)
+ # 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)
+ # rating_virtual_price: FloatProperty(name="Virtual Price",
+ # description="How much would you pay for this object if buing it?",
+ # default=0, min=0, max=10000)
rating_problems: StringProperty(
name="Problems",
description="Problems found/ why did you take points down - this will be available for the author"
@@ -1400,14 +1427,15 @@ class BlenderKitSceneSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
update=search.search_update
)
+
def fix_subdir(self, context):
'''Fixes project subdicrectory settings if people input invalid path.'''
# pp = pathlib.PurePath(self.project_subdir)
pp = self.project_subdir[:]
- pp = pp.replace('\\','')
- pp = pp.replace('/','')
- pp = pp.replace(':','')
+ pp = pp.replace('\\', '')
+ pp = pp.replace('/', '')
+ pp = pp.replace(':', '')
pp = '//' + pp
if self.project_subdir != pp:
self.project_subdir = pp
@@ -1418,10 +1446,11 @@ def fix_subdir(self, context):
"and uses it for storing assets."
def draw_message(self, context):
- ui_panels.label_multiline(self.layout, text=message, icon='NONE', width=400)
+ 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):
# this must match the addon name, use '__package__'
# when defining this in a submodule of a python package.
@@ -1501,7 +1530,7 @@ class BlenderKitAddonPreferences(AddonPreferences):
description="where data will be stored for individual projects",
# subtype='DIR_PATH',
default="//assets",
- update = fix_subdir
+ update=fix_subdir
)
directory_behaviour: EnumProperty(
@@ -1566,10 +1595,11 @@ class BlenderKitAddonPreferences(AddonPreferences):
use_timers: BoolProperty(
name="Use timers",
- description="Use timers for bkit",
+ description="Use timers for BlenderKit. Usefull for debugging since timers seem to be unstable.",
default=True,
update=utils.save_prefs
)
+
# allow_proximity : BoolProperty(
# name="allow proximity data reports",
# description="This sends anonymized proximity data \n \
diff --git a/blenderkit/bkit_oauth.py b/blenderkit/bkit_oauth.py
index 0bf20d4a..ae90b215 100644
--- a/blenderkit/bkit_oauth.py
+++ b/blenderkit/bkit_oauth.py
@@ -26,8 +26,9 @@ if "bpy" in locals():
categories = reload(categories)
oauth = reload(oauth)
ui = reload(ui)
+ ui = reload(ui_panels)
else:
- from blenderkit import tasks_queue, utils, paths, search, categories, oauth, ui
+ from blenderkit import tasks_queue, utils, paths, search, categories, oauth, ui, ui_panels
import bpy
@@ -102,7 +103,7 @@ class RegisterLoginOnline(bpy.types.Operator):
"""Login online on BlenderKit webpage"""
bl_idname = "wm.blenderkit_login"
- bl_label = "BlenderKit login or signup"
+ bl_label = "BlenderKit login/signup"
bl_options = {'REGISTER', 'UNDO'}
signup: BoolProperty(
@@ -112,16 +113,32 @@ class RegisterLoginOnline(bpy.types.Operator):
options={'SKIP_SAVE'}
)
+ message: bpy.props.StringProperty(
+ name="Message",
+ description="",
+ default="You were logged out from BlenderKit. Clicking OK takes you to web login. ")
+
@classmethod
def poll(cls, context):
return True
+ def draw(self, context):
+ layout = self.layout
+ utils.label_multiline(layout, text=self.message)
+
def execute(self, context):
preferences = bpy.context.preferences.addons['blenderkit'].preferences
preferences.login_attempt = True
login_thread(self.signup)
return {'FINISHED'}
+ def invoke(self, context, event):
+ wm = bpy.context.window_manager
+ preferences = bpy.context.preferences.addons['blenderkit'].preferences
+ preferences.api_key_refresh = ''
+ preferences.api_key = ''
+ return wm.invoke_props_dialog(self)
+
class Logout(bpy.types.Operator):
"""Logout from BlenderKit immediately"""
diff --git a/blenderkit/ratings.py b/blenderkit/ratings.py
index dbe8b8eb..48c34a61 100644
--- a/blenderkit/ratings.py
+++ b/blenderkit/ratings.py
@@ -78,6 +78,7 @@ def send_rating_to_thread_quality(url, ratings, headers):
thread = threading.Thread(target=upload_rating_thread, args=(url, ratings, headers))
thread.start()
+
def send_rating_to_thread_work_hours(url, ratings, headers):
'''Sens rating into thread rating, main purpose is for tasks_queue.
One function per property to avoid lost data due to stashing.'''
@@ -93,6 +94,7 @@ def upload_review_thread(url, reviews, headers):
def get_rating(asset_id):
+ #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)
@@ -133,6 +135,7 @@ def update_ratings_work_hours(self, context):
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
@@ -170,26 +173,43 @@ 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
-
-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'}
+def get_assets_for_rating():
+ '''
+ gets assets from scene that could/should be rated by the user.
+ TODO this is only a draft.
+
+ '''
+ assets = []
+ for ob in bpy.context.scene.objects:
+ if ob.get('asset_data'):
+ assets.append(ob)
+ for m in bpy.data.materials:
+ if m.get('asset_data'):
+ assets.append(m)
+ for b in bpy.data.brushes:
+ if b.get('asset_data'):
+ 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 = (
@@ -234,29 +254,43 @@ class UploadRatingOperator(bpy.types.Operator):
return wm.invoke_props_dialog(self)
+
def draw_rating(layout, props, prop_name, name):
# layout.label(name)
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
+ # 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 register_ratings():
pass;
- bpy.utils.register_class(StarRatingOperator)
+ # bpy.utils.register_class(StarRatingOperator)
bpy.utils.register_class(UploadRatingOperator)
def unregister_ratings():
pass;
- bpy.utils.unregister_class(StarRatingOperator)
+ # bpy.utils.unregister_class(StarRatingOperator)
bpy.utils.unregister_class(UploadRatingOperator)
diff --git a/blenderkit/rerequests.py b/blenderkit/rerequests.py
index 587093e0..3d9a4d75 100644
--- a/blenderkit/rerequests.py
+++ b/blenderkit/rerequests.py
@@ -40,7 +40,7 @@ def rerequest(method, url, **kwargs):
# first normal attempt
response = requests.request(method, url, **kwargs)
- utils.p(url)
+ utils.p(url, kwargs)
utils.p(response.status_code)
if response.status_code == 401:
diff --git a/blenderkit/search.py b/blenderkit/search.py
index bae25466..09dfeb65 100644
--- a/blenderkit/search.py
+++ b/blenderkit/search.py
@@ -134,7 +134,7 @@ def scene_load(context):
def fetch_server_data():
- ''' download categories and addon version'''
+ ''' download categories , profile, and refresh token if needed.'''
if not bpy.app.background:
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
api_key = user_preferences.api_key
diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py
index 1083b6a6..b8d8ce73 100644
--- a/blenderkit/ui_panels.py
+++ b/blenderkit/ui_panels.py
@@ -33,58 +33,32 @@ from bpy.types import (
)
import bpy
+import os
+import random
-def label_multiline(layout, text='', icon='NONE', width=-1):
- ''' draw a ui label, but try to split it in multiple lines.'''
- if text.strip() == '':
- return
- lines = text.split('\n')
- if width > 0:
- threshold = int(width / 5.5)
- else:
- threshold = 35
- maxlines = 8
- li = 0
- for l in lines:
- while len(l) > threshold:
- i = l.rfind(' ', 0, threshold)
- if i < 1:
- i = threshold
- l1 = l[:i]
- layout.label(text=l1, icon=icon)
- icon = 'NONE'
- l = l[i:].lstrip()
- li += 1
- if li > maxlines:
- break;
- if li > maxlines:
- break;
- layout.label(text=l, icon=icon)
- icon = 'NONE'
-
# this was moved to separate interface:
-def draw_ratings(layout, context):
+def draw_ratings(layout, context, asset):
# layout.operator("wm.url_open", text="Read rating instructions", icon='QUESTION').url = 'https://support.google.com/?hl=en'
- asset = utils.get_active_asset()
# the following shouldn't happen at all in an optimal case,
# this function should run only when asset was already checked to be existing
if asset == None:
return;
col = layout.column()
- if not utils.user_logged_in():
- label_multiline(layout, text='Please login or sign up '
- 'to rate assets.')
- col.enabled = False
bkit_ratings = asset.bkit_ratings
- ratings.draw_rating(col, bkit_ratings, 'rating_quality', 'Quality')
- col.separator()
- col.prop(bkit_ratings, 'rating_work_hours')
- w = context.region.width
+ # 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:
+ col.separator()
+ col.prop(bkit_ratings, 'rating_work_hours')
+ # w = context.region.width
# layout.label(text='problems')
# layout.prop(bkit_ratings, 'rating_problems', text='')
@@ -97,13 +71,12 @@ def draw_ratings(layout, context):
# re-enable layout if included in longer panel
-def draw_not_logged_in(source):
- title = "User not logged in"
+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):
layout = source.layout
- label_multiline(layout, text='Please login or sign up '
- 'to upload files.')
+ utils.label_multiline(layout, text=message)
draw_login_buttons(layout)
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
@@ -121,7 +94,7 @@ def draw_upload_common(layout, props, asset_type, context):
row = layout.row(align=True)
if props.upload_state != '':
- 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
@@ -210,7 +183,7 @@ def draw_panel_model_upload(self, context):
op.process_source = 'MODEL'
op.process_type = 'THUMBNAILER'
elif props.thumbnail_generating_state != '':
- 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')
@@ -274,7 +247,7 @@ def draw_panel_scene_upload(self, context):
# op.process_source = 'MODEL'
# op.process_type = 'THUMBNAILER'
# elif props.thumbnail_generating_state != '':
- # 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')
@@ -319,7 +292,7 @@ def draw_panel_model_search(self, context):
icon = 'NONE'
if props.report == 'You need Full plan to get this item.':
icon = 'ERROR'
- label_multiline(layout, text=props.report, icon=icon)
+ utils.label_multiline(layout, text=props.report, icon=icon)
if props.report == 'You need Full plan to get this item.':
layout.operator("wm.url_open", text="Get Full plan", icon='URL').url = paths.BLENDERKIT_PLANS
@@ -346,7 +319,7 @@ def draw_panel_scene_search(self, context):
row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(row, props)
layout.prop(props, "own_only")
- label_multiline(layout, text=props.report)
+ utils.label_multiline(layout, text=props.report)
# layout.prop(props, "search_style")
# if props.search_style == 'OTHER':
@@ -376,7 +349,7 @@ class VIEW3D_PT_blenderkit_model_properties(Panel):
o = utils.get_active_model()
# o = bpy.context.active_object
if o.get('asset_data') is None:
- 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:
@@ -400,6 +373,51 @@ 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):
+ layout = self.layout
+ col = layout.box()
+ # split = layout.split(factor=0.5)
+ # col1 = split.column()
+ # col2 = split.column()
+ 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:
+ if image.filepath == tpath:
+ # split = row.split(factor=1.0, align=False)
+ col.template_icon(icon_value=image.preview.icon_id, scale=6.0)
+ break;
+ # layout.label(text = '', icon_value=image.preview.icon_id, scale = 10)
+ col.label(text=asset.name)
+ draw_ratings(col, context, asset=asset)
+
+
+
+
+class VIEW3D_PT_blenderkit_ratings(Panel):
+ bl_category = "BlenderKit"
+ bl_idname = "VIEW3D_PT_blenderkit_ratings"
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_label = "Please rate"
+ bl_context = "objectmode"
+
+ @classmethod
+ def poll(cls, context):
+ #
+ p = bpy.context.view_layer.objects.active is not None
+ 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.
+ # 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:')
+
+ for a in assets:
+ draw_rating_asset(self, context, asset = a)
def draw_login_progress(layout):
layout.label(text='Login through browser')
@@ -492,7 +510,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) # , props)
+ draw_ratings(self.layout, context, asset = o) # , props)
# op.asset_type = 'MODEL'
@@ -536,7 +554,7 @@ def draw_panel_material_upload(self, context):
op.process_source = 'MATERIAL'
op.process_type = 'THUMBNAILER'
elif props.thumbnail_generating_state != '':
- 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')
@@ -557,9 +575,9 @@ def draw_panel_material_search(self, context):
row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(row, props)
layout.prop(props, "own_only")
- label_multiline(layout, text=props.report)
+ utils.label_multiline(layout, text=props.report)
- # layout.prop(props, 'search_style')
+ # layout.prop(props, 'search_style')F
# if props.search_style == 'OTHER':
# layout.prop(props, 'search_style_other')
# layout.prop(props, 'search_engine')
@@ -570,7 +588,8 @@ def draw_panel_material_search(self, context):
def draw_panel_material_ratings(self, context):
- draw_ratings(self.layout, context) # , props)
+ asset = bpy.context.active_object.active_material
+ draw_ratings(self.layout, context, asset) # , props)
# op.asset_type = 'MATERIAL'
@@ -598,23 +617,28 @@ def draw_panel_brush_search(self, context):
draw_assetbar_show_hide(row, props)
layout.prop(props, "own_only")
- label_multiline(layout, text=props.report)
+ utils.label_multiline(layout, text=props.report)
# draw_panel_categories(self, context)
def draw_panel_brush_ratings(self, context):
# props = utils.get_brush_props(context)
- draw_ratings(self.layout, context) # , props)
+ brush = utils.get_active_brush()
+ draw_ratings(self.layout, context, asset = brush) # , props)
#
# op.asset_type = 'BRUSH'
-def draw_login_buttons(layout):
+def draw_login_buttons(layout, invoke = False):
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
if user_preferences.login_attempt:
draw_login_progress(layout)
else:
+ if invoke:
+ layout.operator_context = 'INVOKE_DEFAULT'
+ else:
+ layout.operator_context = 'EXEC_DEFAULT'
if user_preferences.api_key == '':
layout.operator("wm.blenderkit_login", text="Login",
icon='URL').signup = False
@@ -846,7 +870,7 @@ class VIEW3D_PT_blenderkit_unified(Panel):
layout.separator()
# if bpy.data.filepath == '':
# layout.alert = True
- # label_multiline(layout, text="It's better to save your file first.", width=w)
+ # utils.label_multiline(layout, text="It's better to save your file first.", width=w)
# layout.alert = False
# layout.separator()
@@ -868,7 +892,7 @@ class VIEW3D_PT_blenderkit_unified(Panel):
# noinspection PyCallByClass
draw_panel_brush_search(self, context)
else:
- label_multiline(layout, text='switch to paint or sculpt mode.', width=context.region.width)
+ utils.label_multiline(layout, text='switch to paint or sculpt mode.', width=context.region.width)
return
@@ -886,11 +910,11 @@ class VIEW3D_PT_blenderkit_unified(Panel):
if e not in ('CYCLES', 'BLENDER_EEVEE'):
rtext = 'Only Cycles and EEVEE render engines are currently supported. ' \
'Please use Cycles for all assets you upload to BlenderKit.'
- label_multiline(layout, rtext, icon='ERROR', width=w)
+ utils.label_multiline(layout, rtext, icon='ERROR', width=w)
return;
if ui_props.asset_type == 'MODEL':
- # 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:
@@ -899,12 +923,12 @@ class VIEW3D_PT_blenderkit_unified(Panel):
draw_panel_scene_upload(self, context)
elif ui_props.asset_type == 'MATERIAL':
- # 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:
- 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:
@@ -1029,6 +1053,16 @@ 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"
+
+ def draw(self, context):
+ layout = self.layout
+
+ # utils.label_multiline(layout, text=message)
+ draw_login_buttons(layout)
+
class SetCategoryOperator(bpy.types.Operator):
"""Visit subcategory"""
@@ -1088,9 +1122,42 @@ class UrlPopupDialog(bpy.types.Operator):
def draw(self, context):
layout = self.layout
- label_multiline(layout, text=self.message)
+ utils.label_multiline(layout, text=self.message)
+
+ layout.active_default = True
+ op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION')
+ op.url = self.url
+
+ def execute(self, context):
+ # start_thumbnailer(self, context)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+
+ return wm.invoke_props_dialog(self)
+
+class LoginPopupDialog(bpy.types.Operator):
+ """Generate Cycles thumbnail for model assets"""
+ bl_idname = "wm.blenderkit_url_dialog"
+ bl_label = "BlenderKit login"
+ bl_options = {'REGISTER', 'INTERNAL'}
+
+ message: bpy.props.StringProperty(
+ name="Message",
+ description="",
+ default="Your were logged out from BlenderKit. Please login again. ")
+
+ # @classmethod
+ # def poll(cls, context):
+ # return bpy.context.view_layer.objects.active is not None
+
+ def draw(self, context):
+ layout = self.layout
+ utils.label_multiline(layout, text=self.message)
layout.active_default = True
+ op = layout.operator
op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION')
op.url = self.url
@@ -1227,8 +1294,10 @@ classess = (
VIEW3D_PT_blenderkit_categories,
VIEW3D_PT_blenderkit_import_settings,
VIEW3D_PT_blenderkit_model_properties,
+ # VIEW3D_PT_blenderkit_ratings,
VIEW3D_PT_blenderkit_downloads,
OBJECT_MT_blenderkit_asset_menu,
+ OBJECT_MT_blenderkit_login_menu,
UrlPopupDialog
)
diff --git a/blenderkit/upload.py b/blenderkit/upload.py
index 3afe9815..18e43b8a 100644
--- a/blenderkit/upload.py
+++ b/blenderkit/upload.py
@@ -777,7 +777,7 @@ class UploadOperator(Operator):
props = utils.get_upload_props()
if not utils.user_logged_in():
- ui_panels.draw_not_logged_in(self)
+ ui_panels.draw_not_logged_in(self, message = 'To upload assets you need to login/signup.')
return {'CANCELLED'}
if props.is_private == 'PUBLIC':
diff --git a/blenderkit/utils.py b/blenderkit/utils.py
index 503a93f2..2e59887c 100644
--- a/blenderkit/utils.py
+++ b/blenderkit/utils.py
@@ -263,6 +263,15 @@ def save_prefs(self, context):
except Exception as e:
print(e)
+def get_hidden_texture(tpath, bdata_name, force_reload = False):
+ i = get_hidden_image(tpath, bdata_name, force_reload = force_reload)
+ bdata_name = f".{bdata_name}"
+ t = bpy.data.textures.get(bdata_name)
+ if t is None:
+ t = bpy.data.textures.new('.test', 'IMAGE')
+ if t.image!= i:
+ t.image = i
+ return t
def get_hidden_image(tpath, bdata_name, force_reload=False):
hidden_name = '.%s' % bdata_name
@@ -603,3 +612,32 @@ def guard_from_crash():
if bpy.context.preferences.addons['blenderkit'].preferences is None:
return False;
return True
+
+
+def label_multiline(layout, text='', icon='NONE', width=-1):
+ ''' draw a ui label, but try to split it in multiple lines.'''
+ if text.strip() == '':
+ return
+ lines = text.split('\n')
+ if width > 0:
+ threshold = int(width / 5.5)
+ else:
+ threshold = 35
+ maxlines = 8
+ li = 0
+ for l in lines:
+ while len(l) > threshold:
+ i = l.rfind(' ', 0, threshold)
+ if i < 1:
+ i = threshold
+ l1 = l[:i]
+ layout.label(text=l1, icon=icon)
+ icon = 'NONE'
+ l = l[i:].lstrip()
+ li += 1
+ if li > maxlines:
+ break;
+ if li > maxlines:
+ break;
+ layout.label(text=l, icon=icon)
+ icon = 'NONE' \ No newline at end of file