123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- # ##### 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):
- view_layer = context.view_layer
- return view_layer and view_layer.freestyle_settings.linesets.active
- def execute(self, context):
- import sys
- scene = context.scene
- view_layer = context.view_layer
- lineset = view_layer.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_get() and ob.type == 'MESH' and ob.name != source.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):
- view_layer = context.view_layer
- return view_layer and view_layer.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, internal=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,
- )
|