Grease Pencil: Add LineArt modifier

This adds the LineArt grease pencil modifier.

It takes objects or collections as input and generates various grease
pencil lines from these objects with the help of the active scene
camera. For example it can generate contour lines, intersection lines
and crease lines to name a few.

This is really useful as artists can then use 3D meshes to automatically
generate grease pencil lines for characters, enviroments or other
visualization purposes.

These lines can then be baked and edited as regular grease pencil lines.

Reviewed By: Sebastian Parborg, Antonio Vazquez, Matias Mendiola

Differential Revision: http://developer.blender.org/D8758
This commit is contained in:
YimingWu
2021-03-16 19:35:53 +01:00
committed by Sebastian Parborg
parent 877238e2b7
commit 3e87d8a431
62 changed files with 8056 additions and 28 deletions

View File

@@ -67,6 +67,7 @@ _modules = [
"properties_scene",
"properties_texture",
"properties_world",
"properties_collection",
# Generic Space Modules
#
@@ -104,6 +105,8 @@ import bpy
if bpy.app.build_options.freestyle:
_modules.append("properties_freestyle")
_modules.append("properties_lineart")
__import__(name=__name__, fromlist=_modules)
_namespace = globals()
_modules_loaded = [_namespace[name] for name in _modules]

View File

@@ -0,0 +1,98 @@
# ##### 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>
from bpy.types import Panel
class CollectionButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "collection"
def lineart_make_line_type_entry(col, line_type, text_disp, expand, search_from):
col.prop(line_type, "use", text=text_disp)
if line_type.use and expand:
col.prop_search(line_type, "layer", search_from,
"layers", icon='GREASEPENCIL')
col.prop_search(line_type, "material", search_from,
"materials", icon='SHADING_TEXTURE')
class COLLECTION_PT_collection_flags(CollectionButtonsPanel, Panel):
bl_label = "Restrictions"
@classmethod
def poll(cls, context):
vl = context.view_layer
vlc = vl.active_layer_collection
return (vlc.name != 'Master Collection')
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
collection = context.collection
vl = context.view_layer
vlc = vl.active_layer_collection
col = layout.column(align=True)
col.prop(collection, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
col.prop(collection, "hide_render", toggle=False)
col = layout.column(align=True)
col.prop(vlc, "holdout", toggle=False)
col.prop(vlc, "indirect_only", toggle=False)
class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
bl_label = "Line Art"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
collection = context.collection
row = layout.row()
row.prop(collection, "lineart_usage")
class COLLECTION_PT_instancing(CollectionButtonsPanel, Panel):
bl_label = "Instancing"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
collection = context.collection
row = layout.row()
row.prop(collection, "instance_offset")
classes = (
COLLECTION_PT_collection_flags,
COLLECTION_PT_lineart_collection,
COLLECTION_PT_instancing,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)

View File

@@ -0,0 +1,59 @@
# ##### 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>
from bpy.types import Panel
class LineartButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
class OBJECT_PT_lineart(LineartButtonsPanel, Panel):
bl_label = "Line Art"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
ob = context.object
return (ob.type in {'MESH', 'FONT', 'CURVE', 'SURFACE'})
def draw(self, context):
layout = self.layout
lineart = context.object.lineart
layout.use_property_split = True
layout.prop(lineart, 'usage')
layout.use_property_split = True
row = layout.row(heading="Override Crease")
row.prop(lineart, "use_crease_override", text="")
row.prop(lineart, "crease_threshold", slider=True, text="")
classes = (
OBJECT_PT_lineart,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)

View File

@@ -274,6 +274,38 @@ class MATERIAL_PT_viewport(MaterialButtonsPanel, Panel):
col.prop(mat, "roughness")
class MATERIAL_PT_lineart(MaterialButtonsPanel, Panel):
bl_label = "Line Art"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
mat = context.material
return mat and not mat.grease_pencil
def draw(self, context):
layout = self.layout
mat = context.material
lineart = mat.lineart
layout.prop(lineart, "use_transparency")
if lineart.use_transparency:
layout.label(text="Transparency Masks:")
row = layout.row(align=True)
row.prop(lineart, "transparency_mask_0", text="0", toggle=True)
row.prop(lineart, "transparency_mask_1", text="1", toggle=True)
row.prop(lineart, "transparency_mask_2", text="2", toggle=True)
row.prop(lineart, "transparency_mask_3", text="3", toggle=True)
row.prop(lineart, "transparency_mask_4", text="4", toggle=True)
row.prop(lineart, "transparency_mask_5", text="5", toggle=True)
row.prop(lineart, "transparency_mask_6", text="6", toggle=True)
row.prop(lineart, "transparency_mask_7", text="7", toggle=True)
classes = (
MATERIAL_MT_context_menu,
MATERIAL_UL_matslots,
@@ -282,6 +314,7 @@ classes = (
EEVEE_MATERIAL_PT_surface,
EEVEE_MATERIAL_PT_volume,
EEVEE_MATERIAL_PT_settings,
MATERIAL_PT_lineart,
MATERIAL_PT_viewport,
EEVEE_MATERIAL_PT_viewport_settings,
MATERIAL_PT_custom_props,

View File

@@ -3829,11 +3829,10 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.operator("mesh.mark_sharp")
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
if render.use_freestyle:
col.separator()
col.separator()
col.operator("mesh.mark_freestyle_edge").clear = False
col.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
col.operator("mesh.mark_freestyle_edge").clear = False
col.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
col.separator()
@@ -4028,11 +4027,10 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
props.use_verts = True
props.clear = True
if render.use_freestyle:
layout.separator()
layout.separator()
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
class VIEW3D_MT_edit_mesh_edges(Menu):