Data previews: add utils to generate/clear previews.
Not much to add, you can now clear previews from current .blend file, or a set of non-opened files. Likewise, you can generate previews (for mat/tex, objects, groups, scenes, ...).
This commit is contained in:
		
							
								
								
									
										489
									
								
								release/scripts/modules/bl_previews_utils/bl_previews_render.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										489
									
								
								release/scripts/modules/bl_previews_utils/bl_previews_render.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,489 @@
 | 
				
			|||||||
 | 
					# ***** 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 *****
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# <pep8 compliant>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Populate a template file (POT format currently) from Blender RNA/py/C data.
 | 
				
			||||||
 | 
					# Note: This script is meant to be used from inside Blender!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import collections
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import bpy
 | 
				
			||||||
 | 
					from mathutils import Vector, Euler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INTERN_PREVIEW_TYPES = {'MATERIAL', 'LAMP', 'WORLD', 'TEXTURE', 'IMAGE'}
 | 
				
			||||||
 | 
					OBJECT_TYPES_RENDER = {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def rna_backup_gen(data, include_props=None, exclude_props=None, root=()):
 | 
				
			||||||
 | 
					    # only writable properties...
 | 
				
			||||||
 | 
					    for p in data.bl_rna.properties:
 | 
				
			||||||
 | 
					        pid = p.identifier
 | 
				
			||||||
 | 
					        if pid in {'rna_type',}:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        path = root + (pid,)
 | 
				
			||||||
 | 
					        if include_props is not None and path not in include_props:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        if exclude_props is not None and path in exclude_props:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        val = getattr(data, pid)
 | 
				
			||||||
 | 
					        if val is not None and p.type == 'POINTER':
 | 
				
			||||||
 | 
					            # recurse!
 | 
				
			||||||
 | 
					            yield from rna_backup_gen(val, include_props, exclude_props, root=path)
 | 
				
			||||||
 | 
					        elif data.is_property_readonly(pid):
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            yield path, val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def rna_backup_restore(data, backup):
 | 
				
			||||||
 | 
					    for path, val in backup:
 | 
				
			||||||
 | 
					        dt = data
 | 
				
			||||||
 | 
					        for pid in path[:-1]:
 | 
				
			||||||
 | 
					            dt = getattr(dt, pid)
 | 
				
			||||||
 | 
					        setattr(dt, path[-1], val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def do_previews(do_objects, do_groups, do_scenes, do_data_intern):
 | 
				
			||||||
 | 
					    # Helpers.
 | 
				
			||||||
 | 
					    RenderContext = collections.namedtuple("RenderContext", (
 | 
				
			||||||
 | 
					        "scene", "world", "camera", "lamp", "camera_data", "lamp_data", "image",  # All those are names!
 | 
				
			||||||
 | 
					        "backup_scene", "backup_world", "backup_camera", "backup_lamp", "backup_camera_data", "backup_lamp_data",
 | 
				
			||||||
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RENDER_PREVIEW_SIZE = bpy.app.render_preview_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def render_context_create(engine, objects_ignored):
 | 
				
			||||||
 | 
					        if engine == '__SCENE':
 | 
				
			||||||
 | 
					            backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data = [()] * 6
 | 
				
			||||||
 | 
					            scene = bpy.context.screen.scene
 | 
				
			||||||
 | 
					            exclude_props = {('world',), ('camera',), ('tool_settings',), ('preview',)}
 | 
				
			||||||
 | 
					            backup_scene = tuple(rna_backup_gen(scene, exclude_props=exclude_props))
 | 
				
			||||||
 | 
					            world = scene.world
 | 
				
			||||||
 | 
					            camera = scene.camera
 | 
				
			||||||
 | 
					            if camera:
 | 
				
			||||||
 | 
					                camera_data = camera.data
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                backup_camera, backup_camera_data = [None] * 2
 | 
				
			||||||
 | 
					                camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
 | 
				
			||||||
 | 
					                camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
 | 
				
			||||||
 | 
					                camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ')  # (66.67, 0.0, 45.0)
 | 
				
			||||||
 | 
					                scene.camera = camera
 | 
				
			||||||
 | 
					                scene.objects.link(camera)
 | 
				
			||||||
 | 
					            # TODO: add lamp if none found in scene?
 | 
				
			||||||
 | 
					            lamp = None
 | 
				
			||||||
 | 
					            lamp_data = None
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data = [None] * 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            scene = bpy.data.scenes.new("TEMP_preview_render_scene")
 | 
				
			||||||
 | 
					            world = bpy.data.worlds.new("TEMP_preview_render_world")
 | 
				
			||||||
 | 
					            camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
 | 
				
			||||||
 | 
					            camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
 | 
				
			||||||
 | 
					            lamp_data = bpy.data.lamps.new("TEMP_preview_render_lamp", 'SPOT')
 | 
				
			||||||
 | 
					            lamp = bpy.data.objects.new("TEMP_preview_render_lamp", lamp_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            objects_ignored.add((camera.name, lamp.name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            scene.world = world
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ')  # (66.67, 0.0, 45.0)
 | 
				
			||||||
 | 
					            scene.camera = camera
 | 
				
			||||||
 | 
					            scene.objects.link(camera)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            lamp.rotation_euler = Euler((0.7853981852531433, 0.0, 1.7453292608261108), 'XYZ')  # (45.0, 0.0, 100.0)
 | 
				
			||||||
 | 
					            lamp_data.falloff_type = 'CONSTANT'
 | 
				
			||||||
 | 
					            lamp_data.spot_size = 1.0471975803375244  # 60
 | 
				
			||||||
 | 
					            scene.objects.link(lamp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if engine == 'BLENDER_RENDER':
 | 
				
			||||||
 | 
					                scene.render.engine = 'BLENDER_RENDER'
 | 
				
			||||||
 | 
					                scene.render.alpha_mode = 'TRANSPARENT'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                world.use_sky_blend = True
 | 
				
			||||||
 | 
					                world.horizon_color = 0.9, 0.9, 0.9
 | 
				
			||||||
 | 
					                world.zenith_color = 0.5, 0.5, 0.5
 | 
				
			||||||
 | 
					                world.ambient_color = 0.1, 0.1, 0.1
 | 
				
			||||||
 | 
					                world.light_settings.use_environment_light = True
 | 
				
			||||||
 | 
					                world.light_settings.environment_energy = 1.0
 | 
				
			||||||
 | 
					                world.light_settings.environment_color = 'SKY_COLOR'
 | 
				
			||||||
 | 
					            elif engine == 'CYCLES':
 | 
				
			||||||
 | 
					                scene.render.engine = 'CYCLES'
 | 
				
			||||||
 | 
					                scene.cycles.film_transparent = True
 | 
				
			||||||
 | 
					                # TODO: define Cycles world?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        scene.render.image_settings.file_format = 'PNG'
 | 
				
			||||||
 | 
					        scene.render.image_settings.color_depth = '8'
 | 
				
			||||||
 | 
					        scene.render.image_settings.color_mode = 'RGBA'
 | 
				
			||||||
 | 
					        scene.render.image_settings.compression = 25
 | 
				
			||||||
 | 
					        scene.render.resolution_x = RENDER_PREVIEW_SIZE
 | 
				
			||||||
 | 
					        scene.render.resolution_y = RENDER_PREVIEW_SIZE
 | 
				
			||||||
 | 
					        scene.render.resolution_percentage = 100
 | 
				
			||||||
 | 
					        scene.render.filepath = os.path.join(bpy.app.tempdir, 'TEMP_preview_render.png')
 | 
				
			||||||
 | 
					        scene.render.use_overwrite = True
 | 
				
			||||||
 | 
					        scene.render.use_stamp = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        image = bpy.data.images.new("TEMP_render_image", RENDER_PREVIEW_SIZE, RENDER_PREVIEW_SIZE, alpha=True)
 | 
				
			||||||
 | 
					        image.source = 'FILE'
 | 
				
			||||||
 | 
					        image.filepath = scene.render.filepath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return RenderContext(
 | 
				
			||||||
 | 
					            scene.name, world.name if world else None, camera.name, lamp.name if lamp else None,
 | 
				
			||||||
 | 
					            camera_data.name, lamp_data.name if lamp_data else None, image.name,
 | 
				
			||||||
 | 
					            backup_scene, backup_world, backup_camera, backup_lamp, backup_camera_data, backup_lamp_data,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def render_context_delete(render_context):
 | 
				
			||||||
 | 
					        # We use try/except blocks here to avoid crash, too much things can go wrong, and we want to leave the current
 | 
				
			||||||
 | 
					        # .blend as clean as possible!
 | 
				
			||||||
 | 
					        success = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        scene = bpy.data.scenes[render_context.scene]
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if render_context.backup_scene is None:
 | 
				
			||||||
 | 
					                scene.world = None
 | 
				
			||||||
 | 
					                scene.camera = None
 | 
				
			||||||
 | 
					                if render_context.camera:
 | 
				
			||||||
 | 
					                    scene.objects.unlink(bpy.data.objects[render_context.camera])
 | 
				
			||||||
 | 
					                if render_context.lamp:
 | 
				
			||||||
 | 
					                    scene.objects.unlink(bpy.data.objects[render_context.lamp])
 | 
				
			||||||
 | 
					                bpy.data.scenes.remove(scene)
 | 
				
			||||||
 | 
					                scene = None
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                rna_backup_restore(scene, render_context.backup_scene)
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            print("ERROR:", e)
 | 
				
			||||||
 | 
					            success = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if render_context.world is not None:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                world = bpy.data.worlds[render_context.world]
 | 
				
			||||||
 | 
					                if render_context.backup_world is None:
 | 
				
			||||||
 | 
					                    if scene is not None:
 | 
				
			||||||
 | 
					                        scene.world = None
 | 
				
			||||||
 | 
					                    world.user_clear()
 | 
				
			||||||
 | 
					                    bpy.data.worlds.remove(world)
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    rna_backup_restore(world, render_context.backup_world)
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                print("ERROR:", e)
 | 
				
			||||||
 | 
					                success = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if render_context.camera:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                camera = bpy.data.objects[render_context.camera]
 | 
				
			||||||
 | 
					                if render_context.backup_camera is None:
 | 
				
			||||||
 | 
					                    if scene is not None:
 | 
				
			||||||
 | 
					                        scene.camera = None
 | 
				
			||||||
 | 
					                        scene.objects.unlink(camera)
 | 
				
			||||||
 | 
					                    camera.user_clear()
 | 
				
			||||||
 | 
					                    bpy.data.objects.remove(camera)
 | 
				
			||||||
 | 
					                    bpy.data.cameras.remove(bpy.data.cameras[render_context.camera_data])
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    rna_backup_restore(camera, render_context.backup_camera)
 | 
				
			||||||
 | 
					                    rna_backup_restore(bpy.data.cameras[render_context.camera_data], render_context.backup_camera_data)
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                print("ERROR:", e)
 | 
				
			||||||
 | 
					                success = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if render_context.lamp:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                lamp = bpy.data.objects[render_context.lamp]
 | 
				
			||||||
 | 
					                if render_context.backup_lamp is None:
 | 
				
			||||||
 | 
					                    if scene is not None:
 | 
				
			||||||
 | 
					                        scene.objects.unlink(lamp)
 | 
				
			||||||
 | 
					                    lamp.user_clear()
 | 
				
			||||||
 | 
					                    bpy.data.objects.remove(lamp)
 | 
				
			||||||
 | 
					                    bpy.data.lamps.remove(bpy.data.lamps[render_context.lamp_data])
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    rna_backup_restore(lamp, render_context.backup_lamp)
 | 
				
			||||||
 | 
					                    rna_backup_restore(bpy.data.lamps[render_context.lamp_data], render_context.backup_lamp_data)
 | 
				
			||||||
 | 
					            except Exception as e:
 | 
				
			||||||
 | 
					                print("ERROR:", e)
 | 
				
			||||||
 | 
					                success = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            image = bpy.data.images[render_context.image]
 | 
				
			||||||
 | 
					            image.user_clear()
 | 
				
			||||||
 | 
					            bpy.data.images.remove(image)
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            print("ERROR:", e)
 | 
				
			||||||
 | 
					            success = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return success
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def objects_render_engine_guess(obs):
 | 
				
			||||||
 | 
					        for obname in obs:
 | 
				
			||||||
 | 
					            ob = bpy.data.objects[obname]
 | 
				
			||||||
 | 
					            for matslot in ob.material_slots:
 | 
				
			||||||
 | 
					                mat = matslot.material
 | 
				
			||||||
 | 
					                if mat and mat.use_nodes and mat.node_tree:
 | 
				
			||||||
 | 
					                    for nd in mat.node_tree.nodes:
 | 
				
			||||||
 | 
					                        if nd.shading_compatibility == {'NEW_SHADING'}:
 | 
				
			||||||
 | 
					                            return 'CYCLES'
 | 
				
			||||||
 | 
					        return 'BLENDER_RENDER'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def object_bbox_merge(bbox, ob, ob_space):
 | 
				
			||||||
 | 
					        if ob.bound_box:
 | 
				
			||||||
 | 
					            ob_bbox = ob.bound_box
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            ob_bbox = ((-ob.scale.x, -ob.scale.y, -ob.scale.z), (ob.scale.x, ob.scale.y, ob.scale.z))
 | 
				
			||||||
 | 
					        for v in ob.bound_box:
 | 
				
			||||||
 | 
					            v = ob_space.matrix_world.inverted() * ob.matrix_world * Vector(v)
 | 
				
			||||||
 | 
					            if bbox[0].x > v.x:
 | 
				
			||||||
 | 
					                bbox[0].x = v.x
 | 
				
			||||||
 | 
					            if bbox[0].y > v.y:
 | 
				
			||||||
 | 
					                bbox[0].y = v.y
 | 
				
			||||||
 | 
					            if bbox[0].z > v.z:
 | 
				
			||||||
 | 
					                bbox[0].z = v.z
 | 
				
			||||||
 | 
					            if bbox[1].x < v.x:
 | 
				
			||||||
 | 
					                bbox[1].x = v.x
 | 
				
			||||||
 | 
					            if bbox[1].y < v.y:
 | 
				
			||||||
 | 
					                bbox[1].y = v.y
 | 
				
			||||||
 | 
					            if bbox[1].z < v.z:
 | 
				
			||||||
 | 
					                bbox[1].z = v.z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def objects_bbox_calc(camera, objects):
 | 
				
			||||||
 | 
					        bbox = (Vector((1e9, 1e9, 1e9)), Vector((-1e9, -1e9, -1e9)))
 | 
				
			||||||
 | 
					        for obname in objects:
 | 
				
			||||||
 | 
					            ob = bpy.data.objects[obname]
 | 
				
			||||||
 | 
					            object_bbox_merge(bbox, ob, camera)
 | 
				
			||||||
 | 
					        # Our bbox has been generated in camera local space, bring it back in world one
 | 
				
			||||||
 | 
					        bbox[0][:] = camera.matrix_world * bbox[0]
 | 
				
			||||||
 | 
					        bbox[1][:] = camera.matrix_world * bbox[1]
 | 
				
			||||||
 | 
					        cos = (
 | 
				
			||||||
 | 
					            bbox[0].x, bbox[0].y, bbox[0].z,
 | 
				
			||||||
 | 
					            bbox[0].x, bbox[0].y, bbox[1].z,
 | 
				
			||||||
 | 
					            bbox[0].x, bbox[1].y, bbox[0].z,
 | 
				
			||||||
 | 
					            bbox[0].x, bbox[1].y, bbox[1].z,
 | 
				
			||||||
 | 
					            bbox[1].x, bbox[0].y, bbox[0].z,
 | 
				
			||||||
 | 
					            bbox[1].x, bbox[0].y, bbox[1].z,
 | 
				
			||||||
 | 
					            bbox[1].x, bbox[1].y, bbox[0].z,
 | 
				
			||||||
 | 
					            bbox[1].x, bbox[1].y, bbox[1].z,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return cos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def preview_render_do(render_context, item_container, item_name, objects):
 | 
				
			||||||
 | 
					        scene = bpy.data.scenes[render_context.scene]
 | 
				
			||||||
 | 
					        if objects is not None:
 | 
				
			||||||
 | 
					            camera = bpy.data.objects[render_context.camera]
 | 
				
			||||||
 | 
					            lamp = bpy.data.objects[render_context.lamp] if render_context.lamp is not None else None
 | 
				
			||||||
 | 
					            cos = objects_bbox_calc(camera, objects)
 | 
				
			||||||
 | 
					            loc, ortho_scale = camera.camera_fit_coords(scene, cos)
 | 
				
			||||||
 | 
					            camera.location = loc
 | 
				
			||||||
 | 
					            if lamp:
 | 
				
			||||||
 | 
					                loc, ortho_scale = lamp.camera_fit_coords(scene, cos)
 | 
				
			||||||
 | 
					                lamp.location = loc
 | 
				
			||||||
 | 
					        scene.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bpy.ops.render.render(write_still=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        image = bpy.data.images[render_context.image]
 | 
				
			||||||
 | 
					        item = getattr(bpy.data, item_container)[item_name]
 | 
				
			||||||
 | 
					        image.reload()
 | 
				
			||||||
 | 
					        # Note: we could use struct module here, but not quite sure it'd give any advantage really...
 | 
				
			||||||
 | 
					        pix = tuple((round(r * 255)) + (round(g * 255) << 8) + (round(b * 255) << 16) + (round(a * 255) << 24)
 | 
				
			||||||
 | 
					                    for r, g, b, a in zip(*[iter(image.pixels)] * 4))
 | 
				
			||||||
 | 
					        item.preview.image_size = (RENDER_PREVIEW_SIZE, RENDER_PREVIEW_SIZE)
 | 
				
			||||||
 | 
					        item.preview.image_pixels = pix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # And now, main code!
 | 
				
			||||||
 | 
					    do_save = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_data_intern:
 | 
				
			||||||
 | 
					        bpy.ops.wm.previews_clear(id_type=INTERN_PREVIEW_TYPES)
 | 
				
			||||||
 | 
					        bpy.ops.wm.previews_ensure()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render_contexts = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    objects_ignored = set()
 | 
				
			||||||
 | 
					    groups_ignored = set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    prev_scenename = bpy.context.screen.scene.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_objects:
 | 
				
			||||||
 | 
					        prev_shown = tuple(ob.hide_render for ob in bpy.data.objects)
 | 
				
			||||||
 | 
					        for ob in bpy.data.objects:
 | 
				
			||||||
 | 
					            if ob in objects_ignored:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            ob.hide_render = True
 | 
				
			||||||
 | 
					        for root in bpy.data.objects:
 | 
				
			||||||
 | 
					            if root.name in objects_ignored:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            if root.type not in OBJECT_TYPES_RENDER:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            objects = (root.name,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            render_engine = objects_render_engine_guess(objects)
 | 
				
			||||||
 | 
					            render_context = render_contexts.get(render_engine, None)
 | 
				
			||||||
 | 
					            if render_context is None:
 | 
				
			||||||
 | 
					                render_context = render_context_create(render_engine, objects_ignored)
 | 
				
			||||||
 | 
					                render_contexts[render_engine] = render_context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            scene = bpy.data.scenes[render_context.scene]
 | 
				
			||||||
 | 
					            bpy.context.screen.scene = scene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for obname in objects:
 | 
				
			||||||
 | 
					                ob = bpy.data.objects[obname]
 | 
				
			||||||
 | 
					                if obname not in scene.objects:
 | 
				
			||||||
 | 
					                    scene.objects.link(ob)
 | 
				
			||||||
 | 
					                ob.hide_render = False
 | 
				
			||||||
 | 
					            scene.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            preview_render_do(render_context, 'objects', root.name, objects)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # XXX Hyper Super Uber Suspicious Hack!
 | 
				
			||||||
 | 
					            #     Without this, on windows build, script excepts with following message:
 | 
				
			||||||
 | 
					            #         Traceback (most recent call last):
 | 
				
			||||||
 | 
					            #         File "<string>", line 1, in <module>
 | 
				
			||||||
 | 
					            #         File "<string>", line 451, in <module>
 | 
				
			||||||
 | 
					            #         File "<string>", line 443, in main
 | 
				
			||||||
 | 
					            #         File "<string>", line 327, in do_previews
 | 
				
			||||||
 | 
					            #         OverflowError: Python int too large to convert to C long
 | 
				
			||||||
 | 
					            #    ... :(
 | 
				
			||||||
 | 
					            import sys
 | 
				
			||||||
 | 
					            scene = bpy.data.scenes[render_context.scene]
 | 
				
			||||||
 | 
					            for obname in objects:
 | 
				
			||||||
 | 
					                ob = bpy.data.objects[obname]
 | 
				
			||||||
 | 
					                scene.objects.unlink(ob)
 | 
				
			||||||
 | 
					                ob.hide_render = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for ob, is_rendered in zip(bpy.data.objects, prev_shown):
 | 
				
			||||||
 | 
					            ob.hide_render = is_rendered
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_groups:
 | 
				
			||||||
 | 
					        for grp in bpy.data.groups:
 | 
				
			||||||
 | 
					            if grp.name in groups_ignored:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            objects = tuple(ob.name for ob in grp.objects)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            render_engine = objects_render_engine_guess(objects)
 | 
				
			||||||
 | 
					            render_context = render_contexts.get(render_engine, None)
 | 
				
			||||||
 | 
					            if render_context is None:
 | 
				
			||||||
 | 
					                render_context = render_context_create(render_engine, objects_ignored)
 | 
				
			||||||
 | 
					                render_contexts[render_engine] = render_context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            scene = bpy.data.scenes[render_context.scene]
 | 
				
			||||||
 | 
					            bpy.context.screen.scene = scene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bpy.ops.object.group_instance_add(group=grp.name)
 | 
				
			||||||
 | 
					            grp_ob = next((ob for ob in scene.objects if ob.dupli_group and ob.dupli_group.name == grp.name))
 | 
				
			||||||
 | 
					            grp_obname = grp_ob.name
 | 
				
			||||||
 | 
					            scene.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            preview_render_do(render_context, 'groups', grp.name, objects)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            scene = bpy.data.scenes[render_context.scene]
 | 
				
			||||||
 | 
					            scene.objects.unlink(bpy.data.objects[grp_obname])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bpy.context.screen.scene = bpy.data.scenes[prev_scenename]
 | 
				
			||||||
 | 
					    for render_context in render_contexts.values():
 | 
				
			||||||
 | 
					        if not render_context_delete(render_context):
 | 
				
			||||||
 | 
					            do_save = False  # Do not save file if something went wrong here, we could 'pollute' it with temp data...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_scenes:
 | 
				
			||||||
 | 
					        for scene in bpy.data.scenes:
 | 
				
			||||||
 | 
					            has_camera = scene.camera is not None
 | 
				
			||||||
 | 
					            bpy.context.screen.scene = scene
 | 
				
			||||||
 | 
					            render_context = render_context_create('__SCENE', objects_ignored)
 | 
				
			||||||
 | 
					            scene.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            objects = None
 | 
				
			||||||
 | 
					            if not has_camera:
 | 
				
			||||||
 | 
					                # We had to add a temp camera, now we need to place it to see interesting objects!
 | 
				
			||||||
 | 
					                objects = tuple(ob.name for ob in scene.objects
 | 
				
			||||||
 | 
					                                        if (not ob.hide_render) and (ob.type in OBJECT_TYPES_RENDER))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            preview_render_do(render_context, 'scenes', scene.name, objects)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if not render_context_delete(render_context):
 | 
				
			||||||
 | 
					                do_save = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bpy.context.screen.scene = bpy.data.scenes[prev_scenename]
 | 
				
			||||||
 | 
					    if do_save:
 | 
				
			||||||
 | 
					        print("Saving %s..." % bpy.data.filepath)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            bpy.ops.wm.save_mainfile()
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            # Might fail in some odd cases, like e.g. in regression files we have glsl/ram_glsl.blend which
 | 
				
			||||||
 | 
					            # references an inexistent texture... Better not break in this case, just spit error to console.
 | 
				
			||||||
 | 
					            print("ERROR:", e)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        print("*NOT* Saving %s, because some error(s) happened while deleting temp render data..." % bpy.data.filepath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def do_clear_previews(do_objects, do_groups, do_scenes, do_data_intern):
 | 
				
			||||||
 | 
					    if do_data_intern:
 | 
				
			||||||
 | 
					        bpy.ops.wm.previews_clear(id_type=INTERN_PREVIEW_TYPES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_objects:
 | 
				
			||||||
 | 
					        for ob in bpy.data.objects:
 | 
				
			||||||
 | 
					            ob.preview.image_size = (0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_groups:
 | 
				
			||||||
 | 
					        for grp in bpy.data.groups:
 | 
				
			||||||
 | 
					            grp.preview.image_size = (0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if do_scenes:
 | 
				
			||||||
 | 
					        for scene in bpy.data.scenes:
 | 
				
			||||||
 | 
					            scene.preview.image_size = (0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("Saving %s..." % bpy.data.filepath)
 | 
				
			||||||
 | 
					    bpy.ops.wm.save_mainfile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        import bpy
 | 
				
			||||||
 | 
					    except ImportError:
 | 
				
			||||||
 | 
					        print("This script must run from inside blender")
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    import sys
 | 
				
			||||||
 | 
					    import argparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get rid of Blender args!
 | 
				
			||||||
 | 
					    argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser(description="Use Blender to generate previews for currently open Blender file's items.")
 | 
				
			||||||
 | 
					    parser.add_argument('--clear', default=False, action="store_true", help="Clear previews instead of generating them.")
 | 
				
			||||||
 | 
					    parser.add_argument('--no_scenes', default=True, action="store_false", help="Do not generate/clear previews for scene IDs.")
 | 
				
			||||||
 | 
					    parser.add_argument('--no_groups', default=True, action="store_false", help="Do not generate/clear previews for group IDs.")
 | 
				
			||||||
 | 
					    parser.add_argument('--no_objects', default=True, action="store_false", help="Do not generate/clear previews for object IDs.")
 | 
				
			||||||
 | 
					    parser.add_argument('--no_data_intern', default=True, action="store_false",
 | 
				
			||||||
 | 
					                        help="Do not generate/clear previews for mat/tex/image/etc. IDs (those handled by core Blender code).")
 | 
				
			||||||
 | 
					    args = parser.parse_args(argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.clear:
 | 
				
			||||||
 | 
					        print("clear!")
 | 
				
			||||||
 | 
					        do_clear_previews(do_objects=args.no_objects, do_groups=args.no_groups, do_scenes=args.no_scenes,
 | 
				
			||||||
 | 
					                          do_data_intern=args.no_data_intern)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        print("render!")
 | 
				
			||||||
 | 
					        do_previews(do_objects=args.no_objects, do_groups=args.no_groups, do_scenes=args.no_scenes,
 | 
				
			||||||
 | 
					                    do_data_intern=args.no_data_intern)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    print("\n\n *** Running {} *** \n".format(__file__))
 | 
				
			||||||
 | 
					    print(" *** Blend file {} *** \n".format(bpy.data.filepath))
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
 | 
					    bpy.ops.wm.quit_blender()
 | 
				
			||||||
@@ -28,6 +28,7 @@ _modules = [
 | 
				
			|||||||
    "anim",
 | 
					    "anim",
 | 
				
			||||||
    "clip",
 | 
					    "clip",
 | 
				
			||||||
    "console",
 | 
					    "console",
 | 
				
			||||||
 | 
					    "file",
 | 
				
			||||||
    "image",
 | 
					    "image",
 | 
				
			||||||
    "mask",
 | 
					    "mask",
 | 
				
			||||||
    "mesh",
 | 
					    "mesh",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										243
									
								
								release/scripts/startup/bl_operators/file.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								release/scripts/startup/bl_operators/file.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,243 @@
 | 
				
			|||||||
 | 
					# ##### 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 #####
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# <pep8 compliant>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import bpy
 | 
				
			||||||
 | 
					from bpy.types import Operator
 | 
				
			||||||
 | 
					from bpy.props import (
 | 
				
			||||||
 | 
					        StringProperty,
 | 
				
			||||||
 | 
					        BoolProperty,
 | 
				
			||||||
 | 
					        CollectionProperty,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ########## Datablock previews... ##########
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WM_OT_previews_batch_generate(Operator):
 | 
				
			||||||
 | 
					    """Generate selected .blend file's previews"""
 | 
				
			||||||
 | 
					    bl_idname = "wm.previews_batch_generate"
 | 
				
			||||||
 | 
					    bl_label = "Batch-Generate Previews"
 | 
				
			||||||
 | 
					    bl_options = {'REGISTER'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # -----------
 | 
				
			||||||
 | 
					    # File props.
 | 
				
			||||||
 | 
					    files = CollectionProperty(
 | 
				
			||||||
 | 
					            type=bpy.types.OperatorFileListElement,
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    directory = StringProperty(
 | 
				
			||||||
 | 
					            maxlen=1024,
 | 
				
			||||||
 | 
					            subtype='FILE_PATH',
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Show only images/videos, and directories!
 | 
				
			||||||
 | 
					    filter_blender = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    filter_folder = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # -----------
 | 
				
			||||||
 | 
					    # Own props.
 | 
				
			||||||
 | 
					    use_scenes = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Scenes",
 | 
				
			||||||
 | 
					            description="Generate scenes' previews",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    use_groups = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Groups",
 | 
				
			||||||
 | 
					            description="Generate groups' previews",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    use_objects = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Objects",
 | 
				
			||||||
 | 
					            description="Generate objects' previews",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    use_intern_data = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Mat/Tex/...",
 | 
				
			||||||
 | 
					            description="Generate 'internal' previews (materials, textures, images, etc.)",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use_trusted = BoolProperty(
 | 
				
			||||||
 | 
					            default=False,
 | 
				
			||||||
 | 
					            name="Trusted Blend Files",
 | 
				
			||||||
 | 
					            description="Enable python evaluation for selected files",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def invoke(self, context, event):
 | 
				
			||||||
 | 
					        context.window_manager.fileselect_add(self)
 | 
				
			||||||
 | 
					        return {'RUNNING_MODAL'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def execute(self, context):
 | 
				
			||||||
 | 
					        if "subprocess" in locals():
 | 
				
			||||||
 | 
					            import imp
 | 
				
			||||||
 | 
					            imp.reload(preview_render)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            import os
 | 
				
			||||||
 | 
					            import subprocess
 | 
				
			||||||
 | 
					            from bl_previews_utils import bl_previews_render as preview_render
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        context.window_manager.progress_begin(0, len(self.files))
 | 
				
			||||||
 | 
					        context.window_manager.progress_update(0)
 | 
				
			||||||
 | 
					        for i, fn in enumerate(self.files):
 | 
				
			||||||
 | 
					            blen_path = os.path.join(self.directory, fn.name)
 | 
				
			||||||
 | 
					            cmd = [
 | 
				
			||||||
 | 
					                bpy.app.binary_path,
 | 
				
			||||||
 | 
					                "--background",
 | 
				
			||||||
 | 
					                "--factory-startup",
 | 
				
			||||||
 | 
					                "-noaudio",
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					            if self.use_trusted:
 | 
				
			||||||
 | 
					                cmd.append("--enable-autoexec")
 | 
				
			||||||
 | 
					            cmd.extend([
 | 
				
			||||||
 | 
					                blen_path,
 | 
				
			||||||
 | 
					                "--python",
 | 
				
			||||||
 | 
					                os.path.join(os.path.dirname(preview_render.__file__), "bl_previews_render.py"),
 | 
				
			||||||
 | 
					                "--",
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					            if not self.use_scenes:
 | 
				
			||||||
 | 
					                cmd.append('--no_scenes')
 | 
				
			||||||
 | 
					            if not self.use_groups:
 | 
				
			||||||
 | 
					                cmd.append('--no_groups')
 | 
				
			||||||
 | 
					            if not self.use_objects:
 | 
				
			||||||
 | 
					                cmd.append('--no_objects')
 | 
				
			||||||
 | 
					            if not self.use_intern_data:
 | 
				
			||||||
 | 
					                cmd.append('--no_data_intern')
 | 
				
			||||||
 | 
					            if subprocess.call(cmd):
 | 
				
			||||||
 | 
					                self.report({'ERROR'}, "Previews generation process failed for file '%s'!" % blen_path)
 | 
				
			||||||
 | 
					                context.window_manager.progress_end()
 | 
				
			||||||
 | 
					                return {'CANCELLED'}
 | 
				
			||||||
 | 
					            context.window_manager.progress_update(i + 1)
 | 
				
			||||||
 | 
					        context.window_manager.progress_end()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {'FINISHED'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WM_OT_previews_batch_clear(Operator):
 | 
				
			||||||
 | 
					    """Clear selected .blend file's previews"""
 | 
				
			||||||
 | 
					    bl_idname = "wm.previews_batch_clear"
 | 
				
			||||||
 | 
					    bl_label = "Batch-Clear Previews"
 | 
				
			||||||
 | 
					    bl_options = {'REGISTER'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # -----------
 | 
				
			||||||
 | 
					    # File props.
 | 
				
			||||||
 | 
					    files = CollectionProperty(
 | 
				
			||||||
 | 
					            type=bpy.types.OperatorFileListElement,
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    directory = StringProperty(
 | 
				
			||||||
 | 
					            maxlen=1024,
 | 
				
			||||||
 | 
					            subtype='FILE_PATH',
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Show only images/videos, and directories!
 | 
				
			||||||
 | 
					    filter_blender = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    filter_folder = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            options={'HIDDEN', 'SKIP_SAVE'},
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # -----------
 | 
				
			||||||
 | 
					    # Own props.
 | 
				
			||||||
 | 
					    use_scenes = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Scenes",
 | 
				
			||||||
 | 
					            description="Clear scenes' previews",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    use_groups = BoolProperty(default=True,
 | 
				
			||||||
 | 
					            name="Groups",
 | 
				
			||||||
 | 
					            description="Clear groups' previews",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    use_objects = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Objects",
 | 
				
			||||||
 | 
					            description="Clear objects' previews",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    use_intern_data = BoolProperty(
 | 
				
			||||||
 | 
					            default=True,
 | 
				
			||||||
 | 
					            name="Mat/Tex/...",
 | 
				
			||||||
 | 
					            description="Clear 'internal' previews (materials, textures, images, etc.)",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    use_trusted = BoolProperty(
 | 
				
			||||||
 | 
					            default=False,
 | 
				
			||||||
 | 
					            name="Trusted Blend Files",
 | 
				
			||||||
 | 
					            description="Enable python evaluation for selected files",
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def invoke(self, context, event):
 | 
				
			||||||
 | 
					        context.window_manager.fileselect_add(self)
 | 
				
			||||||
 | 
					        return {'RUNNING_MODAL'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def execute(self, context):
 | 
				
			||||||
 | 
					        if "subprocess" in locals():
 | 
				
			||||||
 | 
					            import imp
 | 
				
			||||||
 | 
					            imp.reload(preview_render)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            import os
 | 
				
			||||||
 | 
					            import subprocess
 | 
				
			||||||
 | 
					            from bl_previews_utils import bl_previews_render as preview_render
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        context.window_manager.progress_begin(0, len(self.files))
 | 
				
			||||||
 | 
					        context.window_manager.progress_update(0)
 | 
				
			||||||
 | 
					        for i, fn in enumerate(self.files):
 | 
				
			||||||
 | 
					            blen_path = os.path.join(self.directory, fn.name)
 | 
				
			||||||
 | 
					            cmd = [
 | 
				
			||||||
 | 
					                bpy.app.binary_path,
 | 
				
			||||||
 | 
					                "--background",
 | 
				
			||||||
 | 
					                "--factory-startup",
 | 
				
			||||||
 | 
					                "-noaudio",
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					            if self.use_trusted:
 | 
				
			||||||
 | 
					                cmd.append("--enable-autoexec")
 | 
				
			||||||
 | 
					            cmd.extend([
 | 
				
			||||||
 | 
					                blen_path,
 | 
				
			||||||
 | 
					                "--python",
 | 
				
			||||||
 | 
					                os.path.join(os.path.dirname(preview_render.__file__), "bl_previews_render.py"),
 | 
				
			||||||
 | 
					                "--",
 | 
				
			||||||
 | 
					                "--clear",
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					            if not self.use_scenes:
 | 
				
			||||||
 | 
					                cmd.append('--no_scenes')
 | 
				
			||||||
 | 
					            if not self.use_groups:
 | 
				
			||||||
 | 
					                cmd.append('--no_groups')
 | 
				
			||||||
 | 
					            if not self.use_objects:
 | 
				
			||||||
 | 
					                cmd.append('--no_objects')
 | 
				
			||||||
 | 
					            if not self.use_intern_data:
 | 
				
			||||||
 | 
					                cmd.append('--no_data_intern')
 | 
				
			||||||
 | 
					            if subprocess.call(cmd):
 | 
				
			||||||
 | 
					                self.report({'ERROR'}, "Previews clear process failed for file '%s'!" % blen_path)
 | 
				
			||||||
 | 
					                context.window_manager.progress_end()
 | 
				
			||||||
 | 
					                return {'CANCELLED'}
 | 
				
			||||||
 | 
					            context.window_manager.progress_update(i + 1)
 | 
				
			||||||
 | 
					        context.window_manager.progress_end()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {'FINISHED'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -203,6 +203,12 @@ class INFO_MT_file_previews(Menu):
 | 
				
			|||||||
        layout = self.layout
 | 
					        layout = self.layout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        layout.operator("wm.previews_ensure")
 | 
					        layout.operator("wm.previews_ensure")
 | 
				
			||||||
 | 
					        layout.operator("wm.previews_batch_generate")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout.separator()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout.operator("wm.previews_clear")
 | 
				
			||||||
 | 
					        layout.operator("wm.previews_batch_clear")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class INFO_MT_game(Menu):
 | 
					class INFO_MT_game(Menu):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,9 @@ int         BKE_idcode_from_name(const char *name);
 | 
				
			|||||||
bool        BKE_idcode_is_linkable(int code);
 | 
					bool        BKE_idcode_is_linkable(int code);
 | 
				
			||||||
bool        BKE_idcode_is_valid(int code);
 | 
					bool        BKE_idcode_is_valid(int code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int         BKE_idcode_to_idfilter(const int idcode);
 | 
				
			||||||
 | 
					int         BKE_idcode_from_idfilter(const int idfilter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Return an ID code and steps the index forward 1.
 | 
					 * Return an ID code and steps the index forward 1.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -165,6 +165,90 @@ int BKE_idcode_from_name(const char *name)
 | 
				
			|||||||
	return idt ? idt->code : 0;
 | 
						return idt ? idt->code : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert an idcode into an idfilter (e.g. ID_OB -> FILTER_ID_OB).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int BKE_idcode_to_idfilter(const int idcode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#define CASE_IDFILTER(_id) case ID_##_id: return FILTER_ID_##_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (idcode) {
 | 
				
			||||||
 | 
							CASE_IDFILTER(AC);
 | 
				
			||||||
 | 
							CASE_IDFILTER(AR);
 | 
				
			||||||
 | 
							CASE_IDFILTER(BR);
 | 
				
			||||||
 | 
							CASE_IDFILTER(CA);
 | 
				
			||||||
 | 
							CASE_IDFILTER(CU);
 | 
				
			||||||
 | 
							CASE_IDFILTER(GD);
 | 
				
			||||||
 | 
							CASE_IDFILTER(GR);
 | 
				
			||||||
 | 
							CASE_IDFILTER(IM);
 | 
				
			||||||
 | 
							CASE_IDFILTER(LA);
 | 
				
			||||||
 | 
							CASE_IDFILTER(LS);
 | 
				
			||||||
 | 
							CASE_IDFILTER(LT);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MA);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MB);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MC);
 | 
				
			||||||
 | 
							CASE_IDFILTER(ME);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MSK);
 | 
				
			||||||
 | 
							CASE_IDFILTER(NT);
 | 
				
			||||||
 | 
							CASE_IDFILTER(OB);
 | 
				
			||||||
 | 
							CASE_IDFILTER(PAL);
 | 
				
			||||||
 | 
							CASE_IDFILTER(PC);
 | 
				
			||||||
 | 
							CASE_IDFILTER(SCE);
 | 
				
			||||||
 | 
							CASE_IDFILTER(SPK);
 | 
				
			||||||
 | 
							CASE_IDFILTER(SO);
 | 
				
			||||||
 | 
							CASE_IDFILTER(TE);
 | 
				
			||||||
 | 
							CASE_IDFILTER(TXT);
 | 
				
			||||||
 | 
							CASE_IDFILTER(VF);
 | 
				
			||||||
 | 
							CASE_IDFILTER(WO);
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef CASE_IDFILTER
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert an idfilter into an idcode (e.g. FILTER_ID_OB -> ID_OB).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int BKE_idcode_from_idfilter(const int idfilter)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#define CASE_IDFILTER(_id) case FILTER_ID_##_id: return ID_##_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (idfilter) {
 | 
				
			||||||
 | 
							CASE_IDFILTER(AC);
 | 
				
			||||||
 | 
							CASE_IDFILTER(AR);
 | 
				
			||||||
 | 
							CASE_IDFILTER(BR);
 | 
				
			||||||
 | 
							CASE_IDFILTER(CA);
 | 
				
			||||||
 | 
							CASE_IDFILTER(CU);
 | 
				
			||||||
 | 
							CASE_IDFILTER(GD);
 | 
				
			||||||
 | 
							CASE_IDFILTER(GR);
 | 
				
			||||||
 | 
							CASE_IDFILTER(IM);
 | 
				
			||||||
 | 
							CASE_IDFILTER(LA);
 | 
				
			||||||
 | 
							CASE_IDFILTER(LS);
 | 
				
			||||||
 | 
							CASE_IDFILTER(LT);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MA);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MB);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MC);
 | 
				
			||||||
 | 
							CASE_IDFILTER(ME);
 | 
				
			||||||
 | 
							CASE_IDFILTER(MSK);
 | 
				
			||||||
 | 
							CASE_IDFILTER(NT);
 | 
				
			||||||
 | 
							CASE_IDFILTER(OB);
 | 
				
			||||||
 | 
							CASE_IDFILTER(PAL);
 | 
				
			||||||
 | 
							CASE_IDFILTER(PC);
 | 
				
			||||||
 | 
							CASE_IDFILTER(SCE);
 | 
				
			||||||
 | 
							CASE_IDFILTER(SPK);
 | 
				
			||||||
 | 
							CASE_IDFILTER(SO);
 | 
				
			||||||
 | 
							CASE_IDFILTER(TE);
 | 
				
			||||||
 | 
							CASE_IDFILTER(TXT);
 | 
				
			||||||
 | 
							CASE_IDFILTER(VF);
 | 
				
			||||||
 | 
							CASE_IDFILTER(WO);
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef CASE_IDFILTER
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Convert an idcode into a name (plural).
 | 
					 * Convert an idcode into a name (plural).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,9 +34,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct bContext;
 | 
					struct bContext;
 | 
				
			||||||
struct ID;
 | 
					struct ID;
 | 
				
			||||||
 | 
					struct Scene;
 | 
				
			||||||
struct PreviewImage;
 | 
					struct PreviewImage;
 | 
				
			||||||
struct PointerRNA;
 | 
					struct PointerRNA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum eIconSizes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct IconFile {
 | 
					typedef struct IconFile {
 | 
				
			||||||
	struct IconFile *next, *prev;
 | 
						struct IconFile *next, *prev;
 | 
				
			||||||
	char filename[256]; /* FILE_MAXFILE size */
 | 
						char filename[256]; /* FILE_MAXFILE size */
 | 
				
			||||||
@@ -60,6 +63,7 @@ int UI_icon_get_height(int icon_id);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void UI_id_icon_render(
 | 
					void UI_id_icon_render(
 | 
				
			||||||
        const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job);
 | 
					        const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job);
 | 
				
			||||||
 | 
					int UI_preview_render_size(enum eIconSizes size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void UI_icon_draw(float x, float y, int icon_id);
 | 
					void UI_icon_draw(float x, float y, int icon_id);
 | 
				
			||||||
void UI_icon_draw_preview(float x, float y, int icon_id);
 | 
					void UI_icon_draw_preview(float x, float y, int icon_id);
 | 
				
			||||||
@@ -78,5 +82,6 @@ int UI_iconfile_get_index(const char *filename);
 | 
				
			|||||||
struct PreviewImage *UI_icon_to_preview(int icon_id);
 | 
					struct PreviewImage *UI_icon_to_preview(int icon_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
 | 
					int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
 | 
				
			||||||
 | 
					int UI_idcode_icon_get(const int idcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /*  __UI_INTERFACE_ICONS_H__ */
 | 
					#endif /*  __UI_INTERFACE_ICONS_H__ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -900,7 +900,7 @@ void UI_icons_init(int first_dyn_id)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Render size for preview images and icons
 | 
					/* Render size for preview images and icons
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int preview_render_size(enum eIconSizes size)
 | 
					int UI_preview_render_size(enum eIconSizes size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (size) {
 | 
						switch (size) {
 | 
				
			||||||
		case ICON_SIZE_ICON:
 | 
							case ICON_SIZE_ICON:
 | 
				
			||||||
@@ -916,7 +916,7 @@ static int preview_render_size(enum eIconSizes size)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
 | 
					static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int render_size = preview_render_size(size);
 | 
						unsigned int render_size = UI_preview_render_size(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!prv_img) {
 | 
						if (!prv_img) {
 | 
				
			||||||
		if (G.debug & G_DEBUG)
 | 
							if (G.debug & G_DEBUG)
 | 
				
			||||||
@@ -1399,6 +1399,68 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
 | 
				
			|||||||
	return rnaicon;
 | 
						return rnaicon;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int UI_idcode_icon_get(const int idcode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (idcode) {
 | 
				
			||||||
 | 
							case ID_AC:
 | 
				
			||||||
 | 
								return ICON_ANIM_DATA;
 | 
				
			||||||
 | 
							case ID_AR:
 | 
				
			||||||
 | 
								return ICON_ARMATURE_DATA;
 | 
				
			||||||
 | 
							case ID_BR:
 | 
				
			||||||
 | 
								return ICON_BRUSH_DATA;
 | 
				
			||||||
 | 
							case ID_CA:
 | 
				
			||||||
 | 
								return ICON_CAMERA_DATA;
 | 
				
			||||||
 | 
							case ID_CU:
 | 
				
			||||||
 | 
								return ICON_CURVE_DATA;
 | 
				
			||||||
 | 
							case ID_GD:
 | 
				
			||||||
 | 
								return ICON_GREASEPENCIL;
 | 
				
			||||||
 | 
							case ID_GR:
 | 
				
			||||||
 | 
								return ICON_GROUP;
 | 
				
			||||||
 | 
							case ID_IM:
 | 
				
			||||||
 | 
								return ICON_IMAGE_DATA;
 | 
				
			||||||
 | 
							case ID_LA:
 | 
				
			||||||
 | 
								return ICON_LAMP_DATA;
 | 
				
			||||||
 | 
							case ID_LS:
 | 
				
			||||||
 | 
								return ICON_LINE_DATA;
 | 
				
			||||||
 | 
							case ID_LT:
 | 
				
			||||||
 | 
								return ICON_LATTICE_DATA;
 | 
				
			||||||
 | 
							case ID_MA:
 | 
				
			||||||
 | 
								return ICON_MATERIAL_DATA;
 | 
				
			||||||
 | 
							case ID_MB:
 | 
				
			||||||
 | 
								return ICON_META_DATA;
 | 
				
			||||||
 | 
							case ID_MC:
 | 
				
			||||||
 | 
								return ICON_CLIP;
 | 
				
			||||||
 | 
							case ID_ME:
 | 
				
			||||||
 | 
								return ICON_MESH_DATA;
 | 
				
			||||||
 | 
							case ID_MSK:
 | 
				
			||||||
 | 
								return ICON_MOD_MASK;  /* TODO! this would need its own icon! */
 | 
				
			||||||
 | 
							case ID_NT:
 | 
				
			||||||
 | 
								return ICON_NODETREE;
 | 
				
			||||||
 | 
							case ID_OB:
 | 
				
			||||||
 | 
								return ICON_OBJECT_DATA;
 | 
				
			||||||
 | 
							case ID_PAL:
 | 
				
			||||||
 | 
								return ICON_COLOR;  /* TODO! this would need its own icon! */
 | 
				
			||||||
 | 
							case ID_PC:
 | 
				
			||||||
 | 
								return ICON_CURVE_BEZCURVE;  /* TODO! this would need its own icon! */
 | 
				
			||||||
 | 
							case ID_SCE:
 | 
				
			||||||
 | 
								return ICON_SCENE_DATA;
 | 
				
			||||||
 | 
							case ID_SPK:
 | 
				
			||||||
 | 
								return ICON_SPEAKER;
 | 
				
			||||||
 | 
							case ID_SO:
 | 
				
			||||||
 | 
								return ICON_SOUND;
 | 
				
			||||||
 | 
							case ID_TE:
 | 
				
			||||||
 | 
								return ICON_TEXTURE_DATA;
 | 
				
			||||||
 | 
							case ID_TXT:
 | 
				
			||||||
 | 
								return ICON_TEXT;
 | 
				
			||||||
 | 
							case ID_VF:
 | 
				
			||||||
 | 
								return ICON_FONT_DATA;
 | 
				
			||||||
 | 
							case ID_WO:
 | 
				
			||||||
 | 
								return ICON_WORLD_DATA;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return ICON_NONE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void icon_draw_at_size(
 | 
					static void icon_draw_at_size(
 | 
				
			||||||
        float x, float y, int icon_id, float aspect, float alpha,
 | 
					        float x, float y, int icon_id, float aspect, float alpha,
 | 
				
			||||||
        enum eIconSizes size, const bool nocreate)
 | 
					        enum eIconSizes size, const bool nocreate)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -290,6 +290,41 @@ enum {
 | 
				
			|||||||
	LIB_ID_RECALC_ALL   = (LIB_ID_RECALC | LIB_ID_RECALC_DATA),
 | 
						LIB_ID_RECALC_ALL   = (LIB_ID_RECALC | LIB_ID_RECALC_DATA),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* To filter ID types (filter_id) */
 | 
				
			||||||
 | 
					/* XXX We cannot put all needed IDs inside an enum...
 | 
				
			||||||
 | 
					 *     We'll have to see whether we can fit all needed ones inside 32 values,
 | 
				
			||||||
 | 
					 *     or if we need to fallback to longlong defines :/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						FILTER_ID_AC        = (1 << 0),
 | 
				
			||||||
 | 
						FILTER_ID_AR        = (1 << 1),
 | 
				
			||||||
 | 
						FILTER_ID_BR        = (1 << 2),
 | 
				
			||||||
 | 
						FILTER_ID_CA        = (1 << 3),
 | 
				
			||||||
 | 
						FILTER_ID_CU        = (1 << 4),
 | 
				
			||||||
 | 
						FILTER_ID_GD        = (1 << 5),
 | 
				
			||||||
 | 
						FILTER_ID_GR        = (1 << 6),
 | 
				
			||||||
 | 
						FILTER_ID_IM        = (1 << 7),
 | 
				
			||||||
 | 
						FILTER_ID_LA        = (1 << 8),
 | 
				
			||||||
 | 
						FILTER_ID_LS        = (1 << 9),
 | 
				
			||||||
 | 
						FILTER_ID_LT        = (1 << 10),
 | 
				
			||||||
 | 
						FILTER_ID_MA        = (1 << 11),
 | 
				
			||||||
 | 
						FILTER_ID_MB        = (1 << 12),
 | 
				
			||||||
 | 
						FILTER_ID_MC        = (1 << 13),
 | 
				
			||||||
 | 
						FILTER_ID_ME        = (1 << 14),
 | 
				
			||||||
 | 
						FILTER_ID_MSK       = (1 << 15),
 | 
				
			||||||
 | 
						FILTER_ID_NT        = (1 << 16),
 | 
				
			||||||
 | 
						FILTER_ID_OB        = (1 << 17),
 | 
				
			||||||
 | 
						FILTER_ID_PAL       = (1 << 18),
 | 
				
			||||||
 | 
						FILTER_ID_PC        = (1 << 19),
 | 
				
			||||||
 | 
						FILTER_ID_SCE       = (1 << 20),
 | 
				
			||||||
 | 
						FILTER_ID_SPK       = (1 << 21),
 | 
				
			||||||
 | 
						FILTER_ID_SO        = (1 << 22),
 | 
				
			||||||
 | 
						FILTER_ID_TE        = (1 << 23),
 | 
				
			||||||
 | 
						FILTER_ID_TXT       = (1 << 24),
 | 
				
			||||||
 | 
						FILTER_ID_VF        = (1 << 25),
 | 
				
			||||||
 | 
						FILTER_ID_WO        = (1 << 26),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -472,14 +472,14 @@ static void rna_ImagePreview_size_set(PointerRNA *ptr, const int *values, enum e
 | 
				
			|||||||
		BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
 | 
							BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BKE_previewimg_ensure(prv_img, size);
 | 
						BKE_previewimg_clear_single(prv_img, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (values[0] && values[1]) {
 | 
						if (values[0] && values[1]) {
 | 
				
			||||||
		prv_img->rect[size] = MEM_callocN(values[0] * values[1] * sizeof(unsigned int), "prv_rect");
 | 
							prv_img->rect[size] = MEM_callocN(values[0] * values[1] * sizeof(unsigned int), "prv_rect");
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		prv_img->w[size] = values[0];
 | 
							prv_img->w[size] = values[0];
 | 
				
			||||||
		prv_img->h[size] = values[1];
 | 
							prv_img->h[size] = values[1];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prv_img->flag[size] |= (PRV_CHANGED | PRV_USER_EDITED);
 | 
						prv_img->flag[size] |= (PRV_CHANGED | PRV_USER_EDITED);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -600,6 +600,14 @@ static void rna_ImagePreview_icon_reload(PreviewImage *prv)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PointerRNA rna_IDPreview_get(PointerRNA *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ID *id = (ID *)ptr->data;
 | 
				
			||||||
 | 
						PreviewImage *prv_img = BKE_previewimg_id_ensure(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rna_def_ID_properties(BlenderRNA *brna)
 | 
					static void rna_def_ID_properties(BlenderRNA *brna)
 | 
				
			||||||
@@ -840,6 +848,11 @@ static void rna_def_ID(BlenderRNA *brna)
 | 
				
			|||||||
	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 | 
						RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 | 
				
			||||||
	RNA_def_property_ui_text(prop, "Library", "Library file the datablock is linked from");
 | 
						RNA_def_property_ui_text(prop, "Library", "Library file the datablock is linked from");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prop = RNA_def_pointer(srna, "preview", "ImagePreview", "Preview",
 | 
				
			||||||
 | 
						                       "Preview image and icon of this datablock (None if not supported for this type of data)");
 | 
				
			||||||
 | 
						RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 | 
				
			||||||
 | 
						RNA_def_property_pointer_funcs(prop, "rna_IDPreview_get", NULL, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* functions */
 | 
						/* functions */
 | 
				
			||||||
	func = RNA_def_function(srna, "copy", "rna_ID_copy");
 | 
						func = RNA_def_function(srna, "copy", "rna_ID_copy");
 | 
				
			||||||
	RNA_def_function_ui_description(func, "Create a copy of this datablock (not supported for all datablocks)");
 | 
						RNA_def_function_ui_description(func, "Create a copy of this datablock (not supported for all datablocks)");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,6 +50,10 @@
 | 
				
			|||||||
#include "BKE_blender.h"
 | 
					#include "BKE_blender.h"
 | 
				
			||||||
#include "BKE_global.h"
 | 
					#include "BKE_global.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "DNA_ID.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "UI_interface_icons.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../generic/py_capi_utils.h"
 | 
					#include "../generic/py_capi_utils.h"
 | 
				
			||||||
#include "../generic/python_utildefines.h"
 | 
					#include "../generic/python_utildefines.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -298,6 +302,14 @@ static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(cl
 | 
				
			|||||||
	return Py_INCREF_RET(bpy_pydriver_Dict);
 | 
						return Py_INCREF_RET(bpy_pydriver_Dict);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyDoc_STRVAR(bpy_app_preview_render_size_doc,
 | 
				
			||||||
 | 
					"Reference size for icon/preview renders (read-only)"
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return PyLong_FromLong((long)UI_preview_render_size(GET_INT_FROM_POINTER(closure)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
 | 
					static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return PyC_UnicodeFromByte(G.autoexec_fail);
 | 
						return PyC_UnicodeFromByte(G.autoexec_fail);
 | 
				
			||||||
@@ -322,6 +334,9 @@ static PyGetSetDef bpy_app_getsets[] = {
 | 
				
			|||||||
	{(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
 | 
						{(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
 | 
				
			||||||
	{(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
 | 
						{(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
 | 
				
			||||||
 | 
					    {(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* security */
 | 
						/* security */
 | 
				
			||||||
	{(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL},
 | 
						{(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL},
 | 
				
			||||||
	{(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET},
 | 
						{(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,6 +74,7 @@
 | 
				
			|||||||
#include "BKE_brush.h"
 | 
					#include "BKE_brush.h"
 | 
				
			||||||
#include "BKE_context.h"
 | 
					#include "BKE_context.h"
 | 
				
			||||||
#include "BKE_depsgraph.h"
 | 
					#include "BKE_depsgraph.h"
 | 
				
			||||||
 | 
					#include "BKE_icons.h"
 | 
				
			||||||
#include "BKE_idprop.h"
 | 
					#include "BKE_idprop.h"
 | 
				
			||||||
#include "BKE_image.h"
 | 
					#include "BKE_image.h"
 | 
				
			||||||
#include "BKE_library.h"
 | 
					#include "BKE_library.h"
 | 
				
			||||||
@@ -4897,6 +4898,72 @@ static void WM_OT_previews_ensure(wmOperatorType *ot)
 | 
				
			|||||||
	ot->exec = previews_ensure_exec;
 | 
						ot->exec = previews_ensure_exec;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* *************************** Datablocks previews clear ************* */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Only types supporting previews currently. */
 | 
				
			||||||
 | 
					static EnumPropertyItem preview_id_type_items[] = {
 | 
				
			||||||
 | 
					    {FILTER_ID_SCE, "SCENE", 0, "Scenes", ""},
 | 
				
			||||||
 | 
					    {FILTER_ID_GR, "GROUP", 0, "Groups", ""},
 | 
				
			||||||
 | 
						{FILTER_ID_OB, "OBJECT", 0, "Objects", ""},
 | 
				
			||||||
 | 
					    {FILTER_ID_MA, "MATERIAL", 0, "Materials", ""},
 | 
				
			||||||
 | 
					    {FILTER_ID_LA, "LAMP", 0, "Lamps", ""},
 | 
				
			||||||
 | 
					    {FILTER_ID_WO, "WORLD", 0, "Worlds", ""},
 | 
				
			||||||
 | 
					    {FILTER_ID_TE, "TEXTURE", 0, "Textures", ""},
 | 
				
			||||||
 | 
					    {FILTER_ID_IM, "IMAGE", 0, "Images", ""},
 | 
				
			||||||
 | 
					#if 0  /* XXX TODO */
 | 
				
			||||||
 | 
					    {FILTER_ID_BR, "BRUSH", 0, "Brushes", ""},
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    {0, NULL, 0, NULL, NULL}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int previews_clear_exec(bContext *C, wmOperator *op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Main *bmain = CTX_data_main(C);
 | 
				
			||||||
 | 
						ListBase *lb[] = {&bmain->object, &bmain->group,
 | 
				
			||||||
 | 
						                  &bmain->mat, &bmain->world, &bmain->lamp, &bmain->tex, &bmain->image, NULL};
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const int id_filters = RNA_enum_get(op->ptr, "id_type");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; lb[i]; i++) {
 | 
				
			||||||
 | 
							ID *id = lb[i]->first;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!id) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//		printf("%s: %d, %d, %d -> %d\n", id->name, GS(id->name), BKE_idcode_to_idfilter(GS(id->name)),
 | 
				
			||||||
 | 
					//		                                 id_filters, BKE_idcode_to_idfilter(GS(id->name)) & id_filters);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!id || !(BKE_idcode_to_idfilter(GS(id->name)) & id_filters)) {
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (; id; id = id->next) {
 | 
				
			||||||
 | 
								PreviewImage *prv_img = BKE_previewimg_id_ensure(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								BKE_previewimg_clear(prv_img);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return OPERATOR_FINISHED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void WM_OT_previews_clear(wmOperatorType *ot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ot->name = "Clear DataBlock Previews";
 | 
				
			||||||
 | 
						ot->idname = "WM_OT_previews_clear";
 | 
				
			||||||
 | 
						ot->description = "Clear datablock previews (only for some types like objects, materials, textures, etc.)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ot->exec = previews_clear_exec;
 | 
				
			||||||
 | 
						ot->invoke = WM_menu_invoke;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ot->prop = RNA_def_enum_flag(ot->srna, "id_type", preview_id_type_items,
 | 
				
			||||||
 | 
						                             FILTER_ID_SCE | FILTER_ID_OB | FILTER_ID_GR |
 | 
				
			||||||
 | 
							                         FILTER_ID_MA | FILTER_ID_LA | FILTER_ID_WO | FILTER_ID_TE | FILTER_ID_IM,
 | 
				
			||||||
 | 
						                             "DataBlock Type", "Which datablock previews to clear");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* *************************** Doc from UI ************* */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op))
 | 
					static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	PointerRNA ptr_props;
 | 
						PointerRNA ptr_props;
 | 
				
			||||||
@@ -5025,6 +5092,7 @@ void wm_operatortype_init(void)
 | 
				
			|||||||
	WM_operatortype_append(WM_OT_console_toggle);
 | 
						WM_operatortype_append(WM_OT_console_toggle);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	WM_operatortype_append(WM_OT_previews_ensure);
 | 
						WM_operatortype_append(WM_OT_previews_ensure);
 | 
				
			||||||
 | 
						WM_operatortype_append(WM_OT_previews_clear);
 | 
				
			||||||
	WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
 | 
						WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user