Newer
Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
if "bpy" in locals():
import importlib
paths = importlib.reload(paths)
ratings = importlib.reload(ratings)
utils = importlib.reload(utils)
search = importlib.reload(search)
upload = importlib.reload(upload)
ui_bgl = importlib.reload(ui_bgl)
download = importlib.reload(download)
bg_blender = importlib.reload(bg_blender)
tasks_queue = importlib.reload(ui_panels)
from blenderkit import paths, ratings, utils, search, upload, ui_bgl, download, bg_blender, colors, tasks_queue, ui_panels
import bpy
import math, random
from bpy.props import (
BoolProperty,
StringProperty
)
from bpy_extras import view3d_utils
import mathutils
from mathutils import Vector
import time
handler_2d = None
handler_3d = None
active_area_pointer = None
active_window_pointer = None
active_region_pointer = None
mappingdict = {
'MODEL': 'model',
'SCENE': 'scene',
'MATERIAL': 'material',
'TEXTURE': 'texture',
'BRUSH': 'brush'
}
verification_icons = {
'ready': 'vs_ready.png',
'deleted': 'vs_deleted.png',
'uploaded': 'vs_uploaded.png',
'uploading': 'vs_uploading.png',
'validated': None,
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
}
# class UI_region():
# def _init__(self, parent = None, x = 10,y = 10 , width = 10, height = 10, img = None, col = None):
def get_approximate_text_width(st):
size = 10
for s in st:
if s in 'i|':
size += 2
elif s in ' ':
size += 4
elif s in 'sfrt':
size += 5
elif s in 'ceghkou':
size += 6
elif s in 'PadnBCST3E':
size += 7
elif s in 'GMODVXYZ':
size += 8
elif s in 'w':
size += 9
elif s in 'm':
size += 10
else:
size += 7
return size # Convert to picas
def add_report(text='', timeout=5, color=colors.GREEN):
global reports
# check for same reports and just make them longer by the timeout.
for old_report in reports:
if old_report.text == text:
old_report.timeout = old_report.age + timeout
return
report = Report(text=text, timeout=timeout, color=color)
reports.append(report)
class Report():
def __init__(self, text='', timeout=5, color=(.5, 1, .5, 1)):
self.text = text
self.timeout = timeout
self.start_time = time.time()
self.color = color
self.draw_color = color
self.age = 0
def fade(self):
fade_time = 1
self.age = time.time() - self.start_time
if self.age + fade_time > self.timeout:
alpha_multiplier = (self.timeout - self.age) / fade_time
self.draw_color = (self.color[0], self.color[1], self.color[2], self.color[3] * alpha_multiplier)
if self.age > self.timeout:
global reports
try:
reports.remove(self)
except Exception as e:
pass;
def draw(self, x, y):
if bpy.context.area.as_pointer() == active_area_pointer:
ui_bgl.draw_text(self.text, x, y + 8, 16, self.draw_color)
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
def get_asset_under_mouse(mousex, mousey):
s = bpy.context.scene
ui_props = bpy.context.scene.blenderkitUI
r = bpy.context.region
search_results = s.get('search results')
if search_results is not None:
h_draw = min(ui_props.hcount, math.ceil(len(search_results) / ui_props.wcount))
for b in range(0, h_draw):
w_draw = min(ui_props.wcount, len(search_results) - b * ui_props.wcount - ui_props.scrolloffset)
for a in range(0, w_draw):
x = ui_props.bar_x + a * (ui_props.margin + ui_props.thumb_size) + ui_props.margin + ui_props.drawoffset
y = ui_props.bar_y - ui_props.margin - (ui_props.thumb_size + ui_props.margin) * (b + 1)
w = ui_props.thumb_size
h = ui_props.thumb_size
if x < mousex < x + w and y < mousey < y + h:
return a + ui_props.wcount * b + ui_props.scrolloffset
# return search_results[a]
return -3
def draw_bbox(location, rotation, bbox_min, bbox_max, progress=None, color=(0, 1, 0, 1)):
ui_props = bpy.context.scene.blenderkitUI
rotation = mathutils.Euler(rotation)
smin = Vector(bbox_min)
smax = Vector(bbox_max)
v0 = Vector(smin)
v1 = Vector((smax.x, smin.y, smin.z))
v2 = Vector((smax.x, smax.y, smin.z))
v3 = Vector((smin.x, smax.y, smin.z))
v4 = Vector((smin.x, smin.y, smax.z))
v5 = Vector((smax.x, smin.y, smax.z))
v6 = Vector((smax.x, smax.y, smax.z))
v7 = Vector((smin.x, smax.y, smax.z))
arrowx = smin.x + (smax.x - smin.x) / 2
arrowy = smin.y - (smax.x - smin.x) / 2
v8 = Vector((arrowx, arrowy, smin.z))
vertices = [v0, v1, v2, v3, v4, v5, v6, v7, v8]
for v in vertices:
v.rotate(rotation)
v += Vector(location)
lines = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [0, 4], [1, 5],
[2, 6], [3, 7], [0, 8], [1, 8]]
ui_bgl.draw_lines(vertices, lines, color)
if progress != None:
color = (color[0], color[1], color[2], .2)
progress = progress * .01
vz0 = (v4 - v0) * progress + v0
vz1 = (v5 - v1) * progress + v1
vz2 = (v6 - v2) * progress + v2
vz3 = (v7 - v3) * progress + v3
rects = (
(v0, v1, vz1, vz0),
(v1, v2, vz2, vz1),
(v2, v3, vz3, vz2),
(v3, v0, vz0, vz3))
for r in rects:
ui_bgl.draw_rect_3d(r, color)
def get_rating_scalevalues(asset_type):
xs = []
if asset_type == 'model':
scalevalues = (0.5, 1, 2, 5, 10, 25, 50, 100, 250)
for v in scalevalues:
a = math.log2(v)
x = (a + 1) * (1. / 9.)
xs.append(x)
else:
scalevalues = (0.2, 1, 2, 3, 4, 5)
for v in scalevalues:
a = v
x = v / 5.
xs.append(x)
return scalevalues, xs
def draw_ratings_bgl():
# return;
ui = bpy.context.scene.blenderkitUI
rating_possible, rated, asset, asset_data = is_rating_possible()
if rating_possible: # (not rated or ui_props.rating_menu_on):
bkit_ratings = asset.bkit_ratings
bgcol = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.inner
textcol = (1, 1, 1, 1)
r = bpy.context.region
font_size = int(ui.rating_ui_scale * 20)
if ui.rating_button_on:
img = utils.get_thumbnail('star_white.png')
ui_bgl.draw_image(ui.rating_x,
ui.rating_y - ui.rating_button_width,
ui.rating_button_width,
ui.rating_button_width,
img, 1)
# if ui_props.asset_type != 'BRUSH':
# thumbnail_image = props.thumbnail
# else:
# b = utils.get_active_brush()
# thumbnail_image = b.icon_filepath
directory = paths.get_temp_dir('%s_search' % asset_data['assetType'])
tpath = os.path.join(directory, asset_data['thumbnail_small'])
img = utils.get_hidden_image(tpath, 'rating_preview')
ui_bgl.draw_image(ui.rating_x + ui.rating_button_width,
ui.rating_y - ui.rating_button_width,
ui.rating_button_width,
ui.rating_button_width,
img, 1)
# ui_bgl.draw_text( 'rate asset %s' % asset_data['name'],r.width - rating_button_width + margin, margin, font_size)
return
ui_bgl.draw_rect(ui.rating_x,
ui.rating_y - ui.rating_ui_height - 2 * ui.margin - font_size,
ui.rating_ui_width + ui.margin,
ui.rating_ui_height + 2 * ui.margin + font_size,
bgcol)
if asset_data['assetType'] == 'model':
ui_img_name = 'rating_ui.png'
else:
ui_img_name = 'rating_ui_empty.png'
text = 'Try to estimate how many hours it would take for a professional artist to create this asset:'
tx = ui.rating_x + ui.workhours_bar_x
# draw_text_block(x=tx, y=ui.rating_y, width=80, font_size=20, line_height=15, text=text, color=colors.TEXT)
img = utils.get_thumbnail(ui_img_name)
ui_bgl.draw_image(ui.rating_x,
ui.rating_y - ui.rating_ui_height - 2 * ui.margin,
ui.rating_ui_width,
ui.rating_ui_height,
img, 1)
img = utils.get_thumbnail('star_white.png')
quality = bkit_ratings.rating_quality
work_hours = bkit_ratings.rating_work_hours
for a in range(0, quality):
ui_bgl.draw_image(ui.rating_x + ui.quality_stars_x + a * ui.star_size,
ui.rating_y - ui.rating_ui_height + ui.quality_stars_y,
ui.star_size,
ui.star_size,
img, 1)
img = utils.get_thumbnail('bar_slider.png')
# for a in range(0,11):
if work_hours > 0.2:
if asset_data['assetType'] == 'model':
complexity = math.log2(work_hours) + 2 # real complexity
complexity = (1. / 9.) * (complexity - 1) * ui.workhours_bar_x_max
else:
complexity = work_hours / 5 * ui.workhours_bar_x_max
ui_bgl.draw_image(
ui.rating_x + ui.workhours_bar_x + int(
complexity),
ui.rating_y - ui.rating_ui_height + ui.workhours_bar_y,
ui.workhours_bar_slider_size,
ui.workhours_bar_slider_size, img, 1)
ui_bgl.draw_text(
str(round(work_hours, 1)),
ui.rating_x + ui.workhours_bar_x - 50,
ui.rating_y - ui.rating_ui_height + ui.workhours_bar_y + 10, font_size)
# (0.5,1,2,4,8,16,32,64,128,256)
# ratings have to be different for models and brushes+materials.
scalevalues, xs = get_rating_scalevalues(asset_data['assetType'])
for v, x in zip(scalevalues, xs):
ui_bgl.draw_rect(ui.rating_x + ui.workhours_bar_x + int(
x * ui.workhours_bar_x_max) - 1 + ui.workhours_bar_slider_size / 2,
ui.rating_y - ui.rating_ui_height + ui.workhours_bar_y,
2,
5,
textcol)
ui_bgl.draw_text(str(v),
ui.rating_x + ui.workhours_bar_x + int(
x * ui.workhours_bar_x_max),
ui.rating_y - ui.rating_ui_height + ui.workhours_bar_y - 30,
font_size)
if work_hours > 0.2 and quality > 0.2:
text = 'Thanks for rating asset %s' % asset_data['name']
else:
text = 'Rate asset %s.' % asset_data['name']
ui_bgl.draw_text(text,
ui.rating_x,
ui.rating_y - ui.margin - font_size,
font_size)
def draw_text_block(x=0, y=0, width=40, font_size=10, line_height=15, text='', color=colors.TEXT):
lines = text.split('\n')
nlines = []
for l in lines:
nlines.extend(search.split_subs(l, ))
column_lines = 0
for l in nlines:
ytext = y - column_lines * line_height
column_lines += 1
ui_bgl.draw_text(l, x, ytext, font_size, color)
def draw_tooltip(x, y, text='', author='', img=None, gravatar=None):
region = bpy.context.region
scale = bpy.context.preferences.view.ui_scale
t = time.time()
ttipmargin = 5
textmargin = 10
font_height = int(12 * scale)
line_height = int(15 * scale)
nameline_height = int(23 * scale)
lines = text.split('\n')
alines = author.split('\n')
ncolumns = 2
# nlines = math.ceil((len(lines) - 1) / ncolumns)
nlines = max(len(lines) - 1, len(alines)) # math.ceil((len(lines) - 1) / ncolumns)
texth = line_height * nlines + nameline_height
if not img or max(img.size[0], img.size[1]) == 0:
isizex = int(512 * scale * img.size[0] / max(img.size[0], img.size[1]))
isizey = int(512 * scale * img.size[1] / max(img.size[0], img.size[1]))
estimated_height = 2 * ttipmargin + textmargin + isizey
if estimated_height > y:
scaledown = y / (estimated_height)
scale *= scaledown
# we need to scale these down to have correct size if the tooltip wouldn't fit.
font_height = int(12 * scale)
line_height = int(15 * scale)
nameline_height = int(23 * scale)
lines = text.split('\n')
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
texth = line_height * nlines + nameline_height
isizex = int(512 * scale * img.size[0] / max(img.size[0], img.size[1]))
isizey = int(512 * scale * img.size[1] / max(img.size[0], img.size[1]))
name_height = int(18 * scale)
x += 2 * ttipmargin
y -= 2 * ttipmargin
width = isizex + 2 * ttipmargin
properties_width = 0
for r in bpy.context.area.regions:
if r.type == 'UI':
properties_width = r.width
x = min(x + width, region.width - properties_width) - width
bgcol = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.inner
bgcol1 = (bgcol[0], bgcol[1], bgcol[2], .6)
textcol = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.text
textcol = (textcol[0], textcol[1], textcol[2], 1)
textcol_mild = (textcol[0] * .8, textcol[1] * .8, textcol[2] * .8, 1)
textcol_strong = (textcol[0] * 1.3, textcol[1] * 1.3, textcol[2] * 1.3, 1)
white = (1, 1, 1, .1)
ui_bgl.draw_rect(x - ttipmargin,
y - 2 * ttipmargin - isizey,
isizex + ttipmargin * 2,
2 * ttipmargin + isizey,
bgcol)
ui_bgl.draw_image(x, y - isizey - ttipmargin, isizex, isizey, img, 1)
# text overlay background
ui_bgl.draw_rect(x - ttipmargin,
y - 2 * ttipmargin - isizey,
isizex + ttipmargin * 2,
2 * ttipmargin + texth,
bgcol1)
# draw gravatar
gsize = 40
if gravatar is not None:
# ui_bgl.draw_image(x + isizex - gsize - textmargin, y - isizey + texth - gsize - nameline_height - textmargin,
# gsize, gsize, gravatar, 1)
ui_bgl.draw_image(x + isizex / 2 + textmargin, y - isizey + texth - gsize - nameline_height - textmargin,
gsize, gsize, gravatar, 1)
column_lines = -1 # start minus one for the name
xtext = x + textmargin
fsize = name_height
tcol = textcol
for l in lines:
ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth
if i == 0:
ytext = y - name_height + 5 - isizey + texth - textmargin
elif i == len(lines) - 1:
ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth
tcol = textcol
tsize = font_height
else:
if l[:4] == 'Tip:':
tcol = textcol_strong
fsize = font_height
i += 1
ui_bgl.draw_text(l, xtext, ytext, fsize, tcol)
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
xtext += int(isizex / ncolumns)
column_lines = 1
for l in alines:
if gravatar is not None:
if column_lines == 1:
xtext += gsize + textmargin
if column_lines == 4:
xtext -= gsize + textmargin
ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth
if i == 0:
ytext = y - name_height + 5 - isizey + texth - textmargin
elif i == len(lines) - 1:
ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth
tcol = textcol
tsize = font_height
else:
if l[:4] == 'Tip:':
tcol = textcol_strong
fsize = font_height
i += 1
column_lines += 1
ui_bgl.draw_text(l, xtext, ytext, fsize, tcol)
# for l in lines:
# if column_lines >= nlines:
# xtext += int(isizex / ncolumns)
# column_lines = 0
# ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth
# if i == 0:
# ytext = y - name_height + 5 - isizey + texth - textmargin
# elif i == len(lines) - 1:
# ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth
# tcol = textcol
# tsize = font_height
# else:
# if l[:4] == 'Tip:':
# tcol = textcol_strong
# fsize = font_height
# i += 1
# column_lines += 1
# ui_bgl.draw_text(l, xtext, ytext, fsize, tcol)
t = time.time()
def draw_tooltip_old(x, y, text='', author='', img=None):
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
region = bpy.context.region
scale = bpy.context.preferences.view.ui_scale
t = time.time()
ttipmargin = 10
font_height = int(12 * scale)
line_height = int(15 * scale)
nameline_height = int(23 * scale)
lines = text.split('\n')
ncolumns = 2
nlines = math.ceil((len(lines) - 1) / ncolumns)
texth = line_height * nlines + nameline_height
isizex = int(512 * scale * img.size[0] / max(img.size[0], img.size[1]))
isizey = int(512 * scale * img.size[1] / max(img.size[0], img.size[1]))
estimated_height = texth + 3 * ttipmargin + isizey
if estimated_height > y:
scaledown = y / (estimated_height)
scale *= scaledown
# we need to scale these down to have correct size if the tooltip wouldn't fit.
font_height = int(12 * scale)
line_height = int(15 * scale)
nameline_height = int(23 * scale)
lines = text.split('\n')
ncolumns = 2
nlines = math.ceil((len(lines) - 1) / ncolumns)
texth = line_height * nlines + nameline_height
isizex = int(512 * scale * img.size[0] / max(img.size[0], img.size[1]))
isizey = int(512 * scale * img.size[1] / max(img.size[0], img.size[1]))
name_height = int(18 * scale)
x += 2 * ttipmargin
y -= 2 * ttipmargin
width = isizex + 2 * ttipmargin
properties_width = 0
for r in bpy.context.area.regions:
if r.type == 'UI':
properties_width = r.width
x = min(x + width, region.width - properties_width) - width
bgcol = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.inner
textcol = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.text
textcol = (textcol[0], textcol[1], textcol[2], 1)
textcol1 = (textcol[0] * .8, textcol[1] * .8, textcol[2] * .8, 1)
white = (1, 1, 1, .1)
ui_bgl.draw_rect(x - ttipmargin,
y - texth - 2 * ttipmargin - isizey,
isizex + ttipmargin * 2,
texth + 3 * ttipmargin + isizey,
bgcol)
i = 0
column_lines = -1 # start minus one for the name
xtext = x
fsize = name_height
tcol = textcol
for l in lines:
if column_lines >= nlines:
column_lines = 0
ytext = y - column_lines * line_height - nameline_height - ttipmargin
if i == 0:
ytext = y - name_height + 5
elif i == len(lines) - 1:
ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin
tcol = textcol
tsize = font_height
else:
if l[:5] == 'tags:':
tcol = textcol1
fsize = font_height
i += 1
ui_bgl.draw_text(l, xtext, ytext, fsize, tcol)
t = time.time()
ui_bgl.draw_image(x, y - texth - isizey - ttipmargin, isizex, isizey, img, 1)
def draw_callback_2d(self, context):
if not utils.guard_from_crash():
return;
Vilém Duha
committed
w = context.window
try:
# self.area might throw error just by itself.
a1 = self.area
Vilém Duha
committed
w1 = self.window
if len(a.spaces[0].region_quadviews) > 0:
# print(dir(bpy.context.region_data))
# print('quad', a.spaces[0].region_3d, a.spaces[0].region_quadviews[0])
if a.spaces[0].region_3d != context.region_data:
go = False
except:
# bpy.types.SpaceView3D.draw_handler_remove(self._handle_2d, 'WINDOW')
# bpy.types.SpaceView3D.draw_handler_remove(self._handle_3d, 'WINDOW')
go = False
Vilém Duha
committed
if go and a == a1 and w == w1:
props = context.scene.blenderkitUI
if props.down_up == 'SEARCH':
draw_ratings_bgl()
draw_callback_2d_search(self, context)
elif props.down_up == 'UPLOAD':
draw_callback_2d_upload_preview(self, context)
def draw_downloader(x, y, percent=0, img=None, text= ''):
if img is not None:
ui_bgl.draw_image(x, y, 50, 50, img, .5)
ui_bgl.draw_rect(x, y, 50, int(0.5 * percent), (.2, 1, .2, .3))
ui_bgl.draw_rect(x - 3, y - 3, 6, 6, (1, 0, 0, .3))
# if asset_data is not None:
# ui_bgl.draw_text(asset_data['name'], x, y, colors.TEXT)
# ui_bgl.draw_text(asset_data['filesSize'])
if text:
ui_bgl.draw_text(text, x, y - 15,12, colors.TEXT)
#asset_data and asset_data.get('filesSize'):
# fs = asset_data['filesSize']
# fsmb = fs // (1024 * 1024)
# fskb = fs % 1024
# if fsmb == 0:
# t += 'files size: %iKB\n' % fskb
# else:
# t += 'files size: %iMB %iKB\n' % (fsmb, fskb)
def draw_progress(x, y, text='', percent=None, color=colors.GREEN):
ui_bgl.draw_text(text, x, y + 8, 16, color)
def draw_callback_3d_progress(self, context):
# 'star trek' mode gets here, blocked by now ;)
for threaddata in download.download_threads:
asset_data = threaddata[1]
tcom = threaddata[2]
if tcom.passargs.get('downloaders'):
for d in tcom.passargs['downloaders']:
if asset_data['assetType'] == 'model':
draw_bbox(d['location'], d['rotation'], asset_data['bbox_min'], asset_data['bbox_max'],
progress=tcom.progress)
def draw_callback_2d_progress(self, context):
green = (.2, 1, .2, .3)
offset = 0
row_height = 35
ui = bpy.context.scene.blenderkitUI
x = ui.reports_x
y = ui.reports_y
index = 0
for threaddata in download.download_threads:
asset_data = threaddata[1]
tcom = threaddata[2]
directory = paths.get_temp_dir('%s_search' % asset_data['assetType'])
tpath = os.path.join(directory, asset_data['thumbnail_small'])
img = utils.get_hidden_image(tpath, asset_data['id'])
if tcom.passargs.get('downloaders'):
for d in tcom.passargs['downloaders']:
loc = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d,
d['location'])
if loc is not None:
if asset_data['assetType'] == 'model':
# models now draw with star trek mode, no need to draw percent for the image.
draw_downloader(loc[0], loc[1], percent=tcom.progress, img=img, text=tcom.report)
draw_downloader(loc[0], loc[1], percent=tcom.progress, img=img, text=tcom.report)
else:
draw_progress(x, y - index * 30, text='downloading %s' % asset_data['name'],
percent=tcom.progress)
index += 1
for process in bg_blender.bg_processes:
tcom = process[1]
draw_progress(x, y - index * 30, '%s' % tcom.lasttext,
tcom.progress)
index += 1
global reports
for report in reports:
report.draw(x, y - index * 30)
index += 1
report.fade()
def draw_callback_2d_upload_preview(self, context):
ui_props = context.scene.blenderkitUI
props = utils.get_upload_props()
#assets which don't need asset preview
if ui_props.asset_type =='HDR':
return
if ui_props.asset_type != 'BRUSH':
ui_props.thumbnail_image = props.thumbnail
else:
b = utils.get_active_brush()
ui_props.thumbnail_image = b.icon_filepath
img = utils.get_hidden_image(ui_props.thumbnail_image, 'upload_preview')
draw_tooltip(ui_props.bar_x, ui_props.bar_y, text=ui_props.tooltip, img=img)
def is_upload_old(asset_data):
'''
estimates if the asset is far too long in the 'uploaded' state
This returns the number of days the validation is over the limit.
'''
date_time_str = asset_data["created"][:10]
# date_time_str = 'Jun 28 2018 7:40AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d')
today = date_time_obj.today()
age = today - date_time_obj
old = datetime.timedelta(days=7)
if age > old:
return (age.days - old.days)
return 0
def draw_callback_2d_search(self, context):
s = bpy.context.scene
ui_props = context.scene.blenderkitUI
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
r = self.region
# hc = bpy.context.preferences.themes[0].view_3d.space.header
# hc = bpy.context.preferences.themes[0].user_interface.wcol_menu_back.inner
# hc = (hc[0], hc[1], hc[2], .2)
hc = (1, 1, 1, .07)
# grey1 = (hc.r * .55, hc.g * .55, hc.b * .55, 1)
grey2 = (hc[0] * .8, hc[1] * .8, hc[2] * .8, .5)
# grey1 = (hc.r, hc.g, hc.b, 1)
white = (1, 1, 1, 0.2)
green = (.2, 1, .2, .7)
highlight = bpy.context.preferences.themes[0].user_interface.wcol_menu_item.inner_sel
highlight = (1, 1, 1, .2)
# highlight = (1, 1, 1, 0.8)
# background of asset bar
# if ui_props.hcount>0:
# #this fixes a draw issue introduced in blender 2.91. draws a very small version of the image to avoid problems
# # with alpha. Not sure why this works.
# img = utils.get_thumbnail('arrow_left.png')
# ui_bgl.draw_image(0, 0, 1,
# 1,
# img,
# 1)
if not ui_props.dragging and ui_props.hcount > 0 and ui_props.wcount>0:
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
if search_results == None:
return
h_draw = min(ui_props.hcount, math.ceil(len(search_results) / ui_props.wcount))
if ui_props.wcount > len(search_results):
bar_width = len(search_results) * (ui_props.thumb_size + ui_props.margin) + ui_props.margin
else:
bar_width = ui_props.bar_width
row_height = ui_props.thumb_size + ui_props.margin
ui_bgl.draw_rect(ui_props.bar_x, ui_props.bar_y - ui_props.bar_height, bar_width,
ui_props.bar_height, hc)
if search_results is not None:
if ui_props.scrolloffset > 0 or ui_props.wcount * ui_props.hcount < len(search_results):
ui_props.drawoffset = 35
else:
ui_props.drawoffset = 0
if ui_props.wcount * ui_props.hcount < len(search_results):
# arrows
arrow_y = ui_props.bar_y - int((ui_props.bar_height + ui_props.thumb_size) / 2) + ui_props.margin
if ui_props.scrolloffset > 0:
if ui_props.active_index == -2:
ui_bgl.draw_rect(ui_props.bar_x, ui_props.bar_y - ui_props.bar_height, 25,
ui_props.bar_height, highlight)
img = utils.get_thumbnail('arrow_left.png')
ui_bgl.draw_image(ui_props.bar_x, arrow_y, 25,
ui_props.thumb_size,
img,
1)
if search_results_orig['count'] - ui_props.scrolloffset > (ui_props.wcount * ui_props.hcount) + 1:
if ui_props.active_index == -1:
ui_bgl.draw_rect(ui_props.bar_x + ui_props.bar_width - 25,
ui_props.bar_y - ui_props.bar_height, 25,
ui_props.bar_height,
highlight)
img1 = utils.get_thumbnail('arrow_right.png')
ui_bgl.draw_image(ui_props.bar_x + ui_props.bar_width - 25,
arrow_y, 25,
ui_props.thumb_size, img1, 1)
for b in range(0, h_draw):
w_draw = min(ui_props.wcount, len(search_results) - b * ui_props.wcount - ui_props.scrolloffset)
y = ui_props.bar_y - (b + 1) * (row_height)
for a in range(0, w_draw):
x = ui_props.bar_x + a * (
ui_props.margin + ui_props.thumb_size) + ui_props.margin + ui_props.drawoffset
#
index = a + ui_props.scrolloffset + b * ui_props.wcount
iname = utils.previmg_name(index)
img = bpy.data.images.get(iname)
if img is not None and img.size[0] > 0 and img.size[1] > 0:
w = int(ui_props.thumb_size * img.size[0] / max(img.size[0], img.size[1]))
h = int(ui_props.thumb_size * img.size[1] / max(img.size[0], img.size[1]))
crop = (0, 0, 1, 1)
if img.size[0] > img.size[1]:
offset = (1 - img.size[1] / img.size[0]) / 2
crop = (offset, 0, 1 - offset, 1)
ui_bgl.draw_image(x, y, w, w, img, 1,
crop=crop)
if index == ui_props.active_index:
ui_bgl.draw_rect(x - ui_props.highlight_margin, y - ui_props.highlight_margin,
w + 2 * ui_props.highlight_margin, w + 2 * ui_props.highlight_margin,
highlight)
# if index == ui_props.active_index:
# ui_bgl.draw_rect(x - highlight_margin, y - highlight_margin,
# w + 2*highlight_margin, h + 2*highlight_margin , highlight)
else:
ui_bgl.draw_rect(x, y, ui_props.thumb_size, ui_props.thumb_size, white)
#code to inform validators that the validation is waiting too long and should be done asap
if result['verificationStatus'] == 'uploaded':
if utils.profile_is_validator():
over_limit = is_upload_old(result)
if over_limit:
redness = min(over_limit*.05,0.5)
red = (1, 0, 0, redness)
ui_bgl.draw_rect(x, y, ui_props.thumb_size, ui_props.thumb_size, red)
ui_bgl.draw_rect(x, y , int(ui_props.thumb_size * result['downloaded'] / 100.0), 2, green)
# object type icons - just a test..., adds clutter/ not so userfull:
# icons = ('type_finished.png', 'type_template.png', 'type_particle_system.png')
if (result.get('canDownload', True)) == 0:
img = utils.get_thumbnail('locked.png')
ui_bgl.draw_image(x + 2, y + 2, 24, 24, img, 1)
v_icon = verification_icons[result.get('verificationStatus', 'validated')]
if v_icon is not None:
img = utils.get_thumbnail(v_icon)
ui_bgl.draw_image(x + ui_props.thumb_size - 26, y + 2, 24, 24, img, 1)
# if user_preferences.api_key == '':
# report = 'Register on BlenderKit website to upload your own assets.'
# ui_bgl.draw_text(report, ui_props.bar_x + ui_props.margin,
# ui_props.bar_y - 25 - ui_props.margin - ui_props.bar_height, 15)
# elif len(search_results) == 0:
# report = 'BlenderKit - No matching results found.'
# ui_bgl.draw_text(report, ui_props.bar_x + ui_props.margin,
# ui_props.bar_y - 25 - ui_props.margin, 15)
s = bpy.context.scene
props = utils.get_search_props()
# if props.report != '' and props.is_searching or props.search_error:
# ui_bgl.draw_text(props.report, ui_props.bar_x,
# ui_props.bar_y - 15 - ui_props.margin - ui_props.bar_height, 15)
props = s.blenderkitUI
if props.draw_tooltip:
# TODO move this lazy loading into a function and don't duplicate through the code
iname = utils.previmg_name(ui_props.active_index, fullsize=True)
directory = paths.get_temp_dir('%s_search' % mappingdict[props.asset_type])
sr = s.get('search results')
if sr != None and -1 < ui_props.active_index < len(sr):
r = sr[ui_props.active_index]
tpath = os.path.join(directory, r['thumbnail'])
if not r['thumbnail']:
tpath = paths.get_addon_thumbnail_path('thumbnail_not_available.jpg')
img = bpy.data.images.get(iname)
if img == None or img.filepath != tpath:
# TODO replace it with a function
if os.path.exists(tpath):
if img is None:
img = bpy.data.images.load(tpath)
img.name = iname
else:
if img.filepath != tpath:
# todo replace imgs reloads with a method that forces unpack for thumbs.
if img.packed_file is not None:
img.unpack(method='USE_ORIGINAL')
img.filepath = tpath
img.reload()
img.name = iname
else:
iname = utils.previmg_name(ui_props.active_index)
img = bpy.data.images.get(iname)
if img:
img.colorspace_settings.name = 'sRGB'
gimg = None
atip = ''
if bpy.context.window_manager.get('bkit authors') is not None:
a = bpy.context.window_manager['bkit authors'].get(r['author']['id'])
if a is not None and a != '':
if a.get('gravatarImg') is not None:
gimg = utils.get_hidden_image(a['gravatarImg'], a['gravatarHash'])
atip = a['tooltip']
draw_tooltip(ui_props.mouse_x, ui_props.mouse_y, text=ui_props.tooltip, author=atip, img=img,
gravatar=gimg)
if ui_props.dragging and (
ui_props.draw_drag_image or ui_props.draw_snapped_bounds) and ui_props.active_index > -1:
iname = utils.previmg_name(ui_props.active_index)
img = bpy.data.images.get(iname)
linelength = 35
ui_bgl.draw_image(ui_props.mouse_x + linelength, ui_props.mouse_y - linelength - ui_props.thumb_size,
ui_props.thumb_size, ui_props.thumb_size, img, 1)
ui_bgl.draw_line2d(ui_props.mouse_x, ui_props.mouse_y, ui_props.mouse_x + linelength,
ui_props.mouse_y - linelength, 2, white)
def draw_callback_3d(self, context):
''' Draw snapped bbox while dragging and in the future other blenderkit related stuff. '''
if not utils.guard_from_crash():
return;
ui = context.scene.blenderkitUI
if ui.dragging and ui.asset_type == 'MODEL':
if ui.draw_snapped_bounds:
draw_bbox(ui.snapped_location, ui.snapped_rotation, ui.snapped_bbox_min, ui.snapped_bbox_max)
def mouse_raycast(context, mx, my):
r = context.region
rv3d = context.region_data
coord = mx, my
# get the ray from the viewport and mouse
view_vector = view3d_utils.region_2d_to_vector_3d(r, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(r, rv3d, coord)
ray_target = ray_origin + (view_vector * 1000000000)
vec = ray_target - ray_origin
has_hit, snapped_location, snapped_normal, face_index, object, matrix = bpy.context.scene.ray_cast(
bpy.context.view_layer.depsgraph, ray_origin, vec)
# rote = mathutils.Euler((0, 0, math.pi))
randoffset = math.pi
if has_hit:
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()