Skip to content
Snippets Groups Projects
ui_panels.py 82.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •             split = split.column()
    
            split.prop(ui_props, 'asset_type', expand=True, icon_only=ui_props.asset_type_fold)
    
    Vilém Duha's avatar
    Vilém Duha committed
            # row = layout.column(align = False)
    
            # layout.prop(ui_props, 'asset_type', expand=False, text='')
    
    Vilem Duha's avatar
    Vilem Duha committed
    
            w = context.region.width
    
            if len(user_preferences.api_key) < 20 and user_preferences.asset_counter > 20:
    
                    draw_login_buttons(layout)
    
                else:
                    op = layout.operator("wm.url_open", text="Get your API Key",
                                         icon='QUESTION')
                    op.url = paths.BLENDERKIT_SIGNUP_URL
                    layout.label(text='Paste your API Key:')
                    layout.prop(user_preferences, 'api_key', text='')
    
    Vilem Duha's avatar
    Vilem Duha committed
                layout.separator()
    
    Vilém Duha's avatar
    Vilém Duha committed
            # if bpy.data.filepath == '':
            #     layout.alert = True
    
            #    utils.label_multiline(layout, text="It's better to save your file first.", width=w)
    
    Vilém Duha's avatar
    Vilém Duha committed
            #     layout.alert = False
            #     layout.separator()
    
            if ui_props.down_up == 'SEARCH':
    
                if utils.profile_is_validator():
                    search_props = utils.get_search_props()
                    layout.prop(search_props, 'search_verification_status')
    
                    layout.prop(search_props, "unrated_only")
    
    
    Vilem Duha's avatar
    Vilem Duha committed
                if ui_props.asset_type == 'MODEL':
                    # noinspection PyCallByClass
                    draw_panel_model_search(self, context)
                if ui_props.asset_type == 'SCENE':
                    # noinspection PyCallByClass
                    draw_panel_scene_search(self, context)
    
                if ui_props.asset_type == 'HDR':
                    # noinspection PyCallByClass
                    draw_panel_hdr_search(self, context)
    
    Vilem Duha's avatar
    Vilem Duha committed
                elif ui_props.asset_type == 'MATERIAL':
                    draw_panel_material_search(self, context)
                elif ui_props.asset_type == 'BRUSH':
                    if context.sculpt_object or context.image_paint_object:
                        # noinspection PyCallByClass
                        draw_panel_brush_search(self, context)
                    else:
    
                        utils.label_multiline(layout, text='Switch to paint or sculpt mode.', width=context.region.width)
    
    Vilem Duha's avatar
    Vilem Duha committed
            elif ui_props.down_up == 'UPLOAD':
                if not ui_props.assetbar_on:
                    text = 'Show asset preview - ;'
                else:
                    text = 'Hide asset preview - ;'
                op = layout.operator('view3d.blenderkit_asset_bar', text=text, icon='EXPORT')
                op.keep_running = False
                op.do_search = False
    
                op.tooltip = 'Show/Hide asset preview'
    
    
    Vilem Duha's avatar
    Vilem Duha committed
                e = s.render.engine
                if e not in ('CYCLES', 'BLENDER_EEVEE'):
                    rtext = 'Only Cycles and EEVEE render engines are currently supported. ' \
                            'Please use Cycles for all assets you upload to BlenderKit.'
    
                    utils.label_multiline(layout, rtext, icon='ERROR', width=w)
    
    Vilem Duha's avatar
    Vilem Duha committed
                    return;
    
                if ui_props.asset_type == 'MODEL':
    
                    # utils.label_multiline(layout, "Uploaded models won't be available in b2.79", icon='ERROR')
    
                    if bpy.context.view_layer.objects.active is not None:
    
    Vilem Duha's avatar
    Vilem Duha committed
                        draw_panel_model_upload(self, context)
                    else:
                        layout.label(text='selet object to upload')
                elif ui_props.asset_type == 'SCENE':
                    draw_panel_scene_upload(self, context)
    
                elif ui_props.asset_type == 'HDR':
                    draw_panel_hdr_upload(self, context)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
                elif ui_props.asset_type == 'MATERIAL':
    
                    # utils.label_multiline(layout, "Uploaded materials won't be available in b2.79", icon='ERROR')
    
                    if bpy.context.view_layer.objects.active is not None and bpy.context.active_object.active_material is not None:
    
    Vilem Duha's avatar
    Vilem Duha committed
                        draw_panel_material_upload(self, context)
                    else:
    
                        utils.label_multiline(layout, text='select object with material to upload materials', width=w)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
                elif ui_props.asset_type == 'BRUSH':
                    if context.sculpt_object or context.image_paint_object:
                        draw_panel_brush_upload(self, context)
                    else:
    
                        layout.label(text='Switch to paint or sculpt mode.')
    
    class BlenderKitWelcomeOperator(bpy.types.Operator):
        """Login online on BlenderKit webpage"""
    
        bl_idname = "wm.blenderkit_welcome"
        bl_label = "Welcome to BlenderKit!"
        bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
    
        step: IntProperty(
            name="step",
            description="Tutorial Step",
            default=0,
            options={'SKIP_SAVE'}
        )
    
        @classmethod
        def poll(cls, context):
            return True
    
        def draw(self, context):
            layout = self.layout
            if self.step == 0:
    
                user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
    
                message = "BlenderKit connects from Blender to an online, " \
                          "community built shared library of models, " \
                          "materials, and brushes. " \
                          "Use addon preferences to set up where files will be saved in the Global directory setting."
    
                utils.label_multiline(layout, text=message, width=300)
                utils.label_multiline(layout, text="\n Let's start by searching for some cool materials?", width=300)
    
                message = "Operator Tutorial called with invalid step"
    
    
        def execute(self, context):
            if self.step == 0:
    
                # move mouse:
                # bpy.context.window_manager.windows[0].cursor_warp(1000, 1000)
                # show n-key sidebar (spaces[index] has to be found for view3d too:
    
                # bpy.context.window_manager.windows[0].screen.areas[5].spaces[0].show_region_ui = False
                print('running search no')
                ui_props = bpy.context.scene.blenderkitUI
                ui_props.asset_type = 'MATERIAL'
    
                bpy.context.scene.blenderkit_mat.search_keywords = 'ice'
                # search.search()
    
            return {'FINISHED'}
    
        def invoke(self, context, event):
            wm = bpy.context.window_manager
            return wm.invoke_props_dialog(self)
    
    def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
    
    Vilém Duha's avatar
    Vilém Duha committed
        author_id = str(asset_data['author'].get('id'))
    
    
        layout.operator_context = 'INVOKE_DEFAULT'
    
    
        if from_panel:
            op = layout.operator('wm.blenderkit_menu_rating_upload', text='Rate')
            op.asset_name = asset_data['name']
            op.asset_id = asset_data['id']
            op.asset_type = asset_data['assetType']
    
        if from_panel and wm.get('bkit authors') is not None and author_id is not None:
    
            a = bpy.context.window_manager['bkit authors'].get(author_id)
            if a is not None:
                # utils.p('author:', a)
    
                op = layout.operator('wm.url_open', text="Open Author's Website")
    
                if a.get('aboutMeUrl') is not None:
                    op.url = a['aboutMeUrl']
    
                else:
                    op.url = paths.get_author_gallery_url(a['id'])
    
                op = layout.operator('view3d.blenderkit_search', text="Show Assets By Author")
                op.keywords = ''
                op.author_id = author_id
    
        op = layout.operator('view3d.blenderkit_search', text='Search Similar')
    
        op.tooltip = 'Search for similar assets in the library'
    
    Vilém Duha's avatar
    Vilém Duha committed
        # build search string from description and tags:
    
        op.keywords = asset_data['name']
        if asset_data.get('description'):
    
    Vilém Duha's avatar
    Vilém Duha committed
            op.keywords += ' ' + asset_data.get('description') + ' '
    
        op.keywords += ' '.join(asset_data.get('tags'))
    
    
        if asset_data.get('canDownload') != 0:
            if len(bpy.context.selected_objects) > 0 and ui_props.asset_type == 'MODEL':
                aob = bpy.context.active_object
                if aob is None:
                    aob = bpy.context.selected_objects[0]
                op = layout.operator('scene.blenderkit_download', text='Replace Active Models')
    
    Vilém Duha's avatar
    Vilém Duha committed
                # this checks if the menu got called from right-click in assetbar(then index is 0 - x) or
    
                # from a panel(then replacement happens from the active model)
    
    Vilém Duha's avatar
    Vilém Duha committed
                if from_panel:
    
    Vilém Duha's avatar
    Vilém Duha committed
                    # called from addon panel
    
    Vilém Duha's avatar
    Vilém Duha committed
                    op.asset_base_id = asset_data['assetBaseId']
    
                else:
                    op.asset_index = ui_props.active_index
    
    
    Vilém Duha's avatar
    Vilém Duha committed
                # op.asset_type = ui_props.asset_type
    
                op.model_location = aob.location
                op.model_rotation = aob.rotation_euler
                op.target_object = aob.name
                op.material_target_slot = aob.active_material_index
                op.replace = True
    
    Vilém Duha's avatar
    Vilém Duha committed
                op.replace_resolution = False
    
            # resolution replacement operator
            # if asset_data['downloaded'] == 100: # only show for downloaded/used assets
            # if ui_props.asset_type in ('MODEL', 'MATERIAL'):
            #     layout.menu(OBJECT_MT_blenderkit_resolution_menu.bl_idname)
    
            if ui_props.asset_type in ('MODEL', 'MATERIAL', 'HDR') and \
    
    Vilém Duha's avatar
    Vilém Duha committed
                    utils.get_param(asset_data, 'textureResolutionMax') is not None and \
                    utils.get_param(asset_data, 'textureResolutionMax') > 512:
    
                s = bpy.context.scene
    
                col = layout.column()
                col.operator_context = 'INVOKE_DEFAULT'
    
                if from_panel:
                    # Called from addon panel
    
                    if asset_data.get('resolution'):
                        op = col.operator('scene.blenderkit_download', text='Replace asset resolution')
                        op.asset_base_id = asset_data['assetBaseId']
                        if asset_data['assetType'] == 'MODEL':
                            o = utils.get_active_model()
                            op.model_location = o.location
                            op.model_rotation = o.rotation_euler
                            op.target_object = o.name
                            op.material_target_slot = o.active_material_index
    
    Vilém Duha's avatar
    Vilém Duha committed
                        elif asset_data['assetType'] == 'MATERIAL':
                            aob = bpy.context.active_object
                            op.model_location = aob.location
                            op.model_rotation = aob.rotation_euler
                            op.target_object = aob.name
    
                            op.material_target_slot = aob.active_material_index
    
    Vilém Duha's avatar
    Vilém Duha committed
                        op.replace_resolution = True
    
                        op.replace = False
    
    
    Vilém Duha's avatar
    Vilém Duha committed
                        op.invoke_resolution = True
                        op.max_resolution = asset_data.get('max_resolution',
                                                           0)  # str(utils.get_param(asset_data, 'textureResolutionMax'))
    
    
                elif asset_data['assetBaseId'] in s['assets used'].keys() and asset_data['assetType'] != 'hdr':
    
    Vilém Duha's avatar
    Vilém Duha committed
                    # HDRs are excluded from replacement, since they are always replaced.
    
    Vilém Duha's avatar
    Vilém Duha committed
                    # called from asset bar:
                    op = col.operator('scene.blenderkit_download', text='Replace asset resolution')
    
                    op.asset_index = ui_props.active_index
                    # op.asset_type = ui_props.asset_type
                    op.replace_resolution = True
    
                    op.replace = False
    
    Vilém Duha's avatar
    Vilém Duha committed
                    op.invoke_resolution = True
                    o = utils.get_active_model()
                    if o and o.get('asset_data'):
    
                        if o['asset_data']['assetBaseId'] == bpy.context.window_manager['search results'][
                            ui_props.active_index]:
    
    Vilém Duha's avatar
    Vilém Duha committed
                            op.model_location = o.location
                            op.model_rotation = o.rotation_euler
    
                            op.model_location = (0, 0, 0)
                            op.model_rotation = (0, 0, 0)
    
    Vilém Duha's avatar
    Vilém Duha committed
                    op.max_resolution = asset_data.get('max_resolution',
                                                       0)  # str(utils.get_param(asset_data, 'textureResolutionMax'))
                # print('operator res ', resolution)
                # op.resolution = resolution
    
    
        wm = bpy.context.window_manager
        profile = wm.get('bkit profile')
        if profile is not None:
            # validation
    
            if author_id == str(profile['user']['id']) or utils.profile_is_validator():
    
                layout.label(text='Management tools:')
    
    
                row = layout.row()
                row.operator_context = 'INVOKE_DEFAULT'
    
                op = layout.operator('wm.blenderkit_fast_metadata', text='Edit Metadata')
    
                op.asset_id = asset_data['id']
    
                op.asset_type = asset_data['assetType']
    
    Vilém Duha's avatar
    Vilém Duha committed
                if asset_data['assetType'] == 'model':
                    op = layout.operator('object.blenderkit_regenerate_thumbnail', text='Regenerate thumbnail')
                    op.asset_index = ui_props.active_index
    
                if asset_data['assetType'] == 'material':
                    op = layout.operator('object.blenderkit_regenerate_material_thumbnail', text='Regenerate thumbnail')
                    op.asset_index = ui_props.active_index
                    # op.asset_id = asset_data['id']
                    # op.asset_type = asset_data['assetType']
    
    
            if author_id == str(profile['user']['id']):
    
                row = layout.row()
                row.operator_context = 'INVOKE_DEFAULT'
                op = row.operator('object.blenderkit_change_status', text='Delete')
                op.asset_id = asset_data['id']
                op.state = 'deleted'
    
    
            if utils.profile_is_validator():
    
                layout.label(text='Dev Tools:')
    
    Vilém Duha's avatar
    Vilém Duha committed
                op = layout.operator('object.blenderkit_print_asset_debug', text='Print asset debug')
                op.asset_id = asset_data['id']
    
    
    # def draw_asset_resolution_replace(self, context, resolution):
    #     layout = self.layout
    #     ui_props = bpy.context.scene.blenderkitUI
    #
    #     op = layout.operator('scene.blenderkit_download', text=resolution)
    #     if ui_props.active_index == -3:
    #         # This happens if the command is called from addon panel
    #         o = utils.get_active_model()
    #         op.asset_base_id = o['asset_data']['assetBaseId']
    #
    #     else:
    #         op.asset_index = ui_props.active_index
    #
    #         op.asset_type = ui_props.asset_type
    #     if len(bpy.context.selected_objects) > 0:  # and ui_props.asset_type == 'MODEL':
    #         aob = bpy.context.active_object
    #         op.model_location = aob.location
    #         op.model_rotation = aob.rotation_euler
    #         op.target_object = aob.name
    #         op.material_target_slot = aob.active_material_index
    #     op.replace_resolution = True
    #     print('operator res ', resolution)
    #     op.resolution = resolution
    
    
    # class OBJECT_MT_blenderkit_resolution_menu(bpy.types.Menu):
    #     bl_label = "Replace Asset Resolution"
    #     bl_idname = "OBJECT_MT_blenderkit_resolution_menu"
    #
    #     def draw(self, context):
    #         ui_props = context.scene.blenderkitUI
    #
    
    #         # sr = bpy.context.window_manager['search results']
    
    #         # sr = bpy.context.window_manager['search results']
    
    Vilém Duha's avatar
    Vilém Duha committed
    #         # asset_data = sr[ui_props.active_index]
    #
    #         for k in resolutions.resolution_props_to_server.keys():
    #             draw_asset_resolution_replace(self, context, k)
    
    
    class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu):
        bl_label = "Asset options:"
        bl_idname = "OBJECT_MT_blenderkit_asset_menu"
    
        def draw(self, context):
            ui_props = context.scene.blenderkitUI
    
    
            sr = bpy.context.window_manager['search results']
    
            asset_data = sr[ui_props.active_index]
            draw_asset_context_menu(self.layout, context, asset_data, from_panel=False)
    
    
    def numeric_to_str(s):
        if s:
            s = str(round(s))
        else:
            s = '-'
        return s
    
    def label_or_url(layout, text='', tooltip='', url='', icon_value=None, icon=None):
        '''automatically switch between different layout options for linking or tooltips'''
        layout.emboss = 'NONE'
        if url != '':
            if icon:
                op = layout.operator('wm.blenderkit_url', text=text, icon=icon)
            elif icon_value:
                op = layout.operator('wm.blenderkit_url', text=text, icon_value=icon_value)
            else:
                op = layout.operator('wm.blenderkit_url', text=text)
            op.url = url
            op.tooltip = tooltip
            layout.label(text='')
            layout.label(text='')
    
            return
        if tooltip != '':
            if icon:
                op = layout.operator('wm.blenderkit_tooltip', text=text, icon=icon)
            elif icon_value:
                op = layout.operator('wm.blenderkit_tooltip', text=text, icon_value=icon_value)
            else:
                op = layout.operator('wm.blenderkit_tooltip', text=text)
            op.tooltip = tooltip
            layout.label(text='')
            layout.label(text='')
            return
        if icon:
            layout.label(text=text, icon=icon)
        elif icon_value:
            layout.label(text=text, icon_value=icon_value)
        else:
            layout.label(text=text)
    
    
    
    class AssetPopupCard(bpy.types.Operator):
        """Generate Cycles thumbnail for model assets"""
        bl_idname = "wm.blenderkit_asset_popup"
        bl_label = "BlenderKit asset popup"
    
    
        width = 700
    
        message: StringProperty(
            name="message",
            description="message",
            default="Rating asset",
            options={'SKIP_SAVE'})
    
        asset_id: StringProperty(
            name="Asset Base Id",
            description="Unique id of the asset (hidden)",
            default="",
            options={'SKIP_SAVE'})
    
        asset_name: StringProperty(
            name="Asset Name",
            description="Name of the asset (hidden)",
            default="",
            options={'SKIP_SAVE'})
    
        asset_type: StringProperty(
            name="Asset type",
            description="asset type",
            default="",
            options={'SKIP_SAVE'})
    
        rating_quality: IntProperty(name="Quality",
                                    description="quality of the material",
                                    default=0,
                                    min=-1, max=10,
    
                                    update=ratings_utils.update_ratings_quality,
    
                                    options={'SKIP_SAVE'})
    
        # the following enum is only to ease interaction - enums support 'drag over' and enable to draw the stars easily.
        rating_quality_ui: EnumProperty(name='rating_quality_ui',
                                        items=ratings_utils.stars_enum_callback,
                                        description='Rating stars 0 - 10',
                                        default=0,
                                        update=ratings_utils.update_quality_ui,
                                        options={'SKIP_SAVE'})
    
        rating_work_hours: FloatProperty(name="Work Hours",
                                         description="How many hours did this work take?",
                                         default=0.00,
                                         min=0.0, max=300,
    
                                         update=ratings_utils.update_ratings_work_hours,
    
                                         options={'SKIP_SAVE'}
                                         )
    
        high_rating_warning = "This is a high rating, please be sure to give such rating only to amazing assets"
    
        rating_work_hours_ui: EnumProperty(name="Work Hours",
                                           description="How many hours did this work take?",
                                           items=[('0', '0', ''),
                                                  ('.5', '0.5', ''),
                                                  ('1', '1', ''),
                                                  ('2', '2', ''),
                                                  ('3', '3', ''),
                                                  ('4', '4', ''),
                                                  ('5', '5', ''),
                                                  ('6', '6', ''),
                                                  ('8', '8', ''),
                                                  ('10', '10', ''),
                                                  ('15', '15', ''),
                                                  ('20', '20', ''),
                                                  ('30', '30', high_rating_warning),
                                                  ('50', '50', high_rating_warning),
                                                  ('100', '100', high_rating_warning),
                                                  ('150', '150', high_rating_warning),
                                                  ('200', '200', high_rating_warning),
                                                  ('250', '250', high_rating_warning),
                                                  ],
                                           default='0', update=ratings_utils.update_ratings_work_hours_ui,
                                           options={'SKIP_SAVE'}
                                           )
    
        rating_work_hours_ui_1_5: EnumProperty(name="Work Hours",
                                               description="How many hours did this work take?",
                                               items=[('0', '0', ''),
                                                      ('.2', '0.2', ''),
                                                      ('.5', '0.5', ''),
                                                      ('1', '1', ''),
                                                      ('2', '2', ''),
                                                      ('3', '3', ''),
                                                      ('4', '4', ''),
                                                      ('5', '5', '')
                                                      ],
                                               default='0',
                                               update=ratings_utils.update_ratings_work_hours_ui_1_5,
                                               options={'SKIP_SAVE'}
                                               )
    
        rating_work_hours_ui_1_10: EnumProperty(name="Work Hours",
                                                description="How many hours did this work take?",
                                                items=[('0', '0', ''),
                                                       ('1', '1', ''),
                                                       ('2', '2', ''),
                                                       ('3', '3', ''),
                                                       ('4', '4', ''),
                                                       ('5', '5', ''),
                                                       ('6', '6', ''),
                                                       ('7', '7', ''),
                                                       ('8', '8', ''),
                                                       ('9', '9', ''),
                                                       ('10', '10', '')
                                                       ],
                                                default='0',
                                                update=ratings_utils.update_ratings_work_hours_ui_1_10,
                                                options={'SKIP_SAVE'}
                                                )
    
    
        @classmethod
        def poll(cls, context):
            return True
    
    
        def draw_menu(self, context, layout):
    
            col = layout.column()
            draw_asset_context_menu(col, context, self.asset_data, from_panel=False)
    
        def draw_property(self, layout, left, right, icon=None, icon_value=None, url='', tooltip=''):
    
            right = str(right)
            row = layout.row()
            split = row.split(factor=0.4)
            split.alignment = 'RIGHT'
            split.label(text=left)
            split = split.split()
    
            split.alignment = 'LEFT'
            #split for questionmark:
            if url!='':
                split = split.split(factor=0.7)
            label_or_url(split,text=right,tooltip=tooltip, url=url, icon_value=icon_value, icon=icon)
            #additional questionmark icon where it's important?
            if url!='':
    
                split = split.split()
                op = split.operator('wm.blenderkit_url', text='', icon='QUESTION')
                op.url = url
                op.tooltip = tooltip
    
        def draw_asset_parameter(self, layout, key='', pretext=''):
            parameter = utils.get_param(self.asset_data, key)
            if parameter == None:
                return
            self.draw_property(layout, pretext, parameter)
    
    
        def draw_properties(self, layout):
    
    
            if type(self.asset_data['parameters']) == list:
                mparams = utils.params_to_dict(self.asset_data['parameters'])
            else:
                mparams = self.asset_data['parameters']
    
            layout = layout.column()
            if len(self.asset_data['description']) > 0:
                box = layout.box()
                box.scale_y = 0.8
    
                box.label(text='Description')
    
                utils.label_multiline(box, self.asset_data['description'], width=200)
    
            pcoll = icons.icon_collections["main"]
    
            box = layout.box()
            box.scale_y = 0.8
    
            box.label(text='Properties')
    
            if self.asset_data.get('license') == 'cc_zero':
                t = 'CC Zero'
                icon = pcoll['cc0']
    
            else:
                t = 'Royalty free'
                icon = pcoll['royalty_free']
    
            self.draw_property(box,
    
                               'License:', t,
    
                               # icon_value=icon.icon_id,
    
                               url="https://www.blenderkit.com/docs/licenses/",
    
                               tooltip='All BlenderKit assets are available for commercial use. \n'\
                                       'Click to read more about BlenderKit licenses on the website'
    
                               )
    
            if upload.can_edit_asset(asset_data=self.asset_data):
                icon = pcoll[self.asset_data['verificationStatus']]
                verification_status_tooltips = {
                    'uploading': "Your asset got stuck during upload. Probably, your file was too large "
                                 "or your connection too slow or interrupting. If you have repeated issues, "
                                 "please contact us and let us know, it might be a bug",
                    'uploaded': "Your asset uploaded successfully. Yay! If it's public, "
                                "it's awaiting validation. If it's private, use it",
                    'on_hold': "Your asset needs some (usually smaller) fixes, "
                               "so we can make it public for everybody."
                               " Please check your email to see the feedback "
                               "that we send to every creator personally",
                    'rejected': "The asset has serious quality issues, " \
                                "and it's probable that it might be good to start " \
                                "all over again or try with something simpler. " \
                                "You also get personal feedback into your e-mail, " \
                                "since we believe that together, we can all learn " \
                                "to become awesome 3D artists",
                    'deleted': "You deleted this asset",
                    'validated': "Your asset passed our validation process, "
                                 "and is now available to BlenderKit users"
    
                }
                self.draw_property(box,
                                   'Verification:',
                                   self.asset_data['verificationStatus'],
                                   icon_value=icon.icon_id,
                                   url="https://www.blenderkit.com/docs/validation-status/",
                                   tooltip=verification_status_tooltips[self.asset_data['verificationStatus']]
    
                                   )
    
            # fs = self.asset_data['files']
            #
            # if fs and len(fs) > 2:
            #     resolutions = ''
            #     list.sort(fs, key=lambda f: f['fileType'])
            #     for f in fs:
            #         if f['fileType'].find('resolution') > -1:
            #             resolutions += f['fileType'][11:] + ' '
            #     resolutions = resolutions.replace('_', '.')
            #     self.draw_property(box, 'Resolutions:', resolutions)
            resolution = utils.get_param(self.asset_data, 'textureResolutionMax')
            if resolution is not None:
    
                ress = f"{int(round(resolution / 1024, 0))}K"
    
                self.draw_property(box, 'Resolution', ress,
                                   tooltip='Maximal resolution of textures in this asset.\n'\
                                            'Most texture asset have also lower resolutions generated.\n'\
                                            'Go to BlenderKit add-on import settings to set default resolution')
    
    
            self.draw_asset_parameter(box, key='designer', pretext='Designer')
    
            self.draw_asset_parameter(box, key='manufacturer', pretext='Manufacturer')  # TODO make them clickable!
    
            self.draw_asset_parameter(box, key='designCollection', pretext='Collection')
            self.draw_asset_parameter(box, key='designVariant', pretext='Variant')
            self.draw_asset_parameter(box, key='designYear', pretext='Design year')
            self.draw_asset_parameter(box, key='faceCount', pretext='Face count')
            # self.draw_asset_parameter(box, key='thumbnailScale', pretext='Preview scale')
            # self.draw_asset_parameter(box, key='purePbr', pretext='Pure PBR')
            # self.draw_asset_parameter(box, key='productionLevel', pretext='Readiness')
            # self.draw_asset_parameter(box, key='condition', pretext='Condition')
            # self.draw_property(box, 'Tags', self.asset_data['tags']) #TODO make them clickable!
            self.draw_asset_parameter(box, key='material_style', pretext='Style')
            self.draw_asset_parameter(box, key='model_style', pretext='Style')
    
    
            if utils.get_param(self.asset_data, 'dimensionX'):
    
                t = '%s×%s×%s m' % (utils.fmt_length(mparams['dimensionX']),
    
                                    utils.fmt_length(mparams['dimensionY']),
                                    utils.fmt_length(mparams['dimensionZ']))
    
                self.draw_property(box, 'Size:', t)
    
    
            # Free/Full plan or private Access
    
            plans_tooltip = 'BlenderKit has 2 plans:\n'\
                                             '  *  Free plan - more than 50% of all assets\n'\
                                             '  *  Full plan - unlimited access to everything'\
                                             'Click to go to subscriptions page.'
            plans_link = 'https://www.blenderkit.com/plans/pricing/'
    
            if self.asset_data['isPrivate']:
                t = 'Private'
                self.draw_property(box, 'Access:', t, icon='LOCKED')
            elif self.asset_data['isFree']:
                t = 'Free plan'
                icon = pcoll['free']
    
                self.draw_property(box, 'Access:', t,
                                   icon_value=icon.icon_id,
                                   tooltip = plans_tooltip,
                                   url= plans_link)
    
            else:
                t = 'Full plan'
                icon = pcoll['full']
    
                self.draw_property(box, 'Access:', t,
                                   icon_value=icon.icon_id,
                                   tooltip=plans_tooltip,
                                   url=plans_link)
    
        def draw_author_area(self, context, layout, width=330):
            self.draw_author(context, layout, width=330)
    
        def draw_author(self, context, layout, width=330):
    
            image_split = 0.25
            text_width = width
            authors = bpy.context.window_manager['bkit authors']
            a = authors.get(self.asset_data['author']['id'])
            if a is not None:  # or a is '' or (a.get('gravatarHash') is not None and a.get('gravatarImg') is None):
    
                row = layout.row()
                author_box = row.box()
                author_box.scale_y = 0.6  # get text lines closer to each other
    
                author_box.label(text='Author')  # just one extra line to give spacing
    
                if hasattr(self, 'gimg'):
    
                    author_left = author_box.split(factor=0.25)
    
                    author_left.template_icon(icon_value=self.gimg.preview.icon_id, scale=7)
    
                    text_area = author_left.split()
                    text_width = int(text_width * (1 - image_split))
                else:
                    text_area = author_box
    
                author_right = text_area.column()
                row = author_right.row()
                col = row.column()
    
                utils.label_multiline(col, text=a['tooltip'], width=text_width)
    
                # check if author didn't fill any data about himself and prompt him if that's the case
    
                if upload.user_is_owner(asset_data=self.asset_data) and a.get('aboutMe') is not None and len(
    
                        a.get('aboutMe', '')) == 0:
    
                    row = col.row()
                    row.enabled = False
                    row.label(text='Please introduce yourself to the community!')
    
    
                    op = col.operator('wm.blenderkit_url', text='Edit your profile')
                    op.url = 'https://www.blenderkit.com/profile'
                    op.tooltip = 'Edit your profile on BlenderKit webpage'
    
                button_row = author_box.row()
                button_row.scale_y = 2.0
    
                if a.get('aboutMeUrl') is not None:
                    url = a['aboutMeUrl']
                    text = url
                    if len(url) > 25:
                        text = url[:25] + '...'
                else:
                    url = paths.get_author_gallery_url(a['id'])
                    text = "Open Author's Profile"
    
                op = button_row.operator('wm.url_open', text=text)
                op.url = url
    
    
                op = button_row.operator('view3d.blenderkit_search', text="Find Assets By Author")
    
                op.keywords = ''
                op.author_id = self.asset_data['author']['id']
    
        def draw_thumbnail_box(self, layout):
            layout.emboss = 'NORMAL'
    
            box_thumbnail = layout.box()
    
    
            box_thumbnail.scale_y = .4
    
    
            box_thumbnail.template_icon(icon_value=self.img.preview.icon_id, scale=34.0)
            # row = box_thumbnail.row()
            # row.scale_y = 4
            # op = row.operator('view3d.asset_drag_drop', text='Drag & Drop from here', depress=True)
    
            row = box_thumbnail.row()
            row.alignment = 'EXPAND'
    
    
            # display_ratings = can_display_ratings(self.asset_data)
    
            rc = self.asset_data.get('ratingsCount')
    
            show_rating_threshold = 0
            show_rating_prompt_threshold = 5
    
    
            if rc:
                rcount = min(rc['quality'], rc['workingHours'])
            else:
                rcount = 0
            if rcount >= show_rating_threshold or upload.can_edit_asset(asset_data=self.asset_data):
    
                s = numeric_to_str(self.asset_data['score'])
                q = numeric_to_str(self.asset_data['ratingsAverage'].get('quality'))
                c = numeric_to_str(self.asset_data['ratingsAverage'].get('workingHours'))
    
                s = '-'
                q = '-'
                c = '-'
    
            pcoll = icons.icon_collections["main"]
    
    
            row.emboss = 'NONE'
            op = row.operator('wm.blenderkit_tooltip', text=str(s), icon_value=pcoll['trophy'].icon_id)
            op.tooltip = 'Asset score calculated from averaged user ratings. \n\n' \
                         'Score = quality × complexity × 10*\n\n *Happiness multiplier'
            row.label(text='   ')
    
            tooltip_extension = f'.\n\nRatings results are shown for assets with more than {show_rating_threshold} ratings'
            op = row.operator('wm.blenderkit_tooltip', text=str(q), icon='SOLO_ON')
            op.tooltip = f"Quality, average from {rc['quality']} ratings" \
                         f"{tooltip_extension if rcount <= show_rating_threshold else ''}"
            row.label(text='   ')
    
            op = row.operator('wm.blenderkit_tooltip', text=str(c), icon_value=pcoll['dumbbell'].icon_id)
            op.tooltip = f"Complexity, average from {rc['workingHours']} ratings" \
                         f"{tooltip_extension if rcount <= show_rating_threshold else ''}"
    
            if rcount <= show_rating_prompt_threshold:
                box_thumbnail.alert = True
    
                box_thumbnail.label(text=f"")
                box_thumbnail.label(text=f"This asset has only {rcount} rating{'' if rcount == 1 else 's'} , please rate.")
    
                # box_thumbnail.label(text=f"Please rate this asset.")
    
        def draw_menu_desc_author(self, context, layout):
            box = layout.column()
    
            box.emboss = 'NORMAL'
            # left - tooltip & params
            row = box.row()
            split_left_left = row.split(factor=0.7)
    
            self.draw_properties(split_left_left)
    
    
            # right - menu
            col1 = split_left_left.split()
            self.draw_menu(context, col1)
    
            # author
    
            self.draw_author_area(context, box, width=330)
    
        def draw(self, context):
            ui_props = context.scene.blenderkitUI
    
    
            sr = bpy.context.window_manager['search results']
    
            asset_data = sr[ui_props.active_index]
    
            self.asset_data = asset_data
    
            layout = self.layout
    
            # top draggabe bar with name of the asset
            top_row = layout.row()
            top_drag_bar = top_row.box()
            top_drag_bar.alignment = 'CENTER'
    
            top_drag_bar.label(text=asset_data['displayName'])
            # left side
            row = layout.row(align=True)
            split_left = row.split(factor=0.5)
            self.draw_thumbnail_box(split_left)
    
            # right split
            split_right = split_left.split()
            self.draw_menu_desc_author(context, split_right)
    
            ratings_box = layout.box()
    
            ratings_box.scale_y = 0.7
    
            ratings_box.label(text='Rate asset quality:')
            ratings.draw_ratings_menu(self, context, ratings_box)
            tip_box = layout.box()
            tip_box.label(text=self.tip)
    
        def execute(self, context):
    
            wm = context.window_manager
            ui_props = context.scene.blenderkitUI
            ui_props.draw_tooltip = False
    
            sr = bpy.context.window_manager['search results']
    
            asset_data = sr[ui_props.active_index]
            self.img = ui.get_large_thumbnail_image(asset_data)
    
            self.asset_type = asset_data['assetType']
    
            self.asset_id = asset_data['id']
    
            # self.tex = utils.get_hidden_texture(self.img)
            # self.tex.update_tag()
    
            authors = bpy.context.window_manager['bkit authors']
            a = authors.get(asset_data['author']['id'])
            if a.get('gravatarImg') is not None:
                self.gimg = utils.get_hidden_image(a['gravatarImg'], a['gravatarHash'])
    
    
            bl_label = asset_data['name']
    
            self.tip = search.get_random_tip()
            self.tip = self.tip.replace('\n', '')
            return wm.invoke_popup(self, width=self.width)
    
    class OBJECT_MT_blenderkit_login_menu(bpy.types.Menu):
        bl_label = "BlenderKit login/signup:"
        bl_idname = "OBJECT_MT_blenderkit_login_menu"
    
        def draw(self, context):
            layout = self.layout
    
            # utils.label_multiline(layout, text=message)
            draw_login_buttons(layout)
    
    
    Vilem Duha's avatar
    Vilem Duha committed
    class SetCategoryOperator(bpy.types.Operator):
        """Visit subcategory"""
        bl_idname = "view3d.blenderkit_set_category"
        bl_label = "BlenderKit Set Active Category"
    
    Vilém Duha's avatar
    Vilém Duha committed
        bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        category: bpy.props.StringProperty(
            name="Category",
            description="set this category active",
            default="")
    
        asset_type: bpy.props.StringProperty(
            name="Asset Type",
            description="asset type",
            default="")
    
        @classmethod
        def poll(cls, context):
            return True
    
        def execute(self, context):
            acat = bpy.context.window_manager['active_category'][self.asset_type]
            if self.category == '':
                acat.remove(acat[-1])
            else:
                acat.append(self.category)
            # we have to write back to wm. Thought this should happen with original list.
            bpy.context.window_manager['active_category'][self.asset_type] = acat
            return {'FINISHED'}
    
    
    
    class UrlPopupDialog(bpy.types.Operator):
        """Generate Cycles thumbnail for model assets"""
        bl_idname = "wm.blenderkit_url_dialog"
        bl_label = "BlenderKit message:"
        bl_options = {'REGISTER', 'INTERNAL'}
    
        url: bpy.props.StringProperty(
            name="Url",
            description="url",
            default="")
    
        link_text: bpy.props.StringProperty(
            name="Url",
            description="url",
            default="Go to website")
    
        message: bpy.props.StringProperty(
            name="Text",
            description="text",
            default="")
    
        # @classmethod
        # def poll(cls, context):
        #     return bpy.context.view_layer.objects.active is not None
    
        def draw(self, context):
            layout = self.layout
    
            utils.label_multiline(layout, text=self.message, width=300)
    
    
            layout.active_default = True
            op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION')
    
            if not utils.user_logged_in():
                utils.label_multiline(layout,
                                      text='Already subscribed? You need to login to access your Full Plan.',
    
    
                layout.operator_context = 'EXEC_DEFAULT'
                layout.operator("wm.blenderkit_login", text="Login",
                                icon='URL').signup = False
    
            op.url = self.url
    
        def execute(self, context):
            # start_thumbnailer(self, context)
            return {'FINISHED'}
    
        def invoke(self, context, event):
            wm = context.window_manager
    
    
            return wm.invoke_props_dialog(self, width=300)
    
    class LoginPopupDialog(bpy.types.Operator):
    
        """Popup a dialog which enables the user to log in after being logged out automatically."""
        bl_idname = "wm.blenderkit_login_dialog"
    
        bl_label = "BlenderKit login"
        bl_options = {'REGISTER', 'INTERNAL'}
    
        message: bpy.props.StringProperty(
            name="Message",
            description="",
            default="Your were logged out from BlenderKit. Please login again. ")
    
        # @classmethod
        # def poll(cls, context):
        #     return bpy.context.view_layer.objects.active is not None
    
        def draw(self, context):
            layout = self.layout
            utils.label_multiline(layout, text=self.message)
    
            layout.active_default = True
    
            op = layout.operator
    
            op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION')
            op.url = self.url
    
        def execute(self, context):
    
    Vilém Duha's avatar
    Vilém Duha committed
            # start_thumbnailer(self, context)
    
            return {'FINISHED'}
    
        def invoke(self, context, event):
            wm = context.window_manager
    
            return wm.invoke_props_dialog(self)
    
    
    
    Vilem Duha's avatar
    Vilem Duha committed
    def draw_panel_categories(self, context):
        s = context.scene
        ui_props = s.blenderkitUI
        user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
        layout = self.layout
        # row = layout.row()
        # row.prop(ui_props, 'asset_type', expand=True, icon_only=True)
        wm = bpy.context.window_manager