Skip to content
Snippets Groups Projects
ui_panels.py 43.1 KiB
Newer Older
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)
    download = importlib.reload(download)
    categories = importlib.reload(categories)
Vilém Duha's avatar
Vilém Duha committed
    icons = importlib.reload(icons)
Vilem Duha's avatar
Vilem Duha committed
else:
Vilém Duha's avatar
Vilém Duha committed
    from blenderkit import paths, ratings, utils, download, categories, icons
Vilem Duha's avatar
Vilem Duha committed

from bpy.types import (
    Panel
)

import bpy


def label_multiline(layout, text='', icon='NONE', width=-1):
    ''' draw a ui label, but try to split it in multiple lines.'''
    if text.strip() == '':
        return
    lines = text.split('\n')
    if width > 0:
        threshold = int(width / 5.5)
    else:
        threshold = 35
Vilem Duha's avatar
Vilem Duha committed
    li = 0
Vilem Duha's avatar
Vilem Duha committed
    for l in lines:
        while len(l) > threshold:
            i = l.rfind(' ', 0, threshold)
            if i < 1:
                i = threshold
            l1 = l[:i]
            layout.label(text=l1, icon=icon)
            icon = 'NONE'
Vilém Duha's avatar
Vilém Duha committed
            l = l[i:].lstrip()
Vilem Duha's avatar
Vilem Duha committed
            li += 1
Vilem Duha's avatar
Vilem Duha committed
            if li > maxlines:
                break;
Vilem Duha's avatar
Vilem Duha committed
        if li > maxlines:
Vilem Duha's avatar
Vilem Duha committed
            break;
        layout.label(text=l, icon=icon)
        icon = 'NONE'


#   this was moved to separate interface:

def draw_ratings(layout, context):
    # layout.operator("wm.url_open", text="Read rating instructions", icon='QUESTION').url = 'https://support.google.com/?hl=en'
    asset = utils.get_active_asset()
Vilém Duha's avatar
Vilém Duha committed
    # the following shouldn't happen at all in an optimal case,
    # this function should run only when asset was already checked to be existing
    if asset == None:
        return;
Vilem Duha's avatar
Vilem Duha committed
    bkit_ratings = asset.bkit_ratings

    ratings.draw_rating(layout, bkit_ratings, 'rating_quality', 'Quality')
    layout.separator()
    layout.prop(bkit_ratings, 'rating_work_hours')
    w = context.region.width

Vilém Duha's avatar
Vilém Duha committed
    # layout.label(text='problems')
    # layout.prop(bkit_ratings, 'rating_problems', text='')
    # layout.label(text='compliments')
    # layout.prop(bkit_ratings, 'rating_compliments', text='')
    # row = layout.row()
    # op = row.operator("object.blenderkit_rating_upload", text="Send rating", icon='URL')
    # return op
Vilem Duha's avatar
Vilem Duha committed


def draw_upload_common(layout, props, asset_type, context):
    op = layout.operator("wm.url_open", text="Read upload instructions",
                         icon='QUESTION')
    if asset_type == 'MODEL':
        op.url = paths.BLENDERKIT_MODEL_UPLOAD_INSTRUCTIONS_URL
    if asset_type == 'MATERIAL':
        op.url = paths.BLENDERKIT_MATERIAL_UPLOAD_INSTRUCTIONS_URL
    if asset_type == 'BRUSH':
        op.url = paths.BLENDERKIT_BRUSH_UPLOAD_INSTRUCTIONS_URL
Vilem Duha's avatar
Vilem Duha committed

    row = layout.row(align=True)
    if props.upload_state != '':
        label_multiline(layout, text=props.upload_state, width=context.region.width)
    if props.uploading:
        op = layout.operator('object.kill_bg_process', text="", icon='CANCEL')
        op.process_source = asset_type
        op.process_type = 'UPLOAD'
        layout = layout.column()
        layout.enabled = False

    # if props.upload_state.find('Error') > -1:
    #     layout.label(text = props.upload_state)

    if props.asset_base_id == '':
        optext = 'Upload %s' % asset_type.lower()
        op = layout.operator("object.blenderkit_upload", text=optext, icon='EXPORT')
        op.asset_type = asset_type
Vilem Duha's avatar
Vilem Duha committed

    if props.asset_base_id != '':
        op = layout.operator("object.blenderkit_upload", text='Reupload asset', icon='EXPORT')
Vilem Duha's avatar
Vilem Duha committed
        op.asset_type = asset_type
        op.reupload = True

Vilem Duha's avatar
Vilem Duha committed
        op = layout.operator("object.blenderkit_upload", text='Upload as new asset', icon='EXPORT')
        op.asset_type = asset_type
        op.reupload = False
        # layout.label(text = 'asset id, overwrite only for reuploading')
        layout.label(text='asset has a version online.')
        # row = layout.row()
        # row.enabled = False
        # row.prop(props, 'asset_base_id', icon='FILE_TICK')
        # row = layout.row()
        # row.enabled = False
        # row.prop(props, 'id', icon='FILE_TICK')
Vilem Duha's avatar
Vilem Duha committed

    layout.prop(props, 'category')
    if asset_type == 'MODEL' and props.subcategory != '':  # by now block this for other asset types.
        layout.prop(props, 'subcategory')

    layout.prop(props, 'is_private', expand=True)
    if props.is_private == 'PUBLIC':
        layout.prop(props, 'license')
Vilem Duha's avatar
Vilem Duha committed
def poll_local_panels():
    user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
    return user_preferences.panel_behaviour == 'BOTH' or user_preferences.panel_behaviour == 'LOCAL'


def prop_needed(layout, props, name, value, is_not_filled=''):
    row = layout.row()
    if value == is_not_filled:
        # row.label(text='', icon = 'ERROR')
        icon = 'ERROR'
        row.alert = True
Vilém Duha's avatar
Vilém Duha committed
        row.prop(props, name)  # , icon=icon)
        row.alert = False
Vilem Duha's avatar
Vilem Duha committed
    else:
        # row.label(text='', icon = 'FILE_TICK')
        icon = None
        row.prop(props, name)


def draw_panel_model_upload(self, context):
    ob = bpy.context.active_object
    while ob.parent is not None:
        ob = ob.parent
    props = ob.blenderkit

    layout = self.layout

    draw_upload_common(layout, props, 'MODEL', context)

    prop_needed(layout, props, 'name', props.name)

    col = layout.column()
    if props.is_generating_thumbnail:
        col.enabled = False
    prop_needed(col, props, 'thumbnail', props.has_thumbnail, False)
    if bpy.context.scene.render.engine in ('CYCLES', 'BLENDER_EEVEE'):
        col.operator("object.blenderkit_generate_thumbnail", text='Generate thumbnail', icon='IMAGE')

    # row = layout.row(align=True)
    if props.is_generating_thumbnail:
        row = layout.row(align=True)
        row.label(text=props.thumbnail_generating_state)
        op = row.operator('object.kill_bg_process', text="", icon='CANCEL')
        op.process_source = 'MODEL'
        op.process_type = 'THUMBNAILER'
    elif props.thumbnail_generating_state != '':
        label_multiline(layout, text=props.thumbnail_generating_state)

    layout.prop(props, 'description')
Vilem Duha's avatar
Vilem Duha committed
    # prop_needed(layout, props, 'style', props.style)
    # prop_needed(layout, props, 'production_level', props.production_level)
    layout.prop(props, 'style')
Vilem Duha's avatar
Vilem Duha committed
    layout.prop(props, 'production_level')

    layout.prop(props, 'condition')
    layout.prop(props, 'is_free')
    layout.prop(props, 'pbr')
    layout.label(text='design props:')
    layout.prop(props, 'manufacturer')
    layout.prop(props, 'designer')
    layout.prop(props, 'design_collection')
    layout.prop(props, 'design_variant')
    layout.prop(props, 'use_design_year')
    if props.use_design_year:
        layout.prop(props, 'design_year')

    row = layout.row()
    row.prop(props, 'work_hours')

    layout.prop(props, 'adult')


def draw_panel_scene_upload(self, context):
    s = bpy.context.scene
    props = s.blenderkit

    layout = self.layout
    if bpy.app.debug_value != -1:
        layout.label(text='Scene upload not Implemented')
        return
    draw_upload_common(layout, props, 'SCENE', context)

    #    layout = layout.column()

    # row = layout.row()

    # if props.dimensions[0] + props.dimensions[1] == 0 and props.face_count == 0:
    #     icon = 'ERROR'
    #     layout.operator("object.blenderkit_auto_tags", text='Auto fill tags', icon=icon)
    # else:
    #     layout.operator("object.blenderkit_auto_tags", text='Auto fill tags')

    prop_needed(layout, props, 'name', props.name)

    col = layout.column()
    # if props.is_generating_thumbnail:
    #     col.enabled = False
    prop_needed(col, props, 'thumbnail', props.has_thumbnail, False)
    # if bpy.context.scene.render.engine == 'CYCLES':
    #     col.operator("object.blenderkit_generate_thumbnail", text='Generate thumbnail', icon='IMAGE_COL')

    # row = layout.row(align=True)
    # if props.is_generating_thumbnail:
    #     row = layout.row(align=True)
    #     row.label(text = props.thumbnail_generating_state)
    #     op = row.operator('object.kill_bg_process', text="", icon='CANCEL')
    #     op.process_source = 'MODEL'
    #     op.process_type = 'THUMBNAILER'
    # elif props.thumbnail_generating_state != '':
    #     label_multiline(layout, text = props.thumbnail_generating_state)

    layout.prop(props, 'description')
Vilem Duha's avatar
Vilem Duha committed
    layout.prop(props, 'style')
    layout.prop(props, 'production_level')
    layout.prop(props, 'use_design_year')
    if props.use_design_year:
        layout.prop(props, 'design_year')
    layout.prop(props, 'condition')
    row = layout.row()
    row.prop(props, 'work_hours')
    layout.prop(props, 'adult')

Vilém Duha's avatar
Vilém Duha committed

def draw_assetbar_show_hide(layout, props):
    s = bpy.context.scene
    ui_props = s.blenderkitUI

    if ui_props.assetbar_on:
        icon = 'HIDE_OFF'
        ttip = 'Click to Hide Asset Bar'
    else:
        icon = 'HIDE_ON'
        ttip = 'Click to Show Asset Bar'
    op = layout.operator('view3d.blenderkit_asset_bar', text='', icon=icon)
    op.keep_running = False
    op.do_search = False

    op.tooltip = ttip

Vilem Duha's avatar
Vilem Duha committed

def draw_panel_model_search(self, context):
    s = context.scene
Vilem Duha's avatar
Vilem Duha committed
    props = s.blenderkit_models
    layout = self.layout

    row = layout.row()
    row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
    draw_assetbar_show_hide(row, props)
Vilem Duha's avatar
Vilem Duha committed

    icon = 'NONE'
    if props.report == 'You need Full plan to get this item.':
Vilem Duha's avatar
Vilem Duha committed
        icon = 'ERROR'
    label_multiline(layout, text=props.report, icon=icon)
    if props.report == 'You need Full plan to get this item.':
        layout.operator("wm.url_open", text="Get Full plan", icon='URL').url = paths.BLENDERKIT_PLANS
    layout.prop(props, "search_style")
Vilém Duha's avatar
Vilém Duha committed
    layout.prop(props, "own_only")
Vilem Duha's avatar
Vilem Duha committed
    # if props.search_style == 'OTHER':
    #     layout.prop(props, "search_style_other")
    # layout.prop(props, "search_engine")
    # col = layout.column()
    # layout.prop(props, 'append_link', expand=True, icon_only=False)
    # layout.prop(props, 'import_as', expand=True, icon_only=False)

Vilém Duha's avatar
Vilém Duha committed
    layout.prop(props, "search_advanced")
Vilem Duha's avatar
Vilem Duha committed
    if props.search_advanced:
        layout.separator()

        # layout.label(text = "common searches keywords:")
        # layout.prop(props, "search_global_keywords", text = "")
        # layout.prop(props, "search_modifier_keywords")
        # if props.search_engine == 'OTHER':
        #     layout.prop(props, "search_engine_keyword")
        layout.prop(props, "search_condition", text='Condition')  # , text ='condition of object new/old e.t.c.')
Vilem Duha's avatar
Vilem Duha committed

        # DESIGN YEAR
        layout.prop(props, "search_design_year", text='designed in ( min - max )')
Vilém Duha's avatar
Vilém Duha committed
        if props.search_design_year:
            row = layout.row(align=True)
            row.prop(props, "search_design_year_min", text='min')
            row.prop(props, "search_design_year_max", text='max')
Vilem Duha's avatar
Vilem Duha committed

        # POLYCOUNT
Vilém Duha's avatar
Vilém Duha committed
        layout.prop(props, "search_polycount", text='Poly count in ( min - max )')
        if props.search_polycount:
            row = layout.row(align=True)
            row.prop(props, "search_polycount_min", text='min')
            row.prop(props, "search_polycount_max", text='max')
Vilem Duha's avatar
Vilem Duha committed

        # TEXTURE RESOLUTION
        layout.prop(props, "search_texture_resolution", text='texture resolution ( min - max )')
Vilém Duha's avatar
Vilém Duha committed
        if props.search_texture_resolution:
            row = layout.row(align=True)
            row.prop(props, "search_texture_resolution_min", text='min')
            row.prop(props, "search_texture_resolution_max", text='max')
        # FILE SIZE
        layout.prop(props, "search_file_size", text='File size ( min - max )')
        if props.search_file_size:
            row = layout.row(align=True)
            row.prop(props, "search_file_size_min", text='min')
            row.prop(props, "search_file_size_max", text='max')

        # layout.prop(props, "search_procedural", expand=True)
Vilem Duha's avatar
Vilem Duha committed
        # ADULT
        # layout.prop(props, "search_adult")  # , text ='condition of object new/old e.t.c.')
Vilem Duha's avatar
Vilem Duha committed

    draw_panel_categories(self, context)

    layout.separator()
Vilém Duha's avatar
Vilém Duha committed
    layout.label(text='Import method:')
    row = layout.row()
    row.prop(props, 'append_method', expand=True, icon_only=False)
Vilem Duha's avatar
Vilem Duha committed
    layout.prop(props, 'randomize_rotation')
    if props.randomize_rotation:
        layout.prop(props, 'randomize_rotation_amount')


def draw_panel_scene_search(self, context):
    s = context.scene
    props = s.blenderkit_scene
    layout = self.layout
    # layout.label(text = "common search properties:")
    row = layout.row()
    row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
    draw_assetbar_show_hide(row, props)
Vilém Duha's avatar
Vilém Duha committed
    layout.prop(props, "own_only")
Vilem Duha's avatar
Vilem Duha committed
    label_multiline(layout, text=props.report)

    # layout.prop(props, "search_style")
    # if props.search_style == 'OTHER':
    #     layout.prop(props, "search_style_other")
Vilem Duha's avatar
Vilem Duha committed
    # layout.prop(props, "search_engine")
Vilem Duha's avatar
Vilem Duha committed
    layout.separator()
    draw_panel_categories(self, context)


class VIEW3D_PT_blenderkit_model_properties(Panel):
    bl_category = "BlenderKit"
    bl_idname = "VIEW3D_PT_blenderkit_model_properties"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_label = "Selected Model"
Vilem Duha's avatar
Vilem Duha committed
    bl_context = "objectmode"

    @classmethod
    def poll(cls, context):
        p = bpy.context.view_layer.objects.active is not None
Vilem Duha's avatar
Vilem Duha committed
        return p

    def draw(self, context):
        # draw asset properties here
        layout = self.layout

        o = utils.get_active_model()
        # o = bpy.context.active_object
        if o.get('asset_data') is None:
Vilém Duha's avatar
Vilém Duha committed
            label_multiline(layout, text='To upload this asset to BlenderKit, go to the Find and Upload Assets panel.')
            layout.prop(o, 'name')

        if o.get('asset_data') is not None:
            ad = o['asset_data']
            layout.label(text=str(ad['name']))
            if o.instance_type == 'COLLECTION' and o.instance_collection is not None:
                layout.operator('object.blenderkit_bring_to_scene', text='Bring to scene')

Vilém Duha's avatar
Vilém Duha committed
            draw_panel_model_rating(self, context)

            # if 'rig' in ad['tags']:
            #     # layout.label(text = 'can make proxy')
            #     layout.operator('object.blenderkit_make_proxy', text = 'Make Armature proxy')
        # fast upload, blocked by now
        # else:
        #     op = layout.operator("object.blenderkit_upload", text='Store as private', icon='EXPORT')
        #     op.asset_type = 'MODEL'
        #     op.fast = True
        # fun override project, not finished
Vilem Duha's avatar
Vilem Duha committed
        # layout.operator('object.blenderkit_color_corrector')

def draw_login_progress(layout):
    layout.label(text='Login through browser')
    layout.label(text='in progress.')
    layout.operator("wm.blenderkit_login_cancel", text="Cancel", icon='CANCEL')
Vilem Duha's avatar
Vilem Duha committed
class VIEW3D_PT_blenderkit_profile(Panel):
    bl_category = "BlenderKit"
    bl_idname = "VIEW3D_PT_blenderkit_profile"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
Vilém Duha's avatar
Vilém Duha committed
    bl_label = "BlenderKit Profile"
Vilem Duha's avatar
Vilem Duha committed

    @classmethod
    def poll(cls, context):
Vilem Duha's avatar
Vilem Duha committed

    def draw(self, context):
        # draw asset properties here
        layout = self.layout
        user_preferences = bpy.context.preferences.addons['blenderkit'].preferences

        if user_preferences.login_attempt:
Vilem Duha's avatar
Vilem Duha committed
            return

Vilém Duha's avatar
Vilém Duha committed
        if user_preferences.api_key != '':
Vilem Duha's avatar
Vilem Duha committed
            me = bpy.context.window_manager.get('bkit profile')
            if me is not None:
                me = me['user']
                # user name
Vilém Duha's avatar
Vilém Duha committed
                layout.label(text='Me: %s %s' % (me['firstName'], me['lastName']))
                # layout.label(text='Email: %s' % (me['email']))

                # plan information

                # pcoll = icons.icon_collections["main"]
                # my_icon = pcoll['free']
                # row = layout.row()
                # row.label(text='My plan:')
                # row.label(text='Free plan', icon_value=my_icon.icon_id)
                # layout.operator("wm.url_open", text="Change plan",
                #                 icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_PLANS

                # storage statistics
Vilém Duha's avatar
Vilém Duha committed
                # if me.get('sumAssetFilesSize') is not None:  # TODO remove this when production server has these too.
                #     layout.label(text='My public assets: %i MiB' % (me['sumAssetFilesSize']))
                # if me.get('sumPrivateAssetFilesSize') is not None:
                #     layout.label(text='My private assets: %i MiB' % (me['sumPrivateAssetFilesSize']))
                if me.get('remainingPrivateQuota') is not None:
Vilém Duha's avatar
Vilém Duha committed
                    layout.label(text='My free storage: %i MiB' % (me['remainingPrivateQuota']))
            layout.operator("wm.url_open", text="See my uploads",
                            icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_USER_ASSETS
Vilem Duha's avatar
Vilem Duha committed


Loading
Loading full blame...