Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'blenderkit/autothumb.py')
-rw-r--r--blenderkit/autothumb.py671
1 files changed, 0 insertions, 671 deletions
diff --git a/blenderkit/autothumb.py b/blenderkit/autothumb.py
deleted file mode 100644
index 330d31a2..00000000
--- a/blenderkit/autothumb.py
+++ /dev/null
@@ -1,671 +0,0 @@
-# ##### 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 #####
-
-from blenderkit import paths, utils, bg_blender, ui_panels, icons, tasks_queue, download
-
-import tempfile, os, subprocess, json, sys
-
-import bpy
-from bpy.props import (
- FloatProperty,
- IntProperty,
- EnumProperty,
- BoolProperty,
- StringProperty,
-)
-
-BLENDERKIT_EXPORT_DATA_FILE = "data.json"
-
-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
-
-
-def check_thumbnail(props, imgpath):
- img = utils.get_hidden_image(imgpath, 'upload_preview', force_reload=True)
- # print(' check thumbnail ', img)
- 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 = ''
-
- tex = utils.get_hidden_texture(img.name)
- # pcoll = icons.icon_collections["previews"]
- # pcoll.load(img.name, img.filepath, 'IMAGE')
-
- return img
- 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
- img = check_thumbnail(props, imgpath)
-
-
-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 \
- 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)
-
-
-def start_thumbnailer(self=None, json_args=None, props=None, wait=False, add_bg_process=True):
- # Prepare to save the file
-
- binary_path = bpy.app.binary_path
- script_path = os.path.dirname(os.path.realpath(__file__))
-
- ext = '.blend'
-
- tfpath = paths.get_thumbnailer_filepath()
- datafile = os.path.join(json_args['tempdir'], BLENDERKIT_EXPORT_DATA_FILE)
- try:
- with open(datafile, 'w', encoding='utf-8') as s:
- json.dump(json_args, s, ensure_ascii=False, indent=4)
-
- proc = subprocess.Popen([
- binary_path,
- "--background",
- "-noaudio",
- tfpath,
- "--python", os.path.join(script_path, "autothumb_model_bg.py"),
- "--", datafile,
- ], bufsize=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE, creationflags=utils.get_process_flags())
-
- 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,
- 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'}
-
-
-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'
-
- binary_path = bpy.app.binary_path
- script_path = os.path.dirname(os.path.realpath(__file__))
-
- tfpath = paths.get_material_thumbnailer_filepath()
- datafile = os.path.join(json_args['tempdir'], BLENDERKIT_EXPORT_DATA_FILE)
-
- try:
- with open(datafile, 'w', encoding='utf-8') as s:
- json.dump(json_args, s, ensure_ascii=False, indent=4)
-
- proc = subprocess.Popen([
- binary_path,
- "--background",
- "-noaudio",
- tfpath,
- "--python", os.path.join(script_path, "autothumb_material_bg.py"),
- "--", datafile,
- ], bufsize=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE, creationflags=utils.get_process_flags())
-
- 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,
- eval_path_state=eval_path_state,
- eval_path=eval_path, process_type='THUMBNAILER', process=proc)
- if props:
- props.thumbnail_generating_state = 'Saving .blend file'
-
- if wait:
- while proc.poll() is None:
- stdout_data, stderr_data = proc.communicate()
- print(stdout_data)
- except Exception as e:
- if self:
- self.report({'WARNING'}, "Error while packing file: %s" % str(e))
- else:
- print(e)
- return {'FINISHED'}
-
-
-class GenerateThumbnailOperator(bpy.types.Operator):
- """Generate Cycles thumbnail for model assets"""
- bl_idname = "object.blenderkit_generate_thumbnail"
- bl_label = "BlenderKit Thumbnail Generator"
- bl_options = {'REGISTER', 'INTERNAL'}
-
- @classmethod
- def poll(cls, context):
- return bpy.context.view_layer.objects.active is not None
-
- 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')
- layout.prop(props, 'thumbnail_denoising')
- preferences = bpy.context.preferences.addons['blenderkit'].preferences
- layout.prop(preferences, "thumbnail_use_gpu")
-
- def execute(self, context):
- 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'
-
- # if this isn't here, blender crashes.
- bpy.context.preferences.filepaths.file_preview_type = 'NONE'
- # 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)
- 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'}
-
- 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
- """
- 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 ')
- 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")
-
- 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'}
-
- return wm.invoke_props_dialog(self)
-
-
-class GenerateMaterialThumbnailOperator(bpy.types.Operator):
- """Generate default thumbnail with Cycles renderer"""
- bl_idname = "object.blenderkit_generate_material_thumbnail"
- bl_label = "BlenderKit Material Thumbnail Generator"
- bl_options = {'REGISTER', 'INTERNAL'}
-
- @classmethod
- def poll(cls, context):
- return bpy.context.view_layer.objects.active is not None
-
- 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')
- 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):
- asset = bpy.context.active_object.active_material
- tempdir = tempfile.mkdtemp()
- filepath = os.path.join(tempdir, "material_thumbnailer_cycles.blend")
- # if this isn't here, blender crashes.
- bpy.context.preferences.filepaths.file_preview_type = 'NONE'
-
- # 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)
- an_slug = paths.slugify(asset.name)
-
- thumb_path = os.path.join(thumb_dir, an_slug)
- rel_thumb_path = os.path.join('//', an_slug)
-
- # auto increase number of the generated thumbnail.
- i = 0
- while os.path.isfile(thumb_path + '.png'):
- thumb_path = os.path.join(thumb_dir, an_slug + '_' + str(i).zfill(4))
- rel_thumb_path = os.path.join('//', an_slug + '_' + 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)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- return wm.invoke_props_dialog(self)
-
-
-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
- """
- 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()
- an_slug = paths.slugify(asset_data['name'])
-
- tempdir = tempfile.mkdtemp()
-
- thumb_path = os.path.join(tempdir,an_slug)
-
- 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 = bpy.context.window_manager.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)
-
-
-def register_thumbnailer():
- bpy.utils.register_class(GenerateThumbnailOperator)
- bpy.utils.register_class(ReGenerateThumbnailOperator)
- bpy.utils.register_class(GenerateMaterialThumbnailOperator)
- bpy.utils.register_class(ReGenerateMaterialThumbnailOperator)
-
-
-def unregister_thumbnailer():
- bpy.utils.unregister_class(GenerateThumbnailOperator)
- bpy.utils.unregister_class(ReGenerateThumbnailOperator)
- bpy.utils.unregister_class(GenerateMaterialThumbnailOperator)
- bpy.utils.unregister_class(ReGenerateMaterialThumbnailOperator)