Skip to content
Snippets Groups Projects
ui.py 76.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Vilem Duha's avatar
    Vilem Duha committed
    # ##### 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)
    
        colors = importlib.reload(colors)
    
        tasks_queue = importlib.reload(tasks_queue)
    
    Vilem Duha's avatar
    Vilem Duha committed
    else:
    
        from blenderkit import paths, ratings, utils, search, upload, ui_bgl, download, bg_blender, colors, tasks_queue
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    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
    import os
    
    
    handler_2d = None
    handler_3d = None
    
    active_area = None
    active_area = None
    active_window = None
    active_region = None
    
    
    reports = []
    
    Vilem Duha's avatar
    Vilem Duha committed
    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',
    
    Vilem Duha's avatar
    Vilem Duha committed
        'on_hold': 'vs_on_hold.png',
    
        'rejected': 'vs_rejected.png'
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    }
    
    
    # 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 == active_area:
                ui_bgl.draw_text(self.text, x, y + 8, 16, self.draw_color)
    
    Vilem Duha's avatar
    Vilem Duha committed
    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
    
    
    Vilem Duha's avatar
    Vilem Duha committed
    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'])
    
    Vilem Duha's avatar
    Vilem Duha committed
                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)
    
    Vilem Duha's avatar
    Vilem Duha committed
            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':
    
    Vilem Duha's avatar
    Vilem Duha committed
                    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'])
    
    Vilem Duha's avatar
    Vilem Duha committed
            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')
    
        # 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
    
    
    Vilém Duha's avatar
    Vilém Duha committed
        if not img or max(img.size[0], img.size[1]) == 0:
    
    Vilém Duha's avatar
    Vilém Duha committed
            return;
    
        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')
    
            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)
    
        # main preview image
    
        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
    
            ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth
    
                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)
    
        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):
    
    Vilem Duha's avatar
    Vilem Duha committed
        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
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        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
    
    Vilem Duha's avatar
    Vilem Duha committed
        xtext = x
        fsize = name_height
        tcol = textcol
        for l in lines:
    
            if column_lines >= nlines:
    
    Vilem Duha's avatar
    Vilem Duha committed
                xtext += int(isizex / ncolumns)
    
                column_lines = 0
            ytext = y - column_lines * line_height - nameline_height - ttipmargin
    
    Vilem Duha's avatar
    Vilem Duha committed
            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
    
    Vilem Duha's avatar
    Vilem Duha committed
            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;
    
    
    Vilem Duha's avatar
    Vilem Duha committed
        a = context.area
    
    Vilem Duha's avatar
    Vilem Duha committed
        try:
            # self.area might throw error just by itself.
            a1 = self.area
    
    Vilem Duha's avatar
    Vilem Duha committed
            go = True
    
            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
    
    Vilem Duha's avatar
    Vilem Duha committed
        except:
            # bpy.types.SpaceView3D.draw_handler_remove(self._handle_2d, 'WINDOW')
            # bpy.types.SpaceView3D.draw_handler_remove(self._handle_3d, 'WINDOW')
            go = False
    
    Vilem Duha's avatar
    Vilem Duha committed
            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):
        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))
    
    
    
    def draw_progress(x, y, text='', percent=None, color=colors.GREEN):
    
    Vilem Duha's avatar
    Vilem Duha committed
        ui_bgl.draw_rect(x, y, percent, 5, color)
    
        ui_bgl.draw_text(text, x, y + 8, 16, color)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
    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':
    
    Vilem Duha's avatar
    Vilem Duha committed
                        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'])
    
    
    Vilem Duha's avatar
    Vilem Duha committed
            if tcom.passargs.get('downloaders'):
                for d in tcom.passargs['downloaders']:
    
    Vilem Duha's avatar
    Vilem Duha committed
                    loc = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d,
                                                                d['location'])
    
                        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)
                        else:
                            draw_downloader(loc[0], loc[1], percent=tcom.progress, img=img)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
            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()
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
    def draw_callback_2d_upload_preview(self, context):
        ui_props = context.scene.blenderkitUI
    
        props = utils.get_upload_props()
        if props != None and ui_props.draw_tooltip:
    
    Vilém Duha's avatar
    Vilém Duha committed
    
    
    Vilem Duha's avatar
    Vilem Duha committed
            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)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
    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
    
    Vilém Duha's avatar
    Vilém Duha committed
        if not ui_props.dragging and ui_props.hcount>0:
    
    Vilem Duha's avatar
    Vilem Duha committed
            search_results = s.get('search results')
    
    Vilem Duha's avatar
    Vilem Duha committed
            search_results_orig = s.get('search results orig')
    
    Vilem Duha's avatar
    Vilem Duha committed
            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:
    
    Vilem Duha's avatar
    Vilem Duha committed
                        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)
    
    Vilem Duha's avatar
    Vilem Duha committed
                    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:
    
    Vilém Duha's avatar
    Vilém Duha committed
                            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)
    
    
    Vilem Duha's avatar
    Vilem Duha committed
                            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:
    
    Vilém Duha's avatar
    Vilém Duha committed
                            ui_bgl.draw_rect(x, y, ui_props.thumb_size, ui_props.thumb_size, white)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
                        result = search_results[index]
                        if result['downloaded'] > 0:
                            ui_bgl.draw_rect(x, y - 2, int(w * 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:
    
    Vilem Duha's avatar
    Vilem Duha committed
                            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')]
    
    Vilem Duha's avatar
    Vilem Duha committed
                        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)
    
    Vilem Duha's avatar
    Vilem Duha committed
            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)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
            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):
    
    Vilem Duha's avatar
    Vilem Duha committed
                    r = sr[ui_props.active_index]
                    tpath = os.path.join(directory, r['thumbnail'])
    
                    img = bpy.data.images.get(iname)
                    if img == None or img.filepath != tpath:
    
                        # TODO replace it with a function
                        if os.path.exists(tpath):
    
    Vilem Duha's avatar
    Vilem Duha committed
    
                            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)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        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;
    
    
    Vilem Duha's avatar
    Vilem Duha committed
        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)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        # 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()
    
            snapped_rotation = snapped_normal.to_track_quat('Z', 'Y').to_euler()
    
    
    
    Vilem Duha's avatar
    Vilem Duha committed
            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
            else:
                randoffset = props.offset_rotation_amount  # we don't rotate this way on walls and ceilings. + math.pi
            # snapped_rotation.z += math.pi + (random.random() - 0.5) * .2
    
        else:
            snapped_rotation = mathutils.Quaternion((0, 0, 0, 0)).to_euler()
    
        snapped_rotation.rotate_axis('Z', randoffset)
    
        return has_hit, snapped_location, snapped_normal, snapped_rotation, face_index, object, matrix
    
    
    def floor_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 * 1000)
    
        # various intersection plane normals are needed for corner cases that might actually happen quite often - in front and side view.
        # default plane normal is scene floor.
        plane_normal = (0, 0, 1)
        if math.isclose(view_vector.x, 0, abs_tol=1e-4) and math.isclose(view_vector.z, 0, abs_tol=1e-4):
            plane_normal = (0, 1, 0)
        elif math.isclose(view_vector.z, 0, abs_tol=1e-4):
            plane_normal = (1, 0, 0)
    
        snapped_location = mathutils.geometry.intersect_line_plane(ray_origin, ray_target, (0, 0, 0), plane_normal,
                                                                   False)
        if snapped_location != None:
            has_hit = True
            snapped_normal = Vector((0, 0, 1))
            face_index = None
            object = None
            matrix = None
            snapped_rotation = snapped_normal.to_track_quat('Z', 'Y').to_euler()
            props = bpy.context.scene.blenderkit_models
            if props.randomize_rotation:
                randoffset = props.offset_rotation_amount + math.pi + (
                        random.random() - 0.5) * props.randomize_rotation_amount
            else:
                randoffset = props.offset_rotation_amount + math.pi
            snapped_rotation.rotate_axis('Z', randoffset)
    
        return has_hit, snapped_location, snapped_normal, snapped_rotation, face_index, object, matrix