Example #1
0
 def from_lineset(cls,
                  lineset,
                  filepath,
                  res_y,
                  split_at_invisible,
                  use_stroke_color,
                  frame_current,
                  *,
                  name=""):
     """Builds a SVGPathShader using data from the given lineset"""
     name = name or lineset.name
     linestyle = lineset.linestyle
     # extract style attributes from the linestyle and scene
     svg = getCurrentScene().svg_export
     style = {
         'fill': 'none',
         'stroke-width': linestyle.thickness,
         'stroke-linecap': linestyle.caps.lower(),
         'stroke-opacity': linestyle.alpha,
         'stroke': format_rgb(linestyle.color),
         'stroke-linejoin': svg.line_join_type.lower(),
     }
     # get dashed line pattern (if specified)
     if linestyle.use_dashed_line:
         style['stroke-dasharray'] = ",".join(
             str(elem) for elem in get_dashed_pattern(linestyle))
     # return instance
     return cls(name, style, filepath, res_y, split_at_invisible,
                use_stroke_color, frame_current)
Example #2
0
 def __init__(self, blend, influence, mapping, invert, curve, target, range_min, range_max):
     CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
     if target is None:
         raise ValueError("AlphaDistanceFromObjectShader: target can't be None ")
     self.range = BoundedProperty(range_min, range_max, range_max - range_min)
     # construct a model-view matrix
     matrix = getCurrentScene().camera.matrix_world.inverted()
     # get the object location in the camera coordinate
     self.loc = matrix * target.location
 def __init__(self, blend, influence, ramp, target, range_min, range_max):
     ColorRampModifier.__init__(self, blend, influence, ramp)
     if target is None:
         raise ValueError("ColorDistanceFromObjectShader: target can't be None ")
     self.range = Range(range_min, range_max, range_max - range_min)
     # construct a model-view matrix
     matrix = getCurrentScene().camera.matrix_world.inverted()
     # get the object location in the camera coordinate
     self.loc = matrix * target.location
Example #4
0
 def __init__(self, blend, influence, mapping, invert, curve, target, range_min, range_max):
     CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
     if target is None:
         raise ValueError("AlphaDistanceFromObjectShader: target can't be None ")
     self.range = BoundedProperty(range_min, range_max, range_max - range_min)
     # construct a model-view matrix
     matrix = getCurrentScene().camera.matrix_world.inverted()
     # get the object location in the camera coordinate
     self.loc = matrix * target.location
 def __init__(self, thickness_position, thickness_ratio,
              blend, influence, mapping, invert, curve, target, range_min, range_max, value_min, value_max):
     ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
     CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
     if target is None:
         raise ValueError("ThicknessDistanceFromObjectShader: target can't be None ")
     self.range = Range(range_min, range_max, range_max - range_min)
     self.value = Value(value_min, value_max, value_max - value_min)
     # construct a model-view matrix
     matrix = getCurrentScene().camera.matrix_world.inverted()
     # get the object location in the camera coordinate
     self.loc = matrix * target.location
 def from_lineset(cls, lineset, filepath, res_y, split_at_invisible, frame_current, *, name=""):
     """Builds a SVGPathShader using data from the given lineset"""
     name = name or lineset.name
     linestyle = lineset.linestyle
     # extract style attributes from the linestyle and scene
     svg = getCurrentScene().svg_export
     style = {
         'fill': 'none',
         'stroke-width': linestyle.thickness,
         'stroke-linecap': linestyle.caps.lower(),
         'stroke-opacity': linestyle.alpha,
         'stroke': 'rgb({}, {}, {})'.format(*(int(c * 255) for c in linestyle.color)),
         'stroke-linejoin': svg.line_join_type.lower(),
         }
     # get dashed line pattern (if specified)
     if linestyle.use_dashed_line:
         style['stroke-dasharray'] = ",".join(str(elem) for elem in get_dashed_pattern(linestyle))
     # return instance
     return cls(name, style, filepath, res_y, split_at_invisible, frame_current)
def postprocess(frame_start=None, frame_end=None, interval=0):
    """
    frame_start: the start frame (default Scene.frame_start)
    frame_end: the end frame (default: Scene.frame_end)
    interval: the number of frames inserted as interval between two strokes
    """
 
    totlen = 0.0
    nstrokes = Operators.get_strokes_size()
    #print('#strokes', nstrokes)
    for i in range(nstrokes):
        stroke = Operators.get_stroke_from_index(i)
        totlen += stroke.length_2d
    #print('totlen', totlen)
 
    scene = getCurrentScene()
    sta = scene.frame_start if frame_start is None else frame_start
    end = scene.frame_end if frame_end is None else frame_end
    cur = scene.frame_current
    fac = (cur - sta) / (end - sta)
    #print('fac', fac)
 
    totDrawingFrames = (end - sta + 1) - interval * (nstrokes - 1)
    if totDrawingFrames < 0:
        raise RuntimeError('The number of frames is too small')
 
    lengthPerFrame = totlen / totDrawingFrames
    #print('lengthPerFrame', lengthPerFrame)
 
    thresh = (cur - sta + 1) * lengthPerFrame + 1e-6
    #print('thresh', thresh)
 
    curlen = 0.0
    for i in range(nstrokes):
        stroke = Operators.get_stroke_from_index(i)
        for svert in stroke:
            svert.attribute.visible = curlen + svert.curvilinear_abscissa < thresh
        curlen += stroke.length_2d + lengthPerFrame * interval
    #print('done')
Example #8
0
def postprocess(frame_start=None, frame_end=None, interval=0):
    """
    frame_start: the start frame (default Scene.frame_start)
    frame_end: the end frame (default: Scene.frame_end)
    interval: the number of frames inserted as interval between two strokes
    """

    totlen = 0.0
    nstrokes = Operators.get_strokes_size()
    #print('#strokes', nstrokes)
    for i in range(nstrokes):
        stroke = Operators.get_stroke_from_index(i)
        totlen += stroke.length_2d
    #print('totlen', totlen)

    scene = getCurrentScene()
    sta = scene.frame_start if frame_start is None else frame_start
    end = scene.frame_end if frame_end is None else frame_end
    cur = scene.frame_current
    fac = (cur - sta) / (end - sta)
    #print('fac', fac)

    totDrawingFrames = (end - sta + 1) - interval * (nstrokes - 1)
    if totDrawingFrames < 0:
        raise RuntimeError('The number of frames is too small')

    lengthPerFrame = totlen / totDrawingFrames
    #print('lengthPerFrame', lengthPerFrame)

    thresh = (cur - sta + 1) * lengthPerFrame + 1e-6
    #print('thresh', thresh)

    curlen = 0.0
    for i in range(nstrokes):
        stroke = Operators.get_stroke_from_index(i)
        for svert in stroke:
            svert.attribute.visible = curlen + svert.curvilinear_abscissa < thresh
        curlen += stroke.length_2d + lengthPerFrame * interval
Example #9
0
def process(layer_name, lineset_name):
    scene = getCurrentScene()
    layer = scene.render.layers[layer_name]
    lineset = layer.freestyle_settings.linesets[lineset_name]
    linestyle = lineset.linestyle

    selection_criteria = []
    # prepare selection criteria by visibility
    if lineset.select_by_visibility:
        if lineset.visibility == 'VISIBLE':
            selection_criteria.append(
                QuantitativeInvisibilityUP1D(0))
        elif lineset.visibility == 'HIDDEN':
            selection_criteria.append(
                NotUP1D(QuantitativeInvisibilityUP1D(0)))
        elif lineset.visibility == 'RANGE':
            selection_criteria.append(
                QuantitativeInvisibilityRangeUP1D(lineset.qi_start, lineset.qi_end))
    # prepare selection criteria by edge types
    if lineset.select_by_edge_types:
        edge_type_criteria = []
        if lineset.select_silhouette:
            upred = pyNatureUP1D(Nature.SILHOUETTE)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_silhouette else upred)
        if lineset.select_border:
            upred = pyNatureUP1D(Nature.BORDER)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_border else upred)
        if lineset.select_crease:
            upred = pyNatureUP1D(Nature.CREASE)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_crease else upred)
        if lineset.select_ridge_valley:
            upred = pyNatureUP1D(Nature.RIDGE)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_ridge_valley else upred)
        if lineset.select_suggestive_contour:
            upred = pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_suggestive_contour else upred)
        if lineset.select_material_boundary:
            upred = pyNatureUP1D(Nature.MATERIAL_BOUNDARY)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_material_boundary else upred)
        if lineset.select_edge_mark:
            upred = pyNatureUP1D(Nature.EDGE_MARK)
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_edge_mark else upred)
        if lineset.select_contour:
            upred = ContourUP1D()
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_contour else upred)
        if lineset.select_external_contour:
            upred = ExternalContourUP1D()
            edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_external_contour else upred)
        if lineset.edge_type_combination == 'OR':
            upred = OrUP1D(*edge_type_criteria)
        else:
            upred = AndUP1D(*edge_type_criteria)
        if upred is not None:
            if lineset.edge_type_negation == 'EXCLUSIVE':
                upred = NotUP1D(upred)
            selection_criteria.append(upred)
    # prepare selection criteria by face marks
    if lineset.select_by_face_marks:
        if lineset.face_mark_condition == 'BOTH':
            upred = FaceMarkBothUP1D()
        else:
            upred = FaceMarkOneUP1D()

        if lineset.face_mark_negation == 'EXCLUSIVE':
            upred = NotUP1D(upred)
        selection_criteria.append(upred)
    # prepare selection criteria by group of objects
    if lineset.select_by_group:
        if lineset.group is not None:
            names = {ob.name: True for ob in lineset.group.objects}
            upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
            selection_criteria.append(upred)
    # prepare selection criteria by image border
    if lineset.select_by_image_border:
        upred = WithinImageBoundaryUP1D(*ContextFunctions.get_border())
        selection_criteria.append(upred)
    # select feature edges
    upred = AndUP1D(*selection_criteria)
    if upred is None:
        upred = TrueUP1D()
    Operators.select(upred)
    # join feature edges to form chains
    if linestyle.use_chaining:
        if linestyle.chaining == 'PLAIN':
            if linestyle.use_same_object:
                Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
            else:
                Operators.bidirectional_chain(ChainPredicateIterator(upred, TrueBP1D()), NotUP1D(upred))
        elif linestyle.chaining == 'SKETCHY':
            if linestyle.use_same_object:
                Operators.bidirectional_chain(pySketchyChainSilhouetteIterator(linestyle.rounds))
            else:
                Operators.bidirectional_chain(pySketchyChainingIterator(linestyle.rounds))
    else:
        Operators.chain(ChainPredicateIterator(FalseUP1D(), FalseBP1D()), NotUP1D(upred))
    # split chains
    if linestyle.material_boundary:
        Operators.sequential_split(MaterialBoundaryUP0D())
    if linestyle.use_angle_min or linestyle.use_angle_max:
        angle_min = linestyle.angle_min if linestyle.use_angle_min else None
        angle_max = linestyle.angle_max if linestyle.use_angle_max else None
        Operators.sequential_split(Curvature2DAngleThresholdUP0D(angle_min, angle_max))
    if linestyle.use_split_length:
        Operators.sequential_split(Length2DThresholdUP0D(linestyle.split_length), 1.0)
    if linestyle.use_split_pattern:
        pattern = []
        if linestyle.split_dash1 > 0 and linestyle.split_gap1 > 0:
            pattern.append(linestyle.split_dash1)
            pattern.append(linestyle.split_gap1)
        if linestyle.split_dash2 > 0 and linestyle.split_gap2 > 0:
            pattern.append(linestyle.split_dash2)
            pattern.append(linestyle.split_gap2)
        if linestyle.split_dash3 > 0 and linestyle.split_gap3 > 0:
            pattern.append(linestyle.split_dash3)
            pattern.append(linestyle.split_gap3)
        if len(pattern) > 0:
            sampling = 1.0
            controller = SplitPatternController(pattern, sampling)
            Operators.sequential_split(SplitPatternStartingUP0D(controller),
                                       SplitPatternStoppingUP0D(controller),
                                       sampling)
    # sort selected chains
    if linestyle.use_sorting:
        integration = integration_types.get(linestyle.integration_type, IntegrationType.MEAN)
        if linestyle.sort_key == 'DISTANCE_FROM_CAMERA':
            bpred = pyZBP1D(integration)
        elif linestyle.sort_key == '2D_LENGTH':
            bpred = Length2DBP1D()
        elif linestyle.sort_key == 'PROJECTED_X':
            bpred = pyProjectedXBP1D(integration)
        elif linestyle.sort_key == 'PROJECTED_Y':
            bpred = pyProjectedYBP1D(integration)
        if linestyle.sort_order == 'REVERSE':
            bpred = NotBP1D(bpred)
        Operators.sort(bpred)
    # select chains
    if linestyle.use_length_min or linestyle.use_length_max:
        length_min = linestyle.length_min if linestyle.use_length_min else None
        length_max = linestyle.length_max if linestyle.use_length_max else None
        Operators.select(LengthThresholdUP1D(length_min, length_max))
    if linestyle.use_chain_count:
        Operators.select(pyNFirstUP1D(linestyle.chain_count))
    # prepare a list of stroke shaders
    shaders_list = []
    for m in linestyle.geometry_modifiers:
        if not m.use:
            continue
        if m.type == 'SAMPLING':
            shaders_list.append(SamplingShader(
                m.sampling))
        elif m.type == 'BEZIER_CURVE':
            shaders_list.append(BezierCurveShader(
                m.error))
        elif m.type == 'SINUS_DISPLACEMENT':
            shaders_list.append(SinusDisplacementShader(
                m.wavelength, m.amplitude, m.phase))
        elif m.type == 'SPATIAL_NOISE':
            shaders_list.append(SpatialNoiseShader(
                m.amplitude, m.scale, m.octaves, m.smooth, m.use_pure_random))
        elif m.type == 'PERLIN_NOISE_1D':
            shaders_list.append(PerlinNoise1DShader(
                m.frequency, m.amplitude, m.octaves, m.angle, _seed.get(m.seed)))
        elif m.type == 'PERLIN_NOISE_2D':
            shaders_list.append(PerlinNoise2DShader(
                m.frequency, m.amplitude, m.octaves, m.angle, _seed.get(m.seed)))
        elif m.type == 'BACKBONE_STRETCHER':
            shaders_list.append(BackboneStretcherShader(
                m.backbone_length))
        elif m.type == 'TIP_REMOVER':
            shaders_list.append(TipRemoverShader(
                m.tip_length))
        elif m.type == 'POLYGONIZATION':
            shaders_list.append(PolygonalizationShader(
                m.error))
        elif m.type == 'GUIDING_LINES':
            shaders_list.append(GuidingLinesShader(
                m.offset))
        elif m.type == 'BLUEPRINT':
            if m.shape == 'CIRCLES':
                shaders_list.append(pyBluePrintCirclesShader(
                    m.rounds, m.random_radius, m.random_center))
            elif m.shape == 'ELLIPSES':
                shaders_list.append(pyBluePrintEllipsesShader(
                    m.rounds, m.random_radius, m.random_center))
            elif m.shape == 'SQUARES':
                shaders_list.append(pyBluePrintSquaresShader(
                    m.rounds, m.backbone_length, m.random_backbone))
        elif m.type == '2D_OFFSET':
            shaders_list.append(Offset2DShader(
                m.start, m.end, m.x, m.y))
        elif m.type == '2D_TRANSFORM':
            shaders_list.append(Transform2DShader(
                m.pivot, m.scale_x, m.scale_y, m.angle, m.pivot_u, m.pivot_x, m.pivot_y))
    # -- Base color, alpha and thickness -- #
    if (not linestyle.use_chaining) or (linestyle.chaining == 'PLAIN' and linestyle.use_same_object):
        thickness_position = linestyle.thickness_position
    else:
        thickness_position = 'CENTER'
        import bpy
        if bpy.app.debug_freestyle:
            print("Warning: Thickness position options are applied when chaining is disabled\n"
                  "         or the Plain chaining is used with the Same Object option enabled.")
    shaders_list.append(ConstantColorShader(*(linestyle.color), alpha=linestyle.alpha))
    shaders_list.append(BaseThicknessShader(linestyle.thickness, thickness_position,
                                            linestyle.thickness_ratio))
    # -- Modifiers -- #
    for m in linestyle.color_modifiers:
        if not m.use:
            continue
        if m.type == 'ALONG_STROKE':
            shaders_list.append(ColorAlongStrokeShader(
                m.blend, m.influence, m.color_ramp))
        elif m.type == 'DISTANCE_FROM_CAMERA':
            shaders_list.append(ColorDistanceFromCameraShader(
                m.blend, m.influence, m.color_ramp,
                m.range_min, m.range_max))
        elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
            shaders_list.append(ColorDistanceFromObjectShader(
                m.blend, m.influence, m.color_ramp, m.target,
                m.range_min, m.range_max))
        elif m.type == 'MATERIAL':
            shaders_list.append(ColorMaterialShader(
                m.blend, m.influence, m.color_ramp, m.material_attribute,
                m.use_ramp))
    for m in linestyle.alpha_modifiers:
        if not m.use:
            continue
        if m.type == 'ALONG_STROKE':
            shaders_list.append(AlphaAlongStrokeShader(
                m.blend, m.influence, m.mapping, m.invert, m.curve))
        elif m.type == 'DISTANCE_FROM_CAMERA':
            shaders_list.append(AlphaDistanceFromCameraShader(
                m.blend, m.influence, m.mapping, m.invert, m.curve,
                m.range_min, m.range_max))
        elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
            shaders_list.append(AlphaDistanceFromObjectShader(
                m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
                m.range_min, m.range_max))
        elif m.type == 'MATERIAL':
            shaders_list.append(AlphaMaterialShader(
                m.blend, m.influence, m.mapping, m.invert, m.curve,
                m.material_attribute))
    for m in linestyle.thickness_modifiers:
        if not m.use:
            continue
        if m.type == 'ALONG_STROKE':
            shaders_list.append(ThicknessAlongStrokeShader(
                thickness_position, linestyle.thickness_ratio,
                m.blend, m.influence, m.mapping, m.invert, m.curve,
                m.value_min, m.value_max))
        elif m.type == 'DISTANCE_FROM_CAMERA':
            shaders_list.append(ThicknessDistanceFromCameraShader(
                thickness_position, linestyle.thickness_ratio,
                m.blend, m.influence, m.mapping, m.invert, m.curve,
                m.range_min, m.range_max, m.value_min, m.value_max))
        elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
            shaders_list.append(ThicknessDistanceFromObjectShader(
                thickness_position, linestyle.thickness_ratio,
                m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
                m.range_min, m.range_max, m.value_min, m.value_max))
        elif m.type == 'MATERIAL':
            shaders_list.append(ThicknessMaterialShader(
                thickness_position, linestyle.thickness_ratio,
                m.blend, m.influence, m.mapping, m.invert, m.curve,
                m.material_attribute, m.value_min, m.value_max))
        elif m.type == 'CALLIGRAPHY':
            shaders_list.append(CalligraphicThicknessShader(
                thickness_position, linestyle.thickness_ratio,
                m.blend, m.influence,
                m.orientation, m.thickness_min, m.thickness_max))
    # -- Textures -- #
    has_tex = False
    if scene.render.use_shading_nodes:
        if linestyle.use_nodes and linestyle.node_tree:
            shaders_list.append(BlenderTextureShader(linestyle.node_tree))
            has_tex = True
    else:
        if linestyle.use_texture:
            textures = tuple(BlenderTextureShader(slot) for slot in linestyle.texture_slots if slot is not None)
            if textures:
                shaders_list.extend(textures)
                has_tex = True
    if has_tex:
        shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
    # -- Stroke caps -- #
    if linestyle.caps == 'ROUND':
        shaders_list.append(RoundCapShader())
    elif linestyle.caps == 'SQUARE':
        shaders_list.append(SquareCapShader())
    # -- Dashed line -- #
    if linestyle.use_dashed_line:
        pattern = []
        if linestyle.dash1 > 0 and linestyle.gap1 > 0:
            pattern.append(linestyle.dash1)
            pattern.append(linestyle.gap1)
        if linestyle.dash2 > 0 and linestyle.gap2 > 0:
            pattern.append(linestyle.dash2)
            pattern.append(linestyle.gap2)
        if linestyle.dash3 > 0 and linestyle.gap3 > 0:
            pattern.append(linestyle.dash3)
            pattern.append(linestyle.gap3)
        if len(pattern) > 0:
            shaders_list.append(DashedLineShader(pattern))
    # create strokes using the shaders list
    Operators.create(TrueUP1D(), shaders_list)
Example #10
0
 def __init__(self):
     scene = getCurrentScene()
     self.persp_camera = (scene.camera.data.type == 'PERSP')
Example #11
0
def process(layer_name, lineset_name):
    scene = getCurrentScene()
    layer = scene.render.layers[layer_name]
    lineset = layer.freestyle_settings.linesets[lineset_name]
    linestyle = lineset.linestyle

    selection_criteria = []
    # prepare selection criteria by visibility
    if lineset.select_by_visibility:
        if lineset.visibility == 'VISIBLE':
            selection_criteria.append(QuantitativeInvisibilityUP1D(0))
        elif lineset.visibility == 'HIDDEN':
            selection_criteria.append(NotUP1D(QuantitativeInvisibilityUP1D(0)))
        elif lineset.visibility == 'RANGE':
            selection_criteria.append(
                QuantitativeInvisibilityRangeUP1D(lineset.qi_start,
                                                  lineset.qi_end))
    # prepare selection criteria by edge types
    if lineset.select_by_edge_types:
        edge_type_criteria = []
        if lineset.select_silhouette:
            upred = pyNatureUP1D(Nature.SILHOUETTE)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_silhouette else upred)
        if lineset.select_border:
            upred = pyNatureUP1D(Nature.BORDER)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_border else upred)
        if lineset.select_crease:
            upred = pyNatureUP1D(Nature.CREASE)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_crease else upred)
        if lineset.select_ridge_valley:
            upred = pyNatureUP1D(Nature.RIDGE)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_ridge_valley else upred)
        if lineset.select_suggestive_contour:
            upred = pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_suggestive_contour else upred
            )
        if lineset.select_material_boundary:
            upred = pyNatureUP1D(Nature.MATERIAL_BOUNDARY)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_material_boundary else upred)
        if lineset.select_edge_mark:
            upred = pyNatureUP1D(Nature.EDGE_MARK)
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_edge_mark else upred)
        if lineset.select_contour:
            upred = ContourUP1D()
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_contour else upred)
        if lineset.select_external_contour:
            upred = ExternalContourUP1D()
            edge_type_criteria.append(
                NotUP1D(upred) if lineset.exclude_external_contour else upred)
        if lineset.edge_type_combination == 'OR':
            upred = OrUP1D(*edge_type_criteria)
        else:
            upred = AndUP1D(*edge_type_criteria)
        if upred is not None:
            if lineset.edge_type_negation == 'EXCLUSIVE':
                upred = NotUP1D(upred)
            selection_criteria.append(upred)
    # prepare selection criteria by face marks
    if lineset.select_by_face_marks:
        if lineset.face_mark_condition == 'BOTH':
            upred = FaceMarkBothUP1D()
        else:
            upred = FaceMarkOneUP1D()

        if lineset.face_mark_negation == 'EXCLUSIVE':
            upred = NotUP1D(upred)
        selection_criteria.append(upred)
    # prepare selection criteria by group of objects
    if lineset.select_by_group:
        if lineset.group is not None:
            names = {ob.name: True for ob in lineset.group.objects}
            upred = ObjectNamesUP1D(names,
                                    lineset.group_negation == 'EXCLUSIVE')
            selection_criteria.append(upred)
    # prepare selection criteria by image border
    if lineset.select_by_image_border:
        upred = WithinImageBoundaryUP1D(*ContextFunctions.get_border())
        selection_criteria.append(upred)
    # select feature edges
    upred = AndUP1D(*selection_criteria)
    if upred is None:
        upred = TrueUP1D()
    Operators.select(upred)
    # join feature edges to form chains
    if linestyle.use_chaining:
        if linestyle.chaining == 'PLAIN':
            if linestyle.use_same_object:
                Operators.bidirectional_chain(ChainSilhouetteIterator(),
                                              NotUP1D(upred))
            else:
                Operators.bidirectional_chain(
                    ChainPredicateIterator(upred, TrueBP1D()), NotUP1D(upred))
        elif linestyle.chaining == 'SKETCHY':
            if linestyle.use_same_object:
                Operators.bidirectional_chain(
                    pySketchyChainSilhouetteIterator(linestyle.rounds))
            else:
                Operators.bidirectional_chain(
                    pySketchyChainingIterator(linestyle.rounds))
    else:
        Operators.chain(ChainPredicateIterator(FalseUP1D(), FalseBP1D()),
                        NotUP1D(upred))
    # split chains
    if linestyle.material_boundary:
        Operators.sequential_split(MaterialBoundaryUP0D())
    if linestyle.use_angle_min or linestyle.use_angle_max:
        angle_min = linestyle.angle_min if linestyle.use_angle_min else None
        angle_max = linestyle.angle_max if linestyle.use_angle_max else None
        Operators.sequential_split(
            Curvature2DAngleThresholdUP0D(angle_min, angle_max))
    if linestyle.use_split_length:
        Operators.sequential_split(
            Length2DThresholdUP0D(linestyle.split_length), 1.0)
    if linestyle.use_split_pattern:
        pattern = []
        if linestyle.split_dash1 > 0 and linestyle.split_gap1 > 0:
            pattern.append(linestyle.split_dash1)
            pattern.append(linestyle.split_gap1)
        if linestyle.split_dash2 > 0 and linestyle.split_gap2 > 0:
            pattern.append(linestyle.split_dash2)
            pattern.append(linestyle.split_gap2)
        if linestyle.split_dash3 > 0 and linestyle.split_gap3 > 0:
            pattern.append(linestyle.split_dash3)
            pattern.append(linestyle.split_gap3)
        if len(pattern) > 0:
            sampling = 1.0
            controller = SplitPatternController(pattern, sampling)
            Operators.sequential_split(SplitPatternStartingUP0D(controller),
                                       SplitPatternStoppingUP0D(controller),
                                       sampling)
    # sort selected chains
    if linestyle.use_sorting:
        integration = integration_types.get(linestyle.integration_type,
                                            IntegrationType.MEAN)
        if linestyle.sort_key == 'DISTANCE_FROM_CAMERA':
            bpred = pyZBP1D(integration)
        elif linestyle.sort_key == '2D_LENGTH':
            bpred = Length2DBP1D()
        elif linestyle.sort_key == 'PROJECTED_X':
            bpred = pyProjectedXBP1D(integration)
        elif linestyle.sort_key == 'PROJECTED_Y':
            bpred = pyProjectedYBP1D(integration)
        if linestyle.sort_order == 'REVERSE':
            bpred = NotBP1D(bpred)
        Operators.sort(bpred)
    # select chains
    if linestyle.use_length_min or linestyle.use_length_max:
        length_min = linestyle.length_min if linestyle.use_length_min else None
        length_max = linestyle.length_max if linestyle.use_length_max else None
        Operators.select(LengthThresholdUP1D(length_min, length_max))
    if linestyle.use_chain_count:
        Operators.select(pyNFirstUP1D(linestyle.chain_count))
    # prepare a list of stroke shaders
    shaders_list = []
    for m in linestyle.geometry_modifiers:
        if not m.use:
            continue
        if m.type == 'SAMPLING':
            shaders_list.append(SamplingShader(m.sampling))
        elif m.type == 'BEZIER_CURVE':
            shaders_list.append(BezierCurveShader(m.error))
        elif m.type == 'SINUS_DISPLACEMENT':
            shaders_list.append(
                SinusDisplacementShader(m.wavelength, m.amplitude, m.phase))
        elif m.type == 'SPATIAL_NOISE':
            shaders_list.append(
                SpatialNoiseShader(m.amplitude, m.scale, m.octaves, m.smooth,
                                   m.use_pure_random))
        elif m.type == 'PERLIN_NOISE_1D':
            shaders_list.append(
                PerlinNoise1DShader(m.frequency, m.amplitude, m.octaves,
                                    m.angle, _seed.get(m.seed)))
        elif m.type == 'PERLIN_NOISE_2D':
            shaders_list.append(
                PerlinNoise2DShader(m.frequency, m.amplitude, m.octaves,
                                    m.angle, _seed.get(m.seed)))
        elif m.type == 'BACKBONE_STRETCHER':
            shaders_list.append(BackboneStretcherShader(m.backbone_length))
        elif m.type == 'TIP_REMOVER':
            shaders_list.append(TipRemoverShader(m.tip_length))
        elif m.type == 'POLYGONIZATION':
            shaders_list.append(PolygonalizationShader(m.error))
        elif m.type == 'GUIDING_LINES':
            shaders_list.append(GuidingLinesShader(m.offset))
        elif m.type == 'BLUEPRINT':
            if m.shape == 'CIRCLES':
                shaders_list.append(
                    pyBluePrintCirclesShader(m.rounds, m.random_radius,
                                             m.random_center))
            elif m.shape == 'ELLIPSES':
                shaders_list.append(
                    pyBluePrintEllipsesShader(m.rounds, m.random_radius,
                                              m.random_center))
            elif m.shape == 'SQUARES':
                shaders_list.append(
                    pyBluePrintSquaresShader(m.rounds, m.backbone_length,
                                             m.random_backbone))
        elif m.type == '2D_OFFSET':
            shaders_list.append(Offset2DShader(m.start, m.end, m.x, m.y))
        elif m.type == '2D_TRANSFORM':
            shaders_list.append(
                Transform2DShader(m.pivot, m.scale_x, m.scale_y, m.angle,
                                  m.pivot_u, m.pivot_x, m.pivot_y))
    # -- Base color, alpha and thickness -- #
    if (not linestyle.use_chaining) or (linestyle.chaining == 'PLAIN'
                                        and linestyle.use_same_object):
        thickness_position = linestyle.thickness_position
    else:
        thickness_position = 'CENTER'
        import bpy
        if bpy.app.debug_freestyle:
            print(
                "Warning: Thickness position options are applied when chaining is disabled\n"
                "         or the Plain chaining is used with the Same Object option enabled."
            )
    shaders_list.append(
        ConstantColorShader(*(linestyle.color), alpha=linestyle.alpha))
    shaders_list.append(
        BaseThicknessShader(linestyle.thickness, thickness_position,
                            linestyle.thickness_ratio))
    # -- Modifiers -- #
    for m in linestyle.color_modifiers:
        if not m.use:
            continue
        if m.type == 'ALONG_STROKE':
            shaders_list.append(
                ColorAlongStrokeShader(m.blend, m.influence, m.color_ramp))
        elif m.type == 'DISTANCE_FROM_CAMERA':
            shaders_list.append(
                ColorDistanceFromCameraShader(m.blend, m.influence,
                                              m.color_ramp, m.range_min,
                                              m.range_max))
        elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
            shaders_list.append(
                ColorDistanceFromObjectShader(m.blend, m.influence,
                                              m.color_ramp, m.target,
                                              m.range_min, m.range_max))
        elif m.type == 'MATERIAL':
            shaders_list.append(
                ColorMaterialShader(m.blend, m.influence, m.color_ramp,
                                    m.material_attribute, m.use_ramp))
    for m in linestyle.alpha_modifiers:
        if not m.use:
            continue
        if m.type == 'ALONG_STROKE':
            shaders_list.append(
                AlphaAlongStrokeShader(m.blend, m.influence, m.mapping,
                                       m.invert, m.curve))
        elif m.type == 'DISTANCE_FROM_CAMERA':
            shaders_list.append(
                AlphaDistanceFromCameraShader(m.blend, m.influence, m.mapping,
                                              m.invert, m.curve, m.range_min,
                                              m.range_max))
        elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
            shaders_list.append(
                AlphaDistanceFromObjectShader(m.blend, m.influence, m.mapping,
                                              m.invert, m.curve, m.target,
                                              m.range_min, m.range_max))
        elif m.type == 'MATERIAL':
            shaders_list.append(
                AlphaMaterialShader(m.blend, m.influence, m.mapping, m.invert,
                                    m.curve, m.material_attribute))
    for m in linestyle.thickness_modifiers:
        if not m.use:
            continue
        if m.type == 'ALONG_STROKE':
            shaders_list.append(
                ThicknessAlongStrokeShader(thickness_position,
                                           linestyle.thickness_ratio, m.blend,
                                           m.influence, m.mapping, m.invert,
                                           m.curve, m.value_min, m.value_max))
        elif m.type == 'DISTANCE_FROM_CAMERA':
            shaders_list.append(
                ThicknessDistanceFromCameraShader(thickness_position,
                                                  linestyle.thickness_ratio,
                                                  m.blend, m.influence,
                                                  m.mapping, m.invert, m.curve,
                                                  m.range_min, m.range_max,
                                                  m.value_min, m.value_max))
        elif m.type == 'DISTANCE_FROM_OBJECT' and m.target is not None:
            shaders_list.append(
                ThicknessDistanceFromObjectShader(
                    thickness_position, linestyle.thickness_ratio, m.blend,
                    m.influence, m.mapping, m.invert, m.curve, m.target,
                    m.range_min, m.range_max, m.value_min, m.value_max))
        elif m.type == 'MATERIAL':
            shaders_list.append(
                ThicknessMaterialShader(thickness_position,
                                        linestyle.thickness_ratio, m.blend,
                                        m.influence, m.mapping, m.invert,
                                        m.curve, m.material_attribute,
                                        m.value_min, m.value_max))
        elif m.type == 'CALLIGRAPHY':
            shaders_list.append(
                CalligraphicThicknessShader(thickness_position,
                                            linestyle.thickness_ratio, m.blend,
                                            m.influence, m.orientation,
                                            m.thickness_min, m.thickness_max))
    # -- Textures -- #
    has_tex = False
    if scene.render.use_shading_nodes:
        if linestyle.use_nodes and linestyle.node_tree:
            shaders_list.append(BlenderTextureShader(linestyle.node_tree))
            has_tex = True
    else:
        if linestyle.use_texture:
            textures = tuple(
                BlenderTextureShader(slot) for slot in linestyle.texture_slots
                if slot is not None)
            if textures:
                shaders_list.extend(textures)
                has_tex = True
    if has_tex:
        shaders_list.append(StrokeTextureStepShader(linestyle.texture_spacing))
    # -- Stroke caps -- #
    if linestyle.caps == 'ROUND':
        shaders_list.append(RoundCapShader())
    elif linestyle.caps == 'SQUARE':
        shaders_list.append(SquareCapShader())
    # -- Dashed line -- #
    if linestyle.use_dashed_line:
        pattern = []
        if linestyle.dash1 > 0 and linestyle.gap1 > 0:
            pattern.append(linestyle.dash1)
            pattern.append(linestyle.gap1)
        if linestyle.dash2 > 0 and linestyle.gap2 > 0:
            pattern.append(linestyle.dash2)
            pattern.append(linestyle.gap2)
        if linestyle.dash3 > 0 and linestyle.gap3 > 0:
            pattern.append(linestyle.dash3)
            pattern.append(linestyle.gap3)
        if len(pattern) > 0:
            shaders_list.append(DashedLineShader(pattern))
    # create strokes using the shaders list
    Operators.create(TrueUP1D(), shaders_list)
Example #12
0
 def __init__(self):
     scene = getCurrentScene()
     self.persp_camera = (scene.camera.data.type == 'PERSP')