Skip to content
Snippets Groups Projects
autothumb.py 24.9 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 #####
    
    
    Vilém Duha's avatar
    Vilém Duha committed
    from blenderkit import paths, utils, bg_blender, ui_panels, icons, tasks_queue, download
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    import tempfile, os, subprocess, json, sys
    
    import bpy
    
    Vilém Duha's avatar
    Vilém Duha committed
    from bpy.props import (
        FloatProperty,
        IntProperty,
        EnumProperty,
        BoolProperty,
        StringProperty,
    )
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    BLENDERKIT_EXPORT_DATA_FILE = "data.json"
    
    
    Vilém Duha's avatar
    Vilém Duha committed
    thumbnail_resolutions = (
        ('256', '256', ''),
        ('512', '512', ''),
        ('1024', '1024 - minimum for public', ''),
        ('2048', '2048', ''),
    )
    
    thumbnail_angles = (
        ('DEFAULT', 'default', ''),
        ('FRONT', 'front', ''),
        ('SIDE', 'side', ''),
        ('TOP', 'top', ''),
    )
    
    thumbnail_snap = (
        ('GROUND', 'ground', ''),
        ('WALL', 'wall', ''),
        ('CEILING', 'ceiling', ''),
        ('FLOAT', 'floating', ''),
    )
    
    
    def get_texture_ui(tpath, iname):
        tex = bpy.data.textures.get(iname)
    
        if tpath.startswith('//'):
            tpath = bpy.path.abspath(tpath)
    
        if not tex or not tex.image or not tex.image.filepath == tpath:
            tasks_queue.add_task((utils.get_hidden_image, (tpath, iname)), only_last=True)
            tasks_queue.add_task((utils.get_hidden_texture, (iname,)), only_last=True)
            return None
        return tex
    
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    def check_thumbnail(props, imgpath):
        img = utils.get_hidden_image(imgpath, 'upload_preview', force_reload=True)
    
    Vilem Duha's avatar
    Vilem Duha committed
        if img is not None:  # and img.size[0] == img.size[1] and img.size[0] >= 512 and (
            # img.file_format == 'JPEG' or img.file_format == 'PNG'):
            props.has_thumbnail = True
            props.thumbnail_generating_state = ''
    
    Vilém Duha's avatar
    Vilém Duha committed
    
            tex = utils.get_hidden_texture(img.name)
            # pcoll = icons.icon_collections["previews"]
            # pcoll.load(img.name, img.filepath, 'IMAGE')
    
            return img
    
    Vilem Duha's avatar
    Vilem Duha committed
        else:
            props.has_thumbnail = False
        output = ''
        if img is None or img.size[0] == 0 or img.filepath.find('thumbnail_notready.jpg') > -1:
            output += 'No thumbnail or wrong file path\n'
        else:
            pass;
            # this is causing problems on some platforms, don't know why..
            # if img.size[0] != img.size[1]:
            #     output += 'image not a square\n'
            # if img.size[0] < 512:
            #     output += 'image too small, should be at least 512x512\n'
            # if img.file_format != 'JPEG' or img.file_format != 'PNG':
            #     output += 'image has to be a jpeg or png'
        props.thumbnail_generating_state = output
    
    
    def update_upload_model_preview(self, context):
        ob = utils.get_active_model()
        if ob is not None:
            props = ob.blenderkit
            imgpath = props.thumbnail
    
    Vilém Duha's avatar
    Vilém Duha committed
            img = check_thumbnail(props, imgpath)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
    def update_upload_scene_preview(self, context):
        s = bpy.context.scene
        props = s.blenderkit
        imgpath = props.thumbnail
        check_thumbnail(props, imgpath)
    
    
    def update_upload_material_preview(self, context):
        if hasattr(bpy.context, 'active_object') \
    
                and bpy.context.view_layer.objects.active is not None \
    
    Vilem Duha's avatar
    Vilem Duha committed
                and bpy.context.active_object.active_material is not None:
            mat = bpy.context.active_object.active_material
            props = mat.blenderkit
            imgpath = props.thumbnail
            check_thumbnail(props, imgpath)
    
    
    def update_upload_brush_preview(self, context):
        brush = utils.get_active_brush()
        if brush is not None:
            props = brush.blenderkit
            imgpath = bpy.path.abspath(brush.icon_filepath)
            check_thumbnail(props, imgpath)
    
    
    
    Vilém Duha's avatar
    Vilém Duha committed
    def start_thumbnailer(self=None, json_args=None, props=None, wait=False, add_bg_process=True):
    
    Vilem Duha's avatar
    Vilem Duha committed
        # Prepare to save the file
    
        binary_path = bpy.app.binary_path
        script_path = os.path.dirname(os.path.realpath(__file__))
    
    Vilém Duha's avatar
    Vilém Duha committed
    
        ext = '.blend'
    
    
    Vilem Duha's avatar
    Vilem Duha committed
        tfpath = paths.get_thumbnailer_filepath()
    
    Vilém Duha's avatar
    Vilém Duha committed
        datafile = os.path.join(json_args['tempdir'], BLENDERKIT_EXPORT_DATA_FILE)
    
    Vilem Duha's avatar
    Vilem Duha committed
        try:
    
    Vilém Duha's avatar
    Vilém Duha committed
            with open(datafile, 'w', encoding='utf-8') as s:
                json.dump(json_args, s, ensure_ascii=False, indent=4)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
            proc = subprocess.Popen([
                binary_path,
                "--background",
                "-noaudio",
                tfpath,
                "--python", os.path.join(script_path, "autothumb_model_bg.py"),
    
    Vilém Duha's avatar
    Vilém Duha committed
                "--", datafile,
    
            ], bufsize=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE, creationflags=utils.get_process_flags())
    
    Vilém Duha's avatar
    Vilém Duha committed
            eval_path_computing = "bpy.data.objects['%s'].blenderkit.is_generating_thumbnail" % json_args['asset_name']
            eval_path_state = "bpy.data.objects['%s'].blenderkit.thumbnail_generating_state" % json_args['asset_name']
            eval_path = "bpy.data.objects['%s']" % json_args['asset_name']
    
            bg_blender.add_bg_process(name = f"{json_args['asset_name']} thumbnailer" ,eval_path_computing=eval_path_computing, eval_path_state=eval_path_state,
    
    Vilem Duha's avatar
    Vilem Duha committed
                                      eval_path=eval_path, process_type='THUMBNAILER', process=proc)
    
    
        except Exception as e:
            self.report({'WARNING'}, "Error while exporting file: %s" % str(e))
            return {'FINISHED'}
    
    
    
    Vilém Duha's avatar
    Vilém Duha committed
    def start_material_thumbnailer(self=None, json_args=None, props=None, wait=False, add_bg_process=True):
        '''
    
        Parameters
        ----------
        self
        json_args - all arguments:
        props - blenderkit upload props with thumbnail settings, to communicate back, if not present, not used.
        wait - wait for the rendering to finish
    
        Returns
        -------
    
        '''
        if props:
            props.is_generating_thumbnail = True
            props.thumbnail_generating_state = 'starting blender instance'
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        binary_path = bpy.app.binary_path
        script_path = os.path.dirname(os.path.realpath(__file__))
    
    Vilém Duha's avatar
    Vilém Duha committed
    
    
    Vilem Duha's avatar
    Vilem Duha committed
        tfpath = paths.get_material_thumbnailer_filepath()
    
    Vilém Duha's avatar
    Vilém Duha committed
        datafile = os.path.join(json_args['tempdir'], BLENDERKIT_EXPORT_DATA_FILE)
    
    Vilém Duha's avatar
    Vilém Duha committed
        try:
            with open(datafile, 'w', encoding='utf-8') as s:
                json.dump(json_args, s, ensure_ascii=False, indent=4)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
            proc = subprocess.Popen([
                binary_path,
                "--background",
                "-noaudio",
                tfpath,
                "--python", os.path.join(script_path, "autothumb_material_bg.py"),
    
    Vilém Duha's avatar
    Vilém Duha committed
                "--", datafile,
    
            ], bufsize=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE, creationflags=utils.get_process_flags())
    
    Vilém Duha's avatar
    Vilém Duha committed
            eval_path_computing = "bpy.data.materials['%s'].blenderkit.is_generating_thumbnail" % json_args['asset_name']
            eval_path_state = "bpy.data.materials['%s'].blenderkit.thumbnail_generating_state" % json_args['asset_name']
            eval_path = "bpy.data.materials['%s']" % json_args['asset_name']
    
            bg_blender.add_bg_process(name=f"{json_args['asset_name']} thumbnailer", eval_path_computing=eval_path_computing,
    
    Vilém Duha's avatar
    Vilém Duha committed
                                      eval_path_state=eval_path_state,
    
    Vilem Duha's avatar
    Vilem Duha committed
                                      eval_path=eval_path, process_type='THUMBNAILER', process=proc)
    
    Vilém Duha's avatar
    Vilém Duha committed
            if props:
                props.thumbnail_generating_state = 'Saving .blend file'
    
    Vilém Duha's avatar
    Vilém Duha committed
            if wait:
                while proc.poll() is None:
                    stdout_data, stderr_data = proc.communicate()
                    print(stdout_data)
    
    Vilem Duha's avatar
    Vilem Duha committed
        except Exception as e:
    
    Vilém Duha's avatar
    Vilém Duha committed
            if self:
                self.report({'WARNING'}, "Error while packing file: %s" % str(e))
            else:
                print(e)
    
    Vilem Duha's avatar
    Vilem Duha committed
            return {'FINISHED'}
    
    
    class GenerateThumbnailOperator(bpy.types.Operator):
    
        """Generate Cycles thumbnail for model assets"""
    
    Vilem Duha's avatar
    Vilem Duha committed
        bl_idname = "object.blenderkit_generate_thumbnail"
        bl_label = "BlenderKit Thumbnail Generator"
    
    Vilém Duha's avatar
    Vilém Duha committed
        bl_options = {'REGISTER', 'INTERNAL'}
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        @classmethod
        def poll(cls, context):
    
            return bpy.context.view_layer.objects.active is not None
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        def draw(self, context):
            ob = bpy.context.active_object
            while ob.parent is not None:
                ob = ob.parent
            props = ob.blenderkit
            layout = self.layout
            layout.label(text='thumbnailer settings')
            layout.prop(props, 'thumbnail_background_lightness')
            layout.prop(props, 'thumbnail_angle')
            layout.prop(props, 'thumbnail_snap_to')
            layout.prop(props, 'thumbnail_samples')
    
            layout.prop(props, 'thumbnail_resolution')
    
    Vilem Duha's avatar
    Vilem Duha committed
            layout.prop(props, 'thumbnail_denoising')
    
    Vilém Duha's avatar
    Vilém Duha committed
            preferences = bpy.context.preferences.addons['blenderkit'].preferences
            layout.prop(preferences, "thumbnail_use_gpu")
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        def execute(self, context):
    
    Vilém Duha's avatar
    Vilém Duha committed
            asset = utils.get_active_model()
            asset.blenderkit.is_generating_thumbnail = True
            asset.blenderkit.thumbnail_generating_state = 'starting blender instance'
    
            tempdir = tempfile.mkdtemp()
            ext = '.blend'
            filepath = os.path.join(tempdir, "thumbnailer_blenderkit" + ext)
    
            path_can_be_relative = True
            file_dir = os.path.dirname(bpy.data.filepath)
            if file_dir == '':
                file_dir = tempdir
                path_can_be_relative = False
    
            an_slug = paths.slugify(asset.name)
            thumb_path = os.path.join(file_dir, an_slug)
            if path_can_be_relative:
                rel_thumb_path = os.path.join('//', an_slug)
            else:
                rel_thumb_path = thumb_path
    
    
            i = 0
            while os.path.isfile(thumb_path + '.jpg'):
                thumb_path = os.path.join(file_dir, an_slug + '_' + str(i).zfill(4))
                rel_thumb_path = os.path.join('//', an_slug + '_' + str(i).zfill(4))
                i += 1
            bkit = asset.blenderkit
    
            bkit.thumbnail = rel_thumb_path + '.jpg'
            bkit.thumbnail_generating_state = 'Saving .blend file'
    
            # save a copy of actual scene but don't interfere with the users models
            bpy.ops.wm.save_as_mainfile(filepath=filepath, compress=False, copy=True)
            # get all included objects
            obs = utils.get_hierarchy(asset)
            obnames = []
            for ob in obs:
                obnames.append(ob.name)
    
            args_dict = {
                "type": "material",
                "asset_name": asset.name,
                "filepath": filepath,
                "thumbnail_path": thumb_path,
                "tempdir": tempdir,
            }
            thumbnail_args = {
                "type": "model",
                "models": str(obnames),
                "thumbnail_angle": bkit.thumbnail_angle,
                "thumbnail_snap_to": bkit.thumbnail_snap_to,
                "thumbnail_background_lightness": bkit.thumbnail_background_lightness,
                "thumbnail_resolution": bkit.thumbnail_resolution,
                "thumbnail_samples": bkit.thumbnail_samples,
                "thumbnail_denoising": bkit.thumbnail_denoising,
            }
            args_dict.update(thumbnail_args)
    
            start_thumbnailer(self,
                              json_args=args_dict,
                              props=asset.blenderkit, wait=False)
    
    Vilem Duha's avatar
    Vilem Duha committed
            return {'FINISHED'}
    
        def invoke(self, context, event):
            wm = context.window_manager
    
    Vilém Duha's avatar
    Vilém Duha committed
            # if bpy.data.filepath == '':
            #     ui_panels.ui_message(
            #         title="Can't render thumbnail",
            #         message="please save your file first")
            #
            #     return {'FINISHED'}
    
            return wm.invoke_props_dialog(self)
    
    
    class ReGenerateThumbnailOperator(bpy.types.Operator):
    
        """
            Generate default thumbnail with Cycles renderer and upload it.
            Works also for assets from search results, without being downloaded before.
        """
    
    Vilém Duha's avatar
    Vilém Duha committed
        bl_idname = "object.blenderkit_regenerate_thumbnail"
        bl_label = "BlenderKit Thumbnail Re-generate"
        bl_options = {'REGISTER', 'INTERNAL'}
    
        asset_index: IntProperty(name="Asset Index", description='asset index in search results', default=-1)
    
        thumbnail_background_lightness: FloatProperty(name="Thumbnail Background Lightness",
                                                      description="set to make your material stand out", default=1.0,
                                                      min=0.01, max=10)
    
        thumbnail_angle: EnumProperty(
            name='Thumbnail Angle',
            items=thumbnail_angles,
            default='DEFAULT',
            description='thumbnailer angle',
        )
    
        thumbnail_snap_to: EnumProperty(
            name='Model Snaps To:',
            items=thumbnail_snap,
            default='GROUND',
            description='typical placing of the interior. Leave on ground for most objects that respect gravity :)',
        )
    
        thumbnail_resolution: EnumProperty(
            name="Resolution",
            items=thumbnail_resolutions,
            description="Thumbnail resolution",
            default="1024",
        )
    
        thumbnail_samples: IntProperty(name="Cycles Samples",
                                       description="cycles samples setting", default=100,
                                       min=5, max=5000)
        thumbnail_denoising: BoolProperty(name="Use Denoising",
                                          description="Use denoising", default=True)
    
        @classmethod
        def poll(cls, context):
            return True  # bpy.context.view_layer.objects.active is not None
    
        def draw(self, context):
            props = self
            layout = self.layout
    
            # layout.label('This will re-generate thumbnail and directly upload it to server. You should see your updated thumbnail online depending ')
    
    Vilém Duha's avatar
    Vilém Duha committed
            layout.label(text='thumbnailer settings')
            layout.prop(props, 'thumbnail_background_lightness')
            layout.prop(props, 'thumbnail_angle')
            layout.prop(props, 'thumbnail_snap_to')
            layout.prop(props, 'thumbnail_samples')
            layout.prop(props, 'thumbnail_resolution')
            layout.prop(props, 'thumbnail_denoising')
            preferences = bpy.context.preferences.addons['blenderkit'].preferences
            layout.prop(preferences, "thumbnail_use_gpu")
    
    Vilém Duha's avatar
    Vilém Duha committed
        def execute(self, context):
            if not self.asset_index > -1:
                return {'CANCELLED'}
    
            # either get the data from search results
            sr = bpy.context.window_manager['search results']
            asset_data = sr[self.asset_index].to_dict()
    
            tempdir = tempfile.mkdtemp()
    
            an_slug = paths.slugify(asset_data['name'])
            thumb_path = os.path.join(tempdir, an_slug)
    
    
            args_dict = {
                "type": "material",
                "asset_name": asset_data['name'],
                "asset_data": asset_data,
                # "filepath": filepath,
                "thumbnail_path": thumb_path,
                "tempdir": tempdir,
                "do_download": True,
                "upload_after_render": True,
            }
            thumbnail_args = {
                "type": "model",
                "thumbnail_angle": self.thumbnail_angle,
                "thumbnail_snap_to": self.thumbnail_snap_to,
                "thumbnail_background_lightness": self.thumbnail_background_lightness,
                "thumbnail_resolution": self.thumbnail_resolution,
                "thumbnail_samples": self.thumbnail_samples,
                "thumbnail_denoising": self.thumbnail_denoising,
            }
            args_dict.update(thumbnail_args)
    
            start_thumbnailer(self,
                              json_args=args_dict,
                              wait=False)
            return {'FINISHED'}
    
        def invoke(self, context, event):
            wm = context.window_manager
            # if bpy.data.filepath == '':
            #     ui_panels.ui_message(
            #         title="Can't render thumbnail",
            #         message="please save your file first")
            #
            #     return {'FINISHED'}
    
    Vilem Duha's avatar
    Vilem Duha committed
            return wm.invoke_props_dialog(self)
    
    
    class GenerateMaterialThumbnailOperator(bpy.types.Operator):
    
    Vilém Duha's avatar
    Vilém Duha committed
        """Generate default thumbnail with Cycles renderer."""
    
    Vilém Duha's avatar
    Vilém Duha committed
        bl_idname = "object.blenderkit_generate_material_thumbnail"
    
    Vilem Duha's avatar
    Vilem Duha committed
        bl_label = "BlenderKit Material Thumbnail Generator"
    
    Vilém Duha's avatar
    Vilém Duha committed
        bl_options = {'REGISTER', 'INTERNAL'}
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        @classmethod
        def poll(cls, context):
    
            return bpy.context.view_layer.objects.active is not None
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        def check(self, context):
            return True
    
        def draw(self, context):
            layout = self.layout
            props = bpy.context.active_object.active_material.blenderkit
            layout.prop(props, 'thumbnail_generator_type')
            layout.prop(props, 'thumbnail_scale')
            layout.prop(props, 'thumbnail_background')
            if props.thumbnail_background:
                layout.prop(props, 'thumbnail_background_lightness')
    
            layout.prop(props, 'thumbnail_resolution')
    
    Vilem Duha's avatar
    Vilem Duha committed
            layout.prop(props, 'thumbnail_samples')
            layout.prop(props, 'thumbnail_denoising')
            layout.prop(props, 'adaptive_subdivision')
    
    Vilém Duha's avatar
    Vilém Duha committed
            preferences = bpy.context.preferences.addons['blenderkit'].preferences
            layout.prop(preferences, "thumbnail_use_gpu")
    
    Vilem Duha's avatar
    Vilem Duha committed
    
        def execute(self, context):
    
    Vilém Duha's avatar
    Vilém Duha committed
            asset = bpy.context.active_object.active_material
            tempdir = tempfile.mkdtemp()
            filepath = os.path.join(tempdir, "material_thumbnailer_cycles.blend")
            # save a copy of actual scene but don't interfere with the users models
            bpy.ops.wm.save_as_mainfile(filepath=filepath, compress=False, copy=True)
    
            thumb_dir = os.path.dirname(bpy.data.filepath)
            thumb_path = os.path.join(thumb_dir, asset.name)
            rel_thumb_path = os.path.join('//', asset.name)
            # auto increase number of the generated thumbnail.
            i = 0
            while os.path.isfile(thumb_path + '.png'):
                thumb_path = os.path.join(thumb_dir, asset.name + '_' + str(i).zfill(4))
                rel_thumb_path = os.path.join('//', asset.name + '_' + str(i).zfill(4))
                i += 1
    
            asset.blenderkit.thumbnail = rel_thumb_path + '.png'
            bkit = asset.blenderkit
    
            args_dict = {
                "type": "material",
                "asset_name": asset.name,
                "filepath": filepath,
                "thumbnail_path": thumb_path,
                "tempdir": tempdir,
            }
    
            thumbnail_args = {
                "thumbnail_type": bkit.thumbnail_generator_type,
                "thumbnail_scale": bkit.thumbnail_scale,
                "thumbnail_background": bkit.thumbnail_background,
                "thumbnail_background_lightness": bkit.thumbnail_background_lightness,
                "thumbnail_resolution": bkit.thumbnail_resolution,
                "thumbnail_samples": bkit.thumbnail_samples,
                "thumbnail_denoising": bkit.thumbnail_denoising,
                "adaptive_subdivision": bkit.adaptive_subdivision,
                "texture_size_meters": bkit.texture_size_meters,
            }
            args_dict.update(thumbnail_args)
            start_material_thumbnailer(self,
                                       json_args=args_dict,
                                       props=asset.blenderkit, wait=False)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
            return {'FINISHED'}
    
        def invoke(self, context, event):
            wm = context.window_manager
            return wm.invoke_props_dialog(self)
    
    
    
    Vilém Duha's avatar
    Vilém Duha committed
    class ReGenerateMaterialThumbnailOperator(bpy.types.Operator):
        """
    
            Generate default thumbnail with Cycles renderer and upload it.
    
            Works also for assets from search results, without being downloaded before
    
    Vilém Duha's avatar
    Vilém Duha committed
        """
        bl_idname = "object.blenderkit_regenerate_material_thumbnail"
        bl_label = "BlenderKit Material Thumbnail Re-Generator"
        bl_options = {'REGISTER', 'INTERNAL'}
    
        asset_index: IntProperty(name="Asset Index", description='asset index in search results', default=-1)
    
        thumbnail_scale: FloatProperty(name="Thumbnail Object Size",
                                       description="Size of material preview object in meters."
                                                   "Change for materials that look better at sizes different than 1m",
                                       default=1, min=0.00001, max=10)
        thumbnail_background: BoolProperty(name="Thumbnail Background (for Glass only)",
                                           description="For refractive materials, you might need a background.\n"
                                                       "Don't use for other types of materials.\n"
                                                       "Transparent background is preferred",
                                           default=False)
        thumbnail_background_lightness: FloatProperty(name="Thumbnail Background Lightness",
                                                      description="Set to make your material stand out with enough contrast",
                                                      default=.9,
                                                      min=0.00001, max=1)
        thumbnail_samples: IntProperty(name="Cycles Samples",
                                       description="Cycles samples", default=100,
                                       min=5, max=5000)
        thumbnail_denoising: BoolProperty(name="Use Denoising",
                                          description="Use denoising", default=True)
        adaptive_subdivision: BoolProperty(name="Adaptive Subdivide",
                                           description="Use adaptive displacement subdivision", default=False)
    
        thumbnail_resolution: EnumProperty(
            name="Resolution",
            items=thumbnail_resolutions,
            description="Thumbnail resolution",
            default="1024",
        )
    
        thumbnail_generator_type: EnumProperty(
            name="Thumbnail Style",
            items=(
                ('BALL', 'Ball', ""),
                ('BALL_COMPLEX', 'Ball complex', 'Complex ball to highlight edgewear or material thickness'),
                ('FLUID', 'Fluid', 'Fluid'),
                ('CLOTH', 'Cloth', 'Cloth'),
                ('HAIR', 'Hair', 'Hair  ')
            ),
            description="Style of asset",
            default="BALL",
        )
    
        @classmethod
        def poll(cls, context):
            return True  # bpy.context.view_layer.objects.active is not None
    
        def check(self, context):
            return True
    
        def draw(self, context):
            layout = self.layout
            props = self
            layout.prop(props, 'thumbnail_generator_type')
            layout.prop(props, 'thumbnail_scale')
            layout.prop(props, 'thumbnail_background')
            if props.thumbnail_background:
                layout.prop(props, 'thumbnail_background_lightness')
            layout.prop(props, 'thumbnail_resolution')
            layout.prop(props, 'thumbnail_samples')
            layout.prop(props, 'thumbnail_denoising')
            layout.prop(props, 'adaptive_subdivision')
            preferences = bpy.context.preferences.addons['blenderkit'].preferences
            layout.prop(preferences, "thumbnail_use_gpu")
    
        def execute(self, context):
    
            if not self.asset_index > -1:
                return {'CANCELLED'}
    
            # either get the data from search results
            sr = bpy.context.window_manager['search results']
            asset_data = sr[self.asset_index].to_dict()
    
            tempdir = tempfile.mkdtemp()
    
            thumb_path = os.path.join(tempdir, asset_data['name'])
    
            args_dict = {
                "type": "material",
                "asset_name": asset_data['name'],
                "asset_data": asset_data,
                "thumbnail_path": thumb_path,
                "tempdir": tempdir,
                "do_download": True,
                "upload_after_render": True,
            }
            thumbnail_args = {
                "thumbnail_type": self.thumbnail_generator_type,
                "thumbnail_scale": self.thumbnail_scale,
                "thumbnail_background": self.thumbnail_background,
                "thumbnail_background_lightness": self.thumbnail_background_lightness,
                "thumbnail_resolution": self.thumbnail_resolution,
                "thumbnail_samples": self.thumbnail_samples,
                "thumbnail_denoising": self.thumbnail_denoising,
                "adaptive_subdivision": self.adaptive_subdivision,
                "texture_size_meters": utils.get_param(asset_data, 'textureSizeMeters', 1.0),
            }
            args_dict.update(thumbnail_args)
            start_material_thumbnailer(self,
                                       json_args=args_dict,
                                       wait=False)
    
            return {'FINISHED'}
    
        def invoke(self, context, event):
            # scene = bpy.context.scene
            # ui_props = scene.blenderkitUI
            # if ui_props.active_index > -1:
            #     sr = bpy.context.window_manager['search results']
            #     self.asset_data = dict(sr[ui_props.active_index])
            # else:
            #
            #     active_asset = utils.get_active_asset_by_type(asset_type = self.asset_type)
            #     self.asset_data = active_asset.get('asset_data')
    
            wm = context.window_manager
            return wm.invoke_props_dialog(self)
    
    
    
    Vilem Duha's avatar
    Vilem Duha committed
    def register_thumbnailer():
        bpy.utils.register_class(GenerateThumbnailOperator)
    
    Vilém Duha's avatar
    Vilém Duha committed
        bpy.utils.register_class(ReGenerateThumbnailOperator)
    
    Vilem Duha's avatar
    Vilem Duha committed
        bpy.utils.register_class(GenerateMaterialThumbnailOperator)
    
    Vilém Duha's avatar
    Vilém Duha committed
        bpy.utils.register_class(ReGenerateMaterialThumbnailOperator)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
    def unregister_thumbnailer():
        bpy.utils.unregister_class(GenerateThumbnailOperator)
    
    Vilém Duha's avatar
    Vilém Duha committed
        bpy.utils.unregister_class(ReGenerateThumbnailOperator)
    
    Vilem Duha's avatar
    Vilem Duha committed
        bpy.utils.unregister_class(GenerateMaterialThumbnailOperator)
    
    Vilém Duha's avatar
    Vilém Duha committed
        bpy.utils.unregister_class(ReGenerateMaterialThumbnailOperator)