231 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# ##### 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.props import (
 | 
						|
    BoolProperty,
 | 
						|
    EnumProperty,
 | 
						|
    StringProperty,
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
 | 
						|
    """Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object """
 | 
						|
    """(either a user-specified object or the active camera)"""
 | 
						|
    bl_idname = "scene.freestyle_fill_range_by_selection"
 | 
						|
    bl_label = "Fill Range by Selection"
 | 
						|
    bl_options = {'INTERNAL'}
 | 
						|
 | 
						|
    type = EnumProperty(
 | 
						|
            name="Type", description="Type of the modifier to work on",
 | 
						|
            items=(("COLOR", "Color", "Color modifier type"),
 | 
						|
                   ("ALPHA", "Alpha", "Alpha modifier type"),
 | 
						|
                   ("THICKNESS", "Thickness", "Thickness modifier type")),
 | 
						|
            )
 | 
						|
    name = StringProperty(
 | 
						|
            name="Name",
 | 
						|
            description="Name of the modifier to work on",
 | 
						|
            )
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def poll(cls, context):
 | 
						|
        rl = context.scene.render.layers.active
 | 
						|
        return rl and rl.freestyle_settings.linesets.active
 | 
						|
 | 
						|
    def execute(self, context):
 | 
						|
        import sys
 | 
						|
 | 
						|
        scene = context.scene
 | 
						|
        rl = scene.render.layers.active
 | 
						|
        lineset = rl.freestyle_settings.linesets.active
 | 
						|
        linestyle = lineset.linestyle
 | 
						|
        # Find the modifier to work on
 | 
						|
        if self.type == 'COLOR':
 | 
						|
            m = linestyle.color_modifiers[self.name]
 | 
						|
        elif self.type == 'ALPHA':
 | 
						|
            m = linestyle.alpha_modifiers[self.name]
 | 
						|
        else:
 | 
						|
            m = linestyle.thickness_modifiers[self.name]
 | 
						|
        # Find the reference object
 | 
						|
        if m.type == 'DISTANCE_FROM_CAMERA':
 | 
						|
            ref = scene.camera
 | 
						|
            matrix_to_camera = ref.matrix_world.inverted()
 | 
						|
        elif m.type == 'DISTANCE_FROM_OBJECT':
 | 
						|
            if m.target is None:
 | 
						|
                self.report({'ERROR'}, "Target object not specified")
 | 
						|
                return {'CANCELLED'}
 | 
						|
            ref = m.target
 | 
						|
            target_location = ref.location
 | 
						|
        else:
 | 
						|
            self.report({'ERROR'}, "Unexpected modifier type: " + m.type)
 | 
						|
            return {'CANCELLED'}
 | 
						|
        # Find selected vertices in editmesh
 | 
						|
        ob = context.active_object
 | 
						|
        if ob.type == 'MESH' and ob.mode == 'EDIT' and ob.name != ref.name:
 | 
						|
            bpy.ops.object.mode_set(mode='OBJECT')
 | 
						|
            selected_verts = [v for v in ob.data.vertices if v.select]
 | 
						|
            bpy.ops.object.mode_set(mode='EDIT')
 | 
						|
            # Compute the min/max distance from the reference to mesh vertices
 | 
						|
            min_dist = sys.float_info.max
 | 
						|
            max_dist = -min_dist
 | 
						|
            if m.type == 'DISTANCE_FROM_CAMERA':
 | 
						|
                ob_to_cam = matrix_to_camera * ob.matrix_world
 | 
						|
                for vert in selected_verts:
 | 
						|
                    # dist in the camera space
 | 
						|
                    dist = (ob_to_cam * vert.co).length
 | 
						|
                    min_dist = min(dist, min_dist)
 | 
						|
                    max_dist = max(dist, max_dist)
 | 
						|
            elif m.type == 'DISTANCE_FROM_OBJECT':
 | 
						|
                for vert in selected_verts:
 | 
						|
                    # dist in the world space
 | 
						|
                    dist = (ob.matrix_world * vert.co - target_location).length
 | 
						|
                    min_dist = min(dist, min_dist)
 | 
						|
                    max_dist = max(dist, max_dist)
 | 
						|
            # Fill the Range Min/Max entries with the computed distances
 | 
						|
            m.range_min = min_dist
 | 
						|
            m.range_max = max_dist
 | 
						|
            return {'FINISHED'}
 | 
						|
        # Find selected mesh objects
 | 
						|
        selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != ref.name]
 | 
						|
        if selection:
 | 
						|
            # Compute the min/max distance from the reference to mesh vertices
 | 
						|
            min_dist = sys.float_info.max
 | 
						|
            max_dist = -min_dist
 | 
						|
            if m.type == 'DISTANCE_FROM_CAMERA':
 | 
						|
                for ob in selection:
 | 
						|
                    ob_to_cam = matrix_to_camera * ob.matrix_world
 | 
						|
                    for vert in ob.data.vertices:
 | 
						|
                        # dist in the camera space
 | 
						|
                        dist = (ob_to_cam * vert.co).length
 | 
						|
                        min_dist = min(dist, min_dist)
 | 
						|
                        max_dist = max(dist, max_dist)
 | 
						|
            elif m.type == 'DISTANCE_FROM_OBJECT':
 | 
						|
                for ob in selection:
 | 
						|
                    for vert in ob.data.vertices:
 | 
						|
                        # dist in the world space
 | 
						|
                        dist = (ob.matrix_world * vert.co - target_location).length
 | 
						|
                        min_dist = min(dist, min_dist)
 | 
						|
                        max_dist = max(dist, max_dist)
 | 
						|
            # Fill the Range Min/Max entries with the computed distances
 | 
						|
            m.range_min = min_dist
 | 
						|
            m.range_max = max_dist
 | 
						|
        return {'FINISHED'}
 | 
						|
 | 
						|
 | 
						|
class SCENE_OT_freestyle_add_edge_marks_to_keying_set(bpy.types.Operator):
 | 
						|
    '''Add the data paths to the Freestyle Edge Mark property of selected edges to the active keying set'''
 | 
						|
    bl_idname = "scene.freestyle_add_edge_marks_to_keying_set"
 | 
						|
    bl_label = "Add Edge Marks to Keying Set"
 | 
						|
    bl_options = {'UNDO'}
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def poll(cls, context):
 | 
						|
        ob = context.active_object
 | 
						|
        return (ob and ob.type == 'MESH')
 | 
						|
 | 
						|
    def execute(self, context):
 | 
						|
        # active keying set
 | 
						|
        scene = context.scene
 | 
						|
        ks = scene.keying_sets.active
 | 
						|
        if ks is None:
 | 
						|
            ks = scene.keying_sets.new(idname="FreestyleEdgeMarkKeyingSet", name="Freestyle Edge Mark Keying Set")
 | 
						|
            ks.bl_description = ""
 | 
						|
        # add data paths to the keying set
 | 
						|
        ob = context.active_object
 | 
						|
        ob_mode = ob.mode
 | 
						|
        mesh = ob.data
 | 
						|
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 | 
						|
        for i, edge in enumerate(mesh.edges):
 | 
						|
            if not edge.hide and edge.select:
 | 
						|
                path = 'edges[%d].use_freestyle_mark' % i
 | 
						|
                ks.paths.add(mesh, path, index=0)
 | 
						|
        bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
 | 
						|
        return {'FINISHED'}
 | 
						|
 | 
						|
 | 
						|
class SCENE_OT_freestyle_add_face_marks_to_keying_set(bpy.types.Operator):
 | 
						|
    '''Add the data paths to the Freestyle Face Mark property of selected polygons to the active keying set'''
 | 
						|
    bl_idname = "scene.freestyle_add_face_marks_to_keying_set"
 | 
						|
    bl_label = "Add Face Marks to Keying Set"
 | 
						|
    bl_options = {'UNDO'}
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def poll(cls, context):
 | 
						|
        ob = context.active_object
 | 
						|
        return (ob and ob.type == 'MESH')
 | 
						|
 | 
						|
    def execute(self, context):
 | 
						|
        # active keying set
 | 
						|
        scene = context.scene
 | 
						|
        ks = scene.keying_sets.active
 | 
						|
        if ks is None:
 | 
						|
            ks = scene.keying_sets.new(idname="FreestyleFaceMarkKeyingSet", name="Freestyle Face Mark Keying Set")
 | 
						|
            ks.bl_description = ""
 | 
						|
        # add data paths to the keying set
 | 
						|
        ob = context.active_object
 | 
						|
        ob_mode = ob.mode
 | 
						|
        mesh = ob.data
 | 
						|
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 | 
						|
        for i, polygon in enumerate(mesh.polygons):
 | 
						|
            if not polygon.hide and polygon.select:
 | 
						|
                path = 'polygons[%d].use_freestyle_mark' % i
 | 
						|
                ks.paths.add(mesh, path, index=0)
 | 
						|
        bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
 | 
						|
        return {'FINISHED'}
 | 
						|
 | 
						|
 | 
						|
class SCENE_OT_freestyle_module_open(bpy.types.Operator):
 | 
						|
    """Open a style module file"""
 | 
						|
    bl_idname = "scene.freestyle_module_open"
 | 
						|
    bl_label = "Open Style Module File"
 | 
						|
    bl_options = {'INTERNAL'}
 | 
						|
 | 
						|
    filepath = StringProperty(subtype='FILE_PATH')
 | 
						|
 | 
						|
    make_internal = BoolProperty(
 | 
						|
        name="Make internal",
 | 
						|
        description="Make module file internal after loading",
 | 
						|
        default=True)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def poll(cls, context):
 | 
						|
        rl = context.scene.render.layers.active
 | 
						|
        return rl and rl.freestyle_settings.mode == 'SCRIPT'
 | 
						|
 | 
						|
    def invoke(self, context, event):
 | 
						|
        self.freestyle_module = context.freestyle_module
 | 
						|
        wm = context.window_manager
 | 
						|
        wm.fileselect_add(self)
 | 
						|
        return {'RUNNING_MODAL'}
 | 
						|
 | 
						|
    def execute(self, context):
 | 
						|
        text = bpy.data.texts.load(self.filepath, self.make_internal)
 | 
						|
        self.freestyle_module.script = text
 | 
						|
        return {'FINISHED'}
 | 
						|
 | 
						|
 | 
						|
classes = (
 | 
						|
    SCENE_OT_freestyle_add_edge_marks_to_keying_set,
 | 
						|
    SCENE_OT_freestyle_add_face_marks_to_keying_set,
 | 
						|
    SCENE_OT_freestyle_fill_range_by_selection,
 | 
						|
    SCENE_OT_freestyle_module_open,
 | 
						|
)
 |