Newer
Older
# split = row
# split = layout.row()
else:
split = split.column()
split.prop(ui_props, 'asset_type', expand=True, icon_only=ui_props.asset_type_fold)
# layout.prop(ui_props, 'asset_type', expand=False, text='')
Vilem Duha
committed
if user_preferences.login_attempt:
draw_login_progress(layout)
Vilem Duha
committed
return
if len(user_preferences.api_key) < 20 and user_preferences.asset_counter > 20:
if user_preferences.enable_oauth:
else:
op = layout.operator("wm.url_open", text="Get your API Key",
icon='QUESTION')
op.url = paths.BLENDERKIT_SIGNUP_URL
layout.label(text='Paste your API Key:')
layout.prop(user_preferences, 'api_key', text='')
# utils.label_multiline(layout, text="It's better to save your file first.", width=w)
if utils.profile_is_validator():
search_props = utils.get_search_props()
layout.prop(search_props, 'search_verification_status')
layout.prop(search_props, "unrated_only")
if ui_props.asset_type == 'MODEL':
# noinspection PyCallByClass
draw_panel_model_search(self, context)
if ui_props.asset_type == 'SCENE':
# noinspection PyCallByClass
draw_panel_scene_search(self, context)
if ui_props.asset_type == 'HDR':
# noinspection PyCallByClass
draw_panel_hdr_search(self, context)
elif ui_props.asset_type == 'MATERIAL':
draw_panel_material_search(self, context)
elif ui_props.asset_type == 'BRUSH':
if context.sculpt_object or context.image_paint_object:
# noinspection PyCallByClass
draw_panel_brush_search(self, context)
else:
utils.label_multiline(layout, text='Switch to paint or sculpt mode.', width=context.region.width)
elif ui_props.down_up == 'UPLOAD':
if not ui_props.assetbar_on:
text = 'Show asset preview - ;'
else:
text = 'Hide asset preview - ;'
op = layout.operator('view3d.blenderkit_asset_bar', text=text, icon='EXPORT')
op.keep_running = False
op.do_search = False
op.tooltip = 'Show/Hide asset preview'
e = s.render.engine
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.'
utils.label_multiline(layout, rtext, icon='ERROR', width=w)
return;
if ui_props.asset_type == 'MODEL':
# 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:
layout.label(text='selet object to upload')
elif ui_props.asset_type == 'SCENE':
draw_panel_scene_upload(self, context)
elif ui_props.asset_type == 'HDR':
draw_panel_hdr_upload(self, context)
# 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)
elif ui_props.asset_type == 'BRUSH':
if context.sculpt_object or context.image_paint_object:
draw_panel_brush_upload(self, context)
else:
layout.label(text='Switch to paint or sculpt mode.')
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
class BlenderKitWelcomeOperator(bpy.types.Operator):
"""Login online on BlenderKit webpage"""
bl_idname = "wm.blenderkit_welcome"
bl_label = "Welcome to BlenderKit!"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
step: IntProperty(
name="step",
description="Tutorial Step",
default=0,
options={'SKIP_SAVE'}
)
@classmethod
def poll(cls, context):
return True
def draw(self, context):
layout = self.layout
if self.step == 0:
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)
layout.template_icon(icon_value=self.img.preview.icon_id, scale=18)
# utils.label_multiline(layout, text="\n Let's start by searching for some cool materials?", width=300)
op = layout.operator("wm.url_open", text='Watch Video Tutorial', icon='QUESTION')
op.url = paths.BLENDERKIT_MANUAL
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:
# 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
random_searches = [
('MATERIAL','ice'),
('MODEL','car'),
('MODEL','vase'),
('MODEL','grass'),
('MODEL','plant'),
('MODEL','man'),
('MATERIAL','metal'),
('MATERIAL','wood'),
('MATERIAL','floor'),
('MATERIAL','bricks'),
]
random_search = random.choice(random_searches)
ui_props.asset_type = random_search[0]
bpy.context.scene.blenderkit_mat.search_keywords = ''#random_search[1]
bpy.context.scene.blenderkit_mat.search_keywords = '+is_free:true+score_gte:1000+order:-created'#random_search[1]
return {'FINISHED'}
def invoke(self, context, event):
wm = bpy.context.window_manager
img = utils.get_thumbnail('intro.jpg')
utils.img_to_preview(img, copy_original = True)
self.img = img
w, a, r = utils.get_largest_area(area_type='VIEW_3D')
if a is not None:
a.spaces.active.show_region_ui = True
return wm.invoke_props_dialog(self, width = 500)
def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
ui_props = context.scene.blenderkitUI
wm = bpy.context.window_manager
layout.operator_context = 'INVOKE_DEFAULT'
if from_panel:
op = layout.operator('wm.blenderkit_menu_rating_upload', text='Rate')
op.asset_name = asset_data['name']
op.asset_id = asset_data['id']
op.asset_type = asset_data['assetType']
if from_panel and wm.get('bkit authors') is not None and author_id is not None:
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.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
op = layout.operator('view3d.blenderkit_search', text='Search Similar')
op.esc = True
op.tooltip = 'Search for similar assets in the library'
op.keywords = asset_data['name']
if asset_data.get('description'):
op.keywords += ' '.join(asset_data.get('tags'))
if asset_data.get('canDownload') != 0:
if len(bpy.context.selected_objects) > 0 and ui_props.asset_type == 'MODEL':
aob = bpy.context.active_object
if aob is None:
aob = bpy.context.selected_objects[0]
op = layout.operator('scene.blenderkit_download', text='Replace Active Models')
# this checks if the menu got called from right-click in assetbar(then index is 0 - x) or
# from a panel(then replacement happens from the active model)
else:
op.asset_index = ui_props.active_index
op.model_location = aob.location
op.model_rotation = aob.rotation_euler
op.target_object = aob.name
op.material_target_slot = aob.active_material_index
op.replace = True
op.replace_resolution = False
# resolution replacement operator
# if asset_data['downloaded'] == 100: # only show for downloaded/used assets
# if ui_props.asset_type in ('MODEL', 'MATERIAL'):
# layout.menu(OBJECT_MT_blenderkit_resolution_menu.bl_idname)
if ui_props.asset_type in ('MODEL', 'MATERIAL', 'HDR') and \
utils.get_param(asset_data, 'textureResolutionMax') is not None and \
utils.get_param(asset_data, 'textureResolutionMax') > 512:
s = bpy.context.scene
col = layout.column()
col.operator_context = 'INVOKE_DEFAULT'
if from_panel:
# Called from addon panel
if asset_data.get('resolution'):
op = col.operator('scene.blenderkit_download', text='Replace asset resolution')
op.asset_base_id = asset_data['assetBaseId']
if asset_data['assetType'] == 'MODEL':
o = utils.get_active_model()
op.model_location = o.location
op.model_rotation = o.rotation_euler
op.target_object = o.name
op.material_target_slot = o.active_material_index
elif asset_data['assetType'] == 'MATERIAL':
aob = bpy.context.active_object
op.model_location = aob.location
op.model_rotation = aob.rotation_euler
op.target_object = aob.name
op.material_target_slot = aob.active_material_index
op.invoke_resolution = True
op.max_resolution = asset_data.get('max_resolution',
0) # str(utils.get_param(asset_data, 'textureResolutionMax'))
elif asset_data['assetBaseId'] in s['assets used'].keys() and asset_data['assetType'] != 'hdr':
# HDRs are excluded from replacement, since they are always replaced.
# called from asset bar:
op = col.operator('scene.blenderkit_download', text='Replace asset resolution')
op.asset_index = ui_props.active_index
# op.asset_type = ui_props.asset_type
op.replace_resolution = True
op.invoke_resolution = True
o = utils.get_active_model()
if o and o.get('asset_data'):
if o['asset_data']['assetBaseId'] == bpy.context.window_manager['search results'][
ui_props.active_index]:
op.model_location = o.location
op.model_rotation = o.rotation_euler
op.model_location = (0, 0, 0)
op.model_rotation = (0, 0, 0)
op.max_resolution = asset_data.get('max_resolution',
0) # str(utils.get_param(asset_data, 'textureResolutionMax'))
# print('operator res ', resolution)
# op.resolution = resolution
wm = bpy.context.window_manager
profile = wm.get('bkit profile')
if profile is not None:
# validation
if author_id == str(profile['user']['id']) or utils.profile_is_validator():
layout.label(text='Management tools:')
row = layout.row()
row.operator_context = 'INVOKE_DEFAULT'
op = layout.operator('wm.blenderkit_fast_metadata', text='Edit Metadata')
op.asset_type = asset_data['assetType']
if asset_data['assetType'] == 'model':
op = layout.operator('object.blenderkit_regenerate_thumbnail', text='Regenerate thumbnail')
op.asset_index = ui_props.active_index
if asset_data['assetType'] == 'material':
op = layout.operator('object.blenderkit_regenerate_material_thumbnail', text='Regenerate thumbnail')
op.asset_index = ui_props.active_index
# op.asset_id = asset_data['id']
# op.asset_type = asset_data['assetType']
if author_id == str(profile['user']['id']):
row = layout.row()
row.operator_context = 'INVOKE_DEFAULT'
op = row.operator('object.blenderkit_change_status', text='Delete')
op.asset_id = asset_data['id']
op.state = 'deleted'
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
op = layout.operator('object.blenderkit_print_asset_debug', text='Print asset debug')
op.asset_id = asset_data['id']
# def draw_asset_resolution_replace(self, context, resolution):
# layout = self.layout
# ui_props = bpy.context.scene.blenderkitUI
#
# op = layout.operator('scene.blenderkit_download', text=resolution)
# if ui_props.active_index == -3:
# # This happens if the command is called from addon panel
# o = utils.get_active_model()
# op.asset_base_id = o['asset_data']['assetBaseId']
#
# else:
# op.asset_index = ui_props.active_index
#
# op.asset_type = ui_props.asset_type
# if len(bpy.context.selected_objects) > 0: # and ui_props.asset_type == 'MODEL':
# aob = bpy.context.active_object
# op.model_location = aob.location
# op.model_rotation = aob.rotation_euler
# op.target_object = aob.name
# op.material_target_slot = aob.active_material_index
# op.replace_resolution = True
# print('operator res ', resolution)
# op.resolution = resolution
# class OBJECT_MT_blenderkit_resolution_menu(bpy.types.Menu):
# bl_label = "Replace Asset Resolution"
# bl_idname = "OBJECT_MT_blenderkit_resolution_menu"
#
# def draw(self, context):
# ui_props = context.scene.blenderkitUI
#
# # sr = bpy.context.window_manager['search results']
# # sr = bpy.context.window_manager['search results']
# # asset_data = sr[ui_props.active_index]
#
# for k in resolutions.resolution_props_to_server.keys():
# draw_asset_resolution_replace(self, context, k)
class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu):
bl_label = "Asset options:"
bl_idname = "OBJECT_MT_blenderkit_asset_menu"
def draw(self, context):
ui_props = context.scene.blenderkitUI
sr = bpy.context.window_manager['search results']
asset_data = sr[ui_props.active_index]
draw_asset_context_menu(self.layout, context, asset_data, from_panel=False)
def numeric_to_str(s):
if s:
s = str(round(s))
else:
s = '-'
return s
def push_op_left(layout, strength =5):
for a in range(0, strength):
def label_or_url(layout, text='', tooltip='', url='', icon_value=None, icon=None):
'''automatically switch between different layout options for linking or tooltips'''
layout.emboss = 'NONE'
if url != '':
if icon:
op = layout.operator('wm.blenderkit_url', text=text, icon=icon)
elif icon_value:
op = layout.operator('wm.blenderkit_url', text=text, icon_value=icon_value)
else:
op = layout.operator('wm.blenderkit_url', text=text)
op.url = url
op.tooltip = tooltip
return
if tooltip != '':
if icon:
op = layout.operator('wm.blenderkit_tooltip', text=text, icon=icon)
elif icon_value:
op = layout.operator('wm.blenderkit_tooltip', text=text, icon_value=icon_value)
else:
op = layout.operator('wm.blenderkit_tooltip', text=text)
op.tooltip = tooltip
# these are here to move the text to left, since operators can only center text by default
return
if icon:
layout.label(text=text, icon=icon)
elif icon_value:
layout.label(text=text, icon_value=icon_value)
else:
layout.label(text=text)
class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
"""Generate Cycles thumbnail for model assets"""
bl_idname = "wm.blenderkit_asset_popup"
bl_label = "BlenderKit asset popup"
@classmethod
def poll(cls, context):
return True
def draw_menu(self, context, layout):
# layout = layout.column()
draw_asset_context_menu(layout, context, self.asset_data, from_panel=False)
def draw_property(self, layout, left, right, icon=None, icon_value=None, url='', tooltip=''):
right = str(right)
row = layout.row()
split.alignment = 'RIGHT'
split.label(text=left)
split = split.split()
# split for questionmark:
if url != '':
label_or_url(split, text=right, tooltip=tooltip, url=url, icon_value=icon_value, icon=icon)
# additional questionmark icon where it's important?
if url != '':
split = split.split()
op = split.operator('wm.blenderkit_url', text='', icon='QUESTION')
op.url = url
op.tooltip = tooltip
def draw_asset_parameter(self, layout, key='', pretext=''):
parameter = utils.get_param(self.asset_data, key)
if parameter == None:
return
if type(parameter) == int:
parameter = f"{parameter:,d}"
elif type(parameter) == float:
parameter = f"{parameter:,.1f}"
self.draw_property(layout, pretext, parameter)
if len(self.asset_data['description']) > 0:
box = layout.box()
link_more = utils.label_multiline(box, self.asset_data['description'], width=width, max_lines = 10)
if link_more:
row = box.row()
row.scale_y = 2
op = row.operator('wm.blenderkit_url', text='See full description', icon='URL')
op.url = paths.get_asset_gallery_url(self.asset_data['assetBaseId'])
op.tooltip = 'Read full description on website'
def draw_properties(self, layout, width=250):
if type(self.asset_data['parameters']) == list:
mparams = utils.params_to_dict(self.asset_data['parameters'])
else:
mparams = self.asset_data['parameters']
pcoll = icons.icon_collections["main"]
box = layout.box()
box.label(text='Properties')
if self.asset_data.get('license') == 'cc_zero':
icon = pcoll['cc0']
else:
t = 'Royalty free'
icon = pcoll['royalty_free']
self.draw_property(box,
url="https://www.blenderkit.com/docs/licenses/",
tooltip='All BlenderKit assets are available for commercial use. \n' \
'Click to read more about BlenderKit licenses on the website'
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
)
if upload.can_edit_asset(asset_data=self.asset_data):
icon = pcoll[self.asset_data['verificationStatus']]
verification_status_tooltips = {
'uploading': "Your asset got stuck during upload. Probably, your file was too large "
"or your connection too slow or interrupting. If you have repeated issues, "
"please contact us and let us know, it might be a bug",
'uploaded': "Your asset uploaded successfully. Yay! If it's public, "
"it's awaiting validation. If it's private, use it",
'on_hold': "Your asset needs some (usually smaller) fixes, "
"so we can make it public for everybody."
" Please check your email to see the feedback "
"that we send to every creator personally",
'rejected': "The asset has serious quality issues, " \
"and it's probable that it might be good to start " \
"all over again or try with something simpler. " \
"You also get personal feedback into your e-mail, " \
"since we believe that together, we can all learn " \
"to become awesome 3D artists",
'deleted': "You deleted this asset",
'validated': "Your asset passed our validation process, "
"and is now available to BlenderKit users"
}
self.draw_property(box,
self.asset_data['verificationStatus'],
icon_value=icon.icon_id,
url="https://www.blenderkit.com/docs/validation-status/",
tooltip=verification_status_tooltips[self.asset_data['verificationStatus']]
)
resolution = utils.get_param(self.asset_data, 'textureResolutionMax')
ress = f"{int(round(resolution / 1024, 0))}K"
self.draw_property(box, 'Resolution', ress,
tooltip='Maximal resolution of textures in this asset.\n' \
'Most texture asset have also lower resolutions generated.\n' \
'Go to BlenderKit add-on import settings to set default resolution')
if fs and len(fs) > 2 and utils.profile_is_validator():
resolutions = ''
list.sort(fs, key=lambda f: f['fileType'])
for f in fs:
if f['fileType'].find('resolution') > -1:
resolutions += f['fileType'][11:] + ' '
resolutions = resolutions.replace('_', '.')
self.draw_asset_parameter(box, key='designer', pretext='Designer')
self.draw_asset_parameter(box, key='manufacturer', pretext='Manufacturer') # TODO make them clickable!
self.draw_asset_parameter(box, key='designCollection', pretext='Collection')
self.draw_asset_parameter(box, key='designVariant', pretext='Variant')
self.draw_asset_parameter(box, key='designYear', pretext='Design year')
self.draw_asset_parameter(box, key='faceCount', pretext='Face count')
# self.draw_asset_parameter(box, key='thumbnailScale', pretext='Preview scale')
# self.draw_asset_parameter(box, key='purePbr', pretext='Pure PBR')
# self.draw_asset_parameter(box, key='productionLevel', pretext='Readiness')
# self.draw_asset_parameter(box, key='condition', pretext='Condition')
self.draw_asset_parameter(box, key='material_style', pretext='Style')
self.draw_asset_parameter(box, key='model_style', pretext='Style')
if utils.get_param(self.asset_data, 'dimensionX'):
t = '%s×%s×%s m' % (utils.fmt_length(mparams['dimensionX']),
utils.fmt_length(mparams['dimensionY']),
utils.fmt_length(mparams['dimensionZ']))
if self.asset_data.get('filesSize'):
fs = self.asset_data['filesSize']
fsmb = fs // (1024 * 1024)
fskb = fs % 1024
if fsmb == 0:
self.draw_property(box, 'Original size', f'{fskb} KB')
else:
self.draw_property(box, 'Original size', f'{fsmb} MB')
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
# Tags section
# row = box.row()
# letters_on_row = 0
# max_on_row = width / 10
# for tag in self.asset_data['tags']:
# if tag in ('manifold', 'uv', 'non-manifold'):
# # these are sometimes accidentally stored in the lib
# continue
#
# # row.emboss='NONE'
# # we need to split wisely
# remaining_row = (max_on_row - letters_on_row) / max_on_row
# split_factor = (len(tag) / max_on_row) / remaining_row
# row = row.split(factor=split_factor)
# letters_on_row += len(tag)
# if letters_on_row > max_on_row:
# letters_on_row = len(tag)
# row = box.row()
# remaining_row = (max_on_row - letters_on_row) / max_on_row
# split_factor = (len(tag) / max_on_row) / remaining_row
# row = row.split(factor=split_factor)
#
# op = row.operator('wm')
# op = row.operator('view3d.blenderkit_search', text=tag)
# op.tooltip = f'Search items with tag {tag}'
# # build search string from description and tags:
# op.keywords = f'+tags:{tag}'
# self.draw_property(box, 'Tags', self.asset_data['tags']) #TODO make them clickable!
# Free/Full plan or private Access
plans_tooltip = 'BlenderKit has 2 plans:\n' \
' * Free plan - more than 50% of all assets\n' \
' * Full plan - unlimited access to everything\n' \
'Click to go to subscriptions page'
plans_link = 'https://www.blenderkit.com/plans/pricing/'
if self.asset_data['isPrivate']:
t = 'Private'
elif self.asset_data['isFree']:
t = 'Free plan'
icon = pcoll['free']
tooltip=plans_tooltip,
url=plans_link)
else:
t = 'Full plan'
icon = pcoll['full']
icon_value=icon.icon_id,
tooltip=plans_tooltip,
url=plans_link)
if utils.profile_is_validator():
date = self.asset_data['created'][:10]
date = f"{date[8:10]}. {date[5:7]}. {date[:4]}"
self.draw_property(box, 'Created', date)
box.separator()
def draw_author_area(self, context, layout, width=330):
self.draw_author(context, layout, width=width)
def draw_author(self, context, layout, width=330):
image_split = 0.25
text_width = width
authors = bpy.context.window_manager['bkit authors']
a = authors.get(self.asset_data['author']['id'])
if a is not None: # or a is '' or (a.get('gravatarHash') is not None and a.get('gravatarImg') is None):
row = layout.row()
author_box = row.box()
author_box.scale_y = 0.6 # get text lines closer to each other
author_box.label(text='Author') # just one extra line to give spacing
author_left.template_icon(icon_value=self.gimg.preview.icon_id, scale=7)
text_area = author_left.split()
text_width = int(text_width * (1 - image_split))
else:
text_area = author_box
author_right = text_area.column()
row = author_right.row()
col = row.column()
utils.label_multiline(col, text=a['tooltip'], width=text_width)
# check if author didn't fill any data about himself and prompt him if that's the case
if utils.user_is_owner(asset_data=self.asset_data) and a.get('aboutMe') is not None and len(
row = col.row()
row.enabled = False
row.label(text='Please introduce yourself to the community!')
op = col.operator('wm.blenderkit_url', text='Edit your profile')
op.url = 'https://www.blenderkit.com/profile'
op.tooltip = 'Edit your profile on BlenderKit webpage'
button_row = author_box.row()
button_row.scale_y = 2.0
if a.get('aboutMeUrl') is not None:
url = a['aboutMeUrl']
text = url
if len(url) > 25:
text = url[:25] + '...'
else:
url = paths.get_author_gallery_url(a['id'])
text = "Open Author's Profile"
op = button_row.operator('wm.url_open', text=text)
op.url = url
op = button_row.operator('view3d.blenderkit_search', text="Find Assets By Author")
op.esc = True
op.keywords = ''
op.author_id = self.asset_data['author']['id']
layout.emboss = 'NORMAL'
box_thumbnail = layout.box()
box_thumbnail.template_icon(icon_value=self.img.preview.icon_id, scale=width * .12)
# op = row.operator('view3d.asset_drag_drop', text='Drag & Drop from here', depress=True)
Vilem Duha
committed
# From here on, only ratings are drawn, which won't be displayed for private assets from now on.
if not self.asset_data['isPrivate']:
row = box_thumbnail.row()
row.alignment = 'EXPAND'
# display_ratings = can_display_ratings(self.asset_data)
rc = self.asset_data.get('ratingsCount')
show_rating_threshold = 0
show_rating_prompt_threshold = 5
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
if rc:
rcount = min(rc['quality'], rc['workingHours'])
else:
rcount = 0
if rcount >= show_rating_threshold or upload.can_edit_asset(asset_data=self.asset_data):
s = numeric_to_str(self.asset_data['score'])
q = numeric_to_str(self.asset_data['ratingsAverage'].get('quality'))
c = numeric_to_str(self.asset_data['ratingsAverage'].get('workingHours'))
else:
s = '-'
q = '-'
c = '-'
pcoll = icons.icon_collections["main"]
row.emboss = 'NONE'
op = row.operator('wm.blenderkit_tooltip', text=str(s), icon_value=pcoll['trophy'].icon_id)
op.tooltip = 'Asset score calculated from averaged user ratings. \n\n' \
'Score = quality × complexity × 10*\n\n *Happiness multiplier'
row.label(text=' ')
tooltip_extension = f'.\n\nRatings results are shown for assets with more than {show_rating_threshold} ratings'
op = row.operator('wm.blenderkit_tooltip', text=str(q), icon='SOLO_ON')
op.tooltip = f"Quality, average from {rc['quality']} ratings" \
f"{tooltip_extension if rcount <= show_rating_threshold else ''}"
row.label(text=' ')
op = row.operator('wm.blenderkit_tooltip', text=str(c), icon_value=pcoll['dumbbell'].icon_id)
op.tooltip = f"Complexity, average from {rc['workingHours']} ratings" \
f"{tooltip_extension if rcount <= show_rating_threshold else ''}"
if rcount <= show_rating_prompt_threshold:
box_thumbnail.alert = True
box_thumbnail.label(text=f"")
box_thumbnail.label(text=f"This asset has only {rcount} rating{'' if rcount == 1 else 's'}, please rate.")
# box_thumbnail.label(text=f"Please rate this asset.")
row = box_thumbnail.row()
row.alert = False
row.scale_y = 3
ui_props = bpy.context.scene.blenderkitUI
row.prop(ui_props, 'drag_init_button', icon='MOUSE_LMB_DRAG', text='Click / Drag from here', emboss=True)
def draw_menu_desc_author(self, context, layout, width=330):
box = layout.column()
box.emboss = 'NORMAL'
# left - tooltip & params
row = box.row()
split_left = row.split(factor=split_factor)
col = split_left.column()
width_left = int(width * split_factor)
self.draw_description(col, width=width_left)
self.draw_properties(col, width=width_left)
split_right = split_left.split()
col = split_right.column()
self.draw_menu(context, col)
self.draw_author_area(context, box, width=width)
# self.draw_author_area(context, box, width=width)
#
# col = box.column_flow(columns=2)
# self.draw_menu(context, col)
#
#
# # self.draw_description(box, width=int(width))
# self.draw_properties(box, width=int(width))
# define enum flags
def draw(self, context):
ui_props = context.scene.blenderkitUI
sr = bpy.context.window_manager['search results']
# top draggabe bar with name of the asset
top_row = layout.row()
top_drag_bar = top_row.box()
bcats = bpy.context.window_manager['bkit_categories']
cat_path = categories.get_category_path(bcats,
self.asset_data['category'])[1:]
cat_path_names = categories.get_category_name_path(bcats,
self.asset_data['category'])[1:]
aname = asset_data['displayName']
if 1:
name_row = top_drag_bar.row()
# name_row = name_row.split(factor=0.5)
# name_row = name_row.column()
# name_row = name_row.row()
for i, c in enumerate(cat_path):
cat_name = cat_path_names[i]
op = name_row.operator('view3d.blenderkit_asset_bar', text=cat_name + ' >', emboss=False)
op.do_search = True
op.keep_running = True
op.tooltip = f"Browse {cat_name} category"
op.category = c
# name_row.label(text='>')
name_row.label(text=aname)
push_op_left(name_row, strength = 3)
op = name_row.operator('view3d.close_popup_button', text='', icon = 'CANCEL')
# for i,c in enumerate(cat_path_names):
# cat_path_names[i] = c.capitalize()
# cat_path_names_string = ' > '.join(cat_path_names)
# # box.label(text=cat_path)
#
#
#
#
# # name_row.label(text=' ')
# top_drag_bar.label(text=f'{cat_path_names_string} > {aname}')
# left side
row = layout.row(align=True)
split_ratio = 0.45
split_left = row.split(factor=split_ratio)
left_column = split_left.column()
self.draw_thumbnail_box(left_column, width=int(self.width * split_ratio))
# self.draw_description(left_column, width = int(self.width*split_ratio))
# right split
split_right = split_left.split()
self.draw_menu_desc_author(context, split_right, width=int(self.width * (1 - split_ratio)))
if not utils.user_is_owner(asset_data=asset_data):
# Draw ratings, but not for owners of assets - doesn't make sense.
ratings_box = layout.box()
ratings.draw_ratings_menu(self, context, ratings_box)
# else:
# ratings_box.label('Here you should find ratings, but you can not rate your own assets ;)')
tip_box = layout.box()
tip_box.label(text=self.tip)
def execute(self, context):
wm = context.window_manager
ui_props = context.scene.blenderkitUI
ui_props.draw_tooltip = False
sr = bpy.context.window_manager['search results']
asset_data = sr[ui_props.active_index]
self.img = ui.get_large_thumbnail_image(asset_data)
utils.img_to_preview(self.img, copy_original = True)
self.asset_type = asset_data['assetType']
# self.tex = utils.get_hidden_texture(self.img)
# self.tex.update_tag()
authors = bpy.context.window_manager['bkit authors']
a = authors.get(asset_data['author']['id'])
if a is not None and a.get('gravatarImg') is not None:
self.gimg = utils.get_hidden_image(a['gravatarImg'], a['gravatarHash'])
bl_label = asset_data['name']
self.tip = search.get_random_tip()
self.tip = self.tip.replace('\n', '')
# pre-fill ratings
self.prefill_ratings()
return wm.invoke_popup(self, width=self.width)
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"""
bl_idname = "view3d.blenderkit_set_category"
bl_label = "BlenderKit Set Active Category"
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
category: bpy.props.StringProperty(
name="Category",
description="set this category active",
default="")
asset_type: bpy.props.StringProperty(
name="Asset Type",
description="asset type",
default="")
@classmethod
def poll(cls, context):
return True
def execute(self, context):
acat = bpy.context.window_manager['active_category'][self.asset_type]
if self.category == '':
acat.remove(acat[-1])
else:
acat.append(self.category)
# we have to write back to wm. Thought this should happen with original list.
bpy.context.window_manager['active_category'][self.asset_type] = acat
return {'FINISHED'}
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
class ClosePopupButton(bpy.types.Operator):
"""Visit subcategory"""
bl_idname = "view3d.close_popup_button"
bl_label = "BlenderKit close popup"
bl_options = {'REGISTER', 'INTERNAL'}
@classmethod
def poll(cls, context):
return True
def win_close(self):
VK_ESCAPE = 0x1B
ctypes.windll.user32.keybd_event(VK_ESCAPE)
print('hit escape')
return True
def mouse_trick(self,context,x,y):
# import time
context.area.tag_redraw()
w = context.window
w.cursor_warp(w.x+15,w.y+w.height-15);
# time.sleep(.12)
w.cursor_warp(x,y);
context.area.tag_redraw()
def invoke(self, context, event):