Skip to content
Snippets Groups Projects
ui_panels.py 50.2 KiB
Newer Older
  • Learn to ignore specific revisions
  •             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(self, context, asset_data):
        layout = self.layout
        ui_props = context.scene.blenderkitUI
    
        author_id = str(asset_data['author']['id'])
        wm = bpy.context.window_manager
        if wm.get('bkit authors') 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')
    
        #build search string from description and tags:
        op.keywords = asset_data['name']
        if asset_data.get('description'):
            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)
                if ui_props.active_index == -3:
    
    Vilém Duha's avatar
    Vilém Duha committed
                    # 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
                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
    
        wm = bpy.context.window_manager
        profile = wm.get('bkit profile')
        if profile is not None:
            # validation
            if utils.profile_is_validator():
                layout.label(text='Validation tools:')
                if asset_data['verificationStatus'] != 'uploaded':
                    op = layout.operator('object.blenderkit_change_status', text='set Uploaded')
                    op.asset_id = asset_data['id']
                    op.state = 'uploaded'
                if asset_data['verificationStatus'] != 'validated':
                    op = layout.operator('object.blenderkit_change_status', text='Validate')
                    op.asset_id = asset_data['id']
                    op.state = 'validated'
                if asset_data['verificationStatus'] != 'on_hold':
                    op = layout.operator('object.blenderkit_change_status', text='Put on Hold')
                    op.asset_id = asset_data['id']
                    op.state = 'on_hold'
                if asset_data['verificationStatus'] != 'rejected':
                    op = layout.operator('object.blenderkit_change_status', text='Reject')
                    op.asset_id = asset_data['id']
                    op.state = 'rejected'
    
    
            if author_id == str(profile['user']['id']):
                layout.label(text='Management tools:')
                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='Admin rating Tools:')
    
                op = layout.operator('wm.blenderkit_menu_rating_upload', text='Fast rate')
                op.asset_id = asset_data['id']
                op.asset_type = asset_data['assetType']
    
    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.scene['search results']
    
            sr = bpy.context.scene['search results']
    
            asset_data = sr[ui_props.active_index]
    
            draw_asset_context_menu(self, context, asset_data)
    
    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)
    
            layout.active_default = True
            op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION')
            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)
    
    
    class LoginPopupDialog(bpy.types.Operator):
        """Generate Cycles thumbnail for model assets"""
        bl_idname = "wm.blenderkit_url_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)
        layout.separator()
    
    Vilém Duha's avatar
    Vilém Duha committed
    
    
    Vilem Duha's avatar
    Vilem Duha committed
        layout.label(text='Categories')
        wm = bpy.context.window_manager
    
    Vilém Duha's avatar
    Vilém Duha committed
        if wm.get('bkit_categories') == None:
            return
    
    Vilem Duha's avatar
    Vilem Duha committed
        col = layout.column(align=True)
        if wm.get('active_category') is not None:
            acat = wm['active_category'][ui_props.asset_type]
            if len(acat) > 1:
                # we are in subcategory, so draw the parent button
                op = col.operator('view3d.blenderkit_set_category', text='...', icon='FILE_PARENT')
                op.asset_type = ui_props.asset_type
                op.category = ''
        cats = categories.get_category(wm['bkit_categories'], cat_path=acat)
        # draw freebies only in models parent category
    
        # if ui_props.asset_type == 'MODEL' and len(acat) == 1:
        #     op = col.operator('view3d.blenderkit_asset_bar', text='freebies')
        #     op.free_only = True
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        for c in cats['children']:
            if c['assetCount'] > 0:
                row = col.row(align=True)
                if len(c['children']) > 0 and c['assetCount'] > 15:
                    row = row.split(factor=.8, align=True)
                # row = split.split()
                ctext = '%s (%i)' % (c['name'], c['assetCount'])
                op = row.operator('view3d.blenderkit_asset_bar', text=ctext)
                op.do_search = True
                op.keep_running = True
                op.category = c['slug']
                # TODO enable subcategories, now not working due to some bug on server probably
                if len(c['children']) > 0 and c['assetCount'] > 15:
                    # row = row.split()
                    op = row.operator('view3d.blenderkit_set_category', text='>>')
                    op.asset_type = ui_props.asset_type
                    op.category = c['slug']
                    # for c1 in c['children']:
                    #     if c1['assetCount']>0:
                    #         row = col.row()
                    #         split = row.split(percentage=.2)
                    #         row = split.split()
                    #         row = split.split()
                    #         ctext = '%s (%i)' % (c1['name'], c1['assetCount'])
                    #         op = row.operator('view3d.blenderkit_search', text=ctext)
                    #         op.category = c1['slug']
    
    
    class VIEW3D_PT_blenderkit_downloads(Panel):
        bl_category = "BlenderKit"
        bl_idname = "VIEW3D_PT_blenderkit_downloads"
        bl_space_type = 'VIEW_3D'
        bl_region_type = 'UI'
        bl_label = "Downloads"
    
        @classmethod
        def poll(cls, context):
            return len(download.download_threads) > 0
    
        def draw(self, context):
            layout = self.layout
            for threaddata in download.download_threads:
                tcom = threaddata[2]
                asset_data = threaddata[1]
                row = layout.row()
                row.label(text=asset_data['name'])
                row.label(text=str(int(tcom.progress)) + ' %')
    
                row.operator('scene.blenderkit_download_kill', text='', icon='CANCEL')
    
                if tcom.passargs.get('retry_counter', 0) > 0:
    
                    row = layout.row()
    
                    row.label(text='failed. retrying ... ', icon='ERROR')
                    row.label(text=str(tcom.passargs["retry_counter"]))
    
    
                    layout.separator()
    
    def header_search_draw(self, context):
    
        '''Top bar menu in 3D view'''
    
    
        if not utils.guard_from_crash():
            return;
    
    
        preferences = bpy.context.preferences.addons['blenderkit'].preferences
        if preferences.search_in_header:
            layout = self.layout
            s = bpy.context.scene
            ui_props = s.blenderkitUI
            if ui_props.asset_type == 'MODEL':
                props = s.blenderkit_models
            if ui_props.asset_type == 'MATERIAL':
                props = s.blenderkit_mat
            if ui_props.asset_type == 'BRUSH':
                props = s.blenderkit_brush
    
    Vilém Duha's avatar
    Vilém Duha committed
            # the center snap menu is in edit and object mode if tool settings are off.
            if context.space_data.show_region_tool_header == True or context.mode[:4] not in ('EDIT', 'OBJE'):
    
                layout.separator_spacer()
    
            layout.prop(ui_props, "asset_type", text='', icon='URL')
            layout.prop(props, "search_keywords", text="", icon='VIEWZOOM')
            draw_assetbar_show_hide(layout, props)
    
    
    
    # We can store multiple preview collections here,
    # however in this example we only store "main"
    preview_collections = {}
    
    Vilem Duha's avatar
    Vilem Duha committed
    classess = (
        SetCategoryOperator,
    
    Vilém Duha's avatar
    Vilém Duha committed
        VIEW3D_PT_blenderkit_profile,
        VIEW3D_PT_blenderkit_login,
    
    Vilem Duha's avatar
    Vilem Duha committed
        VIEW3D_PT_blenderkit_unified,
    
        VIEW3D_PT_blenderkit_advanced_model_search,
    
        VIEW3D_PT_blenderkit_advanced_material_search,
    
        VIEW3D_PT_blenderkit_categories,
        VIEW3D_PT_blenderkit_import_settings,
    
    Vilem Duha's avatar
    Vilem Duha committed
        VIEW3D_PT_blenderkit_model_properties,
    
        # VIEW3D_PT_blenderkit_ratings,
    
    Vilem Duha's avatar
    Vilem Duha committed
        VIEW3D_PT_blenderkit_downloads,
    
        OBJECT_MT_blenderkit_asset_menu,
    
        OBJECT_MT_blenderkit_login_menu,
    
        UrlPopupDialog,
        BlenderKitWelcomeOperator,
    
    Vilem Duha's avatar
    Vilem Duha committed
    def register_ui_panels():
        for c in classess:
            bpy.utils.register_class(c)
    
        bpy.types.VIEW3D_MT_editor_menus.append(header_search_draw)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
    def unregister_ui_panels():
    
        bpy.types.VIEW3D_MT_editor_menus.remove(header_search_draw)
    
    Vilem Duha's avatar
    Vilem Duha committed
        for c in classess:
    
            print('unregister', c)
    
    Vilem Duha's avatar
    Vilem Duha committed
            bpy.utils.unregister_class(c)