GPencil: Refactor of Draw Engine, Vertex Paint and all internal functions
This commit is a full refactor of the grease pencil modules including Draw Engine, Modifiers, VFX, depsgraph update, improvements in operators and conversion of Sculpt and Weight paint tools to real brushes. Also, a huge code cleanup has been done at all levels. Thanks to @fclem for his work and yo @pepeland and @mendio for the testing and help in the development. Differential Revision: https://developer.blender.org/D6293
This commit is contained in:
@@ -187,7 +187,6 @@ const UserDef U_default = {
|
||||
.pie_menu_radius = 100,
|
||||
.pie_menu_threshold = 12,
|
||||
.opensubdiv_compute_type = 0,
|
||||
.gpencil_multisamples = 4,
|
||||
.factor_display_type = USER_FACTOR_AS_FACTOR,
|
||||
.render_display_type = USER_RENDER_DISPLAY_WINDOW,
|
||||
.filebrowser_display_type = USER_TEMP_SPACE_DISPLAY_WINDOW,
|
||||
|
||||
@@ -199,6 +199,9 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True):
|
||||
'WEIGHT_PAINT': "weight_tool",
|
||||
'TEXTURE_PAINT': "image_tool",
|
||||
'PAINT_GPENCIL': "gpencil_tool",
|
||||
'VERTEX_GPENCIL': "gpencil_vertex_tool",
|
||||
'SCULPT_GPENCIL': "gpencil_sculpt_tool",
|
||||
'WEIGHT_GPENCIL': "gpencil_weight_tool",
|
||||
}.get(mode, None)
|
||||
if attr is not None:
|
||||
setattr(kmi_hack_brush_select_properties, attr, item.data_block)
|
||||
|
||||
@@ -194,9 +194,26 @@ _km_hierarchy = [
|
||||
('Grease Pencil Stroke Paint (Draw brush)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint (Fill)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint (Erase)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint (Tint)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Paint Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Smooth)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Thickness)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Strength)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Grab)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Push)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Twist)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Pinch)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Randomize)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Sculpt (Clone)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Weight (Draw)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex Mode', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Draw)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Blur)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Average)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Smear)', 'EMPTY', 'WINDOW', []),
|
||||
('Grease Pencil Stroke Vertex (Replace)', 'EMPTY', 'WINDOW', []),
|
||||
]),
|
||||
('Mask Editing', 'EMPTY', 'WINDOW', []),
|
||||
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
|
||||
|
||||
@@ -7,8 +7,6 @@ gpcolor.stroke_style = 'SOLID'
|
||||
gpcolor.color = (0.0, 0.0, 0.0, 0.0)
|
||||
gpcolor.stroke_image = None
|
||||
gpcolor.pixel_size = 100.0
|
||||
gpcolor.use_stroke_pattern = False
|
||||
gpcolor.use_stroke_texture_mix = False
|
||||
gpcolor.mix_stroke_factor = 0.0
|
||||
gpcolor.alignment_mode = 'PATH'
|
||||
gpcolor.fill_style = 'SOLID'
|
||||
@@ -18,18 +16,11 @@ gpcolor.gradient_type = 'LINEAR'
|
||||
gpcolor.mix_color = (1.0, 1.0, 1.0, 0.2)
|
||||
gpcolor.mix_factor = 0.0
|
||||
gpcolor.flip = False
|
||||
gpcolor.pattern_shift = (0.0, 0.0)
|
||||
gpcolor.pattern_scale = (1.0, 1.0)
|
||||
gpcolor.pattern_radius = 0.5
|
||||
gpcolor.pattern_angle = 0.0
|
||||
gpcolor.pattern_gridsize = 0.1
|
||||
gpcolor.use_fill_pattern = False
|
||||
gpcolor.texture_offset = (0.0, 0.0)
|
||||
gpcolor.texture_scale = (1.0, 1.0)
|
||||
gpcolor.texture_angle = 0.0
|
||||
gpcolor.texture_opacity = 1.0
|
||||
gpcolor.texture_clamp = False
|
||||
gpcolor.use_fill_texture_mix = False
|
||||
gpcolor.mix_factor = 0.0
|
||||
gpcolor.show_stroke = False
|
||||
gpcolor.show_fill = True
|
||||
|
||||
@@ -7,8 +7,6 @@ gpcolor.stroke_style = 'SOLID'
|
||||
gpcolor.color = (0.0, 0.0, 0.0, 1.0)
|
||||
gpcolor.stroke_image = None
|
||||
gpcolor.pixel_size = 100.0
|
||||
gpcolor.use_stroke_pattern = False
|
||||
gpcolor.use_stroke_texture_mix = False
|
||||
gpcolor.mix_stroke_factor = 0.0
|
||||
gpcolor.alignment_mode = 'PATH'
|
||||
gpcolor.fill_style = 'SOLID'
|
||||
@@ -18,18 +16,11 @@ gpcolor.gradient_type = 'LINEAR'
|
||||
gpcolor.mix_color = (1.0, 1.0, 1.0, 0.2)
|
||||
gpcolor.mix_factor = 0.0
|
||||
gpcolor.flip = False
|
||||
gpcolor.pattern_shift = (0.0, 0.0)
|
||||
gpcolor.pattern_scale = (1.0, 1.0)
|
||||
gpcolor.pattern_radius = 0.5
|
||||
gpcolor.pattern_angle = 0.0
|
||||
gpcolor.pattern_gridsize = 0.1
|
||||
gpcolor.use_fill_pattern = False
|
||||
gpcolor.texture_offset = (0.0, 0.0)
|
||||
gpcolor.texture_scale = (1.0, 1.0)
|
||||
gpcolor.texture_angle = 0.0
|
||||
gpcolor.texture_opacity = 1.0
|
||||
gpcolor.texture_clamp = False
|
||||
gpcolor.use_fill_texture_mix = False
|
||||
gpcolor.mix_factor = 0.0
|
||||
gpcolor.show_stroke = True
|
||||
gpcolor.show_fill = True
|
||||
|
||||
@@ -7,8 +7,6 @@ gpcolor.stroke_style = 'SOLID'
|
||||
gpcolor.color = (0.0, 0.0, 0.0, 1.0)
|
||||
gpcolor.stroke_image = None
|
||||
gpcolor.pixel_size = 100.0
|
||||
gpcolor.use_stroke_pattern = False
|
||||
gpcolor.use_stroke_texture_mix = False
|
||||
gpcolor.mix_stroke_factor = 0.0
|
||||
gpcolor.alignment_mode = 'PATH'
|
||||
gpcolor.fill_style = 'SOLID'
|
||||
@@ -18,18 +16,11 @@ gpcolor.gradient_type = 'LINEAR'
|
||||
gpcolor.mix_color = (1.0, 1.0, 1.0, 0.2)
|
||||
gpcolor.mix_factor = 0.0
|
||||
gpcolor.flip = False
|
||||
gpcolor.pattern_shift = (0.0, 0.0)
|
||||
gpcolor.pattern_scale = (1.0, 1.0)
|
||||
gpcolor.pattern_radius = 0.5
|
||||
gpcolor.pattern_angle = 0.0
|
||||
gpcolor.pattern_gridsize = 0.1
|
||||
gpcolor.use_fill_pattern = False
|
||||
gpcolor.texture_offset = (0.0, 0.0)
|
||||
gpcolor.texture_scale = (1.0, 1.0)
|
||||
gpcolor.texture_angle = 0.0
|
||||
gpcolor.texture_opacity = 1.0
|
||||
gpcolor.texture_clamp = False
|
||||
gpcolor.use_fill_texture_mix = False
|
||||
gpcolor.mix_factor = 0.0
|
||||
gpcolor.show_stroke = True
|
||||
gpcolor.show_fill = False
|
||||
|
||||
@@ -3168,6 +3168,10 @@ def km_grease_pencil_stroke_edit_mode(params):
|
||||
{"properties": [("mode", 1)]}),
|
||||
("gpencil.selectmode_toggle", {"type": 'THREE', "value": 'PRESS'},
|
||||
{"properties": [("mode", 2)]}),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Context menu
|
||||
*_template_items_context_menu("VIEW3D_MT_gpencil_edit_context_menu", params.context_menu_event),
|
||||
])
|
||||
@@ -3211,6 +3215,10 @@ def km_grease_pencil_stroke_paint_mode(params):
|
||||
{"properties": [("unselected", False)]}),
|
||||
("gpencil.hide", {"type": 'H', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("unselected", True)]}),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Draw context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_draw_context_menu", params.context_menu_event),
|
||||
])
|
||||
@@ -3322,6 +3330,25 @@ def km_grease_pencil_stroke_paint_fill(params):
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_tint(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Tint)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
@@ -3336,14 +3363,22 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.strength')]}),
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt_paint.brush.strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.size')]}),
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt_paint.brush.size')]}),
|
||||
# Copy
|
||||
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Keyframe menu
|
||||
("gpencil.blank_frame_add", {"type": 'I', "value": 'PRESS', "shift": True}, None),
|
||||
("gpencil.active_frames_delete_all", {"type": 'X', "value": 'PRESS', "shift": True}, None),
|
||||
("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_sculpt_context_menu", params.context_menu_event),
|
||||
])
|
||||
@@ -3351,7 +3386,187 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_mode(_params):
|
||||
def km_grease_pencil_stroke_sculpt_smooth(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Smooth)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_thickness(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Thickness)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_strength(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Strength)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_grab(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Grab)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_push(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Push)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_twist(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Twist)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_pinch(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Pinch)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_randomize(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Randomize)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_clone(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Clone)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight Mode",
|
||||
@@ -3360,19 +3575,196 @@ def km_grease_pencil_stroke_weight_mode(_params):
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Painting
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.size')]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Keyframe menu
|
||||
("gpencil.blank_frame_add", {"type": 'I', "value": 'PRESS', "shift": True}, None),
|
||||
("gpencil.active_frames_delete_all", {"type": 'X', "value": 'PRESS', "shift": True}, None),
|
||||
("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_weight_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_draw(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Draw)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Draw
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex Mode",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Tools
|
||||
op_tool("builtin_brush.Draw", {"type": 'D', "value": 'PRESS'}),
|
||||
op_tool("builtin_brush.Blur", {"type": 'F', "value": 'PRESS'}),
|
||||
op_tool("builtin_brush.Average", {"type": 'E', "value": 'PRESS'}),
|
||||
op_tool("builtin.brush.Smear", {"type": 'K', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
("gpencil.blank_frame_add", {"type": 'I', "value": 'PRESS', "shift": True}, None),
|
||||
("gpencil.active_frames_delete_all", {"type": 'X', "value": 'PRESS', "shift": True}, None),
|
||||
("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
# Vertex Paint context menu
|
||||
op_panel("VIEW3D_PT_gpencil_vertex_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_draw(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Draw)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.weight_brush.strength')]}),
|
||||
# Brush sze
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.weight_brush.size')]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_blur(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Blur)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_average(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Average)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_smear(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Smear)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_replace(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Replace)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
@@ -6053,18 +6445,13 @@ def km_3d_view_tool_edit_gpencil_to_sphere(params):
|
||||
)
|
||||
|
||||
|
||||
# Also used for weight paint.
|
||||
def km_3d_view_tool_sculpt_gpencil_paint(_params):
|
||||
def km_3d_view_tool_edit_gpencil_transform_fill(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt Gpencil, Paint",
|
||||
"3D View Tool: Edit Gpencil, Transform Fill",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.transform_fill", {"type": params.tool_tweak, "value": 'ANY'},
|
||||
{"properties": [("release_confirm", True)]}),
|
||||
]},
|
||||
)
|
||||
|
||||
@@ -6201,8 +6588,25 @@ def generate_keymaps(params=None):
|
||||
km_grease_pencil_stroke_paint_draw_brush(params),
|
||||
km_grease_pencil_stroke_paint_erase(params),
|
||||
km_grease_pencil_stroke_paint_fill(params),
|
||||
km_grease_pencil_stroke_paint_tint(params),
|
||||
km_grease_pencil_stroke_sculpt_mode(params),
|
||||
km_grease_pencil_stroke_sculpt_smooth(params),
|
||||
km_grease_pencil_stroke_sculpt_thickness(params),
|
||||
km_grease_pencil_stroke_sculpt_strength(params),
|
||||
km_grease_pencil_stroke_sculpt_grab(params),
|
||||
km_grease_pencil_stroke_sculpt_push(params),
|
||||
km_grease_pencil_stroke_sculpt_twist(params),
|
||||
km_grease_pencil_stroke_sculpt_pinch(params),
|
||||
km_grease_pencil_stroke_sculpt_randomize(params),
|
||||
km_grease_pencil_stroke_sculpt_clone(params),
|
||||
km_grease_pencil_stroke_weight_mode(params),
|
||||
km_grease_pencil_stroke_weight_draw(params),
|
||||
km_grease_pencil_stroke_vertex_mode(params),
|
||||
km_grease_pencil_stroke_vertex_draw(params),
|
||||
km_grease_pencil_stroke_vertex_blur(params),
|
||||
km_grease_pencil_stroke_vertex_average(params),
|
||||
km_grease_pencil_stroke_vertex_smear(params),
|
||||
km_grease_pencil_stroke_vertex_replace(params),
|
||||
km_face_mask(params),
|
||||
km_weight_paint_vertex_selection(params),
|
||||
km_pose(params),
|
||||
@@ -6345,7 +6749,7 @@ def generate_keymaps(params=None):
|
||||
km_3d_view_tool_edit_gpencil_bend(params),
|
||||
km_3d_view_tool_edit_gpencil_shear(params),
|
||||
km_3d_view_tool_edit_gpencil_to_sphere(params),
|
||||
km_3d_view_tool_sculpt_gpencil_paint(params),
|
||||
km_3d_view_tool_edit_gpencil_transform_fill(params),
|
||||
km_3d_view_tool_sculpt_gpencil_select(params),
|
||||
km_3d_view_tool_sculpt_gpencil_select_box(params),
|
||||
km_3d_view_tool_sculpt_gpencil_select_circle(params),
|
||||
|
||||
@@ -2364,6 +2364,10 @@ def km_grease_pencil_stroke_paint_mode(params):
|
||||
op_tool_cycle("builtin_brush.Erase", {"type": 'E', "value": 'PRESS'}),
|
||||
op_tool_cycle("builtin.cutter", {"type": 'K', "value": 'PRESS'}),
|
||||
op_tool_cycle("builtin.cursor", {"type": 'C', "value": 'PRESS'}),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'M', "value": 'PRESS'}),
|
||||
# Keyframe menu
|
||||
op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
@@ -2470,6 +2474,25 @@ def km_grease_pencil_stroke_paint_fill(params):
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_tint(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Tint)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
@@ -2481,21 +2504,199 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
items.extend([
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
# Painting
|
||||
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt_paint.brush.strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt_paint.brush.size')]}),
|
||||
# Copy
|
||||
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Context menu
|
||||
op_panel("VIEW3D_PT_gpencil_sculpt_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_smooth(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Smooth)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_thickness(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Thickness)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_strength(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Strength)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_grab(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Grab)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_push(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Push)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_twist(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Twist)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_pinch(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Pinch)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_randomize(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Randomize)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_clone(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Clone)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'U', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'S', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.size')]}),
|
||||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_sculpt_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
@@ -2510,24 +2711,181 @@ def km_grease_pencil_stroke_weight_mode(params):
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
# Painting
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'U', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.weight_brush.strength')]}),
|
||||
# Brush size.
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_weight_paint.brush.strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'S', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.weight_brush.size')]}),
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt.brush.size')]}),
|
||||
# Context menu
|
||||
*_template_items_context_panel("VIEW3D_PT_gpencil_weight_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_draw(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Draw)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("gpencil.weight_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex Mode",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
# Tools
|
||||
op_tool("builtin_brush.Draw", {"type": 'D', "value": 'PRESS'}),
|
||||
op_tool("builtin_brush.Blur", {"type": 'F', "value": 'PRESS'}),
|
||||
op_tool("builtin_brush.Average", {"type": 'E', "value": 'PRESS'}),
|
||||
op_tool("builtin.brush.Smear", {"type": 'K', "value": 'PRESS'}),
|
||||
op_tool("builtin.brush.Replace", {"type": 'R', "value": 'PRESS'}),
|
||||
# Vertex Paint context menu
|
||||
op_panel("VIEW3D_PT_gpencil_vertex_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
def km_grease_pencil_stroke_vertex_draw(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Draw)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_blur(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Blur)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_average(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Average)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_smear(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Smear)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'U', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'S', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_replace(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Replace)",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
# Tint
|
||||
("gpencil.vertex_paint", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("wait_for_input", False)]}),
|
||||
# Brush size
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.size')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
def km_face_mask(params):
|
||||
items = []
|
||||
keymap = (
|
||||
@@ -3679,8 +4037,25 @@ def generate_keymaps_impl(params=None):
|
||||
km_grease_pencil_stroke_paint_draw_brush(params),
|
||||
km_grease_pencil_stroke_paint_erase(params),
|
||||
km_grease_pencil_stroke_paint_fill(params),
|
||||
km_grease_pencil_stroke_paint_tint(params),
|
||||
km_grease_pencil_stroke_sculpt_mode(params),
|
||||
km_grease_pencil_stroke_sculpt_smooth(params),
|
||||
km_grease_pencil_stroke_sculpt_thickness(params),
|
||||
km_grease_pencil_stroke_sculpt_strength(params),
|
||||
km_grease_pencil_stroke_sculpt_grab(params),
|
||||
km_grease_pencil_stroke_sculpt_push(params),
|
||||
km_grease_pencil_stroke_sculpt_twist(params),
|
||||
km_grease_pencil_stroke_sculpt_pinch(params),
|
||||
km_grease_pencil_stroke_sculpt_randomize(params),
|
||||
km_grease_pencil_stroke_sculpt_clone(params),
|
||||
km_grease_pencil_stroke_weight_mode(params),
|
||||
km_grease_pencil_stroke_weight_draw(params),
|
||||
km_grease_pencil_stroke_vertex_mode(params),
|
||||
km_grease_pencil_stroke_vertex_draw(params),
|
||||
km_grease_pencil_stroke_vertex_blur(params),
|
||||
km_grease_pencil_stroke_vertex_average(params),
|
||||
km_grease_pencil_stroke_vertex_smear(params),
|
||||
km_grease_pencil_stroke_vertex_replace(params),
|
||||
km_face_mask(params),
|
||||
km_weight_paint_vertex_selection(params),
|
||||
km_pose(params),
|
||||
|
||||
@@ -642,10 +642,7 @@ class AddPresetGpencilBrush(AddPresetBase, Operator):
|
||||
"brush.smooth_stroke_factor",
|
||||
"settings.pen_smooth_factor",
|
||||
"settings.pen_smooth_steps",
|
||||
"settings.pen_thick_smooth_factor",
|
||||
"settings.pen_thick_smooth_steps",
|
||||
"settings.pen_subdivision_steps",
|
||||
"settings.random_subdiv",
|
||||
"settings.use_settings_random",
|
||||
"settings.random_pressure",
|
||||
"settings.random_strength",
|
||||
@@ -675,8 +672,6 @@ class AddPresetGpencilMaterial(AddPresetBase, Operator):
|
||||
"gpcolor.color",
|
||||
"gpcolor.stroke_image",
|
||||
"gpcolor.pixel_size",
|
||||
"gpcolor.use_stroke_pattern",
|
||||
"gpcolor.use_stroke_texture_mix",
|
||||
"gpcolor.mix_stroke_factor",
|
||||
"gpcolor.alignment_mode",
|
||||
"gpcolor.fill_style",
|
||||
@@ -686,18 +681,11 @@ class AddPresetGpencilMaterial(AddPresetBase, Operator):
|
||||
"gpcolor.mix_color",
|
||||
"gpcolor.mix_factor",
|
||||
"gpcolor.flip",
|
||||
"gpcolor.pattern_shift",
|
||||
"gpcolor.pattern_scale",
|
||||
"gpcolor.pattern_radius",
|
||||
"gpcolor.pattern_angle",
|
||||
"gpcolor.pattern_gridsize",
|
||||
"gpcolor.use_fill_pattern",
|
||||
"gpcolor.texture_offset",
|
||||
"gpcolor.texture_scale",
|
||||
"gpcolor.texture_angle",
|
||||
"gpcolor.texture_opacity",
|
||||
"gpcolor.texture_clamp",
|
||||
"gpcolor.use_fill_texture_mix",
|
||||
"gpcolor.mix_factor",
|
||||
"gpcolor.show_stroke",
|
||||
"gpcolor.show_fill",
|
||||
|
||||
@@ -22,6 +22,7 @@ from bpy.types import Menu, Panel, UIList
|
||||
from rna_prop_ui import PropertyPanel
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilLayerMasksPanel,
|
||||
GreasePencilLayerAdjustmentsPanel,
|
||||
GreasePencilLayerRelationsPanel,
|
||||
GreasePencilLayerDisplayPanel,
|
||||
@@ -116,7 +117,7 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
#layout.use_property_split = True
|
||||
# layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
gpd = context.gpencil
|
||||
@@ -166,7 +167,6 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
|
||||
col = layout.column(align=True)
|
||||
|
||||
if gpl:
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = True
|
||||
@@ -178,6 +178,15 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "use_lights")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_masks(LayerDataButtonsPanel, GreasePencilLayerMasksPanel, Panel):
|
||||
bl_label = "Masks"
|
||||
bl_parent_id = 'DATA_PT_gpencil_layers'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_adjustments(LayerDataButtonsPanel, GreasePencilLayerAdjustmentsPanel, Panel):
|
||||
bl_label = "Adjustments"
|
||||
@@ -264,7 +273,7 @@ class DATA_PT_gpencil_onion_skinning_display(DataButtonsPanel, Panel):
|
||||
col.prop(gpd, "use_onion_fade", text="Fade")
|
||||
sub = layout.column()
|
||||
sub.active = gpd.onion_mode in {'RELATIVE', 'SELECTED'}
|
||||
sub.prop(gpd, "use_onion_loop", text="Loop")
|
||||
sub.prop(gpd, "use_onion_loop", text="Show Start Frame")
|
||||
|
||||
|
||||
class GPENCIL_MT_gpencil_vertex_group(Menu):
|
||||
@@ -364,9 +373,6 @@ class DATA_PT_gpencil_strokes(DataButtonsPanel, Panel):
|
||||
sub.active = gpd.stroke_thickness_space == 'WORLDSPACE'
|
||||
sub.prop(gpd, "pixel_factor", text="Thickness Scale")
|
||||
|
||||
layout.prop(gpd, "use_force_fill_recalc", text="Force Fill Update")
|
||||
layout.prop(gpd, "use_adaptive_uv", text="Adaptive UVs")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
|
||||
bl_label = "Viewport Display"
|
||||
@@ -381,8 +387,6 @@ class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
|
||||
gpl = gpd.layers.active
|
||||
|
||||
layout.prop(gpd, "edit_line_color", text="Edit Line Color")
|
||||
if gpl:
|
||||
layout.prop(gpd, "show_stroke_direction", text="Show Stroke Directions")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_canvas(DataButtonsPanel, Panel):
|
||||
@@ -411,6 +415,7 @@ class DATA_PT_custom_props_gpencil(DataButtonsPanel, PropertyPanel, Panel):
|
||||
_context_path = "object.data"
|
||||
_property_type = bpy.types.GreasePencil
|
||||
|
||||
|
||||
###############################
|
||||
|
||||
|
||||
@@ -420,6 +425,7 @@ classes = (
|
||||
DATA_PT_gpencil_onion_skinning,
|
||||
DATA_PT_gpencil_onion_skinning_custom_colors,
|
||||
DATA_PT_gpencil_onion_skinning_display,
|
||||
DATA_PT_gpencil_layer_masks,
|
||||
DATA_PT_gpencil_layer_adjustments,
|
||||
DATA_PT_gpencil_layer_relations,
|
||||
DATA_PT_gpencil_layer_display,
|
||||
@@ -437,5 +443,6 @@ classes = (
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
|
||||
for cls in classes:
|
||||
register_class(cls)
|
||||
|
||||
@@ -1746,132 +1746,102 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
# ...to avoid lengthy if statements
|
||||
# so each type must have a function here.
|
||||
|
||||
def GP_NOISE(self, layout, ob, md):
|
||||
def gpencil_masking(self, layout, ob, md, use_vertex, use_curve=False):
|
||||
gpd = ob.data
|
||||
layout.separator()
|
||||
layout.label(text="Influence Filters:")
|
||||
|
||||
split = layout.split(factor=0.25)
|
||||
|
||||
col1 = split.column()
|
||||
|
||||
col1.label(text="Layer:")
|
||||
col1.label(text="Material:")
|
||||
if use_vertex:
|
||||
col1.label(text="Vertex Group:")
|
||||
|
||||
col2 = split.column()
|
||||
|
||||
split = col2.split(factor=0.6)
|
||||
row = split.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
row = split.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
split = col2.split(factor=0.6)
|
||||
|
||||
row = split.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
row = split.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
if use_vertex:
|
||||
row = col2.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
if use_curve:
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.prop(md, "use_custom_curve")
|
||||
if md.use_custom_curve:
|
||||
col.template_curve_mapping(md, "curve")
|
||||
|
||||
def GP_NOISE(self, layout, ob, md):
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "factor")
|
||||
row.prop(md, "factor", text="Position")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "factor_strength", text="Strength")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "factor_thickness", text="Thickness")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "factor_uvs", text="UV")
|
||||
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "random", text="", icon='TIME', toggle=True)
|
||||
row = col.row()
|
||||
row.enabled = md.random
|
||||
row.prop(md, "step")
|
||||
row = col.row()
|
||||
row.enabled = md.random
|
||||
row.prop(md, "seed")
|
||||
col.prop(md, "full_stroke")
|
||||
col.prop(md, "move_extreme")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="Affect:")
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
|
||||
row.prop(md, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
|
||||
row.prop(md, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
|
||||
row.prop(md, "use_edit_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
|
||||
subrow = row.row(align=True)
|
||||
subrow.enabled = md.random
|
||||
subrow.prop(md, "step")
|
||||
subrow.prop(md, "seed")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
col.prop(md, "noise_scale")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True, True)
|
||||
|
||||
def GP_SMOOTH(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
col = layout.column()
|
||||
col.prop(md, "factor")
|
||||
col.prop(md, "step")
|
||||
col.prop(md, "step", text="Repeat")
|
||||
|
||||
col.label(text="Affect:")
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
|
||||
row.prop(md, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
|
||||
row.prop(md, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
|
||||
row.prop(md, "use_edit_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
|
||||
row.prop(md, "use_edit_position", text="Position", toggle=True)
|
||||
row.prop(md, "use_edit_strength", text="Strength", toggle=True)
|
||||
row.prop(md, "use_edit_thickness", text="Thickness", toggle=True)
|
||||
row.prop(md, "use_edit_uv", text="UV", toggle=True)
|
||||
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True, True)
|
||||
|
||||
def GP_SUBDIV(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
layout.row().prop(md, "subdivision_type", expand=True)
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "level")
|
||||
row.prop(md, "simple", text="", icon='PARTICLE_POINT')
|
||||
row.prop(md, "level", text="Subdivisions")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, False)
|
||||
|
||||
def GP_SIMPLIFY(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
@@ -1893,77 +1863,21 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
elif md.mode == 'MERGE':
|
||||
col.prop(md, "distance")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, False)
|
||||
|
||||
def GP_THICK(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "thickness", text="Thickness Factor")
|
||||
col = layout.column()
|
||||
|
||||
col.prop(md, "normalize_thickness")
|
||||
|
||||
if not md.normalize_thickness:
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(md, "use_custom_curve")
|
||||
if md.normalize_thickness:
|
||||
col.prop(md, "thickness")
|
||||
else:
|
||||
col.prop(md, "thickness_factor")
|
||||
|
||||
if md.use_custom_curve:
|
||||
col.template_curve_mapping(md, "curve")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True, True)
|
||||
|
||||
def GP_TINT(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@@ -1971,30 +1885,9 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.prop(md, "factor")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(md, "create_materials")
|
||||
row.prop(md, "modify_color")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, False, True)
|
||||
|
||||
def GP_TIME(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
@@ -2040,7 +1933,6 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
def GP_COLOR(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@@ -2050,134 +1942,66 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.prop(md, "value", text="V", slider=True)
|
||||
|
||||
row = layout.row()
|
||||
row.prop(md, "create_materials")
|
||||
row.prop(md, "modify_color")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, False, True)
|
||||
|
||||
def GP_OPACITY(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Opacity:")
|
||||
col.prop(md, "factor")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(md, "opacity_mode", text="Mode")
|
||||
|
||||
if md.opacity_mode == 'MATERIAL':
|
||||
row = layout.row()
|
||||
row.prop(md, "create_materials")
|
||||
row.prop(md, "modify_color", text="Change")
|
||||
col.prop(md, "normalize_opacity")
|
||||
if md.normalize_opacity is True:
|
||||
text="Strength"
|
||||
else:
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
text="Opacity Factor"
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.prop(md, "factor", text=text)
|
||||
col.prop(md, "modify_color")
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True, True)
|
||||
|
||||
def GP_ARRAY(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
|
||||
col = layout.column()
|
||||
col.prop(md, "count")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label(text="Offset:")
|
||||
col.prop(md, "offset", text="")
|
||||
col.prop(md, "offset_object", text="Object")
|
||||
col.prop(md, "use_constant_offset", text="Constant Offset")
|
||||
subcol = col.column()
|
||||
subcol.enabled = md.use_constant_offset
|
||||
subcol.prop(md, "constant_offset", text="")
|
||||
|
||||
col.prop(md, "use_object_offset")
|
||||
subcol = col.column()
|
||||
subcol.enabled = md.use_object_offset
|
||||
subcol.prop(md, "offset_object", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Shift:")
|
||||
col.prop(md, "shift", text="")
|
||||
col.prop(md, "use_relative_offset", text="Relative Offset")
|
||||
subcol = col.column()
|
||||
subcol.enabled = md.use_relative_offset
|
||||
subcol.prop(md, "relative_offset", text="")
|
||||
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.label(text="Rotation:")
|
||||
col.prop(md, "rotation", text="")
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "random_rot", text="", icon='TIME', toggle=True)
|
||||
row.prop(md, "rot_factor", text="")
|
||||
col.label(text="Random Offset:")
|
||||
col.prop(md, "random_offset", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Scale:")
|
||||
col.prop(md, "scale", text="")
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(md, "random_scale", text="", icon='TIME', toggle=True)
|
||||
row.prop(md, "scale_factor", text="")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(md, "replace_material", text="Material")
|
||||
col.prop(md, "keep_on_top", text="Keep original stroke on top")
|
||||
col.label(text="Random Rotation:")
|
||||
col.prop(md, "random_rotation", text="")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Random Scale:")
|
||||
col.prop(md, "random_scale", text="")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(md, "seed")
|
||||
col.separator()
|
||||
col.prop(md, "replace_material", text="Material Override")
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, False)
|
||||
|
||||
def GP_BUILD(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
@@ -2215,7 +2039,6 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
def GP_LATTICE(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@@ -2224,70 +2047,20 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
|
||||
layout.prop(md, "strength", slider=True)
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True)
|
||||
|
||||
def GP_MIRROR(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "x_axis")
|
||||
row.prop(md, "y_axis")
|
||||
row.prop(md, "z_axis")
|
||||
|
||||
layout.label(text="Object:")
|
||||
layout.label(text="Mirror Object:")
|
||||
layout.prop(md, "object", text="")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, False)
|
||||
|
||||
def GP_HOOK(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@@ -2317,71 +2090,16 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
col = split.column()
|
||||
col.prop(md, "use_falloff_uniform")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True)
|
||||
|
||||
def GP_OFFSET(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
col = layout.column()
|
||||
split = layout.split()
|
||||
|
||||
col.prop(md, "location")
|
||||
col.prop(md, "scale")
|
||||
col.prop(md, "rotation")
|
||||
split.column().prop(md, "location")
|
||||
split.column().prop(md, "rotation")
|
||||
split.column().prop(md, "scale")
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Vertex Group:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
|
||||
row.prop(md, "invert_vertex", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
self.gpencil_masking(layout, ob, md, True)
|
||||
|
||||
def GP_ARMATURE(self, layout, ob, md):
|
||||
split = layout.split()
|
||||
@@ -2407,50 +2125,42 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
|
||||
sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
|
||||
|
||||
def GP_MULTIPLY(self, layout, ob, md):
|
||||
gpd = ob.data
|
||||
col = layout.column()
|
||||
|
||||
col.prop(md, "duplications")
|
||||
col.prop(md, "duplicates")
|
||||
subcol = col.column()
|
||||
subcol.enabled = md.duplications > 0
|
||||
subcol.enabled = md.duplicates > 0
|
||||
subcol.prop(md, "distance")
|
||||
subcol.prop(md, "offset", slider=True)
|
||||
|
||||
subcol.separator()
|
||||
|
||||
subcol.prop(md, "enable_fading")
|
||||
if md.enable_fading:
|
||||
subcol.prop(md, "use_fade")
|
||||
if md.use_fade:
|
||||
subcol.prop(md, "fading_center")
|
||||
subcol.prop(md, "fading_thickness", slider=True)
|
||||
subcol.prop(md, "fading_opacity", slider=True)
|
||||
|
||||
subcol.separator()
|
||||
|
||||
col.prop(md, "enable_angle_splitting")
|
||||
if md.enable_angle_splitting:
|
||||
col.prop(md, "split_angle")
|
||||
self.gpencil_masking(layout, ob, md, False)
|
||||
|
||||
def GP_VERTEXCOLOR(self, layout, ob, md):
|
||||
col = layout.column()
|
||||
col.label(text="Object:")
|
||||
col.prop(md, "object", text="")
|
||||
|
||||
col.separator()
|
||||
|
||||
col.label(text="Material:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "material", gpd, "materials", text="", icon='SHADING_TEXTURE')
|
||||
row.prop(md, "invert_materials", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "pass_index", text="Pass")
|
||||
row.prop(md, "invert_material_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
row.prop(md, "radius")
|
||||
row.prop(md, "factor", text="Strength", slider=True)
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.label(text="Colors:")
|
||||
col.template_color_ramp(md, "colors")
|
||||
|
||||
col.label(text="Layer:")
|
||||
row = col.row(align=True)
|
||||
row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
|
||||
row.prop(md, "invert_layers", text="", icon='ARROW_LEFTRIGHT')
|
||||
row = layout.row(align=True)
|
||||
row.prop(md, "layer_pass", text="Pass")
|
||||
row.prop(md, "invert_layer_pass", text="", icon='ARROW_LEFTRIGHT')
|
||||
col.separator()
|
||||
col.prop(md, "vertex_mode")
|
||||
|
||||
self.gpencil_masking(layout, ob, md, True, True)
|
||||
|
||||
|
||||
classes = (
|
||||
@@ -2460,5 +2170,6 @@ classes = (
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
|
||||
for cls in classes:
|
||||
register_class(cls)
|
||||
|
||||
@@ -56,27 +56,30 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
|
||||
|
||||
def FX_BLUR(self, layout, fx):
|
||||
|
||||
layout.prop(fx, "factor", text="Factor")
|
||||
layout.prop(fx, "use_dof_mode", text="Use as Depth Of Field")
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
col.enabled = not fx.use_dof_mode
|
||||
col.prop(fx, "size", text="Size")
|
||||
col.separator()
|
||||
col.prop(fx, "rotation")
|
||||
|
||||
layout.prop(fx, "samples", text="Samples")
|
||||
|
||||
layout.separator()
|
||||
layout.prop(fx, "use_dof_mode")
|
||||
if fx.use_dof_mode:
|
||||
layout.prop(fx, "coc")
|
||||
|
||||
def FX_COLORIZE(self, layout, fx):
|
||||
layout.prop(fx, "mode", text="Mode")
|
||||
|
||||
if fx.mode == 'BITONE':
|
||||
if fx.mode == 'DUOTONE':
|
||||
layout.prop(fx, "low_color", text="Low Color")
|
||||
if fx.mode == 'CUSTOM':
|
||||
layout.prop(fx, "low_color", text="Color")
|
||||
|
||||
if fx.mode == 'BITONE':
|
||||
if fx.mode == 'DUOTONE':
|
||||
layout.prop(fx, "high_color", text="High Color")
|
||||
|
||||
if fx.mode in {'BITONE', 'CUSTOM', 'TRANSPARENT'}:
|
||||
layout.prop(fx, "factor")
|
||||
layout.prop(fx, "factor")
|
||||
|
||||
def FX_WAVE(self, layout, fx):
|
||||
row = layout.row(align=True)
|
||||
@@ -127,16 +130,21 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
|
||||
|
||||
def FX_GLOW(self, layout, fx):
|
||||
layout.prop(fx, "mode")
|
||||
layout.prop(fx, "glow_color")
|
||||
if fx.mode == 'LUMINANCE':
|
||||
layout.prop(fx, "threshold")
|
||||
else:
|
||||
layout.prop(fx, "select_color")
|
||||
|
||||
layout.prop(fx, "glow_color")
|
||||
layout.separator()
|
||||
layout.prop(fx, "radius")
|
||||
layout.prop(fx, "blend_mode", text="Blend")
|
||||
layout.prop(fx, "opacity")
|
||||
|
||||
layout.prop(fx, "size")
|
||||
layout.prop(fx, "rotation")
|
||||
layout.prop(fx, "samples")
|
||||
layout.prop(fx, "use_alpha_mode", text="Use Alpha Mode")
|
||||
|
||||
layout.prop(fx, "use_glow_under", text="Glow Under")
|
||||
|
||||
def FX_SWIRL(self, layout, fx):
|
||||
layout.prop(fx, "object", text="Object")
|
||||
@@ -144,18 +152,10 @@ class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
|
||||
layout.prop(fx, "radius")
|
||||
layout.prop(fx, "angle")
|
||||
|
||||
layout.prop(fx, "use_transparent")
|
||||
|
||||
def FX_FLIP(self, layout, fx):
|
||||
layout.prop(fx, "flip_horizontal")
|
||||
layout.prop(fx, "flip_vertical")
|
||||
|
||||
def FX_LIGHT(self, layout, fx):
|
||||
layout.prop(fx, "object", text="Object")
|
||||
|
||||
layout.prop(fx, "energy")
|
||||
layout.prop(fx, "ambient")
|
||||
|
||||
|
||||
classes = (
|
||||
DATA_PT_shader_fx,
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.types import Menu, UIList
|
||||
from bpy.types import Menu, UIList, Operator
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
|
||||
@@ -108,11 +108,6 @@ class AnnotationDrawingToolsPanel:
|
||||
sub.operator("gpencil.blank_frame_add", icon='FILE_NEW')
|
||||
sub.operator("gpencil.active_frames_delete_all", icon='X', text="Delete Frame(s)")
|
||||
|
||||
#sub = col.column(align=True)
|
||||
#sub.prop(context.tool_settings, "use_gpencil_draw_additive", text="Additive Drawing")
|
||||
#sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing")
|
||||
#sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back")
|
||||
|
||||
col.separator()
|
||||
col.separator()
|
||||
|
||||
@@ -125,9 +120,6 @@ class AnnotationDrawingToolsPanel:
|
||||
elif is_clip_editor:
|
||||
row.prop(context.space_data, "grease_pencil_source", expand=True)
|
||||
|
||||
# col.separator()
|
||||
# col.separator()
|
||||
|
||||
gpencil_stroke_placement_settings(context, col)
|
||||
|
||||
|
||||
@@ -136,29 +128,33 @@ class GreasePencilSculptOptionsPanel:
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool = settings.sculpt_tool
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_sculpt_paint
|
||||
brush = settings.brush
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
|
||||
return bool(tool in {'SMOOTH', 'RANDOMIZE', 'SMOOTH'})
|
||||
return bool(tool in {'SMOOTH', 'RANDOMIZE'})
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool = settings.sculpt_tool
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_sculpt_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
|
||||
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
layout.prop(settings, "use_edit_position", text="Affect Position")
|
||||
layout.prop(settings, "use_edit_strength", text="Affect Strength")
|
||||
layout.prop(settings, "use_edit_thickness", text="Affect Thickness")
|
||||
layout.prop(gp_settings, "use_edit_position", text="Affect Position")
|
||||
layout.prop(gp_settings, "use_edit_strength", text="Affect Strength")
|
||||
layout.prop(gp_settings, "use_edit_thickness", text="Affect Thickness")
|
||||
|
||||
if tool == 'SMOOTH':
|
||||
layout.prop(brush, "use_edit_pressure")
|
||||
layout.prop(gp_settings, "use_edit_pressure")
|
||||
|
||||
layout.prop(settings, "use_edit_uv", text="Affect UV")
|
||||
layout.prop(gp_settings, "use_edit_uv", text="Affect UV")
|
||||
|
||||
|
||||
# GP Object Tool Settings
|
||||
@@ -174,7 +170,7 @@ class GreasePencilDisplayPanel:
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
return brush.gpencil_tool != 'ERASE'
|
||||
else:
|
||||
# GP Sculpt and Weight Paint always have Brush Tip panel.
|
||||
# GP Sculpt, Vertex and Weight Paint always have Brush Tip panel.
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -182,16 +178,18 @@ class GreasePencilDisplayPanel:
|
||||
if self.is_popover:
|
||||
return
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
self.layout.prop(gp_settings, "use_cursor", text="")
|
||||
elif context.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
self.layout.prop(brush, "use_cursor", text="")
|
||||
settings = tool_settings.gpencil_paint
|
||||
elif context.mode == 'SCULPT_GPENCIL':
|
||||
settings = tool_settings.gpencil_sculpt_paint
|
||||
elif context.mode == 'WEIGHT_GPENCIL':
|
||||
settings = tool_settings.gpencil_weight_paint
|
||||
elif context.mode == 'VERTEX_GPENCIL':
|
||||
settings = tool_settings.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
if brush:
|
||||
self.layout.prop(settings, "show_brush", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -199,279 +197,101 @@ class GreasePencilDisplayPanel:
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
ob = context.active_object
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
settings = tool_settings.gpencil_paint
|
||||
elif context.mode == 'SCULPT_GPENCIL':
|
||||
settings = tool_settings.gpencil_sculpt_paint
|
||||
elif context.mode == 'WEIGHT_GPENCIL':
|
||||
settings = tool_settings.gpencil_weight_paint
|
||||
elif context.mode == 'VERTEX_GPENCIL':
|
||||
settings = tool_settings.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
ob = context.active_object
|
||||
if ob.mode == 'PAINT_GPENCIL':
|
||||
brush = tool_settings.gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
if self.is_popover:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "use_cursor", text="")
|
||||
row.prop(settings, "show_brush", text="")
|
||||
row.label(text="Display Cursor")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.active = gp_settings.use_cursor
|
||||
col.active = settings.show_brush
|
||||
|
||||
if brush.gpencil_tool == 'DRAW':
|
||||
col.prop(gp_settings, "show_lasso", text="Show Fill Color While Drawing")
|
||||
|
||||
if brush.gpencil_tool == 'FILL':
|
||||
col.prop(brush, "cursor_color_add", text="Cursor Color")
|
||||
|
||||
elif ob.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
settings = tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
tool = settings.sculpt_tool
|
||||
|
||||
if self.is_popover:
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "use_cursor", text="")
|
||||
row.label(text="Display Cursor")
|
||||
|
||||
elif ob.mode == 'SCULPT_GPENCIL':
|
||||
col = layout.column(align=True)
|
||||
col.active = brush.use_cursor
|
||||
col.active = settings.show_brush
|
||||
|
||||
col.prop(brush, "cursor_color_add", text="Cursor Color")
|
||||
if tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
|
||||
col.prop(brush, "cursor_color_sub", text="Inverse Cursor Color")
|
||||
if brush.gpencil_sculpt_tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
|
||||
col.prop(brush, "cursor_color_subtract", text="Inverse Cursor Color")
|
||||
|
||||
elif ob.mode == 'WEIGHT_GPENCIL':
|
||||
col = layout.column(align=True)
|
||||
col.active = settings.show_brush
|
||||
|
||||
col.prop(brush, "cursor_color_add", text="Cursor Color")
|
||||
|
||||
elif ob.mode == 'VERTEX_GPENCIL':
|
||||
row = layout.row(align=True)
|
||||
row.prop(settings, "show_brush", text="")
|
||||
row.label(text="Display Cursor")
|
||||
|
||||
|
||||
class GPENCIL_MT_pie_tool_palette(Menu):
|
||||
"""A pie menu for quick access to Grease Pencil tools"""
|
||||
bl_label = "Grease Pencil Tools"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
pie = layout.menu_pie()
|
||||
gpd = context.gpencil_data
|
||||
|
||||
# W - Drawing Types
|
||||
col = pie.column()
|
||||
col.operator("gpencil.draw", text="Draw", icon='GREASEPENCIL').mode = 'DRAW'
|
||||
col.operator("gpencil.draw", text="Straight Lines", icon='LINE_DATA').mode = 'DRAW_STRAIGHT'
|
||||
col.operator("gpencil.draw", text="Poly", icon='MESH_DATA').mode = 'DRAW_POLY'
|
||||
|
||||
# E - Eraser
|
||||
# XXX: needs a dedicated icon...
|
||||
col = pie.column()
|
||||
col.operator("gpencil.draw", text="Eraser", icon='FORCE_CURVE').mode = 'ERASER'
|
||||
|
||||
# E - "Settings" Palette is included here too, since it needs to be in a stable position...
|
||||
if gpd and gpd.layers.active:
|
||||
col.separator()
|
||||
col.operator(
|
||||
"wm.call_menu_pie",
|
||||
text="Settings...",
|
||||
icon='SCRIPTWIN').name = "GPENCIL_MT_pie_settings_palette"
|
||||
|
||||
# Editing tools
|
||||
if gpd:
|
||||
if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes:
|
||||
# S - Exit Edit Mode
|
||||
pie.operator("gpencil.editmode_toggle", text="Exit Edit Mode", icon='EDIT')
|
||||
|
||||
# N - Transforms
|
||||
col = pie.column()
|
||||
row = col.row(align=True)
|
||||
row.operator("transform.translate", icon='MAN_TRANS')
|
||||
row.operator("transform.rotate", icon='MAN_ROT')
|
||||
row.operator("transform.resize", text="Scale", icon='MAN_SCALE')
|
||||
row = col.row(align=True)
|
||||
row.label(text="Proportional Edit:")
|
||||
row.prop(context.tool_settings, "use_proportional_edit", text="", icon_only=True)
|
||||
row.prop(context.tool_settings, "proportional_edit_falloff", text="", icon_only=True)
|
||||
|
||||
# NW - Select (Non-Modal)
|
||||
col = pie.column()
|
||||
col.operator("gpencil.select_all", text="Select All", icon='PARTICLE_POINT')
|
||||
col.operator("gpencil.select_all", text="Select Inverse", icon='BLANK1')
|
||||
col.operator("gpencil.select_linked", text="Select Linked", icon='LINKED')
|
||||
col.operator("gpencil.palettecolor_select", text="Select Color", icon='COLOR')
|
||||
|
||||
# NE - Select (Modal)
|
||||
col = pie.column()
|
||||
col.operator("gpencil.select_box", text="Box Select", icon='BORDER_RECT')
|
||||
col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY')
|
||||
col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO')
|
||||
col.operator("gpencil.select_alternate", text="Alternate Select", icon='BORDER_LASSO')
|
||||
|
||||
# SW - Edit Tools
|
||||
col = pie.column()
|
||||
col.operator("gpencil.duplicate_move", icon='PARTICLE_PATH', text="Duplicate")
|
||||
col.operator("gpencil.delete", icon='X', text="Delete...")
|
||||
|
||||
# SE - More Tools
|
||||
pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_MT_pie_tools_more"
|
||||
else:
|
||||
# Toggle Edit Mode
|
||||
pie.operator("gpencil.editmode_toggle", text="Enable Stroke Editing", icon='EDIT')
|
||||
|
||||
|
||||
class GPENCIL_MT_pie_settings_palette(Menu):
|
||||
"""A pie menu for quick access to Grease Pencil settings"""
|
||||
bl_label = "Grease Pencil Settings"
|
||||
class GreasePencilBrushFalloff:
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bool(context.gpencil_data and context.active_gpencil_layer)
|
||||
ts = context.tool_settings
|
||||
settings = None
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
settings = ts.gpencil_paint
|
||||
if context.mode == 'SCULPT_GPENCIL':
|
||||
settings = ts.gpencil_sculpt_paint
|
||||
elif context.mode == 'WEIGHT_GPENCIL':
|
||||
settings = ts.gpencil_weight_paint
|
||||
elif context.mode == 'VERTEX_GPENCIL':
|
||||
settings = ts.gpencil_vertex_paint
|
||||
|
||||
return (settings and settings.brush and settings.brush.curve)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ts = context.tool_settings
|
||||
settings = None
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
settings = ts.gpencil_paint
|
||||
if context.mode == 'SCULPT_GPENCIL':
|
||||
settings = ts.gpencil_sculpt_paint
|
||||
elif context.mode == 'WEIGHT_GPENCIL':
|
||||
settings = ts.gpencil_weight_paint
|
||||
elif context.mode == 'VERTEX_GPENCIL':
|
||||
settings = ts.gpencil_vertex_paint
|
||||
|
||||
pie = layout.menu_pie()
|
||||
gpd = context.gpencil_data
|
||||
gpl = context.active_gpencil_layer
|
||||
palcolor = None # context.active_gpencil_palettecolor
|
||||
if settings:
|
||||
brush = settings.brush
|
||||
|
||||
is_editmode = bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
|
||||
|
||||
# W - Stroke draw settings
|
||||
col = pie.column(align=True)
|
||||
if palcolor is not None:
|
||||
col.enabled = not palcolor.lock
|
||||
col.label(text="Stroke")
|
||||
col.prop(palcolor, "color", text="")
|
||||
col.prop(palcolor, "alpha", text="", slider=True)
|
||||
|
||||
# E - Fill draw settings
|
||||
col = pie.column(align=True)
|
||||
if palcolor is not None:
|
||||
col.enabled = not palcolor.lock
|
||||
col.label(text="Fill")
|
||||
col.prop(palcolor, "fill_color", text="")
|
||||
col.prop(palcolor, "fill_alpha", text="", slider=True)
|
||||
|
||||
# S Brush settings
|
||||
gpencil_active_brush_settings_simple(context, pie)
|
||||
|
||||
# N - Active Layer
|
||||
col = pie.column()
|
||||
col.label(text="Active Layer: ")
|
||||
|
||||
row = col.row()
|
||||
row.operator_context = 'EXEC_REGION_WIN'
|
||||
row.operator_menu_enum("gpencil.layer_change", "layer", text="", icon='GREASEPENCIL')
|
||||
row.prop(gpl, "info", text="")
|
||||
row.operator("gpencil.layer_remove", text="", icon='X')
|
||||
|
||||
row = col.row()
|
||||
row.prop(gpl, "lock")
|
||||
row.prop(gpl, "hide")
|
||||
col.prop(gpl, "use_onion_skinning")
|
||||
|
||||
# NW/NE/SW/SE - These operators are only available in editmode
|
||||
# as they require strokes to be selected to work
|
||||
if is_editmode:
|
||||
# NW - Move stroke Down
|
||||
col = pie.column(align=True)
|
||||
col.label(text="Arrange Strokes")
|
||||
col.operator("gpencil.stroke_arrange", text="Send to Back").direction = 'BOTTOM'
|
||||
col.operator("gpencil.stroke_arrange", text="Send Backward").direction = 'DOWN'
|
||||
|
||||
# NE - Move stroke Up
|
||||
col = pie.column(align=True)
|
||||
col.label(text="Arrange Strokes")
|
||||
col.operator("gpencil.stroke_arrange", text="Bring to Front").direction = 'TOP'
|
||||
col.operator("gpencil.stroke_arrange", text="Bring Forward").direction = 'UP'
|
||||
|
||||
# SW - Move stroke to color
|
||||
col = pie.column(align=True)
|
||||
col.operator("gpencil.stroke_change_color", text="Move to Color")
|
||||
|
||||
# SE - Join strokes
|
||||
col = pie.column(align=True)
|
||||
col.label(text="Join Strokes")
|
||||
row = col.row()
|
||||
row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
|
||||
row.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
|
||||
col.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
||||
col.prop(gpd, "show_stroke_direction", text="Show Drawing Direction")
|
||||
|
||||
|
||||
class GPENCIL_MT_pie_tools_more(Menu):
|
||||
"""A pie menu for accessing more Grease Pencil tools"""
|
||||
bl_label = "More Grease Pencil Tools"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
gpd = context.gpencil_data
|
||||
return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
pie = layout.menu_pie()
|
||||
# gpd = context.gpencil_data
|
||||
|
||||
col = pie.column(align=True)
|
||||
col.operator("gpencil.copy", text="Copy", icon='COPYDOWN')
|
||||
col.operator("gpencil.paste", text="Paste", icon='PASTEDOWN').type = 'ACTIVE'
|
||||
col.operator("gpencil.paste", text="Paste by Layer").type = 'LAYER'
|
||||
|
||||
col = pie.column(align=True)
|
||||
col.operator("gpencil.select_more", icon='ADD')
|
||||
col.operator("gpencil.select_less", icon='REMOVE')
|
||||
|
||||
pie.operator("transform.mirror", icon='MOD_MIRROR')
|
||||
pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM')
|
||||
pie.operator("transform.shear", icon='MOD_TRIANGULATE')
|
||||
pie.operator("transform.tosphere", icon='MOD_MULTIRES')
|
||||
|
||||
pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...")
|
||||
pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_MT_pie_tool_palette"
|
||||
|
||||
|
||||
class GPENCIL_MT_pie_sculpt(Menu):
|
||||
"""A pie menu for accessing Grease Pencil stroke sculpt settings"""
|
||||
bl_label = "Grease Pencil Sculpt"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
gpd = context.gpencil_data
|
||||
return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
pie = layout.menu_pie()
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
|
||||
# W - Launch Sculpt Mode
|
||||
col = pie.column()
|
||||
# col.label(text="Tool:")
|
||||
col.prop(settings, "sculpt_tool", text="")
|
||||
col.operator("gpencil.sculpt_paint", text="Sculpt", icon='SCULPTMODE_HLT')
|
||||
|
||||
# E - Common Settings
|
||||
col = pie.column(align=True)
|
||||
col.prop(brush, "size", slider=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
# row.prop(brush, "use_pressure_strength", text="", icon_only=True)
|
||||
col.prop(brush, "use_falloff")
|
||||
if settings.sculpt_tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(settings, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True)
|
||||
row.prop(settings, "use_edit_strength", text="Strength", icon='COLOR', toggle=True)
|
||||
row.prop(settings, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
|
||||
row.prop(brush, "curve_preset", text="")
|
||||
|
||||
# S - Change Brush Type Shortcuts
|
||||
row = pie.row()
|
||||
row.prop_enum(settings, "tool", value='GRAB')
|
||||
row.prop_enum(settings, "tool", value='PUSH')
|
||||
row.prop_enum(settings, "tool", value='CLONE')
|
||||
if brush.curve_preset == 'CUSTOM':
|
||||
layout.template_curve_mapping(brush, "curve", brush=True)
|
||||
|
||||
# N - Change Brush Type Shortcuts
|
||||
row = pie.row()
|
||||
row.prop_enum(settings, "tool", value='SMOOTH')
|
||||
row.prop_enum(settings, "tool", value='THICKNESS')
|
||||
row.prop_enum(settings, "tool", value='STRENGTH')
|
||||
row.prop_enum(settings, "tool", value='RANDOMIZE')
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
|
||||
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
|
||||
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
|
||||
row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
|
||||
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
|
||||
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
|
||||
|
||||
|
||||
class GPENCIL_MT_snap(Menu):
|
||||
@@ -515,6 +335,32 @@ class GPENCIL_MT_move_to_layer(Menu):
|
||||
layout.operator("gpencil.layer_add", text="New Layer", icon='ADD')
|
||||
|
||||
|
||||
class GPENCIL_MT_layer_active(Menu):
|
||||
bl_label = "Change Active Layer"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
gpd = context.gpencil_data
|
||||
if gpd:
|
||||
gpl_active = context.active_gpencil_layer
|
||||
tot_layers = len(gpd.layers)
|
||||
i = tot_layers - 1
|
||||
while i >= 0:
|
||||
gpl = gpd.layers[i]
|
||||
if gpl.info == gpl_active.info:
|
||||
icon = 'GREASEPENCIL'
|
||||
else:
|
||||
icon = 'NONE'
|
||||
layout.operator("gpencil.layer_active", text=gpl.info, icon=icon).layer = i
|
||||
i -= 1
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.layer_add", text="New Layer", icon='ADD')
|
||||
|
||||
|
||||
class GPENCIL_MT_gpencil_draw_delete(Menu):
|
||||
bl_label = "Delete"
|
||||
|
||||
@@ -800,11 +646,7 @@ class GreasePencilMaterialsPanel:
|
||||
|
||||
if ma is not None and ma.grease_pencil is not None:
|
||||
gpcolor = ma.grease_pencil
|
||||
if (
|
||||
gpcolor.stroke_style == 'SOLID' or
|
||||
gpcolor.use_stroke_pattern or
|
||||
gpcolor.use_stroke_texture_mix
|
||||
):
|
||||
if gpcolor.stroke_style == 'SOLID':
|
||||
row = layout.row()
|
||||
row.prop(gpcolor, "color", text="Stroke Color")
|
||||
|
||||
@@ -813,6 +655,48 @@ class GreasePencilMaterialsPanel:
|
||||
row.template_ID(space, "pin_id")
|
||||
|
||||
|
||||
class GreasePencilVertexcolorPanel:
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ts = context.scene.tool_settings
|
||||
is_vertex = context.mode == 'VERTEX_GPENCIL'
|
||||
gpencil_paint = ts.gpencil_vertex_paint if is_vertex else ts.gpencil_paint
|
||||
brush = gpencil_paint.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool = brush.gpencil_vertex_tool if is_vertex else brush.gpencil_tool
|
||||
|
||||
ob = context.object
|
||||
|
||||
if ob:
|
||||
col = layout.column()
|
||||
col.template_color_picker(brush, "color", value_slider=True)
|
||||
|
||||
sub_row = layout.row(align=True)
|
||||
sub_row.prop(brush, "color", text="")
|
||||
sub_row.prop(brush, "secondary_color", text="")
|
||||
|
||||
sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.template_ID(gpencil_paint, "palette", new="palette.new")
|
||||
if gpencil_paint.palette:
|
||||
layout.template_palette(gpencil_paint, "palette", color=True)
|
||||
|
||||
if tool in {'DRAW', 'FILL'} and is_vertex is False:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor")
|
||||
|
||||
if tool == 'TINT' or is_vertex is True:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
|
||||
|
||||
class GPENCIL_UL_layer(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
# assert(isinstance(item, bpy.types.GPencilLayer)
|
||||
@@ -830,9 +714,10 @@ class GPENCIL_UL_layer(UIList):
|
||||
row.prop(gpl, "info", text="", emboss=False)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "mask_layer", text="",
|
||||
icon='MOD_MASK' if gpl.mask_layer else 'LAYER_ACTIVE',
|
||||
emboss=False)
|
||||
|
||||
icon_mask = 'MOD_MASK' if gpl.use_mask_layer else 'LAYER_ACTIVE'
|
||||
|
||||
row.prop(gpl, "use_mask_layer", text="", icon=icon_mask, emboss=False)
|
||||
|
||||
subrow = row.row(align=True)
|
||||
subrow.prop(
|
||||
@@ -868,16 +753,12 @@ class GreasePencilSimplifyPanel:
|
||||
layout.active = rd.simplify_gpencil
|
||||
|
||||
col = layout.column()
|
||||
col.prop(rd, "simplify_gpencil_onplay", text="Playback Only")
|
||||
col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
|
||||
col.prop(rd, "simplify_gpencil_shader_fx", text="ShaderFX")
|
||||
col.prop(rd, "simplify_gpencil_blend", text="Layers Blending")
|
||||
col.prop(rd, "simplify_gpencil_tint", text="Layers Tinting")
|
||||
|
||||
col.prop(rd, "simplify_gpencil_onplay")
|
||||
col.prop(rd, "simplify_gpencil_view_fill")
|
||||
sub = col.column()
|
||||
sub.active = rd.simplify_gpencil_view_fill
|
||||
sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
|
||||
col.prop(rd, "simplify_gpencil_modifier")
|
||||
col.prop(rd, "simplify_gpencil_shader_fx")
|
||||
col.prop(rd, "simplify_gpencil_tint")
|
||||
col.prop(rd, "simplify_gpencil_antialiasing")
|
||||
|
||||
|
||||
class GreasePencilLayerAdjustmentsPanel:
|
||||
@@ -913,6 +794,65 @@ class GreasePencilLayerAdjustmentsPanel:
|
||||
col.prop(gpl, "lock_material")
|
||||
|
||||
|
||||
class GPENCIL_UL_masks(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
mask = item
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
row = layout.row(align=True)
|
||||
row.prop(mask, "name", text="", emboss=False, icon_value=icon)
|
||||
row.prop(mask, "invert", text="", emboss=False)
|
||||
row.prop(mask, "hide", text="", emboss=False)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.prop(mask, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
|
||||
class GPENCIL_MT_layer_mask_menu(Menu):
|
||||
bl_label = "Layer Specials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob = context.object
|
||||
gpd = ob.data
|
||||
gpl_active = gpd.layers.active
|
||||
done = False
|
||||
for gpl in gpd.layers:
|
||||
if gpl != gpl_active and gpl.info not in gpl_active.mask_layers:
|
||||
done = True
|
||||
layout.operator("gpencil.layer_mask_add", text=gpl.info).name=gpl.info
|
||||
|
||||
if done is False:
|
||||
layout.label(text="No layers to add")
|
||||
|
||||
|
||||
class GreasePencilLayerMasksPanel:
|
||||
def draw_header(self, context):
|
||||
ob = context.active_object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
|
||||
self.layout.prop(gpl, "use_mask_layer", text="")
|
||||
|
||||
def draw(self, context):
|
||||
ob = context.active_object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
|
||||
layout = self.layout
|
||||
layout.enabled = gpl.use_mask_layer
|
||||
|
||||
if gpl:
|
||||
rows = 4
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.template_list("GPENCIL_UL_masks", "", gpl, "mask_layers", gpl.mask_layers,
|
||||
"active_mask_index", rows=rows, sort_lock=True)
|
||||
|
||||
col2 = row.column(align=True)
|
||||
col2.menu("GPENCIL_MT_layer_mask_menu", icon='ADD', text="")
|
||||
col2.operator("gpencil.layer_mask_remove", icon='REMOVE', text="")
|
||||
|
||||
|
||||
class GreasePencilLayerRelationsPanel:
|
||||
|
||||
def draw(self, context):
|
||||
@@ -952,20 +892,58 @@ class GreasePencilLayerDisplayPanel:
|
||||
col.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
|
||||
|
||||
|
||||
classes = (
|
||||
GPENCIL_MT_pie_tool_palette,
|
||||
GPENCIL_MT_pie_settings_palette,
|
||||
GPENCIL_MT_pie_tools_more,
|
||||
GPENCIL_MT_pie_sculpt,
|
||||
class GreasePencilFlipTintColors(Operator):
|
||||
bl_label = "Flip Colors"
|
||||
bl_idname = "gpencil.tint_flip"
|
||||
bl_description = "Switch Tint colors"
|
||||
|
||||
def execute(self, context):
|
||||
try:
|
||||
ts = context.tool_settings
|
||||
settings = None
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
settings = ts.gpencil_paint
|
||||
if context.mode == 'SCULPT_GPENCIL':
|
||||
settings = ts.gpencil_sculpt_paint
|
||||
elif context.mode == 'WEIGHT_GPENCIL':
|
||||
settings = ts.gpencil_weight_paint
|
||||
elif context.mode == 'VERTEX_GPENCIL':
|
||||
settings = ts.gpencil_vertex_paint
|
||||
|
||||
brush = settings.brush
|
||||
if brush is not None:
|
||||
color = brush.color
|
||||
secondary_color = brush.secondary_color
|
||||
|
||||
orig_prim = color.hsv
|
||||
orig_sec = secondary_color.hsv
|
||||
|
||||
color.hsv = orig_sec
|
||||
secondary_color.hsv = orig_prim
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
except Exception as e:
|
||||
utils_core.error_handlers(self, "gpencil.tint_flip", e,
|
||||
"Flip Colors could not be completed")
|
||||
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
classes = (
|
||||
GPENCIL_MT_snap,
|
||||
GPENCIL_MT_cleanup,
|
||||
GPENCIL_MT_move_to_layer,
|
||||
GPENCIL_MT_layer_active,
|
||||
|
||||
GPENCIL_MT_gpencil_draw_delete,
|
||||
GPENCIL_MT_layer_mask_menu,
|
||||
|
||||
GPENCIL_UL_annotation_layer,
|
||||
GPENCIL_UL_layer,
|
||||
GPENCIL_UL_masks,
|
||||
|
||||
GreasePencilFlipTintColors,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
||||
@@ -47,6 +47,11 @@ class GPENCIL_MT_color_context_menu(Menu):
|
||||
layout.separator()
|
||||
|
||||
layout.operator("object.material_slot_remove_unused")
|
||||
layout.operator("gpencil.stroke_merge_material", text="Merge Similar")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("gpencil.material_to_vertex_color", text="Convert Materials to Vertex Color")
|
||||
layout.operator("gpencil.extract_palette_vertex", text="Extract Palette from Vertex Color")
|
||||
|
||||
|
||||
class GPENCIL_UL_matslots(UIList):
|
||||
@@ -142,27 +147,25 @@ class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel):
|
||||
|
||||
col.prop(gpcolor, "stroke_style", text="Style")
|
||||
|
||||
row = col.row()
|
||||
row.prop(gpcolor, "color", text="Base Color")
|
||||
|
||||
if gpcolor.stroke_style == 'TEXTURE':
|
||||
row = col.row()
|
||||
row.enabled = not gpcolor.lock
|
||||
col = row.column(align=True)
|
||||
col.template_ID(gpcolor, "stroke_image", open="image.open")
|
||||
|
||||
if gpcolor.stroke_style == 'TEXTURE':
|
||||
row = col.row()
|
||||
row.prop(gpcolor, "mix_stroke_factor", text="Blend", slider=True)
|
||||
if gpcolor.mode == 'LINE':
|
||||
col.prop(gpcolor, "pixel_size", text="UV Factor")
|
||||
|
||||
col.prop(gpcolor, "use_stroke_pattern", text="Use As Stencil Mask")
|
||||
if gpcolor.use_stroke_pattern is False:
|
||||
col.prop(gpcolor, "use_stroke_texture_mix", text="Mix Color")
|
||||
if gpcolor.use_stroke_texture_mix is True:
|
||||
col.prop(gpcolor, "mix_stroke_factor", text="Factor")
|
||||
|
||||
if (gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern or gpcolor.use_stroke_texture_mix):
|
||||
col.prop(gpcolor, "color", text="Color")
|
||||
|
||||
if gpcolor.mode in {'DOTS', 'BOX'}:
|
||||
col.prop(gpcolor, "alignment_mode")
|
||||
|
||||
if gpcolor.mode == 'LINE' and gpcolor.stroke_style != 'TEXTURE':
|
||||
if gpcolor.mode == 'LINE':
|
||||
col.prop(gpcolor, "use_overlap_strokes")
|
||||
|
||||
|
||||
@@ -188,55 +191,35 @@ class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel):
|
||||
col.enabled = not gpcolor.lock
|
||||
col.prop(gpcolor, "fill_style", text="Style")
|
||||
|
||||
if gpcolor.fill_style == 'GRADIENT':
|
||||
|
||||
if gpcolor.fill_style == 'SOLID':
|
||||
col.prop(gpcolor, "fill_color", text="Base Color")
|
||||
|
||||
elif gpcolor.fill_style == 'GRADIENT':
|
||||
col.prop(gpcolor, "gradient_type")
|
||||
|
||||
if gpcolor.fill_style != 'TEXTURE':
|
||||
col.prop(gpcolor, "fill_color", text="Color")
|
||||
col.prop(gpcolor, "fill_color", text="Base Color")
|
||||
col.prop(gpcolor, "mix_color", text="Secondary Color")
|
||||
col.prop(gpcolor, "mix_factor", text="Blend in Fill Gradient", slider=True)
|
||||
col.prop(gpcolor, "flip", text="Flip Colors")
|
||||
|
||||
if gpcolor.fill_style in {'GRADIENT', 'CHECKER'}:
|
||||
col.prop(gpcolor, "mix_color", text="Secondary Color")
|
||||
col.prop(gpcolor, "texture_offset", text="Location")
|
||||
col.prop(gpcolor, "texture_scale", text="Scale")
|
||||
if gpcolor.gradient_type == 'LINEAR':
|
||||
col.prop(gpcolor, "texture_angle", text="Rotation")
|
||||
|
||||
if gpcolor.fill_style == 'GRADIENT':
|
||||
col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
|
||||
|
||||
if gpcolor.fill_style in {'GRADIENT', 'CHECKER'}:
|
||||
col.prop(gpcolor, "flip", text="Flip Colors")
|
||||
|
||||
col.prop(gpcolor, "pattern_shift", text="Location")
|
||||
col.prop(gpcolor, "pattern_scale", text="Scale")
|
||||
|
||||
if gpcolor.gradient_type == 'RADIAL' and gpcolor.fill_style not in {'SOLID', 'CHECKER'}:
|
||||
col.prop(gpcolor, "pattern_radius", text="Radius")
|
||||
else:
|
||||
if gpcolor.fill_style != 'SOLID':
|
||||
col.prop(gpcolor, "pattern_angle", text="Angle")
|
||||
|
||||
if gpcolor.fill_style == 'CHECKER':
|
||||
col.prop(gpcolor, "pattern_gridsize", text="Box Size")
|
||||
|
||||
# Texture
|
||||
if gpcolor.fill_style == 'TEXTURE' or (gpcolor.use_fill_texture_mix is True and gpcolor.fill_style == 'SOLID'):
|
||||
elif gpcolor.fill_style == 'TEXTURE':
|
||||
col.template_ID(gpcolor, "fill_image", open="image.open")
|
||||
|
||||
if gpcolor.fill_style == 'TEXTURE':
|
||||
col.prop(gpcolor, "use_fill_pattern", text="Use as Stencil Mask")
|
||||
if gpcolor.use_fill_pattern is True:
|
||||
col.prop(gpcolor, "fill_color", text="Color")
|
||||
col.prop(gpcolor, "fill_color", text="Base Color")
|
||||
col.prop(gpcolor, "texture_opacity", slider=True)
|
||||
col.prop(gpcolor, "mix_factor", text="Blend in Fill Texture", slider=True)
|
||||
|
||||
col.prop(gpcolor, "texture_offset", text="Offset")
|
||||
col.prop(gpcolor, "texture_offset", text="Location")
|
||||
col.prop(gpcolor, "texture_angle", text="Rotation")
|
||||
col.prop(gpcolor, "texture_scale", text="Scale")
|
||||
col.prop(gpcolor, "texture_angle")
|
||||
col.prop(gpcolor, "texture_opacity")
|
||||
col.prop(gpcolor, "texture_clamp", text="Clip Image")
|
||||
|
||||
if gpcolor.use_fill_pattern is False:
|
||||
col.prop(gpcolor, "use_fill_texture_mix", text="Mix with Color")
|
||||
|
||||
if gpcolor.use_fill_texture_mix is True:
|
||||
col.prop(gpcolor, "fill_color", text="Mix Color")
|
||||
col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
|
||||
|
||||
|
||||
class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel):
|
||||
bl_label = "Preview"
|
||||
@@ -291,5 +274,6 @@ classes = (
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
|
||||
for cls in classes:
|
||||
register_class(cls)
|
||||
|
||||
@@ -397,6 +397,27 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
|
||||
col.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
|
||||
|
||||
|
||||
class OBJECT_PT_greasepencil_light(ObjectButtonsPanel, Panel):
|
||||
bl_label = "Grease Pencil"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.object) and (context.engine in cls.COMPAT_ENGINES) and (context.object.type == 'GPENCIL')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
layout = self.layout
|
||||
ob = context.object
|
||||
|
||||
col = flow.column()
|
||||
col.prop(ob, "use_grease_pencil_lights", toggle=False)
|
||||
|
||||
|
||||
class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
_context_path = "object"
|
||||
@@ -417,6 +438,7 @@ classes = (
|
||||
OBJECT_PT_display,
|
||||
OBJECT_PT_display_bounds,
|
||||
OBJECT_PT_visibility,
|
||||
OBJECT_PT_greasepencil_light,
|
||||
OBJECT_PT_custom_props,
|
||||
)
|
||||
|
||||
|
||||
@@ -89,8 +89,12 @@ class UnifiedPaintPanel:
|
||||
# Grease Pencil settings
|
||||
elif mode == 'PAINT_GPENCIL':
|
||||
return tool_settings.gpencil_paint
|
||||
elif mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
return tool_settings.gpencil_sculpt
|
||||
elif mode == 'SCULPT_GPENCIL':
|
||||
return tool_settings.gpencil_sculpt_paint
|
||||
elif mode == 'WEIGHT_GPENCIL':
|
||||
return tool_settings.gpencil_weight_paint
|
||||
elif mode == 'VERTEX_GPENCIL':
|
||||
return tool_settings.gpencil_vertex_paint
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
@@ -1019,6 +1023,8 @@ def brush_basic_texpaint_settings(layout, context, brush, *, compact=False):
|
||||
|
||||
|
||||
def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False):
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
|
||||
if gp_settings is None:
|
||||
@@ -1043,7 +1049,7 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
|
||||
row.prop(gp_settings, "eraser_thickness_factor")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "use_cursor", text="Display Cursor")
|
||||
row.prop(settings, "show_brush", text="Display Cursor")
|
||||
|
||||
# FIXME: tools must use their own UI drawing!
|
||||
elif brush.gpencil_tool == 'FILL':
|
||||
@@ -1091,51 +1097,62 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
|
||||
|
||||
|
||||
def brush_basic_gpencil_sculpt_settings(layout, context, brush, *, compact=False):
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_sculpt
|
||||
tool = settings.sculpt_tool
|
||||
gp_settings = brush.gpencil_settings
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "size", slider=True)
|
||||
sub = row.row(align=True)
|
||||
sub.enabled = tool not in {'GRAB', 'CLONE'}
|
||||
sub.prop(brush, "use_pressure_radius", text="")
|
||||
sub.prop(gp_settings, "use_pressure", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
|
||||
layout.prop(brush, "use_falloff")
|
||||
|
||||
if compact:
|
||||
if tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}:
|
||||
row.separator()
|
||||
row.prop(brush, "direction", expand=True, text="")
|
||||
row.prop(gp_settings, "direction", expand=True, text="")
|
||||
else:
|
||||
use_property_split_prev = layout.use_property_split
|
||||
layout.use_property_split = False
|
||||
if tool in {'THICKNESS', 'STRENGTH'}:
|
||||
layout.row().prop(brush, "direction", expand=True)
|
||||
layout.row().prop(gp_settings, "direction", expand=True)
|
||||
elif tool == 'PINCH':
|
||||
row = layout.row(align=True)
|
||||
row.prop_enum(brush, "direction", value='ADD', text="Pinch")
|
||||
row.prop_enum(brush, "direction", value='SUBTRACT', text="Inflate")
|
||||
row.prop_enum(gp_settings, "direction", value='ADD', text="Pinch")
|
||||
row.prop_enum(gp_settings, "direction", value='SUBTRACT', text="Inflate")
|
||||
elif tool == 'TWIST':
|
||||
row = layout.row(align=True)
|
||||
row.prop_enum(brush, "direction", value='ADD', text="CCW")
|
||||
row.prop_enum(brush, "direction", value='SUBTRACT', text="CW")
|
||||
row.prop_enum(gp_settings, "direction", value='ADD', text="CCW")
|
||||
row.prop_enum(gp_settings, "direction", value='SUBTRACT', text="CW")
|
||||
layout.use_property_split = use_property_split_prev
|
||||
|
||||
|
||||
def brush_basic_gpencil_weight_settings(layout, _context, brush, *, compact=False):
|
||||
gp_settings = brush.gpencil_settings
|
||||
layout.prop(brush, "size", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "strength", slider=True)
|
||||
row.prop(brush, "use_pressure_strength", text="")
|
||||
layout.prop(brush, "weight", slider=True)
|
||||
layout.prop(brush, "use_falloff")
|
||||
|
||||
layout.prop(brush, "weight", slider=True)
|
||||
|
||||
|
||||
def brush_basic_gpencil_vertex_settings(layout, _context, brush, *, compact=False):
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
# Brush details
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "size", text="Radius")
|
||||
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
if brush.gpencil_vertex_tool in {'DRAW', 'BLUR', 'SMEAR'}:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "pen_strength", slider=True)
|
||||
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
classes = (
|
||||
VIEW3D_MT_tools_projectpaint_clone,
|
||||
|
||||
@@ -26,6 +26,7 @@ from bpy.types import (
|
||||
)
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilLayerMasksPanel,
|
||||
GreasePencilLayerAdjustmentsPanel,
|
||||
GreasePencilLayerRelationsPanel,
|
||||
GreasePencilLayerDisplayPanel,
|
||||
@@ -699,6 +700,15 @@ class DOPESHEET_PT_gpencil_mode(LayersDopeSheetPanel, Panel):
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "use_lights")
|
||||
|
||||
|
||||
class DOPESHEET_PT_gpencil_layer_masks(LayersDopeSheetPanel, GreasePencilLayerMasksPanel, Panel):
|
||||
bl_label = "Masks"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
class DOPESHEET_PT_gpencil_layer_adjustments(LayersDopeSheetPanel, GreasePencilLayerAdjustmentsPanel, Panel):
|
||||
bl_label = "Adjustments"
|
||||
@@ -736,6 +746,7 @@ classes = (
|
||||
DOPESHEET_MT_snap_pie,
|
||||
DOPESHEET_PT_filters,
|
||||
DOPESHEET_PT_gpencil_mode,
|
||||
DOPESHEET_PT_gpencil_layer_masks,
|
||||
DOPESHEET_PT_gpencil_layer_adjustments,
|
||||
DOPESHEET_PT_gpencil_layer_relations,
|
||||
DOPESHEET_PT_gpencil_layer_display,
|
||||
|
||||
@@ -238,6 +238,11 @@ class IMAGE_MT_image(Menu):
|
||||
layout.separator()
|
||||
layout.operator("image.pack", text="Pack")
|
||||
|
||||
if ima:
|
||||
layout.separator()
|
||||
layout.operator("palette.extract_from_image", text="Extract Palette")
|
||||
layout.operator("gpencil.image_to_grease_pencil", text="Generate Grease Pencil")
|
||||
|
||||
|
||||
class IMAGE_MT_image_invert(Menu):
|
||||
bl_label = "Invert"
|
||||
|
||||
@@ -1455,6 +1455,11 @@ class _defs_gpencil_paint:
|
||||
|
||||
@ToolDef.from_fn
|
||||
def eyedropper():
|
||||
def draw_settings(context, layout, tool):
|
||||
props = tool.operator_properties("ui.eyedropper_gpencil_color")
|
||||
row = layout.row()
|
||||
row.use_property_split = False
|
||||
row.prop(props, "mode", expand=True)
|
||||
return dict(
|
||||
idname="builtin.eyedropper",
|
||||
label="Eyedropper",
|
||||
@@ -1462,6 +1467,7 @@ class _defs_gpencil_paint:
|
||||
cursor='EYEDROPPER',
|
||||
widget=None,
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
|
||||
@@ -1594,6 +1600,23 @@ class _defs_gpencil_edit:
|
||||
draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def transform_fill():
|
||||
def draw_settings(context, layout, tool):
|
||||
props = tool.operator_properties("gpencil.transform_fill")
|
||||
row = layout.row()
|
||||
row.use_property_split = False
|
||||
row.prop(props, "mode", expand=True)
|
||||
|
||||
return dict(
|
||||
idname="builtin.transform_fill",
|
||||
label="Transform Fill",
|
||||
icon="ops.gpencil.transform_fill",
|
||||
cursor='DEFAULT',
|
||||
widget=None,
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
class _defs_gpencil_sculpt:
|
||||
|
||||
@@ -1613,11 +1636,10 @@ class _defs_gpencil_sculpt:
|
||||
context,
|
||||
idname_prefix="builtin_brush.",
|
||||
icon_prefix="ops.gpencil.sculpt_",
|
||||
type=bpy.types.GPencilSculptSettings,
|
||||
attr="sculpt_tool",
|
||||
type=bpy.types.Brush,
|
||||
attr="gpencil_sculpt_tool",
|
||||
tooldef_keywords=dict(
|
||||
operator="gpencil.sculpt_paint",
|
||||
keymap="3D View Tool: Sculpt Gpencil, Paint",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1630,11 +1652,37 @@ class _defs_gpencil_weight:
|
||||
context,
|
||||
idname_prefix="builtin_brush.",
|
||||
icon_prefix="ops.gpencil.sculpt_",
|
||||
type=bpy.types.GPencilSculptSettings,
|
||||
attr="weight_tool",
|
||||
type=bpy.types.Brush,
|
||||
attr="gpencil_weight_tool",
|
||||
tooldef_keywords=dict(
|
||||
operator="gpencil.sculpt_paint",
|
||||
keymap="3D View Tool: Sculpt Gpencil, Paint",
|
||||
operator="gpencil.weight_paint",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class _defs_gpencil_vertex:
|
||||
|
||||
@staticmethod
|
||||
def poll_select_mask(context):
|
||||
if context is None:
|
||||
return True
|
||||
ob = context.active_object
|
||||
ts = context.scene.tool_settings
|
||||
return ob and ob.type == 'GPENCIL' and (ts.use_gpencil_vertex_select_mask_point or
|
||||
ts.use_gpencil_vertex_select_mask_stroke or
|
||||
ts.use_gpencil_vertex_select_mask_segment)
|
||||
|
||||
@staticmethod
|
||||
def generate_from_brushes(context):
|
||||
return generate_from_enum_ex(
|
||||
context,
|
||||
idname_prefix="builtin_brush.",
|
||||
icon_prefix="brush.paint_vertex.",
|
||||
type=bpy.types.Brush,
|
||||
attr="gpencil_vertex_tool",
|
||||
cursor='DOT',
|
||||
tooldef_keywords=dict(
|
||||
operator="gpencil.vertex_paint",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2202,6 +2250,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
_defs_gpencil_edit.tosphere,
|
||||
),
|
||||
None,
|
||||
_defs_gpencil_edit.transform_fill,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
'SCULPT_GPENCIL': [
|
||||
@@ -2219,6 +2269,17 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
'VERTEX_GPENCIL': [
|
||||
_defs_gpencil_vertex.generate_from_brushes,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
None,
|
||||
lambda context: (
|
||||
VIEW3D_PT_tools_active._tools_gpencil_select
|
||||
if _defs_gpencil_vertex.poll_select_mask(context)
|
||||
else ()
|
||||
),
|
||||
],
|
||||
}
|
||||
class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
bl_space_type = 'SEQUENCE_EDITOR'
|
||||
|
||||
@@ -165,11 +165,11 @@ class TOPBAR_PT_gpencil_layers(Panel):
|
||||
|
||||
srow = col.row(align=True)
|
||||
srow.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
srow.prop(gpl, "mask_layer", text="",
|
||||
icon='MOD_MASK' if gpl.mask_layer else 'LAYER_ACTIVE')
|
||||
srow.prop(gpl, "use_mask_layer", text="",
|
||||
icon='MOD_MASK' if gpl.use_mask_layer else 'LAYER_ACTIVE')
|
||||
|
||||
srow = col.row(align=True)
|
||||
srow.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
|
||||
srow.prop(gpl, "use_lights")
|
||||
|
||||
col = row.column()
|
||||
|
||||
|
||||
@@ -668,7 +668,6 @@ class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel):
|
||||
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
|
||||
flow.prop(system, "viewport_aa")
|
||||
flow.prop(system, "gpencil_multi_sample", text="Grease Pencil Multisampling")
|
||||
flow.prop(system, "use_overlay_smooth_wire")
|
||||
flow.prop(system, "use_edit_mode_smooth_wire")
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ from bl_ui.properties_grease_pencil_common import (
|
||||
AnnotationDataPanel,
|
||||
AnnotationOnionSkin,
|
||||
GreasePencilMaterialsPanel,
|
||||
GreasePencilVertexcolorPanel,
|
||||
)
|
||||
from bl_ui.space_toolsystem_common import (
|
||||
ToolActivePanelHelper,
|
||||
@@ -119,21 +120,27 @@ class VIEW3D_HT_tool_header(Header):
|
||||
if is_valid_context:
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
if brush.gpencil_tool != 'ERASE':
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_advanced")
|
||||
if brush.gpencil_tool != 'TINT':
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_advanced")
|
||||
|
||||
if brush.gpencil_tool != 'FILL':
|
||||
if brush.gpencil_tool not in {'FILL', 'TINT'}:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brush_stroke")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_brushcurves")
|
||||
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_paint_appearance")
|
||||
elif tool_mode == 'SCULPT_GPENCIL':
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool = settings.sculpt_tool
|
||||
if tool in {'SMOOTH', 'RANDOMIZE', 'SMOOTH'}:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_options")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
||||
if is_valid_context:
|
||||
brush = context.tool_settings.gpencil_sculpt_paint.brush
|
||||
tool = brush.gpencil_tool
|
||||
if tool in ('SMOOTH', 'RANDOMIZE'):
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_options")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
||||
elif tool_mode == 'WEIGHT_GPENCIL':
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
|
||||
if is_valid_context:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
|
||||
elif tool_mode == 'VERTEX_GPENCIL':
|
||||
if is_valid_context:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_vertex_appearance")
|
||||
|
||||
def draw_mode_settings(self, context):
|
||||
layout = self.layout
|
||||
@@ -425,6 +432,15 @@ class _draw_tool_settings_context_mode:
|
||||
|
||||
row.prop(gp_settings, "use_material_pin", text="")
|
||||
|
||||
if brush.gpencil_tool in {'DRAW', 'FILL'} and ma:
|
||||
row.separator(factor=1.0)
|
||||
subrow = row.row(align=True)
|
||||
row.prop_enum(settings, "color_mode", 'MATERIAL', text="", icon='MATERIAL')
|
||||
row.prop_enum(settings, "color_mode", 'VERTEXCOLOR', text="", icon='VPAINT_HLT')
|
||||
sub_row = row.row(align=True)
|
||||
sub_row.enabled = settings.color_mode == 'VERTEXCOLOR'
|
||||
sub_row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
|
||||
|
||||
row = layout.row(align=True)
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_paint
|
||||
@@ -433,6 +449,10 @@ class _draw_tool_settings_context_mode:
|
||||
if context.object and brush.gpencil_tool in {'FILL', 'DRAW'}:
|
||||
draw_color_selector()
|
||||
|
||||
if context.object and brush.gpencil_tool == 'TINT':
|
||||
row.separator(factor=0.4)
|
||||
row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_paint_settings,
|
||||
)
|
||||
@@ -444,9 +464,8 @@ class _draw_tool_settings_context_mode:
|
||||
def SCULPT_GPENCIL(context, layout, tool):
|
||||
if (tool is None) or (not tool.has_datablock):
|
||||
return False
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
paint = context.tool_settings.gpencil_sculpt_paint
|
||||
brush = paint.brush
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_sculpt_settings,
|
||||
@@ -459,9 +478,8 @@ class _draw_tool_settings_context_mode:
|
||||
def WEIGHT_GPENCIL(context, layout, tool):
|
||||
if (tool is None) or (not tool.has_datablock):
|
||||
return False
|
||||
tool_settings = context.tool_settings
|
||||
settings = tool_settings.gpencil_sculpt
|
||||
brush = settings.brush
|
||||
paint = context.tool_settings.gpencil_weight_paint
|
||||
brush = paint.brush
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_weight_settings,
|
||||
@@ -470,6 +488,31 @@ class _draw_tool_settings_context_mode:
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def VERTEX_GPENCIL(context, layout, tool):
|
||||
if (tool is None) or (not tool.has_datablock):
|
||||
return False
|
||||
|
||||
paint = context.tool_settings.gpencil_vertex_paint
|
||||
brush = paint.brush
|
||||
|
||||
row = layout.row(align=True)
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_vertex_paint
|
||||
row.template_ID_preview(settings, "brush", rows=3, cols=8, hide_buttons=True)
|
||||
|
||||
if brush.gpencil_vertex_tool not in {'BLUR', 'AVERAGE', 'SMEAR'}:
|
||||
row.separator(factor=0.4)
|
||||
row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_vertex_settings,
|
||||
)
|
||||
|
||||
brush_basic_gpencil_vertex_settings(layout, context, brush, compact=True)
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def PARTICLE(context, layout, tool):
|
||||
if (tool is None) or (not tool.has_datablock):
|
||||
@@ -550,7 +593,7 @@ class VIEW3D_HT_header(Header):
|
||||
else:
|
||||
if (object_mode not in {
|
||||
'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
|
||||
'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'
|
||||
'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'
|
||||
}) or has_pose_mode:
|
||||
show_snap = True
|
||||
else:
|
||||
@@ -687,7 +730,14 @@ class VIEW3D_HT_header(Header):
|
||||
row.prop(tool_settings, "use_gpencil_select_mask_stroke", text="")
|
||||
row.prop(tool_settings, "use_gpencil_select_mask_segment", text="")
|
||||
|
||||
if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode:
|
||||
# Select mode for Vertex Paint
|
||||
if gpd.is_stroke_vertex_mode:
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_gpencil_vertex_select_mask_point", text="")
|
||||
row.prop(tool_settings, "use_gpencil_vertex_select_mask_stroke", text="")
|
||||
row.prop(tool_settings, "use_gpencil_vertex_select_mask_segment", text="")
|
||||
|
||||
if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode or gpd.is_stroke_vertex_mode:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING')
|
||||
|
||||
@@ -812,7 +862,8 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
obj = context.active_object
|
||||
mode_string = context.mode
|
||||
edit_object = context.edit_object
|
||||
gp_edit = obj and obj.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}
|
||||
gp_edit = obj and obj.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL',
|
||||
'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}
|
||||
ts = context.scene.tool_settings
|
||||
|
||||
layout.menu("VIEW3D_MT_view")
|
||||
@@ -827,6 +878,8 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
layout.menu("VIEW3D_MT_select_gpencil")
|
||||
elif mode_string == 'EDIT_GPENCIL':
|
||||
layout.menu("VIEW3D_MT_select_gpencil")
|
||||
elif mode_string == 'VERTEX_GPENCIL':
|
||||
layout.menu("VIEW3D_MT_select_gpencil")
|
||||
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
||||
mesh = obj.data
|
||||
if mesh.use_paint_mask:
|
||||
@@ -4650,6 +4703,10 @@ class VIEW3D_MT_paint_gpencil(Menu):
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("GPENCIL_MT_layer_active", text="Active Layer")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_gpencil_animation")
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
|
||||
|
||||
@@ -4708,6 +4765,10 @@ class VIEW3D_MT_edit_gpencil(Menu):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("GPENCIL_MT_layer_active", text="Active Layer")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_gpencil_animation")
|
||||
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
|
||||
|
||||
@@ -4742,6 +4803,7 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
settings = _context.tool_settings.gpencil_sculpt
|
||||
|
||||
layout.operator("gpencil.stroke_subdivide", text="Subdivide").only_selected = False
|
||||
layout.menu("VIEW3D_MT_gpencil_simplify")
|
||||
@@ -4767,6 +4829,10 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
|
||||
layout.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
|
||||
layout.operator_menu_enum("gpencil.stroke_caps_set", text="Toggle Caps", property="type")
|
||||
layout.operator("gpencil.stroke_flip", text="Switch Direction")
|
||||
layout.prop(settings, "use_scale_thickness")
|
||||
|
||||
layout.separator()
|
||||
layout.operator("gpencil.reset_transform_fill", text="Reset Fill Transform")
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_gpencil_point(Menu):
|
||||
@@ -4811,6 +4877,22 @@ class VIEW3D_MT_weight_gpencil(Menu):
|
||||
layout.menu("VIEW3D_MT_gpencil_autoweights")
|
||||
|
||||
|
||||
class VIEW3D_MT_vertex_gpencil(Menu):
|
||||
bl_label = "Paint"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
layout.operator("gpencil.vertex_color_set", text="Set Vertex Colors")
|
||||
layout.separator()
|
||||
layout.operator("gpencil.vertex_color_invert", text="Invert")
|
||||
layout.operator("gpencil.vertex_color_levels", text="Levels")
|
||||
layout.operator("gpencil.vertex_color_hsv", text="Hue Saturation Value")
|
||||
layout.operator("gpencil.vertex_color_brightness_contrast", text="Bright/Contrast")
|
||||
|
||||
layout.separator()
|
||||
layout.menu("VIEW3D_MT_join_palette")
|
||||
|
||||
|
||||
class VIEW3D_MT_gpencil_animation(Menu):
|
||||
bl_label = "Animation"
|
||||
|
||||
@@ -6473,6 +6555,7 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
|
||||
'EDIT_GPENCIL': "Edit Grease Pencil",
|
||||
'SCULPT_GPENCIL': "Sculpt Grease Pencil",
|
||||
'WEIGHT_GPENCIL': "Weight Grease Pencil",
|
||||
'VERTEX_GPENCIL': "Vertex Grease Pencil",
|
||||
'OBJECT': "Grease Pencil",
|
||||
}[context.mode])
|
||||
|
||||
@@ -6497,17 +6580,32 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
|
||||
sub.prop(overlay, "gpencil_fade_layer", text="Fade Layers", slider=True)
|
||||
|
||||
row = col.row()
|
||||
row.prop(overlay, "use_gpencil_paper", text="")
|
||||
row.prop(overlay, "use_gpencil_fade_objects", text="")
|
||||
sub = row.row(align=True)
|
||||
sub.active = overlay.use_gpencil_paper
|
||||
sub.prop(overlay, "gpencil_paper_opacity", text="Fade Objects", slider=True)
|
||||
sub.prop(overlay, "use_gpencil_fade_objects", text="", icon='OUTLINER_OB_GREASEPENCIL')
|
||||
sub.active = overlay.use_gpencil_fade_objects
|
||||
sub.prop(overlay, "gpencil_fade_objects", text="Fade Objects", slider=True)
|
||||
sub.prop(overlay, "use_gpencil_fade_gp_objects", text="", icon='OUTLINER_OB_GREASEPENCIL')
|
||||
|
||||
if context.object.mode in {'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}:
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_multiedit_line_only", text="Only in Multiframe")
|
||||
|
||||
if context.object.mode == 'EDIT_GPENCIL':
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_show_directions")
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_show_material_name", text="Material Name")
|
||||
|
||||
if context.object.mode in {'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
|
||||
layout.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
|
||||
layout.prop(overlay, "use_gpencil_multiedit_line_only", text="Show Edit Lines only in multiframe")
|
||||
layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
|
||||
|
||||
if context.object.mode in {'PAINT_GPENCIL', 'VERTEX_GPENCIL'}:
|
||||
layout.label(text="Vertex Paint")
|
||||
layout.prop(overlay, "gpencil_vertex_paint_opacity", text="Opacity", slider=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_quad_view(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@@ -6783,77 +6881,127 @@ class VIEW3D_MT_gpencil_edit_context_menu(Menu):
|
||||
col.operator("gpencil.reproject", text="Reproject Strokes")
|
||||
|
||||
|
||||
def draw_gpencil_layer_active(context, layout):
|
||||
gpl = context.active_gpencil_layer
|
||||
if gpl:
|
||||
layout.label(text="Active Layer")
|
||||
row = layout.row(align=True)
|
||||
row.operator_context = 'EXEC_REGION_WIN'
|
||||
row.operator_menu_enum("gpencil.layer_change", "layer", text="", icon='GREASEPENCIL')
|
||||
row.prop(gpl, "info", text="")
|
||||
row.operator("gpencil.layer_remove", text="", icon='X')
|
||||
|
||||
|
||||
class VIEW3D_PT_gpencil_sculpt_context_menu(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_label = "Sculpt Context Menu"
|
||||
bl_ui_units_x = 12
|
||||
|
||||
def draw(self, context):
|
||||
brush = context.tool_settings.gpencil_sculpt.brush
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
layout = self.layout
|
||||
|
||||
if context.mode == 'WEIGHT_GPENCIL':
|
||||
layout.prop(brush, "weight")
|
||||
layout.prop(brush, "size", slider=True)
|
||||
layout.prop(brush, "strength")
|
||||
|
||||
layout.separator()
|
||||
# Layers
|
||||
draw_gpencil_layer_active(context, layout)
|
||||
|
||||
# Frames
|
||||
layout.label(text="Frames:")
|
||||
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
class VIEW3D_PT_gpencil_weight_context_menu(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_label = "Weight Paint Context Menu"
|
||||
bl_ui_units_x = 12
|
||||
|
||||
layout.operator("gpencil.blank_frame_add", text="Insert Blank in Active Layer", icon='ADD')
|
||||
layout.operator("gpencil.blank_frame_add", text="Insert Blank in All Layers", icon='ADD').all_layers = True
|
||||
def draw(self, context):
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
layout.separator()
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("gpencil.frame_duplicate", text="Duplicate Active Layer", icon='DUPLICATE')
|
||||
layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers", icon='DUPLICATE').mode = 'ALL'
|
||||
layout.prop(brush, "size", slider=True)
|
||||
layout.prop(brush, "strength")
|
||||
layout.prop(brush, "weight")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.delete", text="Delete Active Layer", icon='REMOVE').type = 'FRAME'
|
||||
layout.operator("gpencil.active_frames_delete_all", text="Delete All Layers", icon='REMOVE')
|
||||
# Layers
|
||||
draw_gpencil_layer_active(context, layout)
|
||||
|
||||
|
||||
class VIEW3D_PT_gpencil_draw_context_menu(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_label = "Draw Context Menu"
|
||||
bl_ui_units_x = 12
|
||||
|
||||
def draw(self, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
layout = self.layout
|
||||
|
||||
if brush.gpencil_tool not in {'ERASE', 'CUTTER', 'EYEDROPPER'} and settings.color_mode == 'VERTEXCOLOR':
|
||||
split = layout.split(factor=0.1)
|
||||
split.prop(brush, "color", text="")
|
||||
split.template_color_picker(brush, "color", value_slider=True)
|
||||
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.prop_menu_enum(gp_settings, "vertex_mode", text="Mode")
|
||||
col.separator()
|
||||
|
||||
if brush.gpencil_tool not in {'FILL', 'CUTTER'}:
|
||||
layout.prop(brush, "size", slider=True)
|
||||
if brush.gpencil_tool not in {'ERASE', 'FILL', 'CUTTER'}:
|
||||
layout.prop(gp_settings, "pen_strength")
|
||||
|
||||
layout.separator()
|
||||
# Layers
|
||||
draw_gpencil_layer_active(context, layout)
|
||||
|
||||
# Frames
|
||||
layout.label(text="Frames:")
|
||||
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
class VIEW3D_PT_gpencil_vertex_context_menu(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_label = "Vertex Paint Context Menu"
|
||||
bl_ui_units_x = 12
|
||||
|
||||
layout.operator("gpencil.blank_frame_add", text="Insert Blank in Active Layer", icon='ADD')
|
||||
layout.operator("gpencil.blank_frame_add", text="Insert Blank in All Layers", icon='ADD').all_layers = True
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
layout.separator()
|
||||
col = layout.column()
|
||||
|
||||
layout.operator("gpencil.frame_duplicate", text="Duplicate Active Layer", icon='DUPLICATE')
|
||||
layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers", icon='DUPLICATE').mode = 'ALL'
|
||||
if brush.gpencil_vertex_tool in {'DRAW', 'REPLACE'}:
|
||||
split = layout.split(factor=0.1)
|
||||
split.prop(brush, "color", text="")
|
||||
split.template_color_picker(brush, "color", value_slider=True)
|
||||
|
||||
layout.separator()
|
||||
col = layout.column()
|
||||
col.separator()
|
||||
col.prop_menu_enum(gp_settings, "vertex_mode", text="Mode")
|
||||
col.separator()
|
||||
|
||||
layout.operator("gpencil.delete", text="Delete Active Layer", icon='REMOVE').type = 'FRAME'
|
||||
layout.operator("gpencil.active_frames_delete_all", text="Delete All Layers", icon='REMOVE')
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "size", text="Radius")
|
||||
row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
if brush.gpencil_vertex_tool in {'DRAW', 'BLUR', 'SMEAR'}:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gp_settings, "pen_strength", slider=True)
|
||||
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
|
||||
|
||||
# Layers
|
||||
draw_gpencil_layer_active(context, layout)
|
||||
|
||||
|
||||
class VIEW3D_PT_paint_vertex_context_menu(Panel):
|
||||
@@ -7037,6 +7185,17 @@ class TOPBAR_PT_gpencil_materials(GreasePencilMaterialsPanel, Panel):
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
|
||||
class TOPBAR_PT_gpencil_vertexcolor(GreasePencilVertexcolorPanel, Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Vertex Color"
|
||||
bl_ui_units_x = 10
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
classes = (
|
||||
VIEW3D_HT_header,
|
||||
VIEW3D_HT_tool_header,
|
||||
@@ -7163,6 +7322,7 @@ classes = (
|
||||
VIEW3D_MT_edit_gpencil_delete,
|
||||
VIEW3D_MT_edit_gpencil_showhide,
|
||||
VIEW3D_MT_weight_gpencil,
|
||||
VIEW3D_MT_vertex_gpencil,
|
||||
VIEW3D_MT_gpencil_animation,
|
||||
VIEW3D_MT_gpencil_simplify,
|
||||
VIEW3D_MT_gpencil_copy_layer,
|
||||
@@ -7249,10 +7409,13 @@ classes = (
|
||||
VIEW3D_PT_paint_vertex_context_menu,
|
||||
VIEW3D_PT_paint_texture_context_menu,
|
||||
VIEW3D_PT_paint_weight_context_menu,
|
||||
VIEW3D_PT_gpencil_vertex_context_menu,
|
||||
VIEW3D_PT_gpencil_sculpt_context_menu,
|
||||
VIEW3D_PT_gpencil_weight_context_menu,
|
||||
VIEW3D_PT_gpencil_draw_context_menu,
|
||||
VIEW3D_PT_sculpt_context_menu,
|
||||
TOPBAR_PT_gpencil_materials,
|
||||
TOPBAR_PT_gpencil_vertexcolor,
|
||||
TOPBAR_PT_annotation_layers,
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ from bpy.types import Menu, Panel, UIList
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilSculptOptionsPanel,
|
||||
GreasePencilDisplayPanel,
|
||||
GreasePencilBrushFalloff,
|
||||
)
|
||||
from bl_ui.properties_paint_common import (
|
||||
UnifiedPaintPanel,
|
||||
@@ -71,6 +72,33 @@ class VIEW3D_MT_brush_context_menu(Menu):
|
||||
layout.operator("brush.reset")
|
||||
|
||||
|
||||
class VIEW3D_MT_brush_gpencil_context_menu(Menu):
|
||||
bl_label = "Brush Specials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ts = context.tool_settings
|
||||
|
||||
settings = None
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
settings = ts.gpencil_paint
|
||||
if context.mode == 'SCULPT_GPENCIL':
|
||||
settings = ts.gpencil_sculpt_paint
|
||||
elif context.mode == 'WEIGHT_GPENCIL':
|
||||
settings = ts.gpencil_weight_paint
|
||||
elif context.mode == 'VERTEX_GPENCIL':
|
||||
settings = ts.gpencil_vertex_paint
|
||||
|
||||
brush = getattr(settings, "brush", None)
|
||||
# skip if no active brush
|
||||
if not brush:
|
||||
layout.label(text="No Brushes currently available", icon='INFO')
|
||||
return
|
||||
|
||||
layout.operator("gpencil.brush_reset")
|
||||
layout.operator("gpencil.brush_reset_all")
|
||||
|
||||
|
||||
class VIEW3D_MT_brush_context_menu_paint_modes(Menu):
|
||||
bl_label = "Enabled Modes"
|
||||
|
||||
@@ -1339,7 +1367,7 @@ class VIEW3D_PT_tools_particlemode_options_display(View3DPanel, Panel):
|
||||
# Grease Pencil drawing brushes
|
||||
|
||||
|
||||
class GreasePencilPanel:
|
||||
class GreasePencilPaintPanel:
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_category = "Tool"
|
||||
|
||||
@@ -1355,7 +1383,7 @@ class GreasePencilPanel:
|
||||
return True
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPanel):
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPaintPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -1370,7 +1398,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePenci
|
||||
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
col.operator("gpencil.brush_presets_create", icon='PRESET_NEW', text="")
|
||||
col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if context.mode == 'PAINT_GPENCIL':
|
||||
brush = tool_settings.gpencil_paint.brush
|
||||
@@ -1383,7 +1411,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePenci
|
||||
layout.row().prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePencilPanel):
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePencilPaintPanel):
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
# What is the point of brush presets? Seems to serve the exact same purpose as brushes themselves??
|
||||
@@ -1431,7 +1459,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool != 'ERASE'
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'TINT'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -1463,11 +1491,11 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
|
||||
ma = brush.gpencil_settings.material
|
||||
|
||||
col.separator()
|
||||
col.prop(gp_settings, "hardeness", slider=True)
|
||||
subcol = col.column(align=True)
|
||||
if ma and ma.grease_pencil.mode == 'LINE':
|
||||
subcol.enabled = False
|
||||
subcol.prop(gp_settings, "gradient_factor", slider=True)
|
||||
subcol.prop(gp_settings, "gradient_shape")
|
||||
subcol.prop(gp_settings, "aspect")
|
||||
|
||||
elif brush.gpencil_tool == 'FILL':
|
||||
row = col.row(align=True)
|
||||
@@ -1479,6 +1507,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
|
||||
col.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
|
||||
col.prop(gp_settings, "fill_threshold", text="Threshold")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_stroke(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings'
|
||||
@@ -1545,7 +1574,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
|
||||
|
||||
def draw_header(self, context):
|
||||
if self.is_popover:
|
||||
@@ -1575,13 +1604,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel):
|
||||
col1.prop(gp_settings, "pen_smooth_factor")
|
||||
col1.prop(gp_settings, "pen_smooth_steps")
|
||||
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "pen_thick_smooth_factor")
|
||||
col1.prop(gp_settings, "pen_thick_smooth_steps", text="Iterations")
|
||||
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "pen_subdivision_steps")
|
||||
col1.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
|
||||
|
||||
col1 = col.column(align=True)
|
||||
col1.prop(gp_settings, "simplify_factor")
|
||||
@@ -1600,7 +1624,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
|
||||
|
||||
def draw_header(self, context):
|
||||
if self.is_popover:
|
||||
@@ -1646,7 +1670,7 @@ class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL'}
|
||||
return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'}
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
@@ -1703,6 +1727,24 @@ class VIEW3D_PT_tools_grease_pencil_brushcurves_jitter(View3DPanel, Panel):
|
||||
use_negative_slope=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
if brush is None:
|
||||
return False
|
||||
|
||||
tool = brush.gpencil_tool
|
||||
|
||||
return (settings and settings.brush and settings.brush.curve and tool == 'TINT')
|
||||
|
||||
|
||||
# Grease Pencil stroke interpolation tools
|
||||
class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@@ -1751,25 +1793,49 @@ class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
|
||||
|
||||
|
||||
# Grease Pencil stroke sculpting tools
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel):
|
||||
class GreasePencilSculptPanel:
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_label = "Brushes"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
return bool(gpd.is_stroke_sculpt_mode)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel, GreasePencilSculptPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_sculpt_paint
|
||||
|
||||
layout.template_icon_view(settings, "sculpt_tool", show_labels=True)
|
||||
row = layout.row()
|
||||
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if context.mode == 'SCULPT_GPENCIL':
|
||||
brush = tool_settings.gpencil_sculpt_paint.brush
|
||||
if brush is not None:
|
||||
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
|
||||
|
||||
if(brush.use_custom_icon):
|
||||
layout.row().prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_category = "Tool"
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel, GreasePencilSculptPanel):
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -1777,7 +1843,8 @@ class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_sculpt_paint
|
||||
brush = settings.brush
|
||||
|
||||
if not self.is_popover:
|
||||
@@ -1786,27 +1853,63 @@ class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel):
|
||||
)
|
||||
brush_basic_gpencil_sculpt_settings(layout, context, brush)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_sculpt_paint
|
||||
return (settings and settings.brush and settings.brush.curve)
|
||||
|
||||
|
||||
# Grease Pencil weight painting tools
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel):
|
||||
class GreasePencilWeightPanel:
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_label = "Brushes"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
return bool(gpd.is_stroke_weight_mode)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel, GreasePencilWeightPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_weight_paint
|
||||
|
||||
layout.template_icon_view(settings, "weight_tool", show_labels=True)
|
||||
row = layout.row()
|
||||
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if context.mode == 'WEIGHT_GPENCIL':
|
||||
brush = tool_settings.gpencil_weight_paint.brush
|
||||
if brush is not None:
|
||||
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
|
||||
|
||||
if(brush.use_custom_icon):
|
||||
layout.row().prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_category = "Tool"
|
||||
class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel, GreasePencilWeightPanel):
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -1814,7 +1917,8 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_weight_paint
|
||||
brush = settings.brush
|
||||
|
||||
if not self.is_popover:
|
||||
@@ -1824,6 +1928,272 @@ class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel):
|
||||
brush_basic_gpencil_weight_settings(layout, context, brush)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_weight_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
|
||||
bl_context = ".greasepencil_weight"
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_weight_paint
|
||||
brush = settings.brush
|
||||
return (settings and settings.brush and settings.brush.curve)
|
||||
|
||||
|
||||
# Grease Pencil vertex painting tools
|
||||
class GreasePencilVertexPanel:
|
||||
bl_context = ".greasepencil_vertex"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.space_data.type in ('VIEW_3D', 'PROPERTIES'):
|
||||
if context.gpencil_data is None:
|
||||
return False
|
||||
|
||||
gpd = context.gpencil_data
|
||||
return bool(gpd.is_stroke_vertex_mode)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_vertex_paint_select(View3DPanel, Panel, GreasePencilVertexPanel):
|
||||
bl_label = "Brushes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.scene.tool_settings
|
||||
gpencil_paint = tool_settings.gpencil_vertex_paint
|
||||
|
||||
row = layout.row()
|
||||
row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8)
|
||||
|
||||
col = row.column()
|
||||
col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if context.mode == 'VERTEX_GPENCIL':
|
||||
brush = tool_settings.gpencil_vertex_paint.brush
|
||||
if brush is not None:
|
||||
col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="")
|
||||
|
||||
if(brush.use_custom_icon):
|
||||
layout.row().prop(brush, "icon_filepath", text="")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_vertex_paint_settings(Panel, View3DPanel, GreasePencilVertexPanel):
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.scene.tool_settings
|
||||
settings = tool_settings.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
|
||||
if not self.is_popover:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic_gpencil_vertex_settings,
|
||||
)
|
||||
brush_basic_gpencil_vertex_settings(layout, context, brush)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_vertex_color(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_vertex"
|
||||
bl_label = "Color"
|
||||
bl_category = "Tool"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
|
||||
if ob is None or brush is None:
|
||||
return False
|
||||
|
||||
if context.region.type == 'TOOL_HEADER' or brush.gpencil_vertex_tool in {'BLUR', 'AVERAGE', 'SMEAR'}:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
col = layout.column()
|
||||
|
||||
col.template_color_picker(brush, "color", value_slider=True)
|
||||
|
||||
sub_row = col.row(align=True)
|
||||
sub_row.prop(brush, "color", text="")
|
||||
sub_row.prop(brush, "secondary_color", text="")
|
||||
|
||||
sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="")
|
||||
|
||||
col.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel):
|
||||
bl_context = ".greasepencil_vertex"
|
||||
bl_label = "Falloff"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_vertex_paint
|
||||
return (settings and settings.brush and settings.brush.curve)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_vertex_palette(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_vertex"
|
||||
bl_label = "Palette"
|
||||
bl_category = "Tool"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_vertex_color'
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_vertex_paint
|
||||
brush = settings.brush
|
||||
|
||||
if ob is None or brush is None:
|
||||
return False
|
||||
|
||||
if brush.gpencil_vertex_tool in {'BLUR', 'AVERAGE', 'SMEAR'}:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_vertex_paint
|
||||
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
row.template_ID(settings, "palette", new="palette.new")
|
||||
if settings.palette:
|
||||
col.template_palette(settings, "palette", color=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Color"
|
||||
bl_category = "Tool"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
if ob is None or brush is None:
|
||||
return False
|
||||
|
||||
if context.region.type == 'TOOL_HEADER':
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
return True
|
||||
|
||||
if brush.gpencil_tool not in {'DRAW', 'FILL'}:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
if brush.gpencil_tool != 'TINT':
|
||||
row = layout.row()
|
||||
row.prop(settings, "color_mode", expand=True)
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
col = layout.column()
|
||||
col.enabled = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
|
||||
|
||||
col.template_color_picker(brush, "color", value_slider=True)
|
||||
|
||||
sub_row = col.row(align=True)
|
||||
sub_row.prop(brush, "color", text="")
|
||||
sub_row.prop(brush, "secondary_color", text="")
|
||||
|
||||
sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="")
|
||||
|
||||
if brush.gpencil_tool in {'DRAW', 'FILL'}:
|
||||
col.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
col.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor")
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
col.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel):
|
||||
bl_context = ".greasepencil_paint"
|
||||
bl_label = "Palette"
|
||||
bl_category = "Tool"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_mixcolor'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
if ob is None or brush is None:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
return True
|
||||
|
||||
if brush.gpencil_tool not in {'DRAW', 'FILL'}:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
ts = context.tool_settings
|
||||
settings = ts.gpencil_paint
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.enabled = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT'
|
||||
|
||||
row = col.row(align=True)
|
||||
row.template_ID(settings, "palette", new="palette.new")
|
||||
if settings.palette:
|
||||
col.template_palette(settings, "palette", color=True)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_sculpt_options(GreasePencilSculptOptionsPanel, Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_sculpt"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings'
|
||||
@@ -1852,6 +2222,11 @@ class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilDisplayPanel,
|
||||
bl_category = "Tool"
|
||||
bl_label = "Cursor"
|
||||
|
||||
class VIEW3D_PT_tools_grease_pencil_vertex_appearance(GreasePencilDisplayPanel, Panel, View3DPanel):
|
||||
bl_context = ".greasepencil_vertex"
|
||||
bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_vertex_paint_settings'
|
||||
bl_category = "Tool"
|
||||
bl_label = "Cursor"
|
||||
|
||||
class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
|
||||
"""Brush settings"""
|
||||
@@ -1863,6 +2238,7 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
|
||||
|
||||
classes = (
|
||||
VIEW3D_MT_brush_context_menu,
|
||||
VIEW3D_MT_brush_gpencil_context_menu,
|
||||
VIEW3D_MT_brush_context_menu_paint_modes,
|
||||
VIEW3D_PT_tools_object_options,
|
||||
VIEW3D_PT_tools_object_options_transform,
|
||||
@@ -1940,7 +2316,19 @@ classes = (
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint_select,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_paint_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_weight_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_vertex_paint_select,
|
||||
VIEW3D_PT_tools_grease_pencil_vertex_paint_settings,
|
||||
VIEW3D_PT_tools_grease_pencil_vertex_appearance,
|
||||
VIEW3D_PT_tools_grease_pencil_interpolate,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_mixcolor,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_mix_palette,
|
||||
|
||||
VIEW3D_PT_tools_grease_pencil_brush_paint_falloff,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_weight_falloff,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_vertex_color,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_vertex_palette,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
* \note Use #STRINGIFY() rather than defining with quotes.
|
||||
*/
|
||||
#define BLENDER_VERSION 283
|
||||
#define BLENDER_SUBVERSION 6
|
||||
#define BLENDER_SUBVERSION 7
|
||||
/** Several breakages with 280, e.g. collections vs layers. */
|
||||
#define BLENDER_MINVERSION 280
|
||||
#define BLENDER_MINSUBVERSION 0
|
||||
|
||||
@@ -46,13 +46,22 @@ void BKE_brush_system_exit(void);
|
||||
|
||||
/* datablock functions */
|
||||
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, const eObjectMode ob_mode);
|
||||
struct Brush *BKE_brush_add_gpencil(struct Main *bmain, struct ToolSettings *ts, const char *name);
|
||||
struct Brush *BKE_brush_add_gpencil(struct Main *bmain,
|
||||
struct ToolSettings *ts,
|
||||
const char *name,
|
||||
eObjectMode mode);
|
||||
bool BKE_brush_delete(struct Main *bmain, struct Brush *brush);
|
||||
void BKE_brush_init_gpencil_settings(struct Brush *brush);
|
||||
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode);
|
||||
struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush);
|
||||
|
||||
void BKE_brush_sculpt_reset(struct Brush *brush);
|
||||
void BKE_brush_gpencil_presets(struct Main *bmain, struct ToolSettings *ts);
|
||||
|
||||
void BKE_brush_gpencil_paint_presets(struct Main *bmain, struct ToolSettings *ts);
|
||||
void BKE_brush_gpencil_vertex_presets(struct Main *bmain, struct ToolSettings *ts);
|
||||
void BKE_brush_gpencil_sculpt_presets(struct Main *bmain, struct ToolSettings *ts);
|
||||
void BKE_brush_gpencil_weight_presets(struct Main *bmain, struct ToolSettings *ts);
|
||||
void BKE_gpencil_brush_preset_set(struct Main *bmain, struct Brush *brush, const short type);
|
||||
|
||||
/* image icon function */
|
||||
struct ImBuf *get_brush_icon(struct Brush *brush);
|
||||
|
||||
@@ -115,8 +115,9 @@ typedef enum eContextObjectMode {
|
||||
CTX_MODE_EDIT_GPENCIL,
|
||||
CTX_MODE_SCULPT_GPENCIL,
|
||||
CTX_MODE_WEIGHT_GPENCIL,
|
||||
CTX_MODE_VERTEX_GPENCIL,
|
||||
} eContextObjectMode;
|
||||
#define CTX_MODE_NUM (CTX_MODE_WEIGHT_GPENCIL + 1)
|
||||
#define CTX_MODE_NUM (CTX_MODE_VERTEX_GPENCIL + 1)
|
||||
|
||||
/* Context */
|
||||
|
||||
|
||||
@@ -32,19 +32,22 @@ struct BoundBox;
|
||||
struct Brush;
|
||||
struct CurveMapping;
|
||||
struct Depsgraph;
|
||||
struct GHash;
|
||||
struct ListBase;
|
||||
struct Main;
|
||||
struct Material;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct SpaceImage;
|
||||
struct ToolSettings;
|
||||
struct bDeformGroup;
|
||||
struct bGPDframe;
|
||||
struct bGPDlayer;
|
||||
struct bGPDlayer_Mask;
|
||||
struct bGPDspoint;
|
||||
struct bGPDstroke;
|
||||
struct bGPdata;
|
||||
|
||||
struct MaterialGPencilStyle;
|
||||
struct MDeformVert;
|
||||
|
||||
#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
|
||||
@@ -54,18 +57,33 @@ struct MDeformVert;
|
||||
#define GPENCIL_SIMPLIFY_FILL(scene, playing) \
|
||||
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
|
||||
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
|
||||
#define GPENCIL_SIMPLIFY_MODIF(scene, playing) \
|
||||
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
|
||||
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
|
||||
#define GPENCIL_SIMPLIFY_MODIF(scene) \
|
||||
((GPENCIL_SIMPLIFY(scene) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
|
||||
#define GPENCIL_SIMPLIFY_FX(scene, playing) \
|
||||
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
|
||||
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
|
||||
#define GPENCIL_SIMPLIFY_BLEND(scene, playing) \
|
||||
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
|
||||
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
|
||||
#define GPENCIL_SIMPLIFY_TINT(scene, playing) \
|
||||
((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
|
||||
(scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT)))
|
||||
#define GPENCIL_SIMPLIFY_TINT(scene) \
|
||||
((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_TINT))
|
||||
#define GPENCIL_SIMPLIFY_AA(scene) \
|
||||
((GPENCIL_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_AA))
|
||||
|
||||
/* Vertex Color macros. */
|
||||
#define GPENCIL_USE_VERTEX_COLOR(toolsettings) \
|
||||
((toolsettings->gp_paint->mode == GPPAINT_FLAG_USE_VERTEXCOLOR))
|
||||
#define GPENCIL_USE_VERTEX_COLOR_STROKE(toolsettings, brush) \
|
||||
((GPENCIL_USE_VERTEX_COLOR(toolsettings) && \
|
||||
((brush->gpencil_settings->vertex_mode == GPPAINT_MODE_STROKE) || \
|
||||
(brush->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH))))
|
||||
#define GPENCIL_USE_VERTEX_COLOR_FILL(toolsettings, brush) \
|
||||
((GPENCIL_USE_VERTEX_COLOR(toolsettings) && \
|
||||
((brush->gpencil_settings->vertex_mode == GPPAINT_MODE_FILL) || \
|
||||
(brush->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH))))
|
||||
#define GPENCIL_TINT_VERTEX_COLOR_STROKE(brush) \
|
||||
((brush->gpencil_settings->vertex_mode == GPPAINT_MODE_STROKE) || \
|
||||
(brush->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH))
|
||||
#define GPENCIL_TINT_VERTEX_COLOR_FILL(brush) \
|
||||
((brush->gpencil_settings->vertex_mode == GPPAINT_MODE_FILL) || \
|
||||
(brush->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH))
|
||||
|
||||
/* ------------ Grease-Pencil API ------------------ */
|
||||
|
||||
@@ -75,8 +93,9 @@ void BKE_gpencil_free_stroke(struct bGPDstroke *gps);
|
||||
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf);
|
||||
void BKE_gpencil_free_frames(struct bGPDlayer *gpl);
|
||||
void BKE_gpencil_free_layers(struct ListBase *list);
|
||||
bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *gpf_eval);
|
||||
void BKE_gpencil_free(struct bGPdata *gpd, bool free_all);
|
||||
void BKE_gpencil_eval_delete(struct bGPdata *gpd_eval);
|
||||
void BKE_gpencil_free_layer_masks(struct bGPDlayer *gpl);
|
||||
|
||||
void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
|
||||
void BKE_gpencil_batch_cache_free(struct bGPdata *gpd);
|
||||
@@ -91,10 +110,11 @@ struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[]);
|
||||
struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src);
|
||||
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src);
|
||||
void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
|
||||
struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src);
|
||||
struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src, const bool dup_points);
|
||||
|
||||
void BKE_gpencil_copy_data(struct bGPdata *gpd_dst, const struct bGPdata *gpd_src, const int flag);
|
||||
struct bGPdata *BKE_gpencil_copy(struct Main *bmain, const struct bGPdata *gpd);
|
||||
|
||||
struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain,
|
||||
const struct bGPdata *gpd,
|
||||
bool internal_copy);
|
||||
@@ -109,6 +129,11 @@ bool BKE_gpencil_material_index_used(struct bGPdata *gpd, int index);
|
||||
void BKE_gpencil_material_remap(struct bGPdata *gpd,
|
||||
const unsigned int *remap,
|
||||
unsigned int remap_len);
|
||||
bool BKE_gpencil_merge_materials_table_get(struct Object *ob,
|
||||
const float hue_threshold,
|
||||
const float sat_threshold,
|
||||
const float val_threshold,
|
||||
struct GHash *r_mat_table);
|
||||
|
||||
/* statistics functions */
|
||||
void BKE_gpencil_stats_update(struct bGPdata *gpd);
|
||||
@@ -124,12 +149,11 @@ void BKE_gpencil_stroke_add_points(struct bGPDstroke *gps,
|
||||
const int totpoints,
|
||||
const float mat[4][4]);
|
||||
|
||||
struct bGPDstroke *BKE_gpencil_add_stroke(struct bGPDframe *gpf,
|
||||
int mat_idx,
|
||||
int totpoints,
|
||||
short thickness);
|
||||
struct bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness);
|
||||
struct bGPDstroke *BKE_gpencil_stroke_add(
|
||||
struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head);
|
||||
|
||||
struct bGPDstroke *BKE_gpencil_add_stroke_existing_style(struct bGPDframe *gpf,
|
||||
struct bGPDstroke *BKE_gpencil_stroke_add_existing_style(struct bGPDframe *gpf,
|
||||
struct bGPDstroke *existing,
|
||||
int mat_idx,
|
||||
int totpoints,
|
||||
@@ -139,7 +163,7 @@ struct bGPDstroke *BKE_gpencil_add_stroke_existing_style(struct bGPDframe *gpf,
|
||||
#define GPENCIL_ALPHA_OPACITY_THRESH 0.001f
|
||||
#define GPENCIL_STRENGTH_MIN 0.003f
|
||||
|
||||
bool gpencil_layer_is_editable(const struct bGPDlayer *gpl);
|
||||
bool BKE_gpencil_layer_is_editable(const struct bGPDlayer *gpl);
|
||||
|
||||
/* How gpencil_layer_getframe() should behave when there
|
||||
* is no existing GP-Frame on the frame requested.
|
||||
@@ -154,17 +178,25 @@ typedef enum eGP_GetFrame_Mode {
|
||||
GP_GETFRAME_ADD_COPY = 2,
|
||||
} eGP_GetFrame_Mode;
|
||||
|
||||
struct bGPDframe *BKE_gpencil_layer_getframe(struct bGPDlayer *gpl,
|
||||
int cframe,
|
||||
eGP_GetFrame_Mode addnew);
|
||||
struct bGPDframe *BKE_gpencil_layer_find_frame(struct bGPDlayer *gpl, int cframe);
|
||||
bool BKE_gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf);
|
||||
struct bGPDframe *BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl,
|
||||
int cframe,
|
||||
eGP_GetFrame_Mode addnew);
|
||||
struct bGPDframe *BKE_gpencil_layer_frame_find(struct bGPDlayer *gpl, int cframe);
|
||||
bool BKE_gpencil_layer_frame_delete(struct bGPDlayer *gpl, struct bGPDframe *gpf);
|
||||
|
||||
struct bGPDlayer *BKE_gpencil_layer_getactive(struct bGPdata *gpd);
|
||||
void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active);
|
||||
struct bGPDlayer *BKE_gpencil_layer_named_get(struct bGPdata *gpd, const char *name);
|
||||
struct bGPDlayer *BKE_gpencil_layer_active_get(struct bGPdata *gpd);
|
||||
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active);
|
||||
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
|
||||
void BKE_gpencil_layer_autolock_set(struct bGPdata *gpd, const bool unlock);
|
||||
|
||||
struct bGPDlayer_Mask *BKE_gpencil_layer_mask_add(struct bGPDlayer *gpl, const char *name);
|
||||
void BKE_gpencil_layer_mask_remove(struct bGPDlayer *gpl, struct bGPDlayer_Mask *mask);
|
||||
void BKE_gpencil_layer_mask_remove_ref(struct bGPdata *gpd, const char *name);
|
||||
struct bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(struct bGPDlayer *gpl, const char *name);
|
||||
void BKE_gpencil_layer_mask_sort(struct bGPdata *gpd, struct bGPDlayer *gpl);
|
||||
void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd);
|
||||
|
||||
/* Brush */
|
||||
struct Material *BKE_gpencil_brush_material_get(struct Brush *brush);
|
||||
void BKE_gpencil_brush_material_set(struct Brush *brush, struct Material *material);
|
||||
@@ -183,9 +215,9 @@ struct Material *BKE_gpencil_object_material_new(struct Main *bmain,
|
||||
const char *name,
|
||||
int *r_index);
|
||||
|
||||
int BKE_gpencil_object_material_get_index(struct Object *ob, struct Material *ma);
|
||||
int BKE_gpencil_object_material_index_get(struct Object *ob, struct Material *ma);
|
||||
|
||||
struct Material *BKE_gpencil_object_material_get_from_brush(struct Object *ob,
|
||||
struct Material *BKE_gpencil_object_material_from_brush_get(struct Object *ob,
|
||||
struct Brush *brush);
|
||||
int BKE_gpencil_object_material_get_index_from_brush(struct Object *ob, struct Brush *brush);
|
||||
|
||||
@@ -206,22 +238,23 @@ bool BKE_gpencil_stroke_select_check(const struct bGPDstroke *gps);
|
||||
|
||||
struct BoundBox *BKE_gpencil_boundbox_get(struct Object *ob);
|
||||
void BKE_gpencil_centroid_3d(struct bGPdata *gpd, float r_centroid[3]);
|
||||
void BKE_gpencil_stroke_boundingbox_calc(struct bGPDstroke *gps);
|
||||
|
||||
/* vertex groups */
|
||||
void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_vgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
|
||||
void BKE_gpencil_stroke_weights_duplicate(struct bGPDstroke *gps_src, struct bGPDstroke *gps_dst);
|
||||
|
||||
/* GPencil geometry evaluation */
|
||||
void BKE_gpencil_eval_geometry(struct Depsgraph *depsgraph, struct bGPdata *gpd);
|
||||
/* Set active frame by layer. */
|
||||
void BKE_gpencil_frame_active_set(struct Depsgraph *depsgraph, struct bGPdata *gpd);
|
||||
|
||||
/* stroke geometry utilities */
|
||||
void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]);
|
||||
void BKE_gpencil_simplify_stroke(struct bGPDstroke *gps, float factor);
|
||||
void BKE_gpencil_simplify_fixed(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_subdivide(struct bGPDstroke *gps, int level, int flag);
|
||||
bool BKE_gpencil_trim_stroke(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_merge_distance_stroke(struct bGPDframe *gpf,
|
||||
void BKE_gpencil_stroke_simplify_adaptive(struct bGPDstroke *gps, float factor);
|
||||
void BKE_gpencil_stroke_simplify_fixed(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_stroke_subdivide(struct bGPDstroke *gps, int level, int type);
|
||||
bool BKE_gpencil_stroke_trim(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_stroke_merge_distance(struct bGPDframe *gpf,
|
||||
struct bGPDstroke *gps,
|
||||
const float threshold,
|
||||
const bool use_unselected);
|
||||
@@ -237,31 +270,33 @@ void BKE_gpencil_stroke_2d_flat_ref(const struct bGPDspoint *ref_points,
|
||||
float (*points2d)[2],
|
||||
const float scale,
|
||||
int *r_direction);
|
||||
void BKE_gpencil_triangulate_stroke_fill(struct bGPdata *gpd, struct bGPDstroke *gps);
|
||||
void BKE_gpencil_stroke_fill_triangulate(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_stroke_geometry_update(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_stroke_uv_update(struct bGPDstroke *gps);
|
||||
|
||||
void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]);
|
||||
|
||||
bool BKE_gpencil_sample_stroke(struct bGPDstroke *gps, const float dist, const bool select);
|
||||
bool BKE_gpencil_smooth_stroke(struct bGPDstroke *gps, int i, float inf);
|
||||
bool BKE_gpencil_smooth_stroke_strength(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_smooth_stroke_thickness(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_smooth_stroke_uv(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_close_stroke(struct bGPDstroke *gps);
|
||||
bool BKE_gpencil_stroke_sample(struct bGPDstroke *gps, const float dist, const bool select);
|
||||
bool BKE_gpencil_stroke_smooth(struct bGPDstroke *gps, int i, float inf);
|
||||
bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_stroke_smooth_thickness(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_stroke_smooth_uv(struct bGPDstroke *gps, int point_index, float influence);
|
||||
bool BKE_gpencil_stroke_close(struct bGPDstroke *gps);
|
||||
void BKE_gpencil_dissolve_points(struct bGPDframe *gpf, struct bGPDstroke *gps, const short tag);
|
||||
|
||||
bool BKE_gpencil_stretch_stroke(struct bGPDstroke *gps, const float dist, const float tip_length);
|
||||
bool BKE_gpencil_trim_stroke_points(struct bGPDstroke *gps,
|
||||
bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps, const float dist, const float tip_length);
|
||||
bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps,
|
||||
const int index_from,
|
||||
const int index_to);
|
||||
bool BKE_gpencil_split_stroke(struct bGPDframe *gpf,
|
||||
bool BKE_gpencil_stroke_split(struct bGPDframe *gpf,
|
||||
struct bGPDstroke *gps,
|
||||
const int before_index,
|
||||
struct bGPDstroke **remaining_gps);
|
||||
bool BKE_gpencil_shrink_stroke(struct bGPDstroke *gps, const float dist);
|
||||
bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, const float dist);
|
||||
|
||||
float BKE_gpencil_stroke_length(const struct bGPDstroke *gps, bool use_3d);
|
||||
|
||||
void BKE_gpencil_get_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe);
|
||||
void BKE_gpencil_frame_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe);
|
||||
float BKE_gpencil_multiframe_falloff_calc(
|
||||
struct bGPDframe *gpf, int actnum, int f_init, int f_end, struct CurveMapping *cur_falloff);
|
||||
|
||||
@@ -273,9 +308,41 @@ void BKE_gpencil_convert_curve(struct Main *bmain,
|
||||
const bool use_collections,
|
||||
const bool only_stroke);
|
||||
|
||||
void BKE_gpencil_palette_ensure(struct Main *bmain, struct Scene *scene);
|
||||
|
||||
bool BKE_gpencil_from_image(struct SpaceImage *sima,
|
||||
struct bGPDframe *gpf,
|
||||
const float size,
|
||||
const bool mask);
|
||||
|
||||
/* Iterator */
|
||||
/* frame & stroke are NULL if it is a layer callback. */
|
||||
typedef void (*gpIterCb)(struct bGPDlayer *layer,
|
||||
struct bGPDframe *frame,
|
||||
struct bGPDstroke *stroke,
|
||||
void *thunk);
|
||||
|
||||
void BKE_gpencil_visible_stroke_iter(struct Object *ob,
|
||||
gpIterCb layer_cb,
|
||||
gpIterCb stroke_cb,
|
||||
void *thunk,
|
||||
bool do_onion,
|
||||
int cfra);
|
||||
|
||||
extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd);
|
||||
extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
|
||||
|
||||
void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
|
||||
const struct bGPDframe *gpf_eval);
|
||||
void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval);
|
||||
|
||||
void BKE_gpencil_parent_matrix_get(const struct Depsgraph *depsgraph,
|
||||
struct Object *obact,
|
||||
struct bGPDlayer *gpl,
|
||||
float diff_mat[4][4]);
|
||||
|
||||
void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct Object *ob);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -141,20 +141,10 @@ typedef struct GpencilModifierTypeInfo {
|
||||
/**
|
||||
* Callback for GP "geometry" modifiers that create extra geometry
|
||||
* in the frame (e.g. Array)
|
||||
*
|
||||
* The gpf parameter contains the GP frame/strokes to operate on. This is
|
||||
* usually a copy of the original (unmodified and saved to files) stroke data.
|
||||
* Modifiers should only add any generated strokes to this frame (and not one accessed
|
||||
* via the gpl parameter).
|
||||
*
|
||||
* The modifier_index parameter indicates where the modifier is
|
||||
* in the modifier stack in relation to other modifiers.
|
||||
*/
|
||||
void (*generateStrokes)(struct GpencilModifierData *md,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Object *ob,
|
||||
struct bGPDlayer *gpl,
|
||||
struct bGPDframe *gpf);
|
||||
struct Object *ob);
|
||||
|
||||
/**
|
||||
* Bake-down GP modifier's effects into the GP data-block.
|
||||
@@ -297,24 +287,6 @@ bool BKE_gpencil_has_geometry_modifiers(struct Object *ob);
|
||||
bool BKE_gpencil_has_time_modifiers(struct Object *ob);
|
||||
bool BKE_gpencil_has_transform_modifiers(struct Object *ob);
|
||||
|
||||
void BKE_gpencil_stroke_modifiers(struct Depsgraph *depsgraph,
|
||||
struct Object *ob,
|
||||
struct bGPDlayer *gpl,
|
||||
struct bGPDframe *gpf,
|
||||
struct bGPDstroke *gps,
|
||||
bool is_render);
|
||||
void BKE_gpencil_geometry_modifiers(struct Depsgraph *depsgraph,
|
||||
struct Object *ob,
|
||||
struct bGPDlayer *gpl,
|
||||
struct bGPDframe *gpf,
|
||||
bool is_render);
|
||||
int BKE_gpencil_time_modifier(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct bGPDlayer *gpl,
|
||||
int cfra,
|
||||
bool is_render);
|
||||
|
||||
void BKE_gpencil_lattice_init(struct Object *ob);
|
||||
void BKE_gpencil_lattice_clear(struct Object *ob);
|
||||
|
||||
@@ -322,6 +294,15 @@ void BKE_gpencil_modifiers_calc(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
|
||||
void BKE_gpencil_prepare_eval_data(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
|
||||
struct bGPDframe *BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct bGPDlayer *gpl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@ struct Brush;
|
||||
struct CurveMapping;
|
||||
struct Depsgraph;
|
||||
struct EnumPropertyItem;
|
||||
struct GHash;
|
||||
struct GridPaintMask;
|
||||
struct ImagePool;
|
||||
struct MLoop;
|
||||
@@ -55,6 +56,7 @@ struct SubdivCCG;
|
||||
struct SubdivCCG;
|
||||
struct Tex;
|
||||
struct ToolSettings;
|
||||
struct tPaletteColorHSV;
|
||||
struct UnifiedPaintSettings;
|
||||
struct View3D;
|
||||
struct ViewLayer;
|
||||
@@ -82,9 +84,13 @@ typedef enum ePaintMode {
|
||||
PAINT_MODE_TEXTURE_2D = 4,
|
||||
PAINT_MODE_SCULPT_UV = 5,
|
||||
PAINT_MODE_GPENCIL = 6,
|
||||
/* Grease Pencil Vertex Paint */
|
||||
PAINT_MODE_VERTEX_GPENCIL = 7,
|
||||
PAINT_MODE_SCULPT_GPENCIL = 8,
|
||||
PAINT_MODE_WEIGHT_GPENCIL = 9,
|
||||
|
||||
/** Keep last. */
|
||||
PAINT_MODE_INVALID = 7,
|
||||
PAINT_MODE_INVALID = 10,
|
||||
} ePaintMode;
|
||||
|
||||
#define PAINT_MODE_HAS_BRUSH(mode) !ELEM(mode, PAINT_MODE_SCULPT_UV)
|
||||
@@ -143,6 +149,15 @@ bool BKE_palette_is_empty(const struct Palette *palette);
|
||||
void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color);
|
||||
void BKE_palette_clear(struct Palette *palette);
|
||||
|
||||
void BKE_palette_sort_hsv(struct tPaletteColorHSV *color_array, const int totcol);
|
||||
void BKE_palette_sort_svh(struct tPaletteColorHSV *color_array, const int totcol);
|
||||
void BKE_palette_sort_vhs(struct tPaletteColorHSV *color_array, const int totcol);
|
||||
void BKE_palette_sort_luminance(struct tPaletteColorHSV *color_array, const int totcol);
|
||||
bool BKE_palette_from_hash(struct Main *bmain,
|
||||
struct GHash *color_table,
|
||||
const char *name,
|
||||
const bool linear);
|
||||
|
||||
/* paint curves */
|
||||
struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
|
||||
struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1124,6 +1124,9 @@ enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
|
||||
else if (object_mode & OB_MODE_WEIGHT_GPENCIL) {
|
||||
return CTX_MODE_WEIGHT_GPENCIL;
|
||||
}
|
||||
else if (object_mode & OB_MODE_VERTEX_GPENCIL) {
|
||||
return CTX_MODE_VERTEX_GPENCIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1140,25 +1143,11 @@ enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
|
||||
/* would prefer if we can use the enum version below over this one - Campbell */
|
||||
/* must be aligned with above enum */
|
||||
static const char *data_mode_strings[] = {
|
||||
"mesh_edit",
|
||||
"curve_edit",
|
||||
"surface_edit",
|
||||
"text_edit",
|
||||
"armature_edit",
|
||||
"mball_edit",
|
||||
"lattice_edit",
|
||||
"posemode",
|
||||
"sculpt_mode",
|
||||
"weightpaint",
|
||||
"vertexpaint",
|
||||
"imagepaint",
|
||||
"particlemode",
|
||||
"objectmode",
|
||||
"greasepencil_paint",
|
||||
"greasepencil_edit",
|
||||
"greasepencil_sculpt",
|
||||
"greasepencil_weight",
|
||||
NULL,
|
||||
"mesh_edit", "curve_edit", "surface_edit", "text_edit",
|
||||
"armature_edit", "mball_edit", "lattice_edit", "posemode",
|
||||
"sculpt_mode", "weightpaint", "vertexpaint", "imagepaint",
|
||||
"particlemode", "objectmode", "greasepencil_paint", "greasepencil_edit",
|
||||
"greasepencil_sculpt", "greasepencil_weight", "greasepencil_vertex", NULL,
|
||||
};
|
||||
BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1,
|
||||
"Must have a string for each context mode")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -96,7 +96,7 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
|
||||
* Ramer - Douglas - Peucker algorithm
|
||||
* by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
|
||||
*/
|
||||
void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
|
||||
void BKE_gpencil_stroke_simplify_adaptive(bGPDstroke *gps, float epsilon)
|
||||
{
|
||||
bGPDspoint *old_points = MEM_dupallocN(gps->points);
|
||||
int totpoints = gps->totpoints;
|
||||
@@ -165,9 +165,6 @@ void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
|
||||
old_dvert = MEM_dupallocN(gps->dvert);
|
||||
}
|
||||
/* resize gps */
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < totpoints; i++) {
|
||||
bGPDspoint *pt_src = &old_points[i];
|
||||
@@ -195,13 +192,16 @@ void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
|
||||
|
||||
gps->totpoints = j;
|
||||
|
||||
/* Calc geometry data. */
|
||||
BKE_gpencil_stroke_geometry_update(gps);
|
||||
|
||||
MEM_SAFE_FREE(old_points);
|
||||
MEM_SAFE_FREE(old_dvert);
|
||||
MEM_SAFE_FREE(marked);
|
||||
}
|
||||
|
||||
/* Simplify alternate vertex of stroke except extremes */
|
||||
void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
|
||||
void BKE_gpencil_stroke_simplify_fixed(bGPDstroke *gps)
|
||||
{
|
||||
if (gps->totpoints < 5) {
|
||||
return;
|
||||
@@ -227,8 +227,6 @@ void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
|
||||
if (gps->dvert != NULL) {
|
||||
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
|
||||
}
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < gps->totpoints; i++) {
|
||||
@@ -256,6 +254,8 @@ void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
|
||||
}
|
||||
|
||||
gps->totpoints = j;
|
||||
/* Calc geometry data. */
|
||||
BKE_gpencil_stroke_geometry_update(gps);
|
||||
|
||||
MEM_SAFE_FREE(old_points);
|
||||
MEM_SAFE_FREE(old_dvert);
|
||||
@@ -357,73 +357,8 @@ bool BKE_gpencil_has_transform_modifiers(Object *ob)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* apply stroke modifiers */
|
||||
void BKE_gpencil_stroke_modifiers(Depsgraph *depsgraph,
|
||||
Object *ob,
|
||||
bGPDlayer *gpl,
|
||||
bGPDframe *gpf,
|
||||
bGPDstroke *gps,
|
||||
bool is_render)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
bGPdata *gpd = ob->data;
|
||||
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti && mti->deformStroke) {
|
||||
mti->deformStroke(md, depsgraph, ob, gpl, gpf, gps);
|
||||
/* subdivide always requires update */
|
||||
if (md->type == eGpencilModifierType_Subdiv) {
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
}
|
||||
/* some modifiers could require a recalc of fill triangulation data */
|
||||
else if (gpd->flag & GP_DATA_STROKE_FORCE_RECALC) {
|
||||
if (ELEM(md->type,
|
||||
eGpencilModifierType_Armature,
|
||||
eGpencilModifierType_Hook,
|
||||
eGpencilModifierType_Lattice,
|
||||
eGpencilModifierType_Offset)) {
|
||||
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* apply stroke geometry modifiers */
|
||||
void BKE_gpencil_geometry_modifiers(
|
||||
Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bool is_render)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
bGPdata *gpd = ob->data;
|
||||
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
|
||||
for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
|
||||
if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti->generateStrokes) {
|
||||
mti->generateStrokes(md, depsgraph, ob, gpl, gpf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* apply time modifiers */
|
||||
int BKE_gpencil_time_modifier(
|
||||
static int gpencil_time_modifier(
|
||||
Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl, int cfra, bool is_render)
|
||||
{
|
||||
GpencilModifierData *md;
|
||||
@@ -454,14 +389,14 @@ int BKE_gpencil_time_modifier(
|
||||
}
|
||||
/* *************************************************** */
|
||||
|
||||
void BKE_gpencil_eval_geometry(Depsgraph *depsgraph, bGPdata *gpd)
|
||||
void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd)
|
||||
{
|
||||
DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd);
|
||||
int ctime = (int)DEG_get_ctime(depsgraph);
|
||||
|
||||
/* update active frame */
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, ctime, GP_GETFRAME_USE_PREV);
|
||||
}
|
||||
|
||||
if (DEG_is_active(depsgraph)) {
|
||||
@@ -471,8 +406,8 @@ void BKE_gpencil_eval_geometry(Depsgraph *depsgraph, bGPdata *gpd)
|
||||
* so that editing tools work with copy-on-write
|
||||
* when the current frame changes
|
||||
*/
|
||||
for (bGPDlayer *gpl = gpd_orig->layers.first; gpl; gpl = gpl->next) {
|
||||
gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
|
||||
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, ctime, GP_GETFRAME_USE_PREV);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -687,7 +622,7 @@ GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *na
|
||||
return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name));
|
||||
}
|
||||
|
||||
void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
|
||||
void BKE_gpencil_stroke_subdivide(bGPDstroke *gps, int level, int type)
|
||||
{
|
||||
bGPDspoint *temp_points;
|
||||
MDeformVert *temp_dverts = NULL;
|
||||
@@ -710,8 +645,6 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
|
||||
temp_dverts = MEM_dupallocN(gps->dvert);
|
||||
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
|
||||
}
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
/* move points from last to first to new place */
|
||||
i2 = gps->totpoints - 1;
|
||||
@@ -726,6 +659,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
|
||||
pt_final->flag = pt->flag;
|
||||
pt_final->runtime.pt_orig = pt->runtime.pt_orig;
|
||||
pt_final->runtime.idx_orig = pt->runtime.idx_orig;
|
||||
copy_v4_v4(pt_final->vert_color, pt->vert_color);
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
dvert = &temp_dverts[i];
|
||||
@@ -749,6 +683,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
|
||||
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
|
||||
pt_final->time = interpf(pt->time, next->time, 0.5f);
|
||||
pt_final->runtime.pt_orig = NULL;
|
||||
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
dvert = &temp_dverts[i];
|
||||
@@ -775,8 +710,8 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
|
||||
MEM_SAFE_FREE(temp_points);
|
||||
MEM_SAFE_FREE(temp_dverts);
|
||||
|
||||
/* move points to smooth stroke (not simple flag )*/
|
||||
if ((flag & GP_SUBDIV_SIMPLE) == 0) {
|
||||
/* move points to smooth stroke (not simple type )*/
|
||||
if (type != GP_SUBDIV_SIMPLE) {
|
||||
/* duplicate points in a temp area with the new subdivide data */
|
||||
temp_points = MEM_dupallocN(gps->points);
|
||||
|
||||
@@ -793,145 +728,186 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
|
||||
MEM_SAFE_FREE(temp_points);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calc geometry data. */
|
||||
BKE_gpencil_stroke_geometry_update(gps);
|
||||
}
|
||||
|
||||
/* Copy frame but do not assign new memory */
|
||||
static void gpencil_frame_copy_noalloc(Object *ob, bGPDframe *gpf, bGPDframe *gpf_eval)
|
||||
/* Remap frame (Time modifier) */
|
||||
static int gpencil_remap_time_get(Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl)
|
||||
{
|
||||
gpf_eval->prev = gpf->prev;
|
||||
gpf_eval->next = gpf->next;
|
||||
gpf_eval->framenum = gpf->framenum;
|
||||
gpf_eval->flag = gpf->flag;
|
||||
gpf_eval->key_type = gpf->key_type;
|
||||
gpf_eval->runtime = gpf->runtime;
|
||||
copy_m4_m4(gpf_eval->runtime.parent_obmat, gpf->runtime.parent_obmat);
|
||||
const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
|
||||
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
|
||||
int cfra_eval = (int)DEG_get_ctime(depsgraph);
|
||||
|
||||
/* copy strokes */
|
||||
BLI_listbase_clear(&gpf_eval->strokes);
|
||||
for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
|
||||
/* make copy of source stroke */
|
||||
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
|
||||
int remap_cfra = cfra_eval;
|
||||
if (time_remap) {
|
||||
remap_cfra = gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
|
||||
}
|
||||
|
||||
/* copy color to temp fields to apply temporal changes in the stroke */
|
||||
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps_src->mat_nr + 1);
|
||||
if (gp_style) {
|
||||
copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
|
||||
copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba);
|
||||
}
|
||||
return remap_cfra;
|
||||
}
|
||||
|
||||
/* Save original pointers for using in edit and select operators. */
|
||||
gps_dst->runtime.gps_orig = gps_src;
|
||||
for (int i = 0; i < gps_src->totpoints; i++) {
|
||||
bGPDspoint *pt_dst = &gps_dst->points[i];
|
||||
pt_dst->runtime.pt_orig = &gps_src->points[i];
|
||||
pt_dst->runtime.idx_orig = i;
|
||||
}
|
||||
/* Get the current frame retimed with time modifiers. */
|
||||
bGPDframe *BKE_gpencil_frame_retime_get(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
bGPDlayer *gpl)
|
||||
{
|
||||
int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl);
|
||||
bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
|
||||
|
||||
BLI_addtail(&gpf_eval->strokes, gps_dst);
|
||||
return gpf;
|
||||
}
|
||||
|
||||
static void gpencil_assign_object_eval(Object *object)
|
||||
{
|
||||
BLI_assert(object->id.tag & LIB_TAG_COPIED_ON_WRITE);
|
||||
|
||||
bGPdata *gpd_eval = object->runtime.gpd_eval;
|
||||
|
||||
gpd_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
|
||||
|
||||
if (object->id.tag & LIB_TAG_COPIED_ON_WRITE) {
|
||||
object->data = gpd_eval;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure there is a evaluated frame */
|
||||
static void gpencil_evaluated_frame_ensure(int idx,
|
||||
Object *ob,
|
||||
bGPDframe *gpf,
|
||||
bGPDframe **gpf_eval)
|
||||
/* Helper: Copy active frame from original datablock to evaluated datablock for modifiers. */
|
||||
static void gpencil_copy_activeframe_to_eval(
|
||||
Depsgraph *depsgraph, Scene *scene, Object *ob, bGPdata *gpd_orig, bGPdata *gpd_eval)
|
||||
{
|
||||
/* Create evaluated frames array data or expand. */
|
||||
bGPDframe *evaluated_frames = ob->runtime.gpencil_evaluated_frames;
|
||||
*gpf_eval = &evaluated_frames[idx];
|
||||
|
||||
/* If already exist a evaluated frame create a new one. */
|
||||
if (*gpf_eval != NULL) {
|
||||
/* first clear temp data */
|
||||
BKE_gpencil_free_frame_runtime_data(*gpf_eval);
|
||||
bGPDlayer *gpl_eval = gpd_eval->layers.first;
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd_orig->layers) {
|
||||
|
||||
if (gpl_eval != NULL) {
|
||||
int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl_orig);
|
||||
|
||||
bGPDframe *gpf_orig = BKE_gpencil_layer_frame_get(
|
||||
gpl_orig, remap_cfra, GP_GETFRAME_USE_PREV);
|
||||
|
||||
if (gpf_orig != NULL) {
|
||||
int gpf_index = BLI_findindex(&gpl_orig->frames, gpf_orig);
|
||||
bGPDframe *gpf_eval = BLI_findlink(&gpl_eval->frames, gpf_index);
|
||||
|
||||
if (gpf_eval != NULL) {
|
||||
/* Delete old strokes. */
|
||||
BKE_gpencil_free_strokes(gpf_eval);
|
||||
/* Copy again strokes. */
|
||||
BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval);
|
||||
|
||||
gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
|
||||
BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
|
||||
}
|
||||
}
|
||||
|
||||
gpl_eval = gpl_eval->next;
|
||||
}
|
||||
}
|
||||
/* Copy data (do not assign new memory). */
|
||||
gpencil_frame_copy_noalloc(ob, gpf, *gpf_eval);
|
||||
}
|
||||
|
||||
static bGPdata *gpencil_copy_for_eval(bGPdata *gpd)
|
||||
{
|
||||
int flags = LIB_ID_COPY_LOCALIZE;
|
||||
|
||||
bGPdata *result;
|
||||
BKE_id_copy_ex(NULL, &gpd->id, (ID **)&result, flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
bGPdata *gpd_eval = (bGPdata *)ob->data;
|
||||
Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
|
||||
bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
|
||||
|
||||
/* Need check if some layer is parented. */
|
||||
bool do_parent = false;
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
|
||||
if (gpl->parent != NULL) {
|
||||
do_parent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval);
|
||||
const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
|
||||
(!GPENCIL_SIMPLIFY_MODIF(scene)));
|
||||
if ((!do_modifiers) && (!do_parent)) {
|
||||
return;
|
||||
}
|
||||
DEG_debug_print_eval(depsgraph, __func__, gpd_eval->id.name, gpd_eval);
|
||||
|
||||
/* If only one user, don't need a new copy, just update data of the frame. */
|
||||
if (gpd_orig->id.us == 1) {
|
||||
ob->runtime.gpd_eval = NULL;
|
||||
gpencil_copy_activeframe_to_eval(depsgraph, scene, ob, ob_orig->data, gpd_eval);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy full Datablock to evaluated version. */
|
||||
ob->runtime.gpd_orig = gpd_orig;
|
||||
if (ob->runtime.gpd_eval != NULL) {
|
||||
BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
|
||||
ob->runtime.gpd_eval = NULL;
|
||||
ob->data = ob->runtime.gpd_orig;
|
||||
}
|
||||
ob->runtime.gpd_eval = gpencil_copy_for_eval(ob->runtime.gpd_orig);
|
||||
gpencil_assign_object_eval(ob);
|
||||
BKE_gpencil_update_orig_pointers(ob_orig, (Object *)ob);
|
||||
}
|
||||
|
||||
/* Calculate gpencil modifiers */
|
||||
void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
/* use original data to set reference pointers to original data */
|
||||
Object *ob_orig = DEG_get_original_object(ob);
|
||||
bGPdata *gpd = (bGPdata *)ob_orig->data;
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
||||
const bool simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, false);
|
||||
const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
|
||||
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
|
||||
int cfra_eval = (int)DEG_get_ctime(depsgraph);
|
||||
|
||||
/* Clear any previous evaluated data. */
|
||||
if (ob->runtime.gpencil_tot_layers > 0) {
|
||||
for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) {
|
||||
bGPDframe *gpf_eval = &ob->runtime.gpencil_evaluated_frames[i];
|
||||
BKE_gpencil_free_frame_runtime_data(gpf_eval);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create array of evaluated frames equal to number of layers. */
|
||||
ob->runtime.gpencil_tot_layers = BLI_listbase_count(&gpd->layers);
|
||||
CLAMP_MIN(ob->runtime.gpencil_tot_layers, 1);
|
||||
if (ob->runtime.gpencil_evaluated_frames == NULL) {
|
||||
ob->runtime.gpencil_evaluated_frames = MEM_callocN(
|
||||
sizeof(struct bGPDframe) * ob->runtime.gpencil_tot_layers, __func__);
|
||||
}
|
||||
else {
|
||||
ob->runtime.gpencil_evaluated_frames = MEM_recallocN(ob->runtime.gpencil_evaluated_frames,
|
||||
sizeof(struct bGPDframe) *
|
||||
ob->runtime.gpencil_tot_layers);
|
||||
const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
|
||||
(!GPENCIL_SIMPLIFY_MODIF(scene)));
|
||||
if (!do_modifiers) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init general modifiers data. */
|
||||
if (ob->greasepencil_modifiers.first) {
|
||||
BKE_gpencil_lattice_init(ob);
|
||||
}
|
||||
BKE_gpencil_lattice_init(ob);
|
||||
|
||||
/* *****************************************************************
|
||||
* Loop all layers, duplicate data and apply modifiers.
|
||||
*
|
||||
* ******************************************************************/
|
||||
int idx = 0;
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
/* Remap frame (Time modifier) */
|
||||
int remap_cfra = cfra_eval;
|
||||
if ((time_remap) && (!simplify_modif)) {
|
||||
remap_cfra = BKE_gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
|
||||
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
|
||||
|
||||
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||
|
||||
if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
|
||||
const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
|
||||
|
||||
if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Apply geometry modifiers (add new geometry). */
|
||||
if (mti && mti->generateStrokes) {
|
||||
mti->generateStrokes(md, depsgraph, ob);
|
||||
}
|
||||
|
||||
/* Apply deform modifiers and Time remap (only change geometry). */
|
||||
if ((time_remap) || (mti && mti->deformStroke)) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
|
||||
if (gpf == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti->deformStroke) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
mti->deformStroke(md, depsgraph, ob, gpl, gpf, gps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
|
||||
|
||||
if (gpf == NULL) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create a duplicate data set of stroke to modify. */
|
||||
bGPDframe *gpf_eval = NULL;
|
||||
gpencil_evaluated_frame_ensure(idx, ob, gpf, &gpf_eval);
|
||||
|
||||
/* Skip all if some disable flag is enabled. */
|
||||
if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Apply geometry modifiers (create new geometry). */
|
||||
if (BKE_gpencil_has_geometry_modifiers(ob)) {
|
||||
BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, gpf_eval, is_render);
|
||||
}
|
||||
|
||||
/* Loop all strokes and deform them. */
|
||||
for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps->next) {
|
||||
/* Apply modifiers that only deform geometry */
|
||||
BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, gpf_eval, gps, is_render);
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Clear any lattice data. */
|
||||
if (ob->greasepencil_modifiers.first) {
|
||||
BKE_gpencil_lattice_clear(ob);
|
||||
}
|
||||
BKE_gpencil_lattice_clear(ob);
|
||||
}
|
||||
|
||||
@@ -738,6 +738,15 @@ static void library_foreach_ID_link(Main *bmain,
|
||||
if (toolsett->gp_paint) {
|
||||
library_foreach_paint(&data, &toolsett->gp_paint->paint);
|
||||
}
|
||||
if (toolsett->gp_vertexpaint) {
|
||||
library_foreach_paint(&data, &toolsett->gp_vertexpaint->paint);
|
||||
}
|
||||
if (toolsett->gp_sculptpaint) {
|
||||
library_foreach_paint(&data, &toolsett->gp_sculptpaint->paint);
|
||||
}
|
||||
if (toolsett->gp_weightpaint) {
|
||||
library_foreach_paint(&data, &toolsett->gp_weightpaint->paint);
|
||||
}
|
||||
|
||||
CALLBACK_INVOKE(toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP);
|
||||
}
|
||||
|
||||
@@ -168,15 +168,12 @@ void BKE_gpencil_material_attr_init(Material *ma)
|
||||
/* set basic settings */
|
||||
gp_style->stroke_rgba[3] = 1.0f;
|
||||
gp_style->fill_rgba[3] = 1.0f;
|
||||
gp_style->pattern_gridsize = 0.1f;
|
||||
gp_style->gradient_radius = 0.5f;
|
||||
ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f);
|
||||
ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f);
|
||||
ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
|
||||
gp_style->texture_opacity = 1.0f;
|
||||
gp_style->texture_pixsize = 100.0f;
|
||||
|
||||
gp_style->flag |= GP_STYLE_STROKE_SHOW;
|
||||
gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -729,8 +729,11 @@ void BKE_object_free_derived_caches(Object *ob)
|
||||
BKE_object_to_mesh_clear(ob);
|
||||
BKE_object_free_curve_cache(ob);
|
||||
|
||||
/* clear grease pencil data */
|
||||
DRW_gpencil_freecache(ob);
|
||||
/* Clear grease pencil data. */
|
||||
if (ob->runtime.gpd_eval != NULL) {
|
||||
BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
|
||||
ob->runtime.gpd_eval = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_free_caches(Object *object)
|
||||
@@ -803,6 +806,9 @@ bool BKE_object_is_in_editmode(const Object *ob)
|
||||
case OB_SURF:
|
||||
case OB_CURVE:
|
||||
return ((Curve *)ob->data)->editnurb != NULL;
|
||||
case OB_GPENCIL:
|
||||
/* Grease Pencil object has no edit mode data. */
|
||||
return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1034,6 +1040,10 @@ static void object_init(Object *ob, const short ob_type)
|
||||
ob->trackflag = OB_NEGZ;
|
||||
ob->upflag = OB_POSY;
|
||||
}
|
||||
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
ob->dtx |= OB_USE_GPENCIL_LIGHTS;
|
||||
}
|
||||
}
|
||||
|
||||
void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
|
||||
@@ -3963,7 +3973,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
|
||||
runtime->data_eval = NULL;
|
||||
runtime->mesh_deform_eval = NULL;
|
||||
runtime->curve_cache = NULL;
|
||||
runtime->gpencil_cache = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_collection_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
@@ -150,6 +151,11 @@ void BKE_object_eval_transform_final(Depsgraph *depsgraph, Object *ob)
|
||||
else {
|
||||
ob->transflag &= ~OB_NEG_SCALE;
|
||||
}
|
||||
|
||||
/* Assign evaluated version. */
|
||||
if ((ob->type == OB_GPENCIL) && (ob->runtime.gpd_eval != NULL)) {
|
||||
ob->data = ob->runtime.gpd_eval;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
@@ -213,9 +219,12 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
|
||||
case OB_LATTICE:
|
||||
BKE_lattice_modifiers_calc(depsgraph, scene, ob);
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL: {
|
||||
BKE_gpencil_prepare_eval_data(depsgraph, scene, ob);
|
||||
BKE_gpencil_modifiers_calc(depsgraph, scene, ob);
|
||||
BKE_gpencil_update_layer_parent(depsgraph, ob);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* particles */
|
||||
|
||||
@@ -215,6 +215,15 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
|
||||
case PAINT_MODE_GPENCIL:
|
||||
paint_ptr = (Paint **)&ts->gp_paint;
|
||||
break;
|
||||
case PAINT_MODE_VERTEX_GPENCIL:
|
||||
paint_ptr = (Paint **)&ts->gp_vertexpaint;
|
||||
break;
|
||||
case PAINT_MODE_SCULPT_GPENCIL:
|
||||
paint_ptr = (Paint **)&ts->gp_sculptpaint;
|
||||
break;
|
||||
case PAINT_MODE_WEIGHT_GPENCIL:
|
||||
paint_ptr = (Paint **)&ts->gp_weightpaint;
|
||||
break;
|
||||
case PAINT_MODE_INVALID:
|
||||
break;
|
||||
}
|
||||
@@ -244,6 +253,12 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
|
||||
return &ts->uvsculpt->paint;
|
||||
case PAINT_MODE_GPENCIL:
|
||||
return &ts->gp_paint->paint;
|
||||
case PAINT_MODE_VERTEX_GPENCIL:
|
||||
return &ts->gp_vertexpaint->paint;
|
||||
case PAINT_MODE_SCULPT_GPENCIL:
|
||||
return &ts->gp_sculptpaint->paint;
|
||||
case PAINT_MODE_WEIGHT_GPENCIL:
|
||||
return &ts->gp_weightpaint->paint;
|
||||
case PAINT_MODE_INVALID:
|
||||
return NULL;
|
||||
default:
|
||||
@@ -270,6 +285,12 @@ const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
|
||||
return rna_enum_brush_uv_sculpt_tool_items;
|
||||
case PAINT_MODE_GPENCIL:
|
||||
return rna_enum_brush_gpencil_types_items;
|
||||
case PAINT_MODE_VERTEX_GPENCIL:
|
||||
return rna_enum_brush_gpencil_vertex_types_items;
|
||||
case PAINT_MODE_SCULPT_GPENCIL:
|
||||
return rna_enum_brush_gpencil_sculpt_types_items;
|
||||
case PAINT_MODE_WEIGHT_GPENCIL:
|
||||
return rna_enum_brush_gpencil_weight_types_items;
|
||||
case PAINT_MODE_INVALID:
|
||||
break;
|
||||
}
|
||||
@@ -292,6 +313,12 @@ const char *BKE_paint_get_tool_prop_id_from_paintmode(ePaintMode mode)
|
||||
return "uv_sculpt_tool";
|
||||
case PAINT_MODE_GPENCIL:
|
||||
return "gpencil_tool";
|
||||
case PAINT_MODE_VERTEX_GPENCIL:
|
||||
return "gpencil_vertex_tool";
|
||||
case PAINT_MODE_SCULPT_GPENCIL:
|
||||
return "gpencil_sculpt_tool";
|
||||
case PAINT_MODE_WEIGHT_GPENCIL:
|
||||
return "gpencil_weight_tool";
|
||||
default:
|
||||
/* invalid paint mode */
|
||||
return NULL;
|
||||
@@ -315,6 +342,12 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
|
||||
return &ts->imapaint.paint;
|
||||
case OB_MODE_PAINT_GPENCIL:
|
||||
return &ts->gp_paint->paint;
|
||||
case OB_MODE_VERTEX_GPENCIL:
|
||||
return &ts->gp_vertexpaint->paint;
|
||||
case OB_MODE_SCULPT_GPENCIL:
|
||||
return &ts->gp_sculptpaint->paint;
|
||||
case OB_MODE_WEIGHT_GPENCIL:
|
||||
return &ts->gp_weightpaint->paint;
|
||||
case OB_MODE_EDIT:
|
||||
return &ts->uvsculpt->paint;
|
||||
default:
|
||||
@@ -429,6 +462,12 @@ ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref)
|
||||
return PAINT_MODE_GPENCIL;
|
||||
case CTX_MODE_PAINT_TEXTURE:
|
||||
return PAINT_MODE_TEXTURE_3D;
|
||||
case CTX_MODE_VERTEX_GPENCIL:
|
||||
return PAINT_MODE_VERTEX_GPENCIL;
|
||||
case CTX_MODE_SCULPT_GPENCIL:
|
||||
return PAINT_MODE_SCULPT_GPENCIL;
|
||||
case CTX_MODE_WEIGHT_GPENCIL:
|
||||
return PAINT_MODE_WEIGHT_GPENCIL;
|
||||
}
|
||||
}
|
||||
else if (tref->space_type == SPACE_IMAGE) {
|
||||
@@ -485,6 +524,18 @@ void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
|
||||
paint->runtime.tool_offset = offsetof(Brush, gpencil_tool);
|
||||
paint->runtime.ob_mode = OB_MODE_PAINT_GPENCIL;
|
||||
}
|
||||
else if (paint == &ts->gp_vertexpaint->paint) {
|
||||
paint->runtime.tool_offset = offsetof(Brush, gpencil_vertex_tool);
|
||||
paint->runtime.ob_mode = OB_MODE_VERTEX_GPENCIL;
|
||||
}
|
||||
else if (paint == &ts->gp_sculptpaint->paint) {
|
||||
paint->runtime.tool_offset = offsetof(Brush, gpencil_sculpt_tool);
|
||||
paint->runtime.ob_mode = OB_MODE_SCULPT_GPENCIL;
|
||||
}
|
||||
else if (paint == &ts->gp_weightpaint->paint) {
|
||||
paint->runtime.tool_offset = offsetof(Brush, gpencil_weight_tool);
|
||||
paint->runtime.ob_mode = OB_MODE_WEIGHT_GPENCIL;
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
}
|
||||
@@ -506,6 +557,12 @@ uint BKE_paint_get_brush_tool_offset_from_paintmode(const ePaintMode mode)
|
||||
return offsetof(Brush, uv_sculpt_tool);
|
||||
case PAINT_MODE_GPENCIL:
|
||||
return offsetof(Brush, gpencil_tool);
|
||||
case PAINT_MODE_VERTEX_GPENCIL:
|
||||
return offsetof(Brush, gpencil_vertex_tool);
|
||||
case PAINT_MODE_SCULPT_GPENCIL:
|
||||
return offsetof(Brush, gpencil_sculpt_tool);
|
||||
case PAINT_MODE_WEIGHT_GPENCIL:
|
||||
return offsetof(Brush, gpencil_weight_tool);
|
||||
case PAINT_MODE_INVALID:
|
||||
break; /* We don't use these yet. */
|
||||
}
|
||||
@@ -639,6 +696,204 @@ bool BKE_palette_is_empty(const struct Palette *palette)
|
||||
return BLI_listbase_is_empty(&palette->colors);
|
||||
}
|
||||
|
||||
/* helper function to sort using qsort */
|
||||
static int palettecolor_compare_hsv(const void *a1, const void *a2)
|
||||
{
|
||||
const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
|
||||
|
||||
/* Hue */
|
||||
if (ps1->h > ps2->h) {
|
||||
return 1;
|
||||
}
|
||||
else if (ps1->h < ps2->h) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Saturation. */
|
||||
if (ps1->s > ps2->s) {
|
||||
return 1;
|
||||
}
|
||||
else if (ps1->s < ps2->s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Value. */
|
||||
if (1.0f - ps1->v > 1.0f - ps2->v) {
|
||||
return 1;
|
||||
}
|
||||
else if (1.0f - ps1->v < 1.0f - ps2->v) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function to sort using qsort */
|
||||
static int palettecolor_compare_svh(const void *a1, const void *a2)
|
||||
{
|
||||
const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
|
||||
|
||||
/* Saturation. */
|
||||
if (ps1->s > ps2->s) {
|
||||
return 1;
|
||||
}
|
||||
else if (ps1->s < ps2->s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Value. */
|
||||
if (1.0f - ps1->v > 1.0f - ps2->v) {
|
||||
return 1;
|
||||
}
|
||||
else if (1.0f - ps1->v < 1.0f - ps2->v) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Hue */
|
||||
if (ps1->h > ps2->h) {
|
||||
return 1;
|
||||
}
|
||||
else if (ps1->h < ps2->h) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int palettecolor_compare_vhs(const void *a1, const void *a2)
|
||||
{
|
||||
const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
|
||||
|
||||
/* Value. */
|
||||
if (1.0f - ps1->v > 1.0f - ps2->v) {
|
||||
return 1;
|
||||
}
|
||||
else if (1.0f - ps1->v < 1.0f - ps2->v) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Hue */
|
||||
if (ps1->h > ps2->h) {
|
||||
return 1;
|
||||
}
|
||||
else if (ps1->h < ps2->h) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Saturation. */
|
||||
if (ps1->s > ps2->s) {
|
||||
return 1;
|
||||
}
|
||||
else if (ps1->s < ps2->s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int palettecolor_compare_luminance(const void *a1, const void *a2)
|
||||
{
|
||||
const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
|
||||
|
||||
float lumi1 = (ps1->rgb[0] + ps1->rgb[1] + ps1->rgb[2]) / 3.0f;
|
||||
float lumi2 = (ps2->rgb[0] + ps2->rgb[1] + ps2->rgb[2]) / 3.0f;
|
||||
|
||||
if (lumi1 > lumi2) {
|
||||
return -1;
|
||||
}
|
||||
else if (lumi1 < lumi2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BKE_palette_sort_hsv(tPaletteColorHSV *color_array, const int totcol)
|
||||
{
|
||||
/* Sort by Hue , Saturation and Value. */
|
||||
qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_hsv);
|
||||
}
|
||||
|
||||
void BKE_palette_sort_svh(tPaletteColorHSV *color_array, const int totcol)
|
||||
{
|
||||
/* Sort by Saturation, Value and Hue. */
|
||||
qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_svh);
|
||||
}
|
||||
|
||||
void BKE_palette_sort_vhs(tPaletteColorHSV *color_array, const int totcol)
|
||||
{
|
||||
/* Sort by Saturation, Value and Hue. */
|
||||
qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_vhs);
|
||||
}
|
||||
|
||||
void BKE_palette_sort_luminance(tPaletteColorHSV *color_array, const int totcol)
|
||||
{
|
||||
/* Sort by Luminance (calculated with the average, enough for sorting). */
|
||||
qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_luminance);
|
||||
}
|
||||
|
||||
bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name, const bool linear)
|
||||
{
|
||||
tPaletteColorHSV *color_array = NULL;
|
||||
tPaletteColorHSV *col_elm = NULL;
|
||||
bool done = false;
|
||||
|
||||
const int totpal = BLI_ghash_len(color_table);
|
||||
|
||||
if (totpal > 0) {
|
||||
color_array = MEM_calloc_arrayN(totpal, sizeof(tPaletteColorHSV), __func__);
|
||||
/* Put all colors in an array. */
|
||||
GHashIterator gh_iter;
|
||||
int t = 0;
|
||||
GHASH_ITER (gh_iter, color_table) {
|
||||
const uint col = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
|
||||
float r, g, b;
|
||||
float h, s, v;
|
||||
cpack_to_rgb(col, &r, &g, &b);
|
||||
rgb_to_hsv(r, g, b, &h, &s, &v);
|
||||
|
||||
col_elm = &color_array[t];
|
||||
col_elm->rgb[0] = r;
|
||||
col_elm->rgb[1] = g;
|
||||
col_elm->rgb[2] = b;
|
||||
col_elm->h = h;
|
||||
col_elm->s = s;
|
||||
col_elm->v = v;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the Palette. */
|
||||
if (totpal > 0) {
|
||||
/* Sort by Hue and saturation. */
|
||||
BKE_palette_sort_hsv(color_array, totpal);
|
||||
|
||||
Palette *palette = BKE_palette_add(bmain, name);
|
||||
if (palette) {
|
||||
for (int i = 0; i < totpal; i++) {
|
||||
col_elm = &color_array[i];
|
||||
PaletteColor *palcol = BKE_palette_color_add(palette);
|
||||
if (palcol) {
|
||||
copy_v3_v3(palcol->rgb, col_elm->rgb);
|
||||
if (linear) {
|
||||
linearrgb_to_srgb_v3_v3(palcol->rgb, palcol->rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
done = false;
|
||||
}
|
||||
|
||||
if (totpal > 0) {
|
||||
MEM_SAFE_FREE(color_array);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
/* are we in vertex paint or weight paint face select mode? */
|
||||
bool BKE_paint_select_face_test(Object *ob)
|
||||
{
|
||||
@@ -720,6 +975,9 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
|
||||
BLI_assert(ELEM(*r_paint,
|
||||
/* Cast is annoying, but prevent NULL-pointer access. */
|
||||
(Paint *)ts->gp_paint,
|
||||
(Paint *)ts->gp_vertexpaint,
|
||||
(Paint *)ts->gp_sculptpaint,
|
||||
(Paint *)ts->gp_weightpaint,
|
||||
(Paint *)ts->sculpt,
|
||||
(Paint *)ts->vpaint,
|
||||
(Paint *)ts->wpaint,
|
||||
@@ -755,6 +1013,18 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
|
||||
GpPaint *data = MEM_callocN(sizeof(*data), __func__);
|
||||
paint = &data->paint;
|
||||
}
|
||||
else if ((GpVertexPaint **)r_paint == &ts->gp_vertexpaint) {
|
||||
GpVertexPaint *data = MEM_callocN(sizeof(*data), __func__);
|
||||
paint = &data->paint;
|
||||
}
|
||||
else if ((GpSculptPaint **)r_paint == &ts->gp_sculptpaint) {
|
||||
GpSculptPaint *data = MEM_callocN(sizeof(*data), __func__);
|
||||
paint = &data->paint;
|
||||
}
|
||||
else if ((GpWeightPaint **)r_paint == &ts->gp_weightpaint) {
|
||||
GpWeightPaint *data = MEM_callocN(sizeof(*data), __func__);
|
||||
paint = &data->paint;
|
||||
}
|
||||
else if ((UvSculpt **)r_paint == &ts->uvsculpt) {
|
||||
UvSculpt *data = MEM_callocN(sizeof(*data), __func__);
|
||||
paint = &data->paint;
|
||||
|
||||
@@ -82,6 +82,15 @@ void BKE_paint_toolslots_init_from_main(struct Main *bmain)
|
||||
if (ts->gp_paint) {
|
||||
paint_toolslots_init(bmain, &ts->gp_paint->paint);
|
||||
}
|
||||
if (ts->gp_vertexpaint) {
|
||||
paint_toolslots_init(bmain, &ts->gp_vertexpaint->paint);
|
||||
}
|
||||
if (ts->gp_sculptpaint) {
|
||||
paint_toolslots_init(bmain, &ts->gp_sculptpaint->paint);
|
||||
}
|
||||
if (ts->gp_weightpaint) {
|
||||
paint_toolslots_init(bmain, &ts->gp_weightpaint->paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,72 +201,6 @@ static void scene_init_data(ID *id)
|
||||
BKE_color_managed_view_settings_init_render(
|
||||
&scene->r.bake.im_format.view_settings, &scene->r.bake.im_format.display_settings, "Filmic");
|
||||
|
||||
/* GP Sculpt brushes */
|
||||
{
|
||||
GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
|
||||
GP_Sculpt_Data *gp_brush;
|
||||
float curcolor_add[3], curcolor_sub[3];
|
||||
ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
|
||||
ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
|
||||
gp_brush->size = 25;
|
||||
gp_brush->strength = 0.3f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_SMOOTH_PRESSURE |
|
||||
GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_THICKNESS];
|
||||
gp_brush->size = 25;
|
||||
gp_brush->strength = 0.5f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_STRENGTH];
|
||||
gp_brush->size = 25;
|
||||
gp_brush->strength = 0.5f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_GRAB];
|
||||
gp_brush->size = 50;
|
||||
gp_brush->strength = 0.3f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_PUSH];
|
||||
gp_brush->size = 25;
|
||||
gp_brush->strength = 0.3f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_TWIST];
|
||||
gp_brush->size = 50;
|
||||
gp_brush->strength = 0.3f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_PINCH];
|
||||
gp_brush->size = 50;
|
||||
gp_brush->strength = 0.5f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
|
||||
gp_brush = &gset->brush[GP_SCULPT_TYPE_RANDOMIZE];
|
||||
gp_brush->size = 25;
|
||||
gp_brush->strength = 0.5f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
}
|
||||
|
||||
/* Curve Profile */
|
||||
scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
|
||||
|
||||
@@ -560,6 +494,18 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
|
||||
ts->gp_paint = MEM_dupallocN(ts->gp_paint);
|
||||
BKE_paint_copy(&ts->gp_paint->paint, &ts->gp_paint->paint, flag);
|
||||
}
|
||||
if (ts->gp_vertexpaint) {
|
||||
ts->gp_vertexpaint = MEM_dupallocN(ts->gp_vertexpaint);
|
||||
BKE_paint_copy(&ts->gp_vertexpaint->paint, &ts->gp_vertexpaint->paint, flag);
|
||||
}
|
||||
if (ts->gp_sculptpaint) {
|
||||
ts->gp_sculptpaint = MEM_dupallocN(ts->gp_sculptpaint);
|
||||
BKE_paint_copy(&ts->gp_sculptpaint->paint, &ts->gp_sculptpaint->paint, flag);
|
||||
}
|
||||
if (ts->gp_weightpaint) {
|
||||
ts->gp_weightpaint = MEM_dupallocN(ts->gp_weightpaint);
|
||||
BKE_paint_copy(&ts->gp_weightpaint->paint, &ts->gp_weightpaint->paint, flag);
|
||||
}
|
||||
|
||||
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
|
||||
ts->imapaint.paintcursor = NULL;
|
||||
@@ -602,6 +548,18 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
|
||||
BKE_paint_free(&toolsettings->gp_paint->paint);
|
||||
MEM_freeN(toolsettings->gp_paint);
|
||||
}
|
||||
if (toolsettings->gp_vertexpaint) {
|
||||
BKE_paint_free(&toolsettings->gp_vertexpaint->paint);
|
||||
MEM_freeN(toolsettings->gp_vertexpaint);
|
||||
}
|
||||
if (toolsettings->gp_sculptpaint) {
|
||||
BKE_paint_free(&toolsettings->gp_sculptpaint->paint);
|
||||
MEM_freeN(toolsettings->gp_sculptpaint);
|
||||
}
|
||||
if (toolsettings->gp_weightpaint) {
|
||||
BKE_paint_free(&toolsettings->gp_weightpaint->paint);
|
||||
MEM_freeN(toolsettings->gp_weightpaint);
|
||||
}
|
||||
BKE_paint_free(&toolsettings->imapaint.paint);
|
||||
|
||||
/* free Grease Pencil interpolation curve */
|
||||
|
||||
@@ -81,7 +81,16 @@ BLI_memblock *BLI_memblock_create_ex(uint elem_size, uint chunk_size)
|
||||
|
||||
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback)
|
||||
{
|
||||
BLI_memblock_clear(mblk, free_callback);
|
||||
int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
|
||||
|
||||
if (free_callback) {
|
||||
for (int i = 0; i <= mblk->elem_last; i++) {
|
||||
int chunk_idx = i / elem_per_chunk;
|
||||
int elem_idx = i - elem_per_chunk * chunk_idx;
|
||||
void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
|
||||
free_callback(val);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mblk->chunk_len; i++) {
|
||||
MEM_SAFE_FREE(mblk->chunk_list[i]);
|
||||
|
||||
@@ -3609,23 +3609,23 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ntree->previews) {
|
||||
bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
|
||||
bNodeInstanceHashIterator iter;
|
||||
if (ntree->previews) {
|
||||
bNodeInstanceHash* new_previews = BKE_node_instance_hash_new("node previews");
|
||||
bNodeInstanceHashIterator iter;
|
||||
|
||||
NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
|
||||
bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
|
||||
if (preview) {
|
||||
bNodePreview *new_preview = newimaadr(fd, preview);
|
||||
if (new_preview) {
|
||||
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
|
||||
BKE_node_instance_hash_insert(new_previews, key, new_preview);
|
||||
}
|
||||
}
|
||||
}
|
||||
BKE_node_instance_hash_free(ntree->previews, NULL);
|
||||
ntree->previews = new_previews;
|
||||
}
|
||||
NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
|
||||
bNodePreview* preview = BKE_node_instance_hash_iterator_get_value(&iter);
|
||||
if (preview) {
|
||||
bNodePreview* new_preview = newimaadr(fd, preview);
|
||||
if (new_preview) {
|
||||
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
|
||||
BKE_node_instance_hash_insert(new_previews, key, new_preview);
|
||||
}
|
||||
}
|
||||
}
|
||||
BKE_node_instance_hash_free(ntree->previews, NULL);
|
||||
ntree->previews = new_previews;
|
||||
}
|
||||
#else
|
||||
/* XXX TODO */
|
||||
ntree->previews = NULL;
|
||||
@@ -4084,10 +4084,10 @@ static void direct_link_text(FileData *fd, Text *text)
|
||||
text->compiled = NULL;
|
||||
|
||||
#if 0
|
||||
if (text->flags & TXT_ISEXT) {
|
||||
BKE_text_reload(text);
|
||||
}
|
||||
/* else { */
|
||||
if (text->flags & TXT_ISEXT) {
|
||||
BKE_text_reload(text);
|
||||
}
|
||||
/* else { */
|
||||
#endif
|
||||
|
||||
link_list(fd, &text->lines);
|
||||
@@ -5071,7 +5071,7 @@ static void lib_link_object(FileData *fd, Main *bmain, Object *ob)
|
||||
* some leaked memory rather then crashing immediately
|
||||
* while bad this _is_ an exceptional case - campbell */
|
||||
#if 0
|
||||
BKE_pose_free(ob->pose);
|
||||
BKE_pose_free(ob->pose);
|
||||
#else
|
||||
MEM_freeN(ob->pose);
|
||||
#endif
|
||||
@@ -5540,15 +5540,15 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, Object *ob)
|
||||
else if (md->type == eModifierType_Collision) {
|
||||
CollisionModifierData *collmd = (CollisionModifierData *)md;
|
||||
#if 0
|
||||
// TODO: CollisionModifier should use pointcache
|
||||
// + have proper reset events before enabling this
|
||||
collmd->x = newdataadr(fd, collmd->x);
|
||||
collmd->xnew = newdataadr(fd, collmd->xnew);
|
||||
collmd->mfaces = newdataadr(fd, collmd->mfaces);
|
||||
// TODO: CollisionModifier should use pointcache
|
||||
// + have proper reset events before enabling this
|
||||
collmd->x = newdataadr(fd, collmd->x);
|
||||
collmd->xnew = newdataadr(fd, collmd->xnew);
|
||||
collmd->mfaces = newdataadr(fd, collmd->mfaces);
|
||||
|
||||
collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
|
||||
collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
|
||||
collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
|
||||
collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
|
||||
collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
|
||||
collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
|
||||
#endif
|
||||
|
||||
collmd->x = NULL;
|
||||
@@ -5752,16 +5752,66 @@ static void direct_link_gpencil_modifiers(FileData *fd, ListBase *lb)
|
||||
direct_link_curvemapping(fd, hmd->curfalloff);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Noise) {
|
||||
NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
|
||||
|
||||
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
|
||||
if (gpmd->curve_intensity) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_intensity);
|
||||
/* initialize the curve. Maybe this could be moved to modififer logic */
|
||||
BKE_curvemapping_initialize(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Thick) {
|
||||
ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
|
||||
|
||||
gpmd->curve_thickness = newdataadr(fd, gpmd->curve_thickness);
|
||||
if (gpmd->curve_thickness) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_thickness);
|
||||
/* initialize the curve. Maybe this could be moved to modififer logic */
|
||||
BKE_curvemapping_initialize(gpmd->curve_thickness);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Vertexcolor) {
|
||||
VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
|
||||
gpmd->colorband = newdataadr(fd, gpmd->colorband);
|
||||
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
|
||||
if (gpmd->curve_intensity) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_intensity);
|
||||
BKE_curvemapping_initialize(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Smooth) {
|
||||
SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
|
||||
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
|
||||
if (gpmd->curve_intensity) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_intensity);
|
||||
BKE_curvemapping_initialize(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Color) {
|
||||
ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
|
||||
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
|
||||
if (gpmd->curve_intensity) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_intensity);
|
||||
BKE_curvemapping_initialize(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Tint) {
|
||||
TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
|
||||
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
|
||||
if (gpmd->curve_intensity) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_intensity);
|
||||
BKE_curvemapping_initialize(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Opacity) {
|
||||
OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
|
||||
gpmd->curve_intensity = newdataadr(fd, gpmd->curve_intensity);
|
||||
if (gpmd->curve_intensity) {
|
||||
direct_link_curvemapping(fd, gpmd->curve_intensity);
|
||||
BKE_curvemapping_initialize(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6333,6 +6383,15 @@ static void lib_link_scene(FileData *fd, Main *UNUSED(bmain), Scene *sce)
|
||||
if (sce->toolsettings->gp_paint) {
|
||||
link_paint(fd, sce, &sce->toolsettings->gp_paint->paint);
|
||||
}
|
||||
if (sce->toolsettings->gp_vertexpaint) {
|
||||
link_paint(fd, sce, &sce->toolsettings->gp_vertexpaint->paint);
|
||||
}
|
||||
if (sce->toolsettings->gp_sculptpaint) {
|
||||
link_paint(fd, sce, &sce->toolsettings->gp_sculptpaint->paint);
|
||||
}
|
||||
if (sce->toolsettings->gp_weightpaint) {
|
||||
link_paint(fd, sce, &sce->toolsettings->gp_weightpaint->paint);
|
||||
}
|
||||
|
||||
if (sce->toolsettings->sculpt) {
|
||||
sce->toolsettings->sculpt->gravity_object = newlibadr(
|
||||
@@ -6615,6 +6674,9 @@ static void direct_link_scene(FileData *fd, Scene *sce)
|
||||
direct_link_paint_helper(fd, sce, (Paint **)&sce->toolsettings->wpaint);
|
||||
direct_link_paint_helper(fd, sce, (Paint **)&sce->toolsettings->uvsculpt);
|
||||
direct_link_paint_helper(fd, sce, (Paint **)&sce->toolsettings->gp_paint);
|
||||
direct_link_paint_helper(fd, sce, (Paint **)&sce->toolsettings->gp_vertexpaint);
|
||||
direct_link_paint_helper(fd, sce, (Paint **)&sce->toolsettings->gp_sculptpaint);
|
||||
direct_link_paint_helper(fd, sce, (Paint **)&sce->toolsettings->gp_weightpaint);
|
||||
|
||||
direct_link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
|
||||
|
||||
@@ -6895,7 +6957,7 @@ static void lib_link_gpencil(FileData *fd, Main *UNUSED(bmain), bGPdata *gpd)
|
||||
{
|
||||
/* Relink all data-lock linked by GP data-lock */
|
||||
/* Layers */
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* Layer -> Parent References */
|
||||
gpl->parent = newlibadr(fd, gpd->id.lib, gpl->parent);
|
||||
}
|
||||
@@ -6909,9 +6971,6 @@ static void lib_link_gpencil(FileData *fd, Main *UNUSED(bmain), bGPdata *gpd)
|
||||
/* relinks grease-pencil data - used for direct_link and old file linkage */
|
||||
static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
|
||||
{
|
||||
bGPDlayer *gpl;
|
||||
bGPDframe *gpf;
|
||||
bGPDstroke *gps;
|
||||
bGPDpalette *palette;
|
||||
|
||||
/* we must firstly have some grease-pencil data to link! */
|
||||
@@ -6929,6 +6988,7 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
|
||||
gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
|
||||
gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
|
||||
gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
|
||||
gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
|
||||
}
|
||||
|
||||
/* init stroke buffer */
|
||||
@@ -6952,7 +7012,7 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
|
||||
/* relink layers */
|
||||
link_list(fd, &gpd->layers);
|
||||
|
||||
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* relink frames */
|
||||
link_list(fd, &gpl->frames);
|
||||
|
||||
@@ -6960,24 +7020,24 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
|
||||
|
||||
gpl->runtime.icon_id = 0;
|
||||
|
||||
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
|
||||
/* Relink masks. */
|
||||
link_list(fd, &gpl->mask_layers);
|
||||
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
||||
/* relink strokes (and their points) */
|
||||
link_list(fd, &gpf->strokes);
|
||||
|
||||
for (gps = gpf->strokes.first; gps; gps = gps->next) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
/* relink stroke points array */
|
||||
gps->points = newdataadr(fd, gps->points);
|
||||
/* Relink geometry*/
|
||||
gps->triangles = newdataadr(fd, gps->triangles);
|
||||
|
||||
/* relink weight data */
|
||||
if (gps->dvert) {
|
||||
gps->dvert = newdataadr(fd, gps->dvert);
|
||||
direct_link_dverts(fd, gps->totpoints, gps->dvert);
|
||||
}
|
||||
|
||||
/* the triangulation is not saved, so need to be recalculated */
|
||||
gps->triangles = NULL;
|
||||
gps->tot_triangles = 0;
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7198,10 +7258,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
|
||||
* so sacrifice a few old files for now to avoid crashes with new files!
|
||||
* committed: r28002 */
|
||||
#if 0
|
||||
sima->gpd = newdataadr(fd, sima->gpd);
|
||||
if (sima->gpd) {
|
||||
direct_link_gpencil(fd, sima->gpd);
|
||||
}
|
||||
sima->gpd = newdataadr(fd, sima->gpd);
|
||||
if (sima->gpd) {
|
||||
direct_link_gpencil(fd, sima->gpd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (sl->spacetype == SPACE_NODE) {
|
||||
@@ -7232,10 +7292,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
|
||||
* simple return NULL here (sergey)
|
||||
*/
|
||||
#if 0
|
||||
if (sseq->gpd) {
|
||||
sseq->gpd = newdataadr(fd, sseq->gpd);
|
||||
direct_link_gpencil(fd, sseq->gpd);
|
||||
}
|
||||
if (sseq->gpd) {
|
||||
sseq->gpd = newdataadr(fd, sseq->gpd);
|
||||
direct_link_gpencil(fd, sseq->gpd);
|
||||
}
|
||||
#endif
|
||||
sseq->scopes.reference_ibuf = NULL;
|
||||
sseq->scopes.zebra_ibuf = NULL;
|
||||
@@ -7906,11 +7966,11 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map,
|
||||
sima->iuser.scene = NULL;
|
||||
|
||||
#if 0
|
||||
/* Those are allocated and freed by space code, no need to handle them here. */
|
||||
MEM_SAFE_FREE(sima->scopes.waveform_1);
|
||||
MEM_SAFE_FREE(sima->scopes.waveform_2);
|
||||
MEM_SAFE_FREE(sima->scopes.waveform_3);
|
||||
MEM_SAFE_FREE(sima->scopes.vecscope);
|
||||
/* Those are allocated and freed by space code, no need to handle them here. */
|
||||
MEM_SAFE_FREE(sima->scopes.waveform_1);
|
||||
MEM_SAFE_FREE(sima->scopes.waveform_2);
|
||||
MEM_SAFE_FREE(sima->scopes.waveform_3);
|
||||
MEM_SAFE_FREE(sima->scopes.vecscope);
|
||||
#endif
|
||||
sima->scopes.ok = 0;
|
||||
|
||||
@@ -8281,8 +8341,8 @@ static void direct_link_speaker(FileData *fd, Speaker *spk)
|
||||
direct_link_animdata(fd, spk->adt);
|
||||
|
||||
#if 0
|
||||
spk->sound = newdataadr(fd, spk->sound);
|
||||
direct_link_sound(fd, spk->sound);
|
||||
spk->sound = newdataadr(fd, spk->sound);
|
||||
direct_link_sound(fd, spk->sound);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -8905,12 +8965,12 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *a
|
||||
while (bhead && bhead->code == DATA) {
|
||||
void *data;
|
||||
#if 0
|
||||
/* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
|
||||
short *sp = fd->filesdna->structs[bhead->SDNAnr];
|
||||
char *tmp = malloc(100);
|
||||
allocname = fd->filesdna->types[sp[0]];
|
||||
strcpy(tmp, allocname);
|
||||
data = read_struct(fd, bhead, tmp);
|
||||
/* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
|
||||
short* sp = fd->filesdna->structs[bhead->SDNAnr];
|
||||
char* tmp = malloc(100);
|
||||
allocname = fd->filesdna->types[sp[0]];
|
||||
strcpy(tmp, allocname);
|
||||
data = read_struct(fd, bhead, tmp);
|
||||
#else
|
||||
data = read_struct(fd, bhead, allocname);
|
||||
#endif
|
||||
@@ -9309,11 +9369,6 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
|
||||
user->walk_navigation.teleport_time = 0.2f; /* s */
|
||||
}
|
||||
|
||||
/* grease pencil multisamples */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "gpencil_multisamples")) {
|
||||
user->gpencil_multisamples = 4;
|
||||
}
|
||||
|
||||
/* tablet pressure threshold */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "float", "pressure_threshold_max")) {
|
||||
user->pressure_threshold_max = 1.0f;
|
||||
@@ -9722,7 +9777,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
|
||||
bhead = read_libblock(fd, libmain, bhead, 0, true, NULL);
|
||||
}
|
||||
break;
|
||||
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
|
||||
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
|
||||
case ID_SCRN:
|
||||
bhead->code = ID_SCR;
|
||||
/* pass on to default */
|
||||
@@ -9877,7 +9932,7 @@ static BHead *find_previous_lib(FileData *fd, BHead *bhead)
|
||||
static BHead *find_bhead(FileData *fd, void *old)
|
||||
{
|
||||
#if 0
|
||||
BHead *bhead;
|
||||
BHead* bhead;
|
||||
#endif
|
||||
struct BHeadSort *bhs, bhs_s;
|
||||
|
||||
@@ -9897,11 +9952,11 @@ static BHead *find_bhead(FileData *fd, void *old)
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
||||
if (bhead->old == old) {
|
||||
return bhead;
|
||||
}
|
||||
}
|
||||
for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
|
||||
if (bhead->old == old) {
|
||||
return bhead;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
@@ -10032,9 +10087,9 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
|
||||
|
||||
/* Commented because this can print way too much. */
|
||||
#if 0
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
|
||||
}
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -10870,7 +10925,7 @@ static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *li
|
||||
|
||||
static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
|
||||
{
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
expand_doit(fd, mainvar, gpl->parent);
|
||||
}
|
||||
|
||||
@@ -11813,9 +11868,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
|
||||
/* Does this library have any more linked data-blocks we need to read? */
|
||||
if (has_linked_ids_to_read(mainptr)) {
|
||||
#if 0
|
||||
printf("Reading linked data-blocks from %s (%s)\n",
|
||||
mainptr->curlib->id.name,
|
||||
mainptr->curlib->name);
|
||||
printf("Reading linked data-blocks from %s (%s)\n",
|
||||
mainptr->curlib->id.name,
|
||||
mainptr->curlib->name);
|
||||
#endif
|
||||
|
||||
/* Open file if it has not been done yet. */
|
||||
|
||||
@@ -1116,80 +1116,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 276, 4)) {
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
if (ts->gp_sculpt.brush[0].size == 0) {
|
||||
GP_Sculpt_Settings *gset = &ts->gp_sculpt;
|
||||
GP_Sculpt_Data *brush;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
|
||||
brush->size = 25;
|
||||
brush->strength = 0.3f;
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_SMOOTH_PRESSURE;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_THICKNESS];
|
||||
brush->size = 25;
|
||||
brush->strength = 0.5f;
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_GRAB];
|
||||
brush->size = 50;
|
||||
brush->strength = 0.3f;
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_PUSH];
|
||||
brush->size = 25;
|
||||
brush->strength = 0.3f;
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_TWIST];
|
||||
brush->size = 50;
|
||||
brush->strength = 0.3f; // XXX?
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_PINCH];
|
||||
brush->size = 50;
|
||||
brush->strength = 0.5f; // XXX?
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_RANDOMIZE];
|
||||
brush->size = 25;
|
||||
brush->strength = 0.5f;
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_CLONE];
|
||||
brush->size = 50;
|
||||
brush->strength = 1.0f;
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "gpencil_v3d_align")) {
|
||||
#if 0 /* XXX: Cannot do this, as we get random crashes... */
|
||||
if (scene->gpd) {
|
||||
bGPdata *gpd = scene->gpd;
|
||||
|
||||
/* Copy over the settings stored in the GP data-block linked to the scene,
|
||||
* for minimal disruption. */
|
||||
ts->gpencil_v3d_align = 0;
|
||||
|
||||
if (gpd->flag & GP_DATA_VIEWALIGN) {
|
||||
ts->gpencil_v3d_align |= GP_PROJECT_VIEWSPACE;
|
||||
}
|
||||
if (gpd->flag & GP_DATA_DEPTH_VIEW) {
|
||||
ts->gpencil_v3d_align |= GP_PROJECT_DEPTH_VIEW;
|
||||
}
|
||||
if (gpd->flag & GP_DATA_DEPTH_STROKE) {
|
||||
ts->gpencil_v3d_align |= GP_PROJECT_DEPTH_STROKE;
|
||||
}
|
||||
|
||||
if (gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) {
|
||||
ts->gpencil_v3d_align |= GP_PROJECT_DEPTH_STROKE_ENDPOINTS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Default to cursor for all standard 3D views */
|
||||
ts->gpencil_v3d_align = GP_PROJECT_VIEWSPACE;
|
||||
}
|
||||
#endif
|
||||
|
||||
ts->gpencil_v3d_align = GP_PROJECT_VIEWSPACE;
|
||||
ts->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
|
||||
ts->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
|
||||
@@ -1203,7 +1130,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
/* Ensure that the datablock's onion-skinning toggle flag
|
||||
* stays in sync with the status of the actual layers
|
||||
*/
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
if (gpl->flag & GP_LAYER_ONIONSKIN) {
|
||||
enabled = true;
|
||||
}
|
||||
@@ -1424,22 +1351,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 277, 3)) {
|
||||
/* ------- init of grease pencil initialization --------------- */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "bGPDpalettecolor", "*palcolor")) {
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
/* initialize use position for sculpt brushes */
|
||||
ts->gp_sculpt.flag |= GP_SCULPT_SETT_FLAG_APPLY_POSITION;
|
||||
|
||||
/* new strength sculpt brush */
|
||||
if (ts->gp_sculpt.brush[0].size >= 11) {
|
||||
GP_Sculpt_Settings *gset = &ts->gp_sculpt;
|
||||
GP_Sculpt_Data *brush;
|
||||
|
||||
brush = &gset->brush[GP_SCULPT_TYPE_STRENGTH];
|
||||
brush->size = 25;
|
||||
brush->strength = 0.5f;
|
||||
brush->flag = GP_SCULPT_FLAG_USE_FALLOFF;
|
||||
}
|
||||
}
|
||||
/* Convert Grease Pencil to new palettes/brushes
|
||||
* Loop all strokes and create the palette and all colors
|
||||
*/
|
||||
@@ -1447,7 +1358,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
if (BLI_listbase_is_empty(&gpd->palettes)) {
|
||||
/* create palette */
|
||||
bGPDpalette *palette = BKE_gpencil_palette_addnew(gpd, "GP_Palette");
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* create color using layer name */
|
||||
bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_addnew(palette, gpl->info);
|
||||
if (palcolor != NULL) {
|
||||
@@ -1475,8 +1386,8 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
ARRAY_SET_ITEMS(gpl->tintcolor, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
/* flush relevant layer-settings to strokes */
|
||||
for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
|
||||
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
/* set stroke to palette and force recalculation */
|
||||
BLI_strncpy(gps->colorname, gpl->info, sizeof(gps->colorname));
|
||||
gps->thickness = gpl->thickness;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_shader_fx_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_genfile.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
@@ -63,6 +64,7 @@
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_constraint.h"
|
||||
@@ -71,6 +73,8 @@
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_freestyle.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_gpencil_modifier.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_lib_id.h"
|
||||
@@ -573,7 +577,7 @@ static void do_versions_fix_annotations(bGPdata *gpd)
|
||||
for (const bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
|
||||
for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
|
||||
/* fix layers */
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* unlock/unhide layer */
|
||||
gpl->flag &= ~GP_LAYER_LOCKED;
|
||||
gpl->flag &= ~GP_LAYER_HIDE;
|
||||
@@ -582,8 +586,8 @@ static void do_versions_fix_annotations(bGPdata *gpd)
|
||||
/* disable tint */
|
||||
gpl->tintcolor[3] = 0.0f;
|
||||
|
||||
for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
|
||||
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
|
||||
/* copy color settings */
|
||||
copy_v4_v4(gpl->color, palcolor->color);
|
||||
@@ -1057,6 +1061,48 @@ static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMa
|
||||
callback(gpmd->curfalloff);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Noise) {
|
||||
NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
callback(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Vertexcolor) {
|
||||
VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
callback(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Smooth) {
|
||||
SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
callback(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Color) {
|
||||
ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
callback(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Opacity) {
|
||||
OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
callback(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Tint) {
|
||||
TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
callback(gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1554,7 +1600,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
|
||||
if (gpd == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
if (STREQ(gpl->info, "RulerData3D")) {
|
||||
gpl->flag |= GP_LAYER_IS_RULER;
|
||||
break;
|
||||
@@ -1588,6 +1634,34 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 282, 2)) {
|
||||
/* Init all Vertex/Sculpt and Weight Paint brushes. */
|
||||
Brush *brush = BLI_findstring(&bmain->brushes, "Pencil", offsetof(ID, name) + 2);
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
BKE_brush_gpencil_vertex_presets(bmain, ts);
|
||||
BKE_brush_gpencil_sculpt_presets(bmain, ts);
|
||||
BKE_brush_gpencil_weight_presets(bmain, ts);
|
||||
|
||||
/* Ensure new Paint modes. */
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_GPENCIL);
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL);
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL);
|
||||
|
||||
/* Set default Draw brush. */
|
||||
if (brush != NULL) {
|
||||
Paint *paint = &ts->gp_paint->paint;
|
||||
BKE_paint_brush_set(paint, brush);
|
||||
/* Enable cursor by default. */
|
||||
paint->flags |= PAINT_SHOW_BRUSH;
|
||||
}
|
||||
/* Ensure Palette by default. */
|
||||
BKE_gpencil_palette_ensure(bmain, scene);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
@@ -1774,36 +1848,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
#endif
|
||||
|
||||
{
|
||||
/* Grease pencil sculpt and paint cursors */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "GP_Sculpt_Settings", "int", "weighttype")) {
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
/* sculpt brushes */
|
||||
GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
|
||||
if (gset) {
|
||||
gset->weighttype = GP_SCULPT_TYPE_WEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
float curcolor_add[3], curcolor_sub[3];
|
||||
ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
|
||||
ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
|
||||
GP_Sculpt_Data *gp_brush;
|
||||
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
/* sculpt brushes */
|
||||
GP_Sculpt_Settings *gset = &ts->gp_sculpt;
|
||||
for (int i = 0; i < GP_SCULPT_TYPE_MAX; i++) {
|
||||
gp_brush = &gset->brush[i];
|
||||
gp_brush->flag |= GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Init grease pencil edit line color */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "float", "line_color[4]")) {
|
||||
for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
|
||||
@@ -1866,8 +1910,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
|
||||
/* init grease pencil grids and paper */
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "gp_paper_opacity", "float", "gpencil_paper_color[3]")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_paper_color[3]")) {
|
||||
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
|
||||
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
|
||||
for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
|
||||
@@ -2621,7 +2664,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "short", "line_change")) {
|
||||
for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
gpl->line_change = gpl->thickness;
|
||||
if ((gpl->thickness < 1) || (gpl->thickness > 10)) {
|
||||
gpl->thickness = 3;
|
||||
@@ -2953,34 +2996,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
/* grease pencil main material show switches */
|
||||
for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) {
|
||||
if (mat->gp_style) {
|
||||
mat->gp_style->flag |= GP_STYLE_STROKE_SHOW;
|
||||
mat->gp_style->flag |= GP_STYLE_FILL_SHOW;
|
||||
mat->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
|
||||
mat->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 33)) {
|
||||
/* Grease pencil reset sculpt brushes after struct rename */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "GP_Sculpt_Settings", "int", "weighttype")) {
|
||||
float curcolor_add[3], curcolor_sub[3];
|
||||
ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
|
||||
ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
|
||||
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
/* sculpt brushes */
|
||||
GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
|
||||
if (gset) {
|
||||
for (int i = 0; i < GP_SCULPT_TYPE_MAX; i++) {
|
||||
GP_Sculpt_Data *gp_brush = &gset->brush[i];
|
||||
gp_brush->size = 30;
|
||||
gp_brush->strength = 0.5f;
|
||||
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
|
||||
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
|
||||
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "overscan")) {
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
@@ -3214,7 +3236,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
/* init Annotations onion skin */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "int", "gstep")) {
|
||||
for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
|
||||
ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
|
||||
}
|
||||
@@ -3420,20 +3442,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
/* Grease pencil target weight */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "GP_Sculpt_Settings", "float", "weight")) {
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
/* sculpt brushes */
|
||||
GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
|
||||
if (gset) {
|
||||
for (int i = 0; i < GP_SCULPT_TYPE_MAX; i++) {
|
||||
GP_Sculpt_Data *gp_brush = &gset->brush[i];
|
||||
gp_brush->weight = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Grease pencil cutter/select segment intersection threshold */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "GP_Sculpt_Settings", "float", "isect_threshold")) {
|
||||
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
||||
@@ -3653,7 +3661,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
if (gpd->flag & GP_DATA_ANNOTATIONS) {
|
||||
continue;
|
||||
}
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* default channel color */
|
||||
ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
|
||||
}
|
||||
@@ -3744,26 +3752,24 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
|
||||
/* init grease pencil brush gradients */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "gradient_f")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "hardeness")) {
|
||||
for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
|
||||
if (brush->gpencil_settings != NULL) {
|
||||
BrushGpencilSettings *gp = brush->gpencil_settings;
|
||||
gp->gradient_f = 1.0f;
|
||||
gp->gradient_s[0] = 1.0f;
|
||||
gp->gradient_s[1] = 1.0f;
|
||||
gp->hardeness = 1.0f;
|
||||
copy_v2_fl(gp->aspect_ratio, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* init grease pencil stroke gradients */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "gradient_f")) {
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "hardeness")) {
|
||||
for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
|
||||
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
|
||||
gps->gradient_f = 1.0f;
|
||||
gps->gradient_s[0] = 1.0f;
|
||||
gps->gradient_s[1] = 1.0f;
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
gps->hardeness = 1.0f;
|
||||
copy_v2_fl(gps->aspect_ratio, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4217,7 +4223,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix wrong 3D viewport copying causing corrupt pointers (T69974). */
|
||||
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
|
||||
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
|
||||
@@ -4507,6 +4512,272 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 283, 7)) {
|
||||
/* Init default Grease Pencil Vertex paint mix factor for Viewport. */
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "View3DOverlay", "float", "gpencil_vertex_paint_opacity")) {
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_VIEW3D) {
|
||||
View3D *v3d = (View3D *)sl;
|
||||
v3d->overlay.gpencil_vertex_paint_opacity = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update Grease Pencil after drawing engine and code refactor.
|
||||
* It uses the seed variable of Array modifier to avoid double patching for
|
||||
* files created with a development version. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "ArrayGpencilModifierData", "int", "seed")) {
|
||||
/* Init new Grease Pencil Paint tools. */
|
||||
{
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (brush->gpencil_settings != NULL) {
|
||||
brush->gpencil_vertex_tool = brush->gpencil_settings->brush_type;
|
||||
brush->gpencil_sculpt_tool = brush->gpencil_settings->brush_type;
|
||||
brush->gpencil_weight_tool = brush->gpencil_settings->brush_type;
|
||||
}
|
||||
}
|
||||
|
||||
BKE_paint_toolslots_init_from_main(bmain);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Material *, mat, &bmain->materials) {
|
||||
MaterialGPencilStyle *gp_style = mat->gp_style;
|
||||
if (gp_style == NULL) {
|
||||
continue;
|
||||
}
|
||||
/* Fix Grease Pencil Material colors to Linear. */
|
||||
srgb_to_linearrgb_v4(gp_style->stroke_rgba, gp_style->stroke_rgba);
|
||||
srgb_to_linearrgb_v4(gp_style->fill_rgba, gp_style->fill_rgba);
|
||||
|
||||
/* Move old gradient variables to texture. */
|
||||
if (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_GRADIENT) {
|
||||
gp_style->texture_angle = gp_style->gradient_angle;
|
||||
copy_v2_v2(gp_style->texture_scale, gp_style->gradient_scale);
|
||||
copy_v2_v2(gp_style->texture_offset, gp_style->gradient_shift);
|
||||
}
|
||||
/* Set Checker material as Solid. This fill mode has been removed and replaced
|
||||
* by textures. */
|
||||
if (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_CHECKER) {
|
||||
gp_style->fill_style = GP_MATERIAL_FILL_STYLE_SOLID;
|
||||
}
|
||||
/* Update Alpha channel for texture opacity. */
|
||||
if (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_TEXTURE) {
|
||||
gp_style->fill_rgba[3] *= gp_style->texture_opacity;
|
||||
}
|
||||
/* Stroke stencil mask to mix = 1. */
|
||||
if (gp_style->flag & GP_MATERIAL_STROKE_PATTERN) {
|
||||
gp_style->mix_stroke_factor = 1.0f;
|
||||
gp_style->flag &= ~GP_MATERIAL_STROKE_PATTERN;
|
||||
}
|
||||
/* Mix disabled, set mix factor to 0. */
|
||||
else if ((gp_style->flag & GP_MATERIAL_STROKE_TEX_MIX) == 0) {
|
||||
gp_style->mix_stroke_factor = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix Grease Pencil VFX and modifiers. */
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* VFX. */
|
||||
LISTBASE_FOREACH (ShaderFxData *, fx, &ob->shader_fx) {
|
||||
switch (fx->type) {
|
||||
case eShaderFxType_Colorize: {
|
||||
ColorizeShaderFxData *vfx = (ColorizeShaderFxData *)fx;
|
||||
if (ELEM(vfx->mode, eShaderFxColorizeMode_GrayScale, eShaderFxColorizeMode_Sepia)) {
|
||||
vfx->factor = 1.0f;
|
||||
}
|
||||
srgb_to_linearrgb_v4(vfx->low_color, vfx->low_color);
|
||||
srgb_to_linearrgb_v4(vfx->high_color, vfx->high_color);
|
||||
break;
|
||||
}
|
||||
case eShaderFxType_Pixel: {
|
||||
PixelShaderFxData *vfx = (PixelShaderFxData *)fx;
|
||||
srgb_to_linearrgb_v4(vfx->rgba, vfx->rgba);
|
||||
break;
|
||||
}
|
||||
case eShaderFxType_Rim: {
|
||||
RimShaderFxData *vfx = (RimShaderFxData *)fx;
|
||||
srgb_to_linearrgb_v3_v3(vfx->rim_rgb, vfx->rim_rgb);
|
||||
srgb_to_linearrgb_v3_v3(vfx->mask_rgb, vfx->mask_rgb);
|
||||
break;
|
||||
}
|
||||
case eShaderFxType_Shadow: {
|
||||
ShadowShaderFxData *vfx = (ShadowShaderFxData *)fx;
|
||||
srgb_to_linearrgb_v4(vfx->shadow_rgba, vfx->shadow_rgba);
|
||||
break;
|
||||
}
|
||||
case eShaderFxType_Glow: {
|
||||
GlowShaderFxData *vfx = (GlowShaderFxData *)fx;
|
||||
srgb_to_linearrgb_v3_v3(vfx->glow_color, vfx->glow_color);
|
||||
vfx->glow_color[3] = 1.0f;
|
||||
srgb_to_linearrgb_v3_v3(vfx->select_color, vfx->select_color);
|
||||
vfx->blur[1] = vfx->blur[0];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modifiers. */
|
||||
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||
switch ((GpencilModifierType)md->type) {
|
||||
case eGpencilModifierType_Array: {
|
||||
ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md;
|
||||
mmd->seed = 1;
|
||||
if ((mmd->offset[0] != 0.0f) || (mmd->offset[1] != 0.0f) ||
|
||||
(mmd->offset[2] != 0.0f)) {
|
||||
mmd->flag |= GP_ARRAY_USE_OFFSET;
|
||||
}
|
||||
if ((mmd->shift[0] != 0.0f) || (mmd->shift[1] != 0.0f) || (mmd->shift[2] != 0.0f)) {
|
||||
mmd->flag |= GP_ARRAY_USE_OFFSET;
|
||||
}
|
||||
if (mmd->object != NULL) {
|
||||
mmd->flag |= GP_ARRAY_USE_OB_OFFSET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Noise: {
|
||||
NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md;
|
||||
mmd->factor /= 25.0f;
|
||||
mmd->factor_thickness = mmd->factor;
|
||||
mmd->factor_strength = mmd->factor;
|
||||
mmd->factor_uvs = mmd->factor;
|
||||
mmd->noise_scale = (mmd->flag & GP_NOISE_FULL_STROKE) ? 0.0f : 1.0f;
|
||||
|
||||
if (mmd->curve_intensity == NULL) {
|
||||
mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (mmd->curve_intensity) {
|
||||
BKE_curvemapping_initialize(mmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Tint: {
|
||||
TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
|
||||
srgb_to_linearrgb_v3_v3(mmd->rgb, mmd->rgb);
|
||||
if (mmd->curve_intensity == NULL) {
|
||||
mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (mmd->curve_intensity) {
|
||||
BKE_curvemapping_initialize(mmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Smooth: {
|
||||
SmoothGpencilModifierData *mmd = (SmoothGpencilModifierData *)md;
|
||||
if (mmd->curve_intensity == NULL) {
|
||||
mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (mmd->curve_intensity) {
|
||||
BKE_curvemapping_initialize(mmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Opacity: {
|
||||
OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
|
||||
if (mmd->curve_intensity == NULL) {
|
||||
mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (mmd->curve_intensity) {
|
||||
BKE_curvemapping_initialize(mmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Color: {
|
||||
ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md;
|
||||
if (mmd->curve_intensity == NULL) {
|
||||
mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (mmd->curve_intensity) {
|
||||
BKE_curvemapping_initialize(mmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Thick: {
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "ThickGpencilModifierData", "float", "thickness_fac")) {
|
||||
ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md;
|
||||
mmd->thickness_fac = mmd->thickness;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Multiply: {
|
||||
MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md;
|
||||
mmd->fading_opacity = 1.0 - mmd->fading_opacity;
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Subdiv: {
|
||||
const short simple = (1 << 0);
|
||||
SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md;
|
||||
if (mmd->flag & simple) {
|
||||
mmd->flag &= ~simple;
|
||||
mmd->type = GP_SUBDIV_SIMPLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eGpencilModifierType_Vertexcolor: {
|
||||
VertexcolorGpencilModifierData *mmd = (VertexcolorGpencilModifierData *)md;
|
||||
if (mmd->curve_intensity == NULL) {
|
||||
mmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
if (mmd->curve_intensity) {
|
||||
BKE_curvemapping_initialize(mmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix Layers Colors and Vertex Colors to Linear.
|
||||
* Also set lights to on for layers. */
|
||||
LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) {
|
||||
if (gpd->flag & GP_DATA_ANNOTATIONS) {
|
||||
continue;
|
||||
}
|
||||
/* Onion colors. */
|
||||
srgb_to_linearrgb_v3_v3(gpd->gcolor_prev, gpd->gcolor_prev);
|
||||
srgb_to_linearrgb_v3_v3(gpd->gcolor_next, gpd->gcolor_next);
|
||||
/* Z-depth Offset. */
|
||||
gpd->zdepth_offset = 0.150f;
|
||||
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
gpl->flag |= GP_LAYER_USE_LIGHTS;
|
||||
srgb_to_linearrgb_v4(gpl->tintcolor, gpl->tintcolor);
|
||||
gpl->vertex_paint_opacity = 1.0f;
|
||||
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
/* Set initial opacity for fill color. */
|
||||
gps->fill_opacity_fac = 1.0f;
|
||||
|
||||
/* Calc geometry data because in old versions this data was not saved. */
|
||||
BKE_gpencil_stroke_geometry_update(gps);
|
||||
|
||||
srgb_to_linearrgb_v4(gps->vert_color_fill, gps->vert_color_fill);
|
||||
int i;
|
||||
bGPDspoint *pt;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
||||
@@ -44,10 +44,12 @@
|
||||
#include "BKE_appdir.h"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_screen.h"
|
||||
@@ -235,6 +237,13 @@ static void blo_update_defaults_screen(bScreen *screen,
|
||||
/* Enable Sliders. */
|
||||
saction->flag |= SACTION_SLIDERS;
|
||||
}
|
||||
else if (sa->spacetype == SPACE_VIEW3D) {
|
||||
View3D *v3d = sa->spacedata.first;
|
||||
/* Set Material Color by default. */
|
||||
v3d->shading.color_type = V3D_SHADING_MATERIAL_COLOR;
|
||||
/* Enable Annotations. */
|
||||
v3d->flag2 |= V3D_SHOW_ANNOTATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -583,7 +592,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
||||
}
|
||||
}
|
||||
|
||||
if (app_template && STREQ(app_template, "2D_Animation")) {
|
||||
/* New grease pencil brushes and vertex paint setup. */
|
||||
{
|
||||
/* Update Grease Pencil brushes. */
|
||||
Brush *brush;
|
||||
|
||||
@@ -617,8 +627,49 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
||||
BKE_id_delete(bmain, brush);
|
||||
}
|
||||
|
||||
/* Rename and fix materials. */
|
||||
if (app_template && STREQ(app_template, "2D_Animation")) {
|
||||
Material *ma = NULL;
|
||||
rename_id_for_versioning(bmain, ID_MA, "Black", "Solid Stroke");
|
||||
rename_id_for_versioning(bmain, ID_MA, "Red", "Squares Stroke");
|
||||
rename_id_for_versioning(bmain, ID_MA, "Grey", "Solid Fill");
|
||||
rename_id_for_versioning(bmain, ID_MA, "Black Dots", "Dots Stroke");
|
||||
|
||||
/* Dots Stroke. */
|
||||
ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2);
|
||||
if (ma == NULL) {
|
||||
ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
|
||||
}
|
||||
ma->gp_style->mode = GP_MATERIAL_MODE_DOT;
|
||||
|
||||
/* Squares Stroke. */
|
||||
ma = BLI_findstring(&bmain->materials, "Squares Stroke", offsetof(ID, name) + 2);
|
||||
if (ma == NULL) {
|
||||
ma = BKE_gpencil_material_add(bmain, "Squares Stroke");
|
||||
}
|
||||
ma->gp_style->mode = GP_MATERIAL_MODE_SQUARE;
|
||||
|
||||
/* Change Solid Fill settings. */
|
||||
ma = BLI_findstring(&bmain->materials, "Solid Fill", offsetof(ID, name) + 2);
|
||||
if (ma != NULL) {
|
||||
ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset all grease pencil brushes. */
|
||||
Scene *scene = bmain->scenes.first;
|
||||
BKE_brush_gpencil_presets(bmain, scene->toolsettings);
|
||||
BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings);
|
||||
|
||||
/* Ensure new Paint modes. */
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_SCULPT_GPENCIL);
|
||||
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_WEIGHT_GPENCIL);
|
||||
|
||||
/* Enable cursor. */
|
||||
GpPaint *gp_paint = scene->toolsettings->gp_paint;
|
||||
gp_paint->paint.flags |= PAINT_SHOW_BRUSH;
|
||||
|
||||
/* Ensure Palette by default. */
|
||||
BKE_gpencil_palette_ensure(bmain, scene);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1830,6 +1830,13 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
|
||||
write_curvemapping(wd, gpmd->curve_thickness);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Noise) {
|
||||
NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md;
|
||||
|
||||
if (gpmd->curve_intensity) {
|
||||
write_curvemapping(wd, gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Hook) {
|
||||
HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
|
||||
|
||||
@@ -1837,6 +1844,39 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase)
|
||||
write_curvemapping(wd, gpmd->curfalloff);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Vertexcolor) {
|
||||
VertexcolorGpencilModifierData *gpmd = (VertexcolorGpencilModifierData *)md;
|
||||
if (gpmd->colorband) {
|
||||
writestruct(wd, DATA, ColorBand, 1, gpmd->colorband);
|
||||
}
|
||||
if (gpmd->curve_intensity) {
|
||||
write_curvemapping(wd, gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Smooth) {
|
||||
SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md;
|
||||
if (gpmd->curve_intensity) {
|
||||
write_curvemapping(wd, gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Color) {
|
||||
ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md;
|
||||
if (gpmd->curve_intensity) {
|
||||
write_curvemapping(wd, gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Opacity) {
|
||||
OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
|
||||
if (gpmd->curve_intensity) {
|
||||
write_curvemapping(wd, gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
else if (md->type == eGpencilModifierType_Tint) {
|
||||
TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md;
|
||||
if (gpmd->curve_intensity) {
|
||||
write_curvemapping(wd, gpmd->curve_intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2546,6 +2586,18 @@ static void write_scene(WriteData *wd, Scene *sce)
|
||||
writestruct(wd, DATA, GpPaint, 1, tos->gp_paint);
|
||||
write_paint(wd, &tos->gp_paint->paint);
|
||||
}
|
||||
if (tos->gp_vertexpaint) {
|
||||
writestruct(wd, DATA, GpVertexPaint, 1, tos->gp_vertexpaint);
|
||||
write_paint(wd, &tos->gp_vertexpaint->paint);
|
||||
}
|
||||
if (tos->gp_sculptpaint) {
|
||||
writestruct(wd, DATA, GpSculptPaint, 1, tos->gp_sculptpaint);
|
||||
write_paint(wd, &tos->gp_sculptpaint->paint);
|
||||
}
|
||||
if (tos->gp_weightpaint) {
|
||||
writestruct(wd, DATA, GpWeightPaint, 1, tos->gp_weightpaint);
|
||||
write_paint(wd, &tos->gp_weightpaint->paint);
|
||||
}
|
||||
/* write grease-pencil custom ipo curve to file */
|
||||
if (tos->gp_interpolate.custom_ipo) {
|
||||
write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
|
||||
@@ -2741,14 +2793,17 @@ static void write_gpencil(WriteData *wd, bGPdata *gpd)
|
||||
|
||||
/* write grease-pencil layers to file */
|
||||
writelist(wd, DATA, bGPDlayer, &gpd->layers);
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
/* Write mask list. */
|
||||
writelist(wd, DATA, bGPDlayer_Mask, &gpl->mask_layers);
|
||||
/* write this layer's frames to file */
|
||||
writelist(wd, DATA, bGPDframe, &gpl->frames);
|
||||
for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
|
||||
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
|
||||
/* write strokes */
|
||||
writelist(wd, DATA, bGPDstroke, &gpf->strokes);
|
||||
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
|
||||
writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
|
||||
writestruct(wd, DATA, bGPDtriangle, gps->tot_triangles, gps->triangles);
|
||||
write_dverts(wd, gps->totpoints, gps->dvert);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1310,7 +1310,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool
|
||||
obdata,
|
||||
NodeType::GEOMETRY,
|
||||
OperationCode::GEOMETRY_EVAL,
|
||||
function_bind(BKE_gpencil_eval_geometry, _1, (bGPdata *)obdata_cow));
|
||||
function_bind(BKE_gpencil_frame_active_set, _1, (bGPdata *)obdata_cow));
|
||||
op_node->set_as_entry();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2123,6 +2123,15 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
|
||||
add_relation(material_key, geometry_key, "Material -> GP Data");
|
||||
}
|
||||
}
|
||||
|
||||
/* Layer parenting need react to the parent object transformation. */
|
||||
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
|
||||
if (gpl->parent != NULL) {
|
||||
ComponentKey transform_key(&gpl->parent->id, NodeType::TRANSFORM);
|
||||
ComponentKey gpd_geom_key(&gpd->id, NodeType::GEOMETRY);
|
||||
add_relation(transform_key, gpd_geom_key, "GPencil Parent Layer");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_scene.h"
|
||||
@@ -791,6 +792,9 @@ void update_id_after_copy(const Depsgraph *depsgraph,
|
||||
}
|
||||
BKE_pose_pchan_index_rebuild(object_cow->pose);
|
||||
}
|
||||
if (object_cow->type == OB_GPENCIL) {
|
||||
BKE_gpencil_update_orig_pointers(object_orig, object_cow);
|
||||
}
|
||||
update_particles_after_copy(depsgraph, object_orig, object_cow);
|
||||
update_modifiers_orig_pointers(object_orig, object_cow);
|
||||
update_proxy_pointers_after_copy(depsgraph, object_orig, object_cow);
|
||||
|
||||
@@ -52,6 +52,7 @@ set(SRC
|
||||
intern/draw_cache_extract_mesh.c
|
||||
intern/draw_cache_impl_curve.c
|
||||
intern/draw_cache_impl_displist.c
|
||||
intern/draw_cache_impl_gpencil.c
|
||||
intern/draw_cache_impl_lattice.c
|
||||
intern/draw_cache_impl_mesh.c
|
||||
intern/draw_cache_impl_metaball.c
|
||||
@@ -111,12 +112,13 @@ set(SRC
|
||||
engines/workbench/workbench_studiolight.c
|
||||
engines/workbench/workbench_volume.c
|
||||
engines/external/external_engine.c
|
||||
engines/gpencil/gpencil_antialiasing.c
|
||||
engines/gpencil/gpencil_cache_utils.c
|
||||
engines/gpencil/gpencil_draw_cache_impl.c
|
||||
engines/gpencil/gpencil_draw_utils.c
|
||||
engines/gpencil/gpencil_draw_data.c
|
||||
engines/gpencil/gpencil_engine.c
|
||||
engines/gpencil/gpencil_engine.h
|
||||
engines/gpencil/gpencil_render.c
|
||||
engines/gpencil/gpencil_shader.c
|
||||
engines/gpencil/gpencil_shader_fx.c
|
||||
engines/select/select_draw_utils.c
|
||||
engines/select/select_engine.c
|
||||
@@ -129,6 +131,7 @@ set(SRC
|
||||
engines/overlay/overlay_engine.c
|
||||
engines/overlay/overlay_extra.c
|
||||
engines/overlay/overlay_facing.c
|
||||
engines/overlay/overlay_gpencil.c
|
||||
engines/overlay/overlay_grid.c
|
||||
engines/overlay/overlay_image.c
|
||||
engines/overlay/overlay_lattice.c
|
||||
@@ -277,36 +280,16 @@ data_to_c_simple(intern/shaders/common_fxaa_lib.glsl SRC)
|
||||
data_to_c_simple(intern/shaders/common_smaa_lib.glsl SRC)
|
||||
data_to_c_simple(intern/shaders/common_fullscreen_vert.glsl SRC)
|
||||
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_fill_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_fill_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_geom.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_simple_mix_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_blend_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_point_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_point_geom.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_point_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_background_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_paper_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_geom.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_edit_point_frag.glsl SRC)
|
||||
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_antialiasing_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_antialiasing_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_common_lib.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_layer_blend_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_mask_invert_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_depth_merge_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_depth_merge_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_vfx_frag.glsl SRC)
|
||||
|
||||
data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
|
||||
data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
|
||||
@@ -340,6 +323,9 @@ data_to_c_simple(engines/overlay/shaders/edit_curve_handle_geom.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_curve_handle_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_curve_point_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_curve_wire_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_gpencil_canvas_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_gpencil_guide_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_gpencil_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_lattice_point_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_lattice_wire_vert.glsl SRC)
|
||||
data_to_c_simple(engines/overlay/shaders/edit_mesh_common_lib.glsl SRC)
|
||||
|
||||
@@ -129,7 +129,6 @@ void DRW_draw_select_id(struct Depsgraph *depsgraph,
|
||||
/* grease pencil render */
|
||||
bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph);
|
||||
void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph);
|
||||
void DRW_gpencil_freecache(struct Object *ob);
|
||||
|
||||
/* This is here because GPUViewport needs it */
|
||||
struct DRWInstanceDataList *DRW_instance_data_list_create(void);
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2019, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "gpencil_engine.h"
|
||||
|
||||
#include "smaa_textures.h"
|
||||
|
||||
void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
|
||||
{
|
||||
GPENCIL_PrivateData *pd = vedata->stl->pd;
|
||||
GPENCIL_FramebufferList *fbl = vedata->fbl;
|
||||
GPENCIL_TextureList *txl = vedata->txl;
|
||||
GPENCIL_PassList *psl = vedata->psl;
|
||||
DRWShadingGroup *grp;
|
||||
|
||||
const float *size = DRW_viewport_size_get();
|
||||
const float *sizeinv = DRW_viewport_invert_size_get();
|
||||
float metrics[4] = {sizeinv[0], sizeinv[1], size[0], size[1]};
|
||||
|
||||
if (pd->simplify_antialias) {
|
||||
/* No AA fallback. */
|
||||
DRW_PASS_CREATE(psl->smaa_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
|
||||
|
||||
GPUShader *sh = GPENCIL_shader_antialiasing(2);
|
||||
grp = DRW_shgroup_create(sh, psl->smaa_resolve_ps);
|
||||
DRW_shgroup_uniform_texture(grp, "blendTex", pd->color_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "doAntiAliasing", false);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "onlyAlpha", pd->draw_wireframe);
|
||||
DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
|
||||
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (txl->smaa_search_tx == NULL) {
|
||||
txl->smaa_search_tx = GPU_texture_create_nD(SEARCHTEX_WIDTH,
|
||||
SEARCHTEX_HEIGHT,
|
||||
0,
|
||||
2,
|
||||
searchTexBytes,
|
||||
GPU_R8,
|
||||
GPU_DATA_UNSIGNED_BYTE,
|
||||
0,
|
||||
false,
|
||||
NULL);
|
||||
|
||||
txl->smaa_area_tx = GPU_texture_create_nD(AREATEX_WIDTH,
|
||||
AREATEX_HEIGHT,
|
||||
0,
|
||||
2,
|
||||
areaTexBytes,
|
||||
GPU_RG8,
|
||||
GPU_DATA_UNSIGNED_BYTE,
|
||||
0,
|
||||
false,
|
||||
NULL);
|
||||
|
||||
GPU_texture_bind(txl->smaa_search_tx, 0);
|
||||
GPU_texture_filter_mode(txl->smaa_search_tx, true);
|
||||
GPU_texture_unbind(txl->smaa_search_tx);
|
||||
|
||||
GPU_texture_bind(txl->smaa_area_tx, 0);
|
||||
GPU_texture_filter_mode(txl->smaa_area_tx, true);
|
||||
GPU_texture_unbind(txl->smaa_area_tx);
|
||||
}
|
||||
|
||||
{
|
||||
pd->smaa_edge_tx = DRW_texture_pool_query_2d(
|
||||
size[0], size[1], GPU_RG8, &draw_engine_gpencil_type);
|
||||
pd->smaa_weight_tx = DRW_texture_pool_query_2d(
|
||||
size[0], size[1], GPU_RGBA8, &draw_engine_gpencil_type);
|
||||
|
||||
GPU_framebuffer_ensure_config(&fbl->smaa_edge_fb,
|
||||
{
|
||||
GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(pd->smaa_edge_tx),
|
||||
});
|
||||
|
||||
GPU_framebuffer_ensure_config(&fbl->smaa_weight_fb,
|
||||
{
|
||||
GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(pd->smaa_weight_tx),
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
/* Stage 1: Edge detection. */
|
||||
DRW_PASS_CREATE(psl->smaa_edge_ps, DRW_STATE_WRITE_COLOR);
|
||||
|
||||
GPUShader *sh = GPENCIL_shader_antialiasing(0);
|
||||
grp = DRW_shgroup_create(sh, psl->smaa_edge_ps);
|
||||
DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx);
|
||||
DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
|
||||
|
||||
DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0);
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
|
||||
}
|
||||
{
|
||||
/* Stage 2: Blend Weight/Coord. */
|
||||
DRW_PASS_CREATE(psl->smaa_weight_ps, DRW_STATE_WRITE_COLOR);
|
||||
|
||||
GPUShader *sh = GPENCIL_shader_antialiasing(1);
|
||||
grp = DRW_shgroup_create(sh, psl->smaa_weight_ps);
|
||||
DRW_shgroup_uniform_texture(grp, "edgesTex", pd->smaa_edge_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "areaTex", txl->smaa_area_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "searchTex", txl->smaa_search_tx);
|
||||
DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
|
||||
|
||||
DRW_shgroup_clear_framebuffer(grp, GPU_COLOR_BIT, 0, 0, 0, 0, 0.0f, 0x0);
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
|
||||
}
|
||||
{
|
||||
/* Stage 3: Resolve. */
|
||||
DRW_PASS_CREATE(psl->smaa_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
|
||||
|
||||
GPUShader *sh = GPENCIL_shader_antialiasing(2);
|
||||
grp = DRW_shgroup_create(sh, psl->smaa_resolve_ps);
|
||||
DRW_shgroup_uniform_texture(grp, "blendTex", pd->smaa_weight_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "colorTex", pd->color_tx);
|
||||
DRW_shgroup_uniform_texture(grp, "revealTex", pd->reveal_tx);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "doAntiAliasing", true);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "onlyAlpha", pd->draw_wireframe);
|
||||
DRW_shgroup_uniform_vec4_copy(grp, "viewportMetrics", metrics);
|
||||
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GPENCIL_antialiasing_draw(struct GPENCIL_Data *vedata)
|
||||
{
|
||||
GPENCIL_FramebufferList *fbl = vedata->fbl;
|
||||
GPENCIL_PrivateData *pd = vedata->stl->pd;
|
||||
GPENCIL_PassList *psl = vedata->psl;
|
||||
|
||||
if (!pd->simplify_antialias) {
|
||||
GPU_framebuffer_bind(fbl->smaa_edge_fb);
|
||||
DRW_draw_pass(psl->smaa_edge_ps);
|
||||
|
||||
GPU_framebuffer_bind(fbl->smaa_weight_fb);
|
||||
DRW_draw_pass(psl->smaa_weight_ps);
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(pd->scene_fb);
|
||||
DRW_draw_pass(psl->smaa_resolve_ps);
|
||||
}
|
||||
@@ -33,324 +33,368 @@
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "BLI_memblock.h"
|
||||
#include "BLI_link_utils.h"
|
||||
|
||||
#include "gpencil_engine.h"
|
||||
|
||||
#include "draw_cache_impl.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
/* verify if exist a non instanced version of the object */
|
||||
static bool gpencil_has_noninstanced_object(Object *ob_instance)
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Object
|
||||
* \{ */
|
||||
|
||||
GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
const ViewLayer *view_layer = draw_ctx->view_layer;
|
||||
Object *ob = NULL;
|
||||
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
|
||||
ob = base->object;
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
continue;
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
GPENCIL_tObject *tgp_ob = BLI_memblock_alloc(pd->gp_object_pool);
|
||||
|
||||
tgp_ob->layers.first = tgp_ob->layers.last = NULL;
|
||||
tgp_ob->vfx.first = tgp_ob->vfx.last = NULL;
|
||||
tgp_ob->camera_z = dot_v3v3(pd->camera_z_axis, ob->obmat[3]);
|
||||
tgp_ob->is_drawmode3d = (gpd->draw_mode == GP_DRAWMODE_3D) || pd->draw_depth_only;
|
||||
tgp_ob->object_scale = mat4_to_scale(ob->obmat);
|
||||
|
||||
/* Find the normal most likely to represent the gpObject. */
|
||||
/* TODO: This does not work quite well if you use
|
||||
* strokes not aligned with the object axes. Maybe we could try to
|
||||
* compute the minimum axis of all strokes. But this would be more
|
||||
* computationaly heavy and should go into the GPData evaluation. */
|
||||
BoundBox *bbox = BKE_object_boundbox_get(ob);
|
||||
/* Convert bbox to matrix */
|
||||
float mat[4][4], size[3], center[3];
|
||||
BKE_boundbox_calc_size_aabb(bbox, size);
|
||||
BKE_boundbox_calc_center_aabb(bbox, center);
|
||||
unit_m4(mat);
|
||||
copy_v3_v3(mat[3], center);
|
||||
/* Avoid division by 0.0 later. */
|
||||
add_v3_fl(size, 1e-8f);
|
||||
rescale_m4(mat, size);
|
||||
/* BBox space to World. */
|
||||
mul_m4_m4m4(mat, ob->obmat, mat);
|
||||
if (DRW_view_is_persp_get(NULL)) {
|
||||
/* BBox center to camera vector. */
|
||||
sub_v3_v3v3(tgp_ob->plane_normal, pd->camera_pos, mat[3]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(tgp_ob->plane_normal, pd->camera_z_axis);
|
||||
}
|
||||
/* World to BBox space. */
|
||||
invert_m4(mat);
|
||||
/* Normalize the vector in BBox space. */
|
||||
mul_mat3_m4_v3(mat, tgp_ob->plane_normal);
|
||||
normalize_v3(tgp_ob->plane_normal);
|
||||
|
||||
transpose_m4(mat);
|
||||
/* mat is now a "normal" matrix which will transform
|
||||
* BBox space normal to world space. */
|
||||
mul_mat3_m4_v3(mat, tgp_ob->plane_normal);
|
||||
normalize_v3(tgp_ob->plane_normal);
|
||||
|
||||
/* Define a matrix that will be used to render a triangle to merge the depth of the rendered
|
||||
* gpencil object with the rest of the scene. */
|
||||
unit_m4(tgp_ob->plane_mat);
|
||||
copy_v3_v3(tgp_ob->plane_mat[2], tgp_ob->plane_normal);
|
||||
orthogonalize_m4(tgp_ob->plane_mat, 2);
|
||||
mul_mat3_m4_v3(ob->obmat, size);
|
||||
float radius = len_v3(size);
|
||||
mul_m4_v3(ob->obmat, center);
|
||||
rescale_m4(tgp_ob->plane_mat, (float[3]){radius, radius, radius});
|
||||
copy_v3_v3(tgp_ob->plane_mat[3], center);
|
||||
|
||||
/* Add to corresponding list if is in front. */
|
||||
if (ob->dtx & OB_DRAWXRAY) {
|
||||
BLI_LINKS_APPEND(&pd->tobjects_infront, tgp_ob);
|
||||
}
|
||||
else {
|
||||
BLI_LINKS_APPEND(&pd->tobjects, tgp_ob);
|
||||
}
|
||||
|
||||
return tgp_ob;
|
||||
}
|
||||
|
||||
#define SORT_IMPL_LINKTYPE GPENCIL_tObject
|
||||
|
||||
#define SORT_IMPL_FUNC gpencil_tobject_sort_fn_r
|
||||
#include "../../blenlib/intern/list_sort_impl.h"
|
||||
#undef SORT_IMPL_FUNC
|
||||
|
||||
#undef SORT_IMPL_LINKTYPE
|
||||
|
||||
static int gpencil_tobject_dist_sort(const void *a, const void *b)
|
||||
{
|
||||
const GPENCIL_tObject *ob_a = (const GPENCIL_tObject *)a;
|
||||
const GPENCIL_tObject *ob_b = (const GPENCIL_tObject *)b;
|
||||
/* Reminder, camera_z is negative in front of the camera. */
|
||||
if (ob_a->camera_z > ob_b->camera_z) {
|
||||
return 1;
|
||||
}
|
||||
else if (ob_a->camera_z < ob_b->camera_z) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void gpencil_object_cache_sort(GPENCIL_PrivateData *pd)
|
||||
{
|
||||
/* Sort object by distance to the camera. */
|
||||
if (pd->tobjects.first) {
|
||||
pd->tobjects.first = gpencil_tobject_sort_fn_r(pd->tobjects.first, gpencil_tobject_dist_sort);
|
||||
/* Relink last pointer. */
|
||||
while (pd->tobjects.last->next) {
|
||||
pd->tobjects.last = pd->tobjects.last->next;
|
||||
}
|
||||
/* is not duplicated and the name is equals */
|
||||
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
|
||||
if (STREQ(ob->id.name, ob_instance->id.name)) {
|
||||
return true;
|
||||
}
|
||||
if (pd->tobjects_infront.first) {
|
||||
pd->tobjects_infront.first = gpencil_tobject_sort_fn_r(pd->tobjects_infront.first,
|
||||
gpencil_tobject_dist_sort);
|
||||
/* Relink last pointer. */
|
||||
while (pd->tobjects_infront.last->next) {
|
||||
pd->tobjects_infront.last = pd->tobjects_infront.last->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Join both lists, adding infront. */
|
||||
if (pd->tobjects_infront.first != NULL) {
|
||||
if (pd->tobjects.last != NULL) {
|
||||
pd->tobjects.last->next = pd->tobjects_infront.first;
|
||||
pd->tobjects.last = pd->tobjects_infront.last;
|
||||
}
|
||||
else {
|
||||
/* Only in front objects. */
|
||||
pd->tobjects.first = pd->tobjects_infront.first;
|
||||
pd->tobjects.last = pd->tobjects_infront.last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Layer
|
||||
* \{ */
|
||||
|
||||
static float gpencil_layer_final_opacity_get(const GPENCIL_PrivateData *pd,
|
||||
const Object *ob,
|
||||
const bGPDlayer *gpl)
|
||||
{
|
||||
const bool is_obact = ((pd->obact) && (pd->obact == ob));
|
||||
const bool is_fade = ((pd->fade_layer_opacity > -1.0f) && (is_obact) &&
|
||||
((gpl->flag & GP_LAYER_ACTIVE) == 0));
|
||||
|
||||
/* Defines layer opacity. For active object depends of layer opacity factor, and
|
||||
* for no active object, depends if the fade grease pencil objects option is enabled. */
|
||||
if (!pd->is_render) {
|
||||
if (is_obact && is_fade) {
|
||||
return gpl->opacity * pd->fade_layer_opacity;
|
||||
}
|
||||
else if (!is_obact && (pd->fade_gp_object_opacity > -1.0f)) {
|
||||
return gpl->opacity * pd->fade_gp_object_opacity;
|
||||
}
|
||||
}
|
||||
return gpl->opacity;
|
||||
}
|
||||
|
||||
static void gpencil_layer_final_tint_and_alpha_get(const GPENCIL_PrivateData *pd,
|
||||
const bGPdata *gpd,
|
||||
const bGPDlayer *gpl,
|
||||
const bGPDframe *gpf,
|
||||
float r_tint[4],
|
||||
float *r_alpha)
|
||||
{
|
||||
const bool use_onion = (gpf != NULL) && (gpf->runtime.onion_id != 0.0f);
|
||||
if (use_onion) {
|
||||
const bool use_onion_custom_col = (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) != 0;
|
||||
const bool use_onion_fade = (gpd->onion_flag & GP_ONION_FADE) != 0;
|
||||
const bool use_next_col = gpf->runtime.onion_id > 0.0f;
|
||||
|
||||
const float *onion_col_custom = (use_onion_custom_col) ?
|
||||
(use_next_col ? gpd->gcolor_next : gpd->gcolor_prev) :
|
||||
U.gpencil_new_layer_col;
|
||||
|
||||
copy_v4_fl4(r_tint, UNPACK3(onion_col_custom), 1.0f);
|
||||
|
||||
*r_alpha = use_onion_fade ? (1.0f / abs(gpf->runtime.onion_id)) : 0.5f;
|
||||
*r_alpha *= gpd->onion_factor;
|
||||
*r_alpha = (gpd->onion_factor > 0.0f) ? clamp_f(*r_alpha, 0.1f, 1.0f) :
|
||||
clamp_f(*r_alpha, 0.01f, 1.0f);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(r_tint, gpl->tintcolor);
|
||||
if (GPENCIL_SIMPLIFY_TINT(pd->scene)) {
|
||||
r_tint[3] = 0.0f;
|
||||
}
|
||||
*r_alpha = 1.0f;
|
||||
}
|
||||
|
||||
*r_alpha *= pd->xray_alpha;
|
||||
}
|
||||
|
||||
GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
|
||||
const Object *ob,
|
||||
const bGPDlayer *gpl,
|
||||
const bGPDframe *gpf,
|
||||
GPENCIL_tObject *tgp_ob)
|
||||
{
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
|
||||
const bool is_in_front = (ob->dtx & OB_DRAWXRAY);
|
||||
const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
|
||||
const bool overide_vertcol = (pd->v3d_color_type != -1);
|
||||
const bool is_vert_col_mode = (pd->v3d_color_type == V3D_SHADING_VERTEX_COLOR) ||
|
||||
GPENCIL_VERTEX_MODE(gpd) || pd->is_render;
|
||||
bool is_masked = (gpl->flag & GP_LAYER_USE_MASK) && !BLI_listbase_is_empty(&gpl->mask_layers);
|
||||
|
||||
float vert_col_opacity = (overide_vertcol) ? (is_vert_col_mode ? 1.0f : 0.0f) :
|
||||
gpl->vertex_paint_opacity;
|
||||
/* Negate thickness sign to tag that strokes are in screen space.
|
||||
* Convert to world units (by default, 1 meter = 2000 px). */
|
||||
float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / GPENCIL_PIXEL_FACTOR);
|
||||
float layer_opacity = gpencil_layer_final_opacity_get(pd, ob, gpl);
|
||||
float layer_tint[4];
|
||||
float layer_alpha;
|
||||
gpencil_layer_final_tint_and_alpha_get(pd, gpd, gpl, gpf, layer_tint, &layer_alpha);
|
||||
|
||||
/* Create the new layer descriptor. */
|
||||
GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
|
||||
BLI_LINKS_APPEND(&tgp_ob->layers, tgp_layer);
|
||||
tgp_layer->layer_id = BLI_findindex(&gpd->layers, gpl);
|
||||
tgp_layer->mask_bits = NULL;
|
||||
tgp_layer->mask_invert_bits = NULL;
|
||||
tgp_layer->blend_ps = NULL;
|
||||
|
||||
/* Masking: Go through mask list and extract valid masks in a bitmap. */
|
||||
if (is_masked) {
|
||||
bool valid_mask = false;
|
||||
/* Warning: only GP_MAX_MASKBITS amount of bits.
|
||||
* TODO(fclem) Find a better system without any limitation. */
|
||||
tgp_layer->mask_bits = BLI_memblock_alloc(pd->gp_maskbit_pool);
|
||||
tgp_layer->mask_invert_bits = BLI_memblock_alloc(pd->gp_maskbit_pool);
|
||||
BLI_bitmap_set_all(tgp_layer->mask_bits, false, GP_MAX_MASKBITS);
|
||||
|
||||
LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
|
||||
bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
|
||||
if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0) &&
|
||||
((mask->flag & GP_MASK_HIDE) == 0)) {
|
||||
int index = BLI_findindex(&gpd->layers, gpl_mask);
|
||||
if (index < GP_MAX_MASKBITS) {
|
||||
const bool invert = (mask->flag & GP_MASK_INVERT) != 0;
|
||||
BLI_BITMAP_SET(tgp_layer->mask_bits, index, true);
|
||||
BLI_BITMAP_SET(tgp_layer->mask_invert_bits, index, invert);
|
||||
valid_mask = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* add a gpencil object to cache to defer drawing */
|
||||
tGPencilObjectCache *gpencil_object_cache_add(tGPencilObjectCache *cache_array,
|
||||
Object *ob,
|
||||
int *gp_cache_size,
|
||||
int *gp_cache_used)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
tGPencilObjectCache *cache_elem = NULL;
|
||||
RegionView3D *rv3d = draw_ctx->rv3d;
|
||||
View3D *v3d = draw_ctx->v3d;
|
||||
tGPencilObjectCache *p = NULL;
|
||||
|
||||
/* By default a cache is created with one block with a predefined number of free slots,
|
||||
* if the size is not enough, the cache is reallocated adding a new block of free slots.
|
||||
* This is done in order to keep cache small. */
|
||||
if (*gp_cache_used + 1 > *gp_cache_size) {
|
||||
if ((*gp_cache_size == 0) || (cache_array == NULL)) {
|
||||
p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE,
|
||||
"tGPencilObjectCache");
|
||||
*gp_cache_size = GP_CACHE_BLOCK_SIZE;
|
||||
if (valid_mask) {
|
||||
pd->use_mask_fb = true;
|
||||
}
|
||||
else {
|
||||
*gp_cache_size += GP_CACHE_BLOCK_SIZE;
|
||||
p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
|
||||
tgp_layer->mask_bits = NULL;
|
||||
}
|
||||
cache_array = p;
|
||||
}
|
||||
/* zero out all pointers */
|
||||
cache_elem = &cache_array[*gp_cache_used];
|
||||
memset(cache_elem, 0, sizeof(*cache_elem));
|
||||
|
||||
cache_elem->ob = ob;
|
||||
cache_elem->gpd = (bGPdata *)ob->data;
|
||||
cache_elem->name = BKE_id_to_unique_string_key(&ob->id);
|
||||
|
||||
copy_v3_v3(cache_elem->loc, ob->obmat[3]);
|
||||
copy_m4_m4(cache_elem->obmat, ob->obmat);
|
||||
cache_elem->idx = *gp_cache_used;
|
||||
|
||||
/* object is duplicated (particle) */
|
||||
if (ob->base_flag & BASE_FROM_DUPLI) {
|
||||
/* Check if the original object is not in the viewlayer
|
||||
* and cannot be managed as dupli. This is slower, but required to keep
|
||||
* the particle drawing FPS and display instanced objects in scene
|
||||
* without the original object */
|
||||
bool has_original = gpencil_has_noninstanced_object(ob);
|
||||
cache_elem->is_dup_ob = (has_original) ? ob->base_flag & BASE_FROM_DUPLI : false;
|
||||
}
|
||||
else {
|
||||
cache_elem->is_dup_ob = false;
|
||||
is_masked = valid_mask;
|
||||
}
|
||||
|
||||
cache_elem->scale = mat4_to_scale(ob->obmat);
|
||||
/* Blending: Force blending for masked layer. */
|
||||
if (is_masked || (gpl->blend_mode != eGplBlendMode_Regular) || (layer_opacity < 1.0f)) {
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL;
|
||||
switch (gpl->blend_mode) {
|
||||
case eGplBlendMode_Regular:
|
||||
state |= DRW_STATE_BLEND_ALPHA_PREMUL;
|
||||
break;
|
||||
case eGplBlendMode_Add:
|
||||
state |= DRW_STATE_BLEND_ADD_FULL;
|
||||
break;
|
||||
case eGplBlendMode_Subtract:
|
||||
state |= DRW_STATE_BLEND_SUB;
|
||||
break;
|
||||
case eGplBlendMode_Multiply:
|
||||
case eGplBlendMode_Divide:
|
||||
case eGplBlendMode_Overlay:
|
||||
state |= DRW_STATE_BLEND_MUL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* save FXs */
|
||||
cache_elem->pixfactor = cache_elem->gpd->pixfactor;
|
||||
cache_elem->shader_fx = ob->shader_fx;
|
||||
if (ELEM(gpl->blend_mode, eGplBlendMode_Subtract, eGplBlendMode_Overlay)) {
|
||||
/* For these effect to propagate, we need a signed floating point buffer. */
|
||||
pd->use_signed_fb = true;
|
||||
}
|
||||
|
||||
/* save wire mode (object mode is always primary option) */
|
||||
if (ob->dt == OB_WIRE) {
|
||||
cache_elem->shading_type[0] = (int)OB_WIRE;
|
||||
tgp_layer->blend_ps = DRW_pass_create("GPencil Blend Layer", state);
|
||||
|
||||
GPUShader *sh = GPENCIL_shader_layer_blend_get();
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
|
||||
DRW_shgroup_uniform_int_copy(grp, "blendMode", gpl->blend_mode);
|
||||
DRW_shgroup_uniform_float_copy(grp, "blendOpacity", layer_opacity);
|
||||
DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
|
||||
DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
|
||||
DRW_shgroup_uniform_texture_ref(grp, "maskBuf", (is_masked) ? &pd->mask_tx : &pd->dummy_tx);
|
||||
DRW_shgroup_stencil_mask(grp, 0xFF);
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
|
||||
|
||||
if (gpl->blend_mode == eGplBlendMode_Overlay) {
|
||||
/* We cannot do custom blending on MultiTarget framebuffers.
|
||||
* Workaround by doing 2 passes. */
|
||||
grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
|
||||
DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL);
|
||||
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ADD_FULL);
|
||||
DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
|
||||
}
|
||||
|
||||
pd->use_layer_fb = true;
|
||||
}
|
||||
else {
|
||||
if (v3d) {
|
||||
cache_elem->shading_type[0] = (int)v3d->shading.type;
|
||||
|
||||
/* Geometry pass */
|
||||
{
|
||||
GPUTexture *depth_tex = (is_in_front) ? pd->dummy_tx : pd->scene_depth_tx;
|
||||
GPUTexture **mask_tex = (is_masked) ? &pd->mask_tx : &pd->dummy_tx;
|
||||
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND_ALPHA_PREMUL;
|
||||
/* For 2D mode, we render all strokes with uniform depth (increasing with stroke id). */
|
||||
state |= tgp_ob->is_drawmode3d ? DRW_STATE_DEPTH_LESS_EQUAL : DRW_STATE_DEPTH_GREATER;
|
||||
/* Always write stencil. Only used as optimization for blending. */
|
||||
state |= DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
|
||||
|
||||
tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
|
||||
|
||||
struct GPUShader *sh = GPENCIL_shader_geometry_get();
|
||||
DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
|
||||
|
||||
DRW_shgroup_uniform_texture_persistent(grp, "gpSceneDepthTexture", depth_tex);
|
||||
DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex);
|
||||
DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal);
|
||||
DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", tgp_ob->is_drawmode3d);
|
||||
DRW_shgroup_uniform_float_copy(grp, "thicknessScale", tgp_ob->object_scale);
|
||||
DRW_shgroup_uniform_vec2_copy(grp, "sizeViewportInv", DRW_viewport_invert_size_get());
|
||||
DRW_shgroup_uniform_vec2_copy(grp, "sizeViewport", DRW_viewport_size_get());
|
||||
DRW_shgroup_uniform_float_copy(grp, "thicknessOffset", (float)gpl->line_change);
|
||||
DRW_shgroup_uniform_float_copy(grp, "thicknessWorldScale", thickness_scale);
|
||||
DRW_shgroup_uniform_float_copy(grp, "vertexColorOpacity", vert_col_opacity);
|
||||
DRW_shgroup_uniform_vec4_copy(grp, "layerTint", layer_tint);
|
||||
DRW_shgroup_uniform_float_copy(grp, "layerOpacity", layer_alpha);
|
||||
DRW_shgroup_stencil_mask(grp, 0xFF);
|
||||
}
|
||||
|
||||
return tgp_layer;
|
||||
}
|
||||
|
||||
GPENCIL_tLayer *gpencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int number)
|
||||
{
|
||||
if (number >= 0) {
|
||||
GPENCIL_tLayer *layer = tgp_ob->layers.first;
|
||||
while (layer != NULL) {
|
||||
if (layer->layer_id == number) {
|
||||
return layer;
|
||||
}
|
||||
layer = layer->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* shgrp array */
|
||||
cache_elem->tot_layers = 0;
|
||||
int totgpl = BLI_listbase_count(&cache_elem->gpd->layers);
|
||||
if (totgpl > 0) {
|
||||
cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__);
|
||||
}
|
||||
|
||||
/* calculate zdepth from point of view */
|
||||
float zdepth = 0.0;
|
||||
if (rv3d) {
|
||||
if (rv3d->is_persp) {
|
||||
zdepth = ED_view3d_calc_zfac(rv3d, ob->obmat[3], NULL);
|
||||
}
|
||||
else {
|
||||
zdepth = -dot_v3v3(rv3d->viewinv[2], ob->obmat[3]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* In render mode, rv3d is not available, so use the distance to camera.
|
||||
* The real distance is not important, but the relative distance to the camera plane
|
||||
* in order to sort by z_depth of the objects
|
||||
*/
|
||||
float vn[3] = {0.0f, 0.0f, -1.0f}; /* always face down */
|
||||
float plane_cam[4];
|
||||
struct Object *camera = draw_ctx->scene->camera;
|
||||
if (camera) {
|
||||
mul_m4_v3(camera->obmat, vn);
|
||||
normalize_v3(vn);
|
||||
plane_from_point_normal_v3(plane_cam, camera->loc, vn);
|
||||
zdepth = dist_squared_to_plane_v3(ob->obmat[3], plane_cam);
|
||||
}
|
||||
}
|
||||
cache_elem->zdepth = zdepth;
|
||||
/* increase slots used in cache */
|
||||
(*gp_cache_used)++;
|
||||
|
||||
return cache_array;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add a shading group to the cache to create later */
|
||||
GpencilBatchGroup *gpencil_group_cache_add(GpencilBatchGroup *cache_array,
|
||||
bGPDlayer *gpl,
|
||||
bGPDframe *gpf,
|
||||
bGPDstroke *gps,
|
||||
const short type,
|
||||
const bool onion,
|
||||
const int vertex_idx,
|
||||
int *grp_size,
|
||||
int *grp_used)
|
||||
{
|
||||
GpencilBatchGroup *cache_elem = NULL;
|
||||
GpencilBatchGroup *p = NULL;
|
||||
|
||||
/* By default a cache is created with one block with a predefined number of free slots,
|
||||
* if the size is not enough, the cache is reallocated adding a new block of free slots.
|
||||
* This is done in order to keep cache small. */
|
||||
if (*grp_used + 1 > *grp_size) {
|
||||
if ((*grp_size == 0) || (cache_array == NULL)) {
|
||||
p = MEM_callocN(sizeof(struct GpencilBatchGroup) * GPENCIL_GROUPS_BLOCK_SIZE,
|
||||
"GpencilBatchGroup");
|
||||
*grp_size = GPENCIL_GROUPS_BLOCK_SIZE;
|
||||
}
|
||||
else {
|
||||
*grp_size += GPENCIL_GROUPS_BLOCK_SIZE;
|
||||
p = MEM_recallocN(cache_array, sizeof(struct GpencilBatchGroup) * *grp_size);
|
||||
}
|
||||
cache_array = p;
|
||||
}
|
||||
/* zero out all data */
|
||||
cache_elem = &cache_array[*grp_used];
|
||||
memset(cache_elem, 0, sizeof(*cache_elem));
|
||||
|
||||
cache_elem->gpl = gpl;
|
||||
cache_elem->gpf = gpf;
|
||||
cache_elem->gps = gps;
|
||||
cache_elem->type = type;
|
||||
cache_elem->onion = onion;
|
||||
cache_elem->vertex_idx = vertex_idx;
|
||||
|
||||
/* increase slots used in cache */
|
||||
(*grp_used)++;
|
||||
|
||||
return cache_array;
|
||||
}
|
||||
|
||||
/* get current cache data */
|
||||
static GpencilBatchCache *gpencil_batch_get_element(Object *ob)
|
||||
{
|
||||
return ob->runtime.gpencil_cache;
|
||||
}
|
||||
|
||||
/* verify if cache is valid */
|
||||
static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra)
|
||||
{
|
||||
bool valid = true;
|
||||
if (cache == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
if (cfra != cache->cache_frame) {
|
||||
valid = false;
|
||||
}
|
||||
else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) {
|
||||
valid = false;
|
||||
}
|
||||
else if (gpd->flag & GP_DATA_PYTHON_UPDATED) {
|
||||
gpd->flag &= ~GP_DATA_PYTHON_UPDATED;
|
||||
valid = false;
|
||||
}
|
||||
else if (cache->is_editmode) {
|
||||
valid = false;
|
||||
}
|
||||
else if (cache->is_dirty) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/* cache init */
|
||||
static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
|
||||
{
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
|
||||
GpencilBatchCache *cache = gpencil_batch_get_element(ob);
|
||||
|
||||
if (!cache) {
|
||||
cache = MEM_callocN(sizeof(*cache), __func__);
|
||||
ob->runtime.gpencil_cache = cache;
|
||||
}
|
||||
else {
|
||||
memset(cache, 0, sizeof(*cache));
|
||||
}
|
||||
|
||||
cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
|
||||
|
||||
cache->is_dirty = true;
|
||||
|
||||
cache->cache_frame = cfra;
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
/* clear cache */
|
||||
static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
|
||||
{
|
||||
if (!cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_BATCH_DISCARD_SAFE(cache->b_stroke.batch);
|
||||
GPU_BATCH_DISCARD_SAFE(cache->b_point.batch);
|
||||
GPU_BATCH_DISCARD_SAFE(cache->b_fill.batch);
|
||||
GPU_BATCH_DISCARD_SAFE(cache->b_edit.batch);
|
||||
GPU_BATCH_DISCARD_SAFE(cache->b_edlin.batch);
|
||||
|
||||
MEM_SAFE_FREE(cache->b_stroke.batch);
|
||||
MEM_SAFE_FREE(cache->b_point.batch);
|
||||
MEM_SAFE_FREE(cache->b_fill.batch);
|
||||
MEM_SAFE_FREE(cache->b_edit.batch);
|
||||
MEM_SAFE_FREE(cache->b_edlin.batch);
|
||||
|
||||
/* internal format data */
|
||||
MEM_SAFE_FREE(cache->b_stroke.format);
|
||||
MEM_SAFE_FREE(cache->b_point.format);
|
||||
MEM_SAFE_FREE(cache->b_fill.format);
|
||||
MEM_SAFE_FREE(cache->b_edit.format);
|
||||
MEM_SAFE_FREE(cache->b_edlin.format);
|
||||
|
||||
MEM_SAFE_FREE(cache->grp_cache);
|
||||
cache->grp_size = 0;
|
||||
cache->grp_used = 0;
|
||||
}
|
||||
|
||||
/* get cache */
|
||||
GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
|
||||
{
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
|
||||
GpencilBatchCache *cache = gpencil_batch_get_element(ob);
|
||||
if (!gpencil_batch_cache_valid(cache, gpd, cfra)) {
|
||||
if (cache) {
|
||||
gpencil_batch_cache_clear(cache);
|
||||
}
|
||||
return gpencil_batch_cache_init(ob, cfra);
|
||||
}
|
||||
else {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
/* set cache as dirty */
|
||||
void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
|
||||
{
|
||||
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
|
||||
}
|
||||
|
||||
/* free batch cache */
|
||||
void DRW_gpencil_batch_cache_free(bGPdata *UNUSED(gpd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* wrapper to clear cache */
|
||||
void DRW_gpencil_freecache(struct Object *ob)
|
||||
{
|
||||
if ((ob) && (ob->type == OB_GPENCIL)) {
|
||||
gpencil_batch_cache_clear(ob->runtime.gpencil_cache);
|
||||
MEM_SAFE_FREE(ob->runtime.gpencil_cache);
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
if (gpd) {
|
||||
gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear all frames evaluated data */
|
||||
for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) {
|
||||
bGPDframe *gpf_eval = &ob->runtime.gpencil_evaluated_frames[i];
|
||||
BKE_gpencil_free_frame_runtime_data(gpf_eval);
|
||||
}
|
||||
|
||||
ob->runtime.gpencil_tot_layers = 0;
|
||||
MEM_SAFE_FREE(ob->runtime.gpencil_evaluated_frames);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2019, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*/
|
||||
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "DNA_light_types.h"
|
||||
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "BLI_hash.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_memblock.h"
|
||||
|
||||
#include "GPU_uniformbuffer.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "gpencil_engine.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Material
|
||||
* \{ */
|
||||
|
||||
static GPENCIL_MaterialPool *gpencil_material_pool_add(GPENCIL_PrivateData *pd)
|
||||
{
|
||||
GPENCIL_MaterialPool *matpool = BLI_memblock_alloc(pd->gp_material_pool);
|
||||
matpool->next = NULL;
|
||||
matpool->used_count = 0;
|
||||
if (matpool->ubo == NULL) {
|
||||
matpool->ubo = GPU_uniformbuffer_create(sizeof(matpool->mat_data), NULL, NULL);
|
||||
}
|
||||
pd->last_material_pool = matpool;
|
||||
return matpool;
|
||||
}
|
||||
|
||||
static struct GPUTexture *gpencil_image_texture_get(Image *image, bool *r_alpha_premult)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
ImageUser iuser = {NULL};
|
||||
struct GPUTexture *gpu_tex = NULL;
|
||||
void *lock;
|
||||
|
||||
iuser.ok = true;
|
||||
ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
|
||||
|
||||
if (ibuf != NULL && ibuf->rect != NULL) {
|
||||
gpu_tex = GPU_texture_from_blender(image, &iuser, ibuf, GL_TEXTURE_2D);
|
||||
*r_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL);
|
||||
}
|
||||
BKE_image_release_ibuf(image, ibuf, lock);
|
||||
|
||||
return gpu_tex;
|
||||
}
|
||||
|
||||
static void gpencil_uv_transform_get(const float ofs[2],
|
||||
const float scale[2],
|
||||
const float rotation,
|
||||
float r_uvmat[3][2])
|
||||
{
|
||||
/* OPTI this could use 3x2 matrices and reduce the number of operations drastically. */
|
||||
float mat[4][4];
|
||||
unit_m4(mat);
|
||||
/* Offset to center. */
|
||||
translate_m4(mat, 0.5f, 0.5f, 0.0f);
|
||||
/* Reversed order. */
|
||||
rescale_m4(mat, (float[3]){1.0f / scale[0], 1.0f / scale[1], 0.0});
|
||||
rotate_m4(mat, 'Z', -rotation);
|
||||
translate_m4(mat, ofs[0], ofs[1], 0.0f);
|
||||
/* Convert to 3x2 */
|
||||
copy_v2_v2(r_uvmat[0], mat[0]);
|
||||
copy_v2_v2(r_uvmat[1], mat[1]);
|
||||
copy_v2_v2(r_uvmat[2], mat[3]);
|
||||
}
|
||||
|
||||
#define HSV_SATURATION 0.5
|
||||
#define HSV_VALUE 0.8
|
||||
|
||||
static void gpencil_object_random_color_get(const Object *ob, float r_color[3])
|
||||
{
|
||||
/* Duplicated from workbench_material.c */
|
||||
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
|
||||
if (ob->id.lib) {
|
||||
hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name);
|
||||
}
|
||||
float hue = BLI_hash_int_01(hash);
|
||||
float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE};
|
||||
hsv_to_rgb_v(hsv, r_color);
|
||||
}
|
||||
|
||||
static void gpencil_shade_color(float color[3])
|
||||
{
|
||||
/* This is scene refered color, not gamma corrected and not per perceptual.
|
||||
* So we lower the threshold a bit. (1.0 / 3.0) */
|
||||
if (color[0] + color[1] + color[2] > 1.1) {
|
||||
add_v3_fl(color, -0.25f);
|
||||
}
|
||||
else {
|
||||
add_v3_fl(color, 0.15f);
|
||||
}
|
||||
CLAMP3(color, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/* Apply all overrides from the solid viewport mode to the GPencil material. */
|
||||
static MaterialGPencilStyle *gpencil_viewport_material_overrides(GPENCIL_PrivateData *pd,
|
||||
Object *ob,
|
||||
int color_type,
|
||||
MaterialGPencilStyle *gp_style)
|
||||
{
|
||||
static MaterialGPencilStyle gp_style_tmp;
|
||||
|
||||
switch (color_type) {
|
||||
case V3D_SHADING_MATERIAL_COLOR:
|
||||
copy_v4_v4(gp_style_tmp.stroke_rgba, gp_style->stroke_rgba);
|
||||
copy_v4_v4(gp_style_tmp.fill_rgba, gp_style->fill_rgba);
|
||||
gp_style = &gp_style_tmp;
|
||||
gp_style->stroke_style = GP_MATERIAL_STROKE_STYLE_SOLID;
|
||||
gp_style->fill_style = GP_MATERIAL_FILL_STYLE_SOLID;
|
||||
break;
|
||||
case V3D_SHADING_TEXTURE_COLOR:
|
||||
memcpy(&gp_style_tmp, gp_style, sizeof(*gp_style));
|
||||
gp_style = &gp_style_tmp;
|
||||
if ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) && (gp_style->sima)) {
|
||||
copy_v4_fl(gp_style->stroke_rgba, 1.0f);
|
||||
gp_style->mix_stroke_factor = 0.0f;
|
||||
}
|
||||
|
||||
if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_TEXTURE) && (gp_style->ima)) {
|
||||
copy_v4_fl(gp_style->fill_rgba, 1.0f);
|
||||
gp_style->mix_factor = 0.0f;
|
||||
}
|
||||
else if (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_GRADIENT) {
|
||||
/* gp_style->fill_rgba is needed for correct gradient. */
|
||||
gp_style->mix_factor = 0.0f;
|
||||
}
|
||||
break;
|
||||
case V3D_SHADING_RANDOM_COLOR:
|
||||
gp_style = &gp_style_tmp;
|
||||
gp_style->stroke_style = GP_MATERIAL_STROKE_STYLE_SOLID;
|
||||
gp_style->fill_style = GP_MATERIAL_FILL_STYLE_SOLID;
|
||||
gpencil_object_random_color_get(ob, gp_style->fill_rgba);
|
||||
gp_style->fill_rgba[3] = 1.0f;
|
||||
copy_v4_v4(gp_style->stroke_rgba, gp_style->fill_rgba);
|
||||
gpencil_shade_color(gp_style->stroke_rgba);
|
||||
break;
|
||||
case V3D_SHADING_SINGLE_COLOR:
|
||||
gp_style = &gp_style_tmp;
|
||||
gp_style->stroke_style = GP_MATERIAL_STROKE_STYLE_SOLID;
|
||||
gp_style->fill_style = GP_MATERIAL_FILL_STYLE_SOLID;
|
||||
copy_v3_v3(gp_style->fill_rgba, pd->v3d_single_color);
|
||||
gp_style->fill_rgba[3] = 1.0f;
|
||||
copy_v4_v4(gp_style->stroke_rgba, gp_style->fill_rgba);
|
||||
gpencil_shade_color(gp_style->stroke_rgba);
|
||||
break;
|
||||
case V3D_SHADING_OBJECT_COLOR:
|
||||
gp_style = &gp_style_tmp;
|
||||
gp_style->stroke_style = GP_MATERIAL_STROKE_STYLE_SOLID;
|
||||
gp_style->fill_style = GP_MATERIAL_FILL_STYLE_SOLID;
|
||||
copy_v4_v4(gp_style->fill_rgba, ob->color);
|
||||
copy_v4_v4(gp_style->stroke_rgba, ob->color);
|
||||
gpencil_shade_color(gp_style->stroke_rgba);
|
||||
break;
|
||||
case V3D_SHADING_VERTEX_COLOR:
|
||||
gp_style = &gp_style_tmp;
|
||||
gp_style->stroke_style = GP_MATERIAL_STROKE_STYLE_SOLID;
|
||||
gp_style->fill_style = GP_MATERIAL_FILL_STYLE_SOLID;
|
||||
copy_v4_fl(gp_style->fill_rgba, 1.0f);
|
||||
copy_v4_fl(gp_style->stroke_rgba, 1.0f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return gp_style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a linked list of material pool containing all materials assigned for a given object.
|
||||
* We merge the material pools together if object does not contain a huge amount of materials.
|
||||
* Also return an offset to the first material of the object in the ubo.
|
||||
**/
|
||||
GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Object *ob, int *ofs)
|
||||
{
|
||||
GPENCIL_MaterialPool *matpool = pd->last_material_pool;
|
||||
|
||||
int mat_len = max_ii(1, ob->totcol);
|
||||
|
||||
bool reuse_matpool = matpool && ((matpool->used_count + mat_len) <= GP_MATERIAL_BUFFER_LEN);
|
||||
|
||||
if (reuse_matpool) {
|
||||
/* Share the matpool with other objects. Return offset to first material. */
|
||||
*ofs = matpool->used_count;
|
||||
}
|
||||
else {
|
||||
matpool = gpencil_material_pool_add(pd);
|
||||
*ofs = 0;
|
||||
}
|
||||
|
||||
/* Force vertex color in solid mode with vertex paint mode. Same behavior as meshes. */
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
int color_type = (pd->v3d_color_type != -1 && GPENCIL_VERTEX_MODE(gpd)) ?
|
||||
V3D_SHADING_VERTEX_COLOR :
|
||||
pd->v3d_color_type;
|
||||
|
||||
GPENCIL_MaterialPool *pool = matpool;
|
||||
for (int i = 0; i < mat_len; i++) {
|
||||
if ((i > 0) && (pool->used_count == GP_MATERIAL_BUFFER_LEN)) {
|
||||
pool->next = gpencil_material_pool_add(pd);
|
||||
pool = pool->next;
|
||||
}
|
||||
int mat_id = pool->used_count++;
|
||||
|
||||
gpMaterial *mat_data = &pool->mat_data[mat_id];
|
||||
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, i + 1);
|
||||
|
||||
if (gp_style->mode == GP_MATERIAL_MODE_LINE) {
|
||||
mat_data->flag = 0;
|
||||
}
|
||||
else {
|
||||
switch (gp_style->alignment_mode) {
|
||||
case GP_MATERIAL_FOLLOW_PATH:
|
||||
mat_data->flag = GP_STROKE_ALIGNMENT_STROKE;
|
||||
break;
|
||||
case GP_MATERIAL_FOLLOW_OBJ:
|
||||
mat_data->flag = GP_STROKE_ALIGNMENT_OBJECT;
|
||||
break;
|
||||
case GP_MATERIAL_FOLLOW_FIXED:
|
||||
default:
|
||||
mat_data->flag = GP_STROKE_ALIGNMENT_FIXED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gp_style->mode == GP_MATERIAL_MODE_DOT) {
|
||||
mat_data->flag |= GP_STROKE_DOTS;
|
||||
}
|
||||
}
|
||||
|
||||
if ((gp_style->mode != GP_MATERIAL_MODE_LINE) ||
|
||||
(gp_style->flag & GP_MATERIAL_DISABLE_STENCIL)) {
|
||||
mat_data->flag |= GP_STROKE_OVERLAP;
|
||||
}
|
||||
|
||||
gp_style = gpencil_viewport_material_overrides(pd, ob, color_type, gp_style);
|
||||
|
||||
/* Stroke Style */
|
||||
if ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) && (gp_style->sima)) {
|
||||
bool premul;
|
||||
pool->tex_stroke[mat_id] = gpencil_image_texture_get(gp_style->sima, &premul);
|
||||
mat_data->flag |= pool->tex_stroke[mat_id] ? GP_STROKE_TEXTURE_USE : 0;
|
||||
mat_data->flag |= premul ? GP_STROKE_TEXTURE_PREMUL : 0;
|
||||
copy_v4_v4(mat_data->stroke_color, gp_style->stroke_rgba);
|
||||
mat_data->stroke_texture_mix = 1.0f - gp_style->mix_stroke_factor;
|
||||
mat_data->stroke_u_scale = 500.0f / gp_style->texture_pixsize;
|
||||
}
|
||||
else /* if (gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_SOLID) */ {
|
||||
pool->tex_stroke[mat_id] = NULL;
|
||||
mat_data->flag &= ~GP_STROKE_TEXTURE_USE;
|
||||
copy_v4_v4(mat_data->stroke_color, gp_style->stroke_rgba);
|
||||
mat_data->stroke_texture_mix = 0.0f;
|
||||
}
|
||||
|
||||
/* Fill Style */
|
||||
if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_TEXTURE) && (gp_style->ima)) {
|
||||
bool use_clip = (gp_style->flag & GP_MATERIAL_TEX_CLAMP) != 0;
|
||||
bool premul;
|
||||
pool->tex_fill[mat_id] = gpencil_image_texture_get(gp_style->ima, &premul);
|
||||
mat_data->flag |= pool->tex_fill[mat_id] ? GP_FILL_TEXTURE_USE : 0;
|
||||
mat_data->flag |= premul ? GP_FILL_TEXTURE_PREMUL : 0;
|
||||
mat_data->flag |= use_clip ? GP_FILL_TEXTURE_CLIP : 0;
|
||||
gpencil_uv_transform_get(gp_style->texture_offset,
|
||||
gp_style->texture_scale,
|
||||
gp_style->texture_angle,
|
||||
mat_data->fill_uv_transform);
|
||||
copy_v4_v4(mat_data->fill_color, gp_style->fill_rgba);
|
||||
mat_data->fill_texture_mix = 1.0f - gp_style->mix_factor;
|
||||
}
|
||||
else if (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_GRADIENT) {
|
||||
bool use_radial = (gp_style->gradient_type == GP_MATERIAL_GRADIENT_RADIAL);
|
||||
pool->tex_fill[mat_id] = NULL;
|
||||
mat_data->flag |= GP_FILL_GRADIENT_USE;
|
||||
mat_data->flag |= use_radial ? GP_FILL_GRADIENT_RADIAL : 0;
|
||||
gpencil_uv_transform_get(gp_style->texture_offset,
|
||||
gp_style->texture_scale,
|
||||
gp_style->texture_angle,
|
||||
mat_data->fill_uv_transform);
|
||||
copy_v4_v4(mat_data->fill_color, gp_style->fill_rgba);
|
||||
copy_v4_v4(mat_data->fill_mix_color, gp_style->mix_rgba);
|
||||
mat_data->fill_texture_mix = 1.0f - gp_style->mix_factor;
|
||||
if (gp_style->flag & GP_MATERIAL_FLIP_FILL) {
|
||||
swap_v4_v4(mat_data->fill_color, mat_data->fill_mix_color);
|
||||
}
|
||||
}
|
||||
else /* if (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) */ {
|
||||
pool->tex_fill[mat_id] = NULL;
|
||||
copy_v4_v4(mat_data->fill_color, gp_style->fill_rgba);
|
||||
mat_data->fill_texture_mix = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return matpool;
|
||||
}
|
||||
|
||||
void gpencil_material_resources_get(GPENCIL_MaterialPool *first_pool,
|
||||
int mat_id,
|
||||
GPUTexture **r_tex_stroke,
|
||||
GPUTexture **r_tex_fill,
|
||||
GPUUniformBuffer **r_ubo_mat)
|
||||
{
|
||||
GPENCIL_MaterialPool *matpool = first_pool;
|
||||
int pool_id = mat_id / GP_MATERIAL_BUFFER_LEN;
|
||||
for (int i = 0; i < pool_id; i++) {
|
||||
matpool = matpool->next;
|
||||
}
|
||||
mat_id = mat_id % GP_MATERIAL_BUFFER_LEN;
|
||||
*r_ubo_mat = matpool->ubo;
|
||||
if (r_tex_fill) {
|
||||
*r_tex_fill = matpool->tex_fill[mat_id];
|
||||
}
|
||||
if (r_tex_stroke) {
|
||||
*r_tex_stroke = matpool->tex_stroke[mat_id];
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Lights
|
||||
* \{ */
|
||||
|
||||
GPENCIL_LightPool *gpencil_light_pool_add(GPENCIL_PrivateData *pd)
|
||||
{
|
||||
GPENCIL_LightPool *lightpool = BLI_memblock_alloc(pd->gp_light_pool);
|
||||
lightpool->light_used = 0;
|
||||
/* Tag light list end. */
|
||||
lightpool->light_data[0].color[0] = -1.0;
|
||||
if (lightpool->ubo == NULL) {
|
||||
lightpool->ubo = GPU_uniformbuffer_create(sizeof(lightpool->light_data), NULL, NULL);
|
||||
}
|
||||
pd->last_light_pool = lightpool;
|
||||
return lightpool;
|
||||
}
|
||||
|
||||
void gpencil_light_ambient_add(GPENCIL_LightPool *lightpool, const float color[3])
|
||||
{
|
||||
if (lightpool->light_used >= GPENCIL_LIGHT_BUFFER_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpLight *gp_light = &lightpool->light_data[lightpool->light_used];
|
||||
gp_light->type = GP_LIGHT_TYPE_AMBIENT;
|
||||
copy_v3_v3(gp_light->color, color);
|
||||
lightpool->light_used++;
|
||||
|
||||
if (lightpool->light_used < GPENCIL_LIGHT_BUFFER_LEN) {
|
||||
/* Tag light list end. */
|
||||
gp_light[1].color[0] = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static float light_power_get(const Light *la)
|
||||
{
|
||||
if (la->type == LA_AREA) {
|
||||
return 1.0f / (4.0f * M_PI);
|
||||
}
|
||||
else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
|
||||
return 1.0f / (4.0f * M_PI * M_PI);
|
||||
}
|
||||
else {
|
||||
return 1.0f / M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob)
|
||||
{
|
||||
Light *la = (Light *)ob->data;
|
||||
|
||||
if (lightpool->light_used >= GPENCIL_LIGHT_BUFFER_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpLight *gp_light = &lightpool->light_data[lightpool->light_used];
|
||||
float(*mat)[4] = (float(*)[4])gp_light->right;
|
||||
|
||||
if (la->type == LA_SPOT) {
|
||||
copy_m4_m4(mat, ob->imat);
|
||||
gp_light->type = GP_LIGHT_TYPE_SPOT;
|
||||
gp_light->spotsize = cosf(la->spotsize * 0.5f);
|
||||
gp_light->spotblend = (1.0f - gp_light->spotsize) * la->spotblend;
|
||||
}
|
||||
else if (la->type == LA_AREA) {
|
||||
/* Simulate area lights using a spot light. */
|
||||
normalize_m4_m4(mat, ob->obmat);
|
||||
invert_m4(mat);
|
||||
gp_light->type = GP_LIGHT_TYPE_SPOT;
|
||||
gp_light->spotsize = cosf(M_PI * 0.5f);
|
||||
gp_light->spotblend = (1.0f - gp_light->spotsize) * 1.0f;
|
||||
}
|
||||
else if (la->type == LA_SUN) {
|
||||
normalize_v3_v3(gp_light->forward, ob->obmat[2]);
|
||||
gp_light->type = GP_LIGHT_TYPE_SUN;
|
||||
}
|
||||
else {
|
||||
gp_light->type = GP_LIGHT_TYPE_POINT;
|
||||
}
|
||||
copy_v4_v4(gp_light->position, ob->obmat[3]);
|
||||
copy_v3_v3(gp_light->color, &la->r);
|
||||
mul_v3_fl(gp_light->color, la->energy * light_power_get(la));
|
||||
|
||||
lightpool->light_used++;
|
||||
|
||||
if (lightpool->light_used < GPENCIL_LIGHT_BUFFER_LEN) {
|
||||
/* Tag light list end. */
|
||||
gp_light[1].color[0] = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single pool containing all lights assigned (light linked) for a given object.
|
||||
**/
|
||||
GPENCIL_LightPool *gpencil_light_pool_create(GPENCIL_PrivateData *pd, Object *UNUSED(ob))
|
||||
{
|
||||
GPENCIL_LightPool *lightpool = pd->last_light_pool;
|
||||
|
||||
if (lightpool == NULL) {
|
||||
lightpool = gpencil_light_pool_add(pd);
|
||||
}
|
||||
/* TODO(fclem) Light linking. */
|
||||
// gpencil_light_pool_populate(lightpool, ob);
|
||||
|
||||
return lightpool;
|
||||
}
|
||||
|
||||
void gpencil_material_pool_free(void *storage)
|
||||
{
|
||||
GPENCIL_MaterialPool *matpool = (GPENCIL_MaterialPool *)storage;
|
||||
DRW_UBO_FREE_SAFE(matpool->ubo);
|
||||
}
|
||||
|
||||
void gpencil_light_pool_free(void *storage)
|
||||
{
|
||||
GPENCIL_LightPool *lightpool = (GPENCIL_LightPool *)storage;
|
||||
DRW_UBO_FREE_SAFE(lightpool->ubo);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name View Layer Data
|
||||
* \{ */
|
||||
|
||||
static void gpencil_view_layer_data_free(void *storage)
|
||||
{
|
||||
GPENCIL_ViewLayerData *vldata = (GPENCIL_ViewLayerData *)storage;
|
||||
|
||||
BLI_memblock_destroy(vldata->gp_light_pool, gpencil_light_pool_free);
|
||||
BLI_memblock_destroy(vldata->gp_material_pool, gpencil_material_pool_free);
|
||||
BLI_memblock_destroy(vldata->gp_maskbit_pool, NULL);
|
||||
BLI_memblock_destroy(vldata->gp_object_pool, NULL);
|
||||
BLI_memblock_destroy(vldata->gp_layer_pool, NULL);
|
||||
BLI_memblock_destroy(vldata->gp_vfx_pool, NULL);
|
||||
}
|
||||
|
||||
GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void)
|
||||
{
|
||||
GPENCIL_ViewLayerData **vldata = (GPENCIL_ViewLayerData **)DRW_view_layer_engine_data_ensure(
|
||||
&draw_engine_gpencil_type, gpencil_view_layer_data_free);
|
||||
|
||||
/* NOTE(fclem) Putting this stuff in viewlayer means it is shared by all viewports.
|
||||
* For now it is ok, but in the future, it could become a problem if we implement
|
||||
* the caching system. */
|
||||
if (*vldata == NULL) {
|
||||
*vldata = MEM_callocN(sizeof(**vldata), "GPENCIL_ViewLayerData");
|
||||
|
||||
(*vldata)->gp_light_pool = BLI_memblock_create(sizeof(GPENCIL_LightPool));
|
||||
(*vldata)->gp_material_pool = BLI_memblock_create(sizeof(GPENCIL_MaterialPool));
|
||||
(*vldata)->gp_maskbit_pool = BLI_memblock_create(BLI_BITMAP_SIZE(GP_MAX_MASKBITS));
|
||||
(*vldata)->gp_object_pool = BLI_memblock_create(sizeof(GPENCIL_tObject));
|
||||
(*vldata)->gp_layer_pool = BLI_memblock_create(sizeof(GPENCIL_tLayer));
|
||||
(*vldata)->gp_vfx_pool = BLI_memblock_create(sizeof(GPENCIL_tVfx));
|
||||
}
|
||||
|
||||
return *vldata;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,10 @@
|
||||
#ifndef __GPENCIL_ENGINE_H__
|
||||
#define __GPENCIL_ENGINE_H__
|
||||
|
||||
#include "DNA_gpencil_types.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
|
||||
extern DrawEngineType draw_engine_gpencil_type;
|
||||
@@ -34,204 +38,201 @@ struct Object;
|
||||
struct RenderEngine;
|
||||
struct RenderLayer;
|
||||
struct bGPDstroke;
|
||||
|
||||
struct View3D;
|
||||
struct GpencilBatchCache;
|
||||
struct GPUBatch;
|
||||
struct GPUVertBuf;
|
||||
struct GPUVertFormat;
|
||||
|
||||
#define GPENCIL_MAX_SHGROUPS 65536
|
||||
#define GPENCIL_GROUPS_BLOCK_SIZE 1024
|
||||
/* used to convert pixel scale. */
|
||||
#define GPENCIL_PIXEL_FACTOR 2000.0f
|
||||
|
||||
/* used to expand VBOs. Size has a big impact in the speed */
|
||||
#define GPENCIL_VBO_BLOCK_SIZE 128
|
||||
|
||||
#define GPENCIL_COLOR_SOLID 0
|
||||
#define GPENCIL_COLOR_TEXTURE 1
|
||||
#define GPENCIL_COLOR_PATTERN 2
|
||||
#define GP_MAX_MASKBITS 256
|
||||
|
||||
/* *********** OBJECTS CACHE *********** */
|
||||
typedef struct tGPencilObjectCache_shgrp {
|
||||
/** type of blend (regular, add, mult, etc...) */
|
||||
int mode;
|
||||
/** flag to enable the layer clamping */
|
||||
bool mask_layer;
|
||||
/** factor to define the opacity of the layer */
|
||||
float blend_opacity;
|
||||
DRWShadingGroup *init_shgrp;
|
||||
DRWShadingGroup *end_shgrp;
|
||||
} tGPencilObjectCache_shgrp;
|
||||
/* UBO structure. Watch out for padding. Must match GLSL declaration. */
|
||||
typedef struct gpMaterial {
|
||||
float stroke_color[4];
|
||||
float fill_color[4];
|
||||
float fill_mix_color[4];
|
||||
float fill_uv_transform[3][2], _pad0[2];
|
||||
float stroke_texture_mix;
|
||||
float stroke_u_scale;
|
||||
float fill_texture_mix;
|
||||
int flag;
|
||||
} gpMaterial;
|
||||
|
||||
/* used to save gpencil object data for drawing */
|
||||
typedef struct tGPencilObjectCache {
|
||||
struct Object *ob;
|
||||
struct bGPdata *gpd;
|
||||
int idx; /*original index, can change after sort */
|
||||
char *name;
|
||||
/* gpMaterial->flag */
|
||||
/* WATCH Keep in sync with GLSL declaration. */
|
||||
#define GP_STROKE_ALIGNMENT_STROKE 1
|
||||
#define GP_STROKE_ALIGNMENT_OBJECT 2
|
||||
#define GP_STROKE_ALIGNMENT_FIXED 3
|
||||
#define GP_STROKE_ALIGNMENT 0x3
|
||||
#define GP_STROKE_OVERLAP (1 << 2)
|
||||
#define GP_STROKE_TEXTURE_USE (1 << 3)
|
||||
#define GP_STROKE_TEXTURE_STENCIL (1 << 4)
|
||||
#define GP_STROKE_TEXTURE_PREMUL (1 << 5)
|
||||
#define GP_STROKE_DOTS (1 << 6)
|
||||
#define GP_FILL_TEXTURE_USE (1 << 10)
|
||||
#define GP_FILL_TEXTURE_PREMUL (1 << 11)
|
||||
#define GP_FILL_TEXTURE_CLIP (1 << 12)
|
||||
#define GP_FILL_GRADIENT_USE (1 << 13)
|
||||
#define GP_FILL_GRADIENT_RADIAL (1 << 14)
|
||||
|
||||
/* effects */
|
||||
bool has_fx;
|
||||
ListBase shader_fx;
|
||||
float pixfactor;
|
||||
DRWShadingGroup *fx_wave_sh;
|
||||
DRWShadingGroup *fx_blur_sh;
|
||||
DRWShadingGroup *fx_colorize_sh;
|
||||
DRWShadingGroup *fx_pixel_sh;
|
||||
DRWShadingGroup *fx_rim_sh;
|
||||
DRWShadingGroup *fx_shadow_sh;
|
||||
DRWShadingGroup *fx_glow_sh;
|
||||
DRWShadingGroup *fx_swirl_sh;
|
||||
DRWShadingGroup *fx_flip_sh;
|
||||
DRWShadingGroup *fx_light_sh;
|
||||
#define GPENCIL_LIGHT_BUFFER_LEN 128
|
||||
|
||||
float loc[3];
|
||||
float obmat[4][4];
|
||||
float zdepth; /* z-depth value to sort gp object */
|
||||
bool is_dup_ob; /* flag to tag duplicate objects */
|
||||
float scale;
|
||||
/* UBO structure. Watch out for padding. Must match GLSL declaration. */
|
||||
typedef struct gpLight {
|
||||
float color[3], type;
|
||||
float right[3], spotsize;
|
||||
float up[3], spotblend;
|
||||
float forward[4];
|
||||
float position[4];
|
||||
} gpLight;
|
||||
|
||||
/* shading type */
|
||||
int shading_type[2];
|
||||
/* gpLight->type */
|
||||
/* WATCH Keep in sync with GLSL declaration. */
|
||||
#define GP_LIGHT_TYPE_POINT 0.0
|
||||
#define GP_LIGHT_TYPE_SPOT 1.0
|
||||
#define GP_LIGHT_TYPE_SUN 2.0
|
||||
#define GP_LIGHT_TYPE_AMBIENT 3.0
|
||||
|
||||
/* GPU data size */
|
||||
int tot_vertex;
|
||||
int tot_triangles;
|
||||
BLI_STATIC_ASSERT_ALIGN(gpMaterial, 16)
|
||||
BLI_STATIC_ASSERT_ALIGN(gpLight, 16)
|
||||
|
||||
/* Save shader groups by layer */
|
||||
int tot_layers;
|
||||
tGPencilObjectCache_shgrp *shgrp_array;
|
||||
/* *********** Draw Datas *********** */
|
||||
typedef struct GPENCIL_MaterialPool {
|
||||
/* Linklist. */
|
||||
struct GPENCIL_MaterialPool *next;
|
||||
/* GPU representatin of materials. */
|
||||
gpMaterial mat_data[GP_MATERIAL_BUFFER_LEN];
|
||||
/* Matching ubo. */
|
||||
struct GPUUniformBuffer *ubo;
|
||||
/* Texture per material. NULL means none. */
|
||||
struct GPUTexture *tex_fill[GP_MATERIAL_BUFFER_LEN];
|
||||
struct GPUTexture *tex_stroke[GP_MATERIAL_BUFFER_LEN];
|
||||
/* Number of material used in this pool. */
|
||||
int used_count;
|
||||
} GPENCIL_MaterialPool;
|
||||
|
||||
} tGPencilObjectCache;
|
||||
typedef struct GPENCIL_LightPool {
|
||||
/* GPU representatin of materials. */
|
||||
gpLight light_data[GPENCIL_LIGHT_BUFFER_LEN];
|
||||
/* Matching ubo. */
|
||||
struct GPUUniformBuffer *ubo;
|
||||
/* Number of light in the pool. */
|
||||
int light_used;
|
||||
} GPENCIL_LightPool;
|
||||
|
||||
typedef struct GPENCIL_ViewLayerData {
|
||||
/* GPENCIL_tObject */
|
||||
struct BLI_memblock *gp_object_pool;
|
||||
/* GPENCIL_tLayer */
|
||||
struct BLI_memblock *gp_layer_pool;
|
||||
/* GPENCIL_tVfx */
|
||||
struct BLI_memblock *gp_vfx_pool;
|
||||
/* GPENCIL_MaterialPool */
|
||||
struct BLI_memblock *gp_material_pool;
|
||||
/* GPENCIL_LightPool */
|
||||
struct BLI_memblock *gp_light_pool;
|
||||
/* BLI_bitmap */
|
||||
struct BLI_memblock *gp_maskbit_pool;
|
||||
} GPENCIL_ViewLayerData;
|
||||
|
||||
/* *********** GPencil *********** */
|
||||
|
||||
typedef struct GPENCIL_tVfx {
|
||||
/** Linklist */
|
||||
struct GPENCIL_tVfx *next;
|
||||
DRWPass *vfx_ps;
|
||||
/* Framebuffer reference since it may not be allocated yet. */
|
||||
GPUFrameBuffer **target_fb;
|
||||
} GPENCIL_tVfx;
|
||||
|
||||
typedef struct GPENCIL_tLayer {
|
||||
/** Linklist */
|
||||
struct GPENCIL_tLayer *next;
|
||||
/** Geometry pass (draw all strokes). */
|
||||
DRWPass *geom_ps;
|
||||
/** Blend pass to composite onto the target buffer (blends modes). NULL if not needed. */
|
||||
DRWPass *blend_ps;
|
||||
/** First shading group created for this layer. Contains all uniforms. */
|
||||
DRWShadingGroup *base_shgrp;
|
||||
/** Layer id of the mask. */
|
||||
BLI_bitmap *mask_bits;
|
||||
BLI_bitmap *mask_invert_bits;
|
||||
/** Index in the layer list. Used as id for masking. */
|
||||
int layer_id;
|
||||
} GPENCIL_tLayer;
|
||||
|
||||
typedef struct GPENCIL_tObject {
|
||||
/** Linklist */
|
||||
struct GPENCIL_tObject *next;
|
||||
|
||||
struct {
|
||||
GPENCIL_tLayer *first, *last;
|
||||
} layers;
|
||||
|
||||
struct {
|
||||
GPENCIL_tVfx *first, *last;
|
||||
} vfx;
|
||||
|
||||
/* Distance to camera. Used for sorting. */
|
||||
float camera_z;
|
||||
/* Used for stroke thickness scaling. */
|
||||
float object_scale;
|
||||
/* Normal used for shading. Based on view angle. */
|
||||
float plane_normal[3];
|
||||
/* Used for drawing depth merge pass. */
|
||||
float plane_mat[4][4];
|
||||
|
||||
bool is_drawmode3d;
|
||||
} GPENCIL_tObject;
|
||||
|
||||
/* *********** LISTS *********** */
|
||||
typedef struct GPENCIL_shgroup {
|
||||
int s_clamp;
|
||||
int stroke_style;
|
||||
int color_type;
|
||||
int mode;
|
||||
int texture_mix;
|
||||
int texture_flip;
|
||||
int texture_clamp;
|
||||
int fill_style;
|
||||
int keep_size;
|
||||
int caps_mode[2];
|
||||
float obj_scale;
|
||||
int xray_mode;
|
||||
int alignment_mode;
|
||||
|
||||
float gradient_f;
|
||||
float gradient_s[2];
|
||||
|
||||
float mix_stroke_factor;
|
||||
|
||||
/* color of the wireframe */
|
||||
float wire_color[4];
|
||||
/* shading type and mode */
|
||||
int shading_type[2];
|
||||
int is_xray;
|
||||
} GPENCIL_shgroup;
|
||||
|
||||
typedef struct GPENCIL_Storage {
|
||||
int shgroup_id; /* total elements */
|
||||
int stroke_style;
|
||||
int color_type;
|
||||
int mode;
|
||||
int xray;
|
||||
int keep_size;
|
||||
float obj_scale;
|
||||
float pixfactor;
|
||||
bool is_playing;
|
||||
bool is_render;
|
||||
bool is_mat_preview;
|
||||
bool is_main_overlay;
|
||||
bool is_main_onion;
|
||||
bool background_ready;
|
||||
int is_xray;
|
||||
bool is_ontop;
|
||||
bool reset_cache;
|
||||
const float *pixsize;
|
||||
float render_pixsize;
|
||||
int tonemapping;
|
||||
int do_select_outline;
|
||||
float select_color[4];
|
||||
short multisamples;
|
||||
float grid_matrix[4][4];
|
||||
|
||||
short framebuffer_flag; /* flag what framebuffer need to create */
|
||||
|
||||
int blend_mode;
|
||||
int mask_layer;
|
||||
|
||||
/* simplify settings*/
|
||||
bool simplify_fill;
|
||||
bool simplify_modif;
|
||||
bool simplify_fx;
|
||||
bool simplify_blend;
|
||||
|
||||
float gradient_f;
|
||||
float gradient_s[2];
|
||||
int alignment_mode;
|
||||
|
||||
float mix_stroke_factor;
|
||||
|
||||
/* Render Matrices and data */
|
||||
float view_vecs[2][4]; /* vec4[2] */
|
||||
|
||||
int shade_render[2];
|
||||
|
||||
Object *camera; /* camera pointer for render mode */
|
||||
} GPENCIL_Storage;
|
||||
|
||||
typedef enum eGpencilFramebuffer_Flag {
|
||||
GP_FRAMEBUFFER_MULTISAMPLE = (1 << 0),
|
||||
GP_FRAMEBUFFER_BASIC = (1 << 1),
|
||||
GP_FRAMEBUFFER_DRAW = (1 << 2),
|
||||
} eGpencilFramebuffer_Flag;
|
||||
|
||||
typedef struct GPENCIL_StorageList {
|
||||
struct GPENCIL_Storage *storage;
|
||||
struct g_data *g_data;
|
||||
struct GPENCIL_shgroup *shgroups;
|
||||
struct GPENCIL_PrivateData *pd;
|
||||
} GPENCIL_StorageList;
|
||||
|
||||
typedef struct GPENCIL_PassList {
|
||||
struct DRWPass *stroke_pass_2d;
|
||||
struct DRWPass *stroke_pass_3d;
|
||||
struct DRWPass *edit_pass;
|
||||
struct DRWPass *drawing_pass;
|
||||
struct DRWPass *mix_pass;
|
||||
struct DRWPass *mix_pass_noblend;
|
||||
struct DRWPass *background_pass;
|
||||
struct DRWPass *paper_pass;
|
||||
struct DRWPass *grid_pass;
|
||||
struct DRWPass *blend_pass;
|
||||
|
||||
/* effects */
|
||||
struct DRWPass *fx_shader_pass;
|
||||
struct DRWPass *fx_shader_pass_blend;
|
||||
|
||||
/* Composite the main GPencil buffer onto the rendered image. */
|
||||
struct DRWPass *composite_ps;
|
||||
/* Composite the object depth to the default depth buffer to occlude overlays. */
|
||||
struct DRWPass *merge_depth_ps;
|
||||
/* Invert mask buffer content. */
|
||||
struct DRWPass *mask_invert_ps;
|
||||
/* Anti-Aliasing. */
|
||||
struct DRWPass *smaa_edge_ps;
|
||||
struct DRWPass *smaa_weight_ps;
|
||||
struct DRWPass *smaa_resolve_ps;
|
||||
} GPENCIL_PassList;
|
||||
|
||||
typedef struct GPENCIL_FramebufferList {
|
||||
struct GPUFrameBuffer *main;
|
||||
struct GPUFrameBuffer *temp_fb_a;
|
||||
struct GPUFrameBuffer *temp_fb_b;
|
||||
struct GPUFrameBuffer *temp_fb_fx;
|
||||
struct GPUFrameBuffer *background_fb;
|
||||
|
||||
struct GPUFrameBuffer *multisample_fb;
|
||||
struct GPUFrameBuffer *render_fb;
|
||||
struct GPUFrameBuffer *gpencil_fb;
|
||||
struct GPUFrameBuffer *snapshot_fb;
|
||||
struct GPUFrameBuffer *layer_fb;
|
||||
struct GPUFrameBuffer *object_fb;
|
||||
struct GPUFrameBuffer *mask_fb;
|
||||
struct GPUFrameBuffer *smaa_edge_fb;
|
||||
struct GPUFrameBuffer *smaa_weight_fb;
|
||||
} GPENCIL_FramebufferList;
|
||||
|
||||
typedef struct GPENCIL_TextureList {
|
||||
struct GPUTexture *texture;
|
||||
|
||||
/* multisample textures */
|
||||
struct GPUTexture *multisample_color;
|
||||
struct GPUTexture *multisample_depth;
|
||||
|
||||
/* Background textures for speed-up drawing. */
|
||||
struct GPUTexture *background_depth_tx;
|
||||
struct GPUTexture *background_color_tx;
|
||||
|
||||
/* Dummy texture to avoid errors cause by empty sampler. */
|
||||
struct GPUTexture *dummy_texture;
|
||||
/* Snapshot for smoother drawing. */
|
||||
struct GPUTexture *snapshot_depth_tx;
|
||||
struct GPUTexture *snapshot_color_tx;
|
||||
struct GPUTexture *snapshot_reveal_tx;
|
||||
/* Textures used by Antialiasing. */
|
||||
struct GPUTexture *smaa_area_tx;
|
||||
struct GPUTexture *smaa_search_tx;
|
||||
/* Textures used during render. Containing underlying rendered scene. */
|
||||
struct GPUTexture *render_depth_tx;
|
||||
struct GPUTexture *render_color_tx;
|
||||
} GPENCIL_TextureList;
|
||||
|
||||
typedef struct GPENCIL_Data {
|
||||
@@ -240,248 +241,175 @@ typedef struct GPENCIL_Data {
|
||||
struct GPENCIL_TextureList *txl;
|
||||
struct GPENCIL_PassList *psl;
|
||||
struct GPENCIL_StorageList *stl;
|
||||
|
||||
/* render textures */
|
||||
struct GPUTexture *render_depth_tx;
|
||||
struct GPUTexture *render_color_tx;
|
||||
|
||||
} GPENCIL_Data;
|
||||
|
||||
/* *********** STATIC *********** */
|
||||
typedef struct g_data {
|
||||
struct DRWShadingGroup *shgrps_edit_point;
|
||||
struct DRWShadingGroup *shgrps_edit_line;
|
||||
struct DRWShadingGroup *shgrps_drawing_stroke;
|
||||
struct DRWShadingGroup *shgrps_drawing_fill;
|
||||
struct DRWShadingGroup *shgrps_grid;
|
||||
typedef struct GPENCIL_PrivateData {
|
||||
/* Pointers copied from GPENCIL_ViewLayerData. */
|
||||
struct BLI_memblock *gp_object_pool;
|
||||
struct BLI_memblock *gp_layer_pool;
|
||||
struct BLI_memblock *gp_vfx_pool;
|
||||
struct BLI_memblock *gp_material_pool;
|
||||
struct BLI_memblock *gp_light_pool;
|
||||
struct BLI_memblock *gp_maskbit_pool;
|
||||
/* Last used material pool. */
|
||||
GPENCIL_MaterialPool *last_material_pool;
|
||||
/* Last used light pool. */
|
||||
GPENCIL_LightPool *last_light_pool;
|
||||
/* Common lightpool containing all lights in the scene. */
|
||||
GPENCIL_LightPool *global_light_pool;
|
||||
/* Common lightpool containing one ambient white light. */
|
||||
GPENCIL_LightPool *shadeless_light_pool;
|
||||
/* Linked list of tObjects. */
|
||||
struct {
|
||||
GPENCIL_tObject *first, *last;
|
||||
} tobjects, tobjects_infront;
|
||||
/* Temp Textures (shared with other engines). */
|
||||
GPUTexture *depth_tx;
|
||||
GPUTexture *color_tx;
|
||||
GPUTexture *color_layer_tx;
|
||||
GPUTexture *color_object_tx;
|
||||
/* Revealage is 1 - alpha */
|
||||
GPUTexture *reveal_tx;
|
||||
GPUTexture *reveal_layer_tx;
|
||||
GPUTexture *reveal_object_tx;
|
||||
/* Mask texture */
|
||||
GPUTexture *mask_tx;
|
||||
/* Anti-Aliasing. */
|
||||
GPUTexture *smaa_edge_tx;
|
||||
GPUTexture *smaa_weight_tx;
|
||||
/* Pointer to dtxl->depth */
|
||||
GPUTexture *scene_depth_tx;
|
||||
GPUFrameBuffer *scene_fb;
|
||||
/* Copy of txl->dummy_tx */
|
||||
GPUTexture *dummy_tx;
|
||||
/* Copy of v3d->shading.single_color. */
|
||||
float v3d_single_color[3];
|
||||
/* Copy of v3d->shading.color_type or -1 to ignore. */
|
||||
int v3d_color_type;
|
||||
/* Current frame */
|
||||
int cfra;
|
||||
/* If we are rendering for final render (F12). */
|
||||
bool is_render;
|
||||
/* If we are in viewport display (used for VFX). */
|
||||
bool is_viewport;
|
||||
/* True in selection and auto_depth drawing */
|
||||
bool draw_depth_only;
|
||||
/* Is shading set to wireframe. */
|
||||
bool draw_wireframe;
|
||||
/* Used by the depth merge step. */
|
||||
int is_stroke_order_3d;
|
||||
float object_bound_mat[4][4];
|
||||
/* Used for computing object distance to camera. */
|
||||
float camera_z_axis[3], camera_z_offset;
|
||||
float camera_pos[3];
|
||||
/* Pseudo depth of field parameter. Used to scale blur radius. */
|
||||
float dof_params[2];
|
||||
/* Used for DoF Setup. */
|
||||
Object *camera;
|
||||
/* Copy of draw_ctx->scene for convenience. */
|
||||
struct Scene *scene;
|
||||
|
||||
int gp_cache_used; /* total objects in cache */
|
||||
int gp_cache_size; /* size of the cache */
|
||||
struct tGPencilObjectCache *gp_object_cache;
|
||||
/* Active object. */
|
||||
Object *obact;
|
||||
/* Object being in draw mode. */
|
||||
struct bGPdata *sbuffer_gpd;
|
||||
/* Layer to append the temp stroke to. */
|
||||
struct bGPDlayer *sbuffer_layer;
|
||||
/* Temporary stroke currently being drawn. */
|
||||
struct bGPDstroke *sbuffer_stroke;
|
||||
/* List of temp objects containing the stroke. */
|
||||
struct {
|
||||
GPENCIL_tObject *first, *last;
|
||||
} sbuffer_tobjects;
|
||||
/* Batches containing the temp stroke. */
|
||||
GPUBatch *stroke_batch;
|
||||
GPUBatch *fill_batch;
|
||||
bool do_fast_drawing;
|
||||
bool snapshot_buffer_dirty;
|
||||
|
||||
/* for buffer only one batch is nedeed because the drawing is only of one stroke */
|
||||
GPUBatch *batch_buffer_stroke;
|
||||
GPUBatch *batch_buffer_fill;
|
||||
GPUBatch *batch_buffer_ctrlpoint;
|
||||
|
||||
/* grid geometry */
|
||||
GPUBatch *batch_grid;
|
||||
|
||||
/* runtime pointers texture */
|
||||
struct GPUTexture *input_depth_tx;
|
||||
struct GPUTexture *input_color_tx;
|
||||
|
||||
/* working textures */
|
||||
struct GPUTexture *temp_color_tx_a;
|
||||
struct GPUTexture *temp_depth_tx_a;
|
||||
|
||||
struct GPUTexture *temp_color_tx_b;
|
||||
struct GPUTexture *temp_depth_tx_b;
|
||||
|
||||
struct GPUTexture *temp_color_tx_fx;
|
||||
struct GPUTexture *temp_depth_tx_fx;
|
||||
|
||||
int session_flag;
|
||||
bool do_instances;
|
||||
|
||||
} g_data; /* Transient data */
|
||||
|
||||
/* flags for fast drawing support */
|
||||
typedef enum eGPsession_Flag {
|
||||
GP_DRW_PAINT_HOLD = (1 << 0),
|
||||
GP_DRW_PAINT_IDLE = (1 << 1),
|
||||
GP_DRW_PAINT_FILLING = (1 << 2),
|
||||
GP_DRW_PAINT_READY = (1 << 3),
|
||||
GP_DRW_PAINT_PAINTING = (1 << 4),
|
||||
} eGPsession_Flag;
|
||||
|
||||
typedef struct GPENCIL_e_data {
|
||||
/* textures */
|
||||
struct GPUTexture *gpencil_blank_texture;
|
||||
|
||||
/* general drawing shaders */
|
||||
struct GPUShader *gpencil_fill_sh;
|
||||
struct GPUShader *gpencil_stroke_sh;
|
||||
struct GPUShader *gpencil_point_sh;
|
||||
struct GPUShader *gpencil_edit_point_sh;
|
||||
struct GPUShader *gpencil_line_sh;
|
||||
struct GPUShader *gpencil_drawing_fill_sh;
|
||||
struct GPUShader *gpencil_fullscreen_sh;
|
||||
struct GPUShader *gpencil_simple_fullscreen_sh;
|
||||
struct GPUShader *gpencil_blend_fullscreen_sh;
|
||||
struct GPUShader *gpencil_background_sh;
|
||||
struct GPUShader *gpencil_paper_sh;
|
||||
|
||||
/* effects */
|
||||
struct GPUShader *gpencil_fx_blur_sh;
|
||||
struct GPUShader *gpencil_fx_colorize_sh;
|
||||
struct GPUShader *gpencil_fx_flip_sh;
|
||||
struct GPUShader *gpencil_fx_glow_prepare_sh;
|
||||
struct GPUShader *gpencil_fx_glow_resolve_sh;
|
||||
struct GPUShader *gpencil_fx_light_sh;
|
||||
struct GPUShader *gpencil_fx_pixel_sh;
|
||||
struct GPUShader *gpencil_fx_rim_prepare_sh;
|
||||
struct GPUShader *gpencil_fx_rim_resolve_sh;
|
||||
struct GPUShader *gpencil_fx_shadow_prepare_sh;
|
||||
struct GPUShader *gpencil_fx_shadow_resolve_sh;
|
||||
struct GPUShader *gpencil_fx_swirl_sh;
|
||||
struct GPUShader *gpencil_fx_wave_sh;
|
||||
|
||||
} GPENCIL_e_data; /* Engine data */
|
||||
|
||||
/* GPUBatch Cache Element */
|
||||
typedef struct GpencilBatchCacheElem {
|
||||
GPUBatch *batch;
|
||||
GPUVertBuf *vbo;
|
||||
int vbo_len;
|
||||
/* attr ids */
|
||||
GPUVertFormat *format;
|
||||
uint pos_id;
|
||||
uint color_id;
|
||||
uint thickness_id;
|
||||
uint uvdata_id;
|
||||
uint prev_pos_id;
|
||||
|
||||
/* size for VBO alloc */
|
||||
int tot_vertex;
|
||||
} GpencilBatchCacheElem;
|
||||
|
||||
/* Defines each batch group to define later the shgroup */
|
||||
typedef struct GpencilBatchGroup {
|
||||
struct bGPDlayer *gpl; /* reference to original layer */
|
||||
struct bGPDframe *gpf; /* reference to original frame */
|
||||
struct bGPDstroke *gps; /* reference to original stroke */
|
||||
short type; /* type of element */
|
||||
bool onion; /* the group is part of onion skin */
|
||||
int vertex_idx; /* index of vertex data */
|
||||
} GpencilBatchGroup;
|
||||
|
||||
typedef enum GpencilBatchGroup_Type {
|
||||
eGpencilBatchGroupType_Stroke = 1,
|
||||
eGpencilBatchGroupType_Point = 2,
|
||||
eGpencilBatchGroupType_Fill = 3,
|
||||
eGpencilBatchGroupType_Edit = 4,
|
||||
eGpencilBatchGroupType_Edlin = 5,
|
||||
} GpencilBatchGroup_Type;
|
||||
|
||||
/* Runtime data for GPU and evaluated frames after applying modifiers */
|
||||
typedef struct GpencilBatchCache {
|
||||
GpencilBatchCacheElem b_stroke;
|
||||
GpencilBatchCacheElem b_point;
|
||||
GpencilBatchCacheElem b_fill;
|
||||
GpencilBatchCacheElem b_edit;
|
||||
GpencilBatchCacheElem b_edlin;
|
||||
|
||||
/** Cache is dirty */
|
||||
bool is_dirty;
|
||||
/** Edit mode flag */
|
||||
bool is_editmode;
|
||||
/** Last cache frame */
|
||||
int cache_frame;
|
||||
|
||||
/** Total groups in arrays */
|
||||
int grp_used;
|
||||
/** Max size of the array */
|
||||
int grp_size;
|
||||
/** Array of cache elements */
|
||||
struct GpencilBatchGroup *grp_cache;
|
||||
} GpencilBatchCache;
|
||||
|
||||
/* general drawing functions */
|
||||
struct DRWShadingGroup *gpencil_shgroup_stroke_create(struct GPENCIL_e_data *e_data,
|
||||
struct GPENCIL_Data *vedata,
|
||||
struct DRWPass *pass,
|
||||
struct GPUShader *shader,
|
||||
struct Object *ob,
|
||||
float (*obmat)[4],
|
||||
struct bGPdata *gpd,
|
||||
struct bGPDlayer *gpl,
|
||||
struct bGPDstroke *gps,
|
||||
struct MaterialGPencilStyle *gp_style,
|
||||
int id,
|
||||
bool onion,
|
||||
const float scale,
|
||||
const int shading_type[2]);
|
||||
void gpencil_populate_datablock(struct GPENCIL_e_data *e_data,
|
||||
void *vedata,
|
||||
struct Object *ob,
|
||||
struct tGPencilObjectCache *cache_ob);
|
||||
void gpencil_populate_buffer_strokes(struct GPENCIL_e_data *e_data,
|
||||
void *vedata,
|
||||
struct ToolSettings *ts,
|
||||
struct Object *ob);
|
||||
void gpencil_populate_multiedit(struct GPENCIL_e_data *e_data,
|
||||
void *vedata,
|
||||
struct Object *ob,
|
||||
struct tGPencilObjectCache *cache_ob);
|
||||
void gpencil_populate_particles(struct GPENCIL_e_data *e_data,
|
||||
struct GHash *gh_objects,
|
||||
void *vedata);
|
||||
|
||||
void gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int rect_h);
|
||||
|
||||
/* create geometry functions */
|
||||
void gpencil_get_point_geom(struct GpencilBatchCacheElem *be,
|
||||
struct bGPDstroke *gps,
|
||||
short thickness,
|
||||
const float ink[4],
|
||||
const int follow_mode);
|
||||
void gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be,
|
||||
struct bGPDstroke *gps,
|
||||
short thickness,
|
||||
const float ink[4]);
|
||||
void gpencil_get_fill_geom(struct GpencilBatchCacheElem *be,
|
||||
struct Object *ob,
|
||||
struct bGPDstroke *gps,
|
||||
const float color[4]);
|
||||
void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
|
||||
struct bGPDstroke *gps,
|
||||
float alpha,
|
||||
short dflag);
|
||||
void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
|
||||
struct bGPDstroke *gps,
|
||||
float alpha,
|
||||
const bool hide_select);
|
||||
|
||||
struct GPUBatch *gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness);
|
||||
struct GPUBatch *gpencil_get_buffer_fill_geom(struct bGPdata *gpd);
|
||||
struct GPUBatch *gpencil_get_buffer_point_geom(struct bGPdata *gpd, short thickness);
|
||||
struct GPUBatch *gpencil_get_buffer_ctrlpoint_geom(struct bGPdata *gpd);
|
||||
struct GPUBatch *gpencil_get_grid(Object *ob);
|
||||
|
||||
/* object cache functions */
|
||||
struct tGPencilObjectCache *gpencil_object_cache_add(struct tGPencilObjectCache *cache_array,
|
||||
struct Object *ob,
|
||||
int *gp_cache_size,
|
||||
int *gp_cache_used);
|
||||
|
||||
bool gpencil_onion_active(struct bGPdata *gpd);
|
||||
|
||||
/* shading groups cache functions */
|
||||
struct GpencilBatchGroup *gpencil_group_cache_add(struct GpencilBatchGroup *cache_array,
|
||||
struct bGPDlayer *gpl,
|
||||
struct bGPDframe *gpf,
|
||||
struct bGPDstroke *gps,
|
||||
const short type,
|
||||
const bool onion,
|
||||
const int vertex_idx,
|
||||
int *grp_size,
|
||||
int *grp_used);
|
||||
/* Display onion skinning */
|
||||
bool do_onion;
|
||||
/* simplify settings */
|
||||
bool simplify_fill;
|
||||
bool simplify_fx;
|
||||
bool simplify_antialias;
|
||||
/* Use scene lighting or flat shading (global setting). */
|
||||
bool use_lighting;
|
||||
/* Use physical lights or just ambient lighting. */
|
||||
bool use_lights;
|
||||
/* Do we need additional framebuffers? */
|
||||
bool use_layer_fb;
|
||||
bool use_object_fb;
|
||||
bool use_mask_fb;
|
||||
/* Some blend mode needs to add negative values.
|
||||
* This is only supported if target texture is signed. */
|
||||
bool use_signed_fb;
|
||||
/* Use only lines for multiedit and not active frame. */
|
||||
bool use_multiedit_lines_only;
|
||||
/* Layer opacity for fading. */
|
||||
float fade_layer_opacity;
|
||||
/* Opacity for fading gpencil objects. */
|
||||
float fade_gp_object_opacity;
|
||||
/* Opacity for fading 3D objects. */
|
||||
float fade_3d_object_opacity;
|
||||
/* Mask opacity uniform. */
|
||||
float mask_opacity;
|
||||
/* Xray transparency in solid mode. */
|
||||
float xray_alpha;
|
||||
/* Mask invert uniform. */
|
||||
int mask_invert;
|
||||
} GPENCIL_PrivateData;
|
||||
|
||||
/* geometry batch cache functions */
|
||||
struct GpencilBatchCache *gpencil_batch_cache_get(struct Object *ob, int cfra);
|
||||
|
||||
/* effects */
|
||||
void GPENCIL_create_fx_shaders(struct GPENCIL_e_data *e_data);
|
||||
void GPENCIL_delete_fx_shaders(struct GPENCIL_e_data *e_data);
|
||||
void GPENCIL_create_fx_passes(struct GPENCIL_PassList *psl);
|
||||
GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob);
|
||||
void gpencil_object_cache_sort(GPENCIL_PrivateData *pd);
|
||||
|
||||
void gpencil_fx_prepare(struct GPENCIL_e_data *e_data,
|
||||
struct GPENCIL_Data *vedata,
|
||||
struct tGPencilObjectCache *cache_ob);
|
||||
void gpencil_fx_draw(struct GPENCIL_e_data *e_data,
|
||||
struct GPENCIL_Data *vedata,
|
||||
struct tGPencilObjectCache *cache_ob);
|
||||
GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
|
||||
const Object *ob,
|
||||
const bGPDlayer *gpl,
|
||||
const bGPDframe *gpf,
|
||||
GPENCIL_tObject *tgp_ob);
|
||||
GPENCIL_tLayer *gpencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int number);
|
||||
|
||||
GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Object *ob, int *ofs);
|
||||
void gpencil_material_resources_get(GPENCIL_MaterialPool *first_pool,
|
||||
int mat_id,
|
||||
struct GPUTexture **r_tex_stroke,
|
||||
struct GPUTexture **r_tex_fill,
|
||||
struct GPUUniformBuffer **r_ubo_mat);
|
||||
|
||||
void gpencil_light_ambient_add(GPENCIL_LightPool *lightpool, const float color[3]);
|
||||
void gpencil_light_pool_populate(GPENCIL_LightPool *matpool, Object *ob);
|
||||
GPENCIL_LightPool *gpencil_light_pool_add(GPENCIL_PrivateData *pd);
|
||||
GPENCIL_LightPool *gpencil_light_pool_create(GPENCIL_PrivateData *pd, Object *ob);
|
||||
|
||||
/* effects */
|
||||
void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObject *tgp_ob);
|
||||
|
||||
/* Shaders */
|
||||
struct GPUShader *GPENCIL_shader_antialiasing(int stage);
|
||||
struct GPUShader *GPENCIL_shader_geometry_get(void);
|
||||
struct GPUShader *GPENCIL_shader_composite_get(void);
|
||||
struct GPUShader *GPENCIL_shader_layer_blend_get(void);
|
||||
struct GPUShader *GPENCIL_shader_mask_invert_get(void);
|
||||
struct GPUShader *GPENCIL_shader_depth_merge_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_blur_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_colorize_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_composite_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_transform_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_glow_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_pixelize_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_rim_get(void);
|
||||
struct GPUShader *GPENCIL_shader_fx_shadow_get(void);
|
||||
|
||||
void GPENCIL_shader_free(void);
|
||||
|
||||
/* Antialiasing */
|
||||
void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata);
|
||||
void GPENCIL_antialiasing_draw(struct GPENCIL_Data *vedata);
|
||||
|
||||
/* main functions */
|
||||
void GPENCIL_engine_init(void *vedata);
|
||||
@@ -493,43 +421,17 @@ void GPENCIL_draw_scene(void *vedata);
|
||||
/* render */
|
||||
void GPENCIL_render_init(struct GPENCIL_Data *ved,
|
||||
struct RenderEngine *engine,
|
||||
struct Depsgraph *depsgraph);
|
||||
struct RenderLayer *render_layer,
|
||||
const struct Depsgraph *depsgraph,
|
||||
const rcti *rect);
|
||||
void GPENCIL_render_to_image(void *vedata,
|
||||
struct RenderEngine *engine,
|
||||
struct RenderLayer *render_layer,
|
||||
const rcti *rect);
|
||||
|
||||
/* TODO: GPXX workaround function to call free memory from draw manager while draw manager support
|
||||
* scene finish callback. */
|
||||
void DRW_gpencil_free_runtime_data(void *ved);
|
||||
|
||||
/* Use of multisample framebuffers. */
|
||||
#define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) \
|
||||
{ \
|
||||
if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \
|
||||
DRW_stats_query_start("GP Multisample Blit"); \
|
||||
GPU_framebuffer_bind(fbl->multisample_fb); \
|
||||
GPU_framebuffer_clear_color_depth_stencil( \
|
||||
fbl->multisample_fb, (const float[4]){0.0f}, 1.0f, 0x0); \
|
||||
DRW_stats_query_end(); \
|
||||
} \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define MULTISAMPLE_GP_SYNC_DISABLE(lvl, fbl, fb, txl) \
|
||||
{ \
|
||||
if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \
|
||||
DRW_stats_query_start("GP Multisample Resolve"); \
|
||||
GPU_framebuffer_bind(fb); \
|
||||
DRW_stats_query_end(); \
|
||||
} \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define GPENCIL_3D_DRAWMODE(ob, gpd) \
|
||||
((gpd) && (gpd->draw_mode == GP_DRAWMODE_3D) && ((ob->dtx & OB_DRAWXRAY) == 0))
|
||||
|
||||
#define GPENCIL_USE_SOLID(stl) \
|
||||
((stl) && ((stl->storage->is_render) || (stl->storage->is_mat_preview)))
|
||||
/* Draw Data. */
|
||||
void gpencil_light_pool_free(void *storage);
|
||||
void gpencil_material_pool_free(void *storage);
|
||||
GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void);
|
||||
|
||||
#endif /* __GPENCIL_ENGINE_H__ */
|
||||
|
||||
@@ -33,66 +33,22 @@
|
||||
|
||||
#include "gpencil_engine.h"
|
||||
|
||||
/* Get pixel size for render
|
||||
* This function uses the same calculation used for viewport, because if use
|
||||
* camera pixelsize, the result is not correct.
|
||||
*/
|
||||
static float get_render_pixelsize(float persmat[4][4], int winx, int winy)
|
||||
{
|
||||
float v1[3], v2[3];
|
||||
float len_px, len_sc;
|
||||
|
||||
v1[0] = persmat[0][0];
|
||||
v1[1] = persmat[1][0];
|
||||
v1[2] = persmat[2][0];
|
||||
|
||||
v2[0] = persmat[0][1];
|
||||
v2[1] = persmat[1][1];
|
||||
v2[2] = persmat[2][1];
|
||||
|
||||
len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
|
||||
len_sc = (float)MAX2(winx, winy);
|
||||
|
||||
return len_px / len_sc;
|
||||
}
|
||||
|
||||
/* init render data */
|
||||
void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph)
|
||||
void GPENCIL_render_init(GPENCIL_Data *vedata,
|
||||
RenderEngine *engine,
|
||||
struct RenderLayer *render_layer,
|
||||
const Depsgraph *depsgraph,
|
||||
const rcti *rect)
|
||||
{
|
||||
GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
|
||||
GPENCIL_StorageList *stl = vedata->stl;
|
||||
GPENCIL_FramebufferList *fbl = vedata->fbl;
|
||||
GPENCIL_TextureList *txl = vedata->txl;
|
||||
|
||||
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||
const float *viewport_size = DRW_viewport_size_get();
|
||||
const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
|
||||
|
||||
/* In render mode the default framebuffer is not generated
|
||||
* because there is no viewport. So we need to manually create one
|
||||
* NOTE : use 32 bit format for precision in render mode.
|
||||
*/
|
||||
/* create multisample framebuffer for AA */
|
||||
if (U.gpencil_multisamples > 0) {
|
||||
int rect_w = (int)viewport_size[0];
|
||||
int rect_h = (int)viewport_size[1];
|
||||
gpencil_multisample_ensure(vedata, rect_w, rect_h);
|
||||
}
|
||||
|
||||
vedata->render_depth_tx = DRW_texture_pool_query_2d(
|
||||
size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type);
|
||||
vedata->render_color_tx = DRW_texture_pool_query_2d(
|
||||
size[0], size[1], GPU_RGBA32F, &draw_engine_gpencil_type);
|
||||
GPU_framebuffer_ensure_config(&fbl->main,
|
||||
{GPU_ATTACHMENT_TEXTURE(vedata->render_depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(vedata->render_color_tx)});
|
||||
|
||||
/* Alloc transient data. */
|
||||
if (!stl->g_data) {
|
||||
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
|
||||
}
|
||||
|
||||
/* Set the pers & view matrix. */
|
||||
float winmat[4][4], viewmat[4][4], viewinv[4][4], persmat[4][4];
|
||||
float winmat[4][4], viewmat[4][4], viewinv[4][4];
|
||||
|
||||
struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
|
||||
float frame = BKE_scene_frame_get(scene);
|
||||
@@ -105,85 +61,101 @@ void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgra
|
||||
DRW_view_default_set(view);
|
||||
DRW_view_set_active(view);
|
||||
|
||||
DRW_view_persmat_get(NULL, persmat, false);
|
||||
/* Create depth texture & color texture from render result. */
|
||||
const char *viewname = RE_GetActiveRenderView(engine->re);
|
||||
RenderPass *rpass_z_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
|
||||
RenderPass *rpass_col_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
|
||||
|
||||
/* calculate pixel size for render */
|
||||
stl->storage->render_pixsize = get_render_pixelsize(persmat, viewport_size[0], viewport_size[1]);
|
||||
float *pix_z = (rpass_z_src) ? rpass_z_src->rect : NULL;
|
||||
float *pix_col = (rpass_col_src) ? rpass_col_src->rect : NULL;
|
||||
|
||||
/* INIT CACHE */
|
||||
GPENCIL_cache_init(vedata);
|
||||
if (!pix_z || !pix_col) {
|
||||
RE_engine_set_error_message(engine,
|
||||
"Warning: To render grease pencil, enable Combined and Z passes.");
|
||||
}
|
||||
|
||||
if (pix_z) {
|
||||
/* Depth need to be remapped to [0..1] range. */
|
||||
pix_z = MEM_dupallocN(pix_z);
|
||||
|
||||
int pix_ct = rpass_z_src->rectx * rpass_z_src->recty;
|
||||
|
||||
if (DRW_view_is_persp_get(view)) {
|
||||
for (int i = 0; i < pix_ct; i++) {
|
||||
pix_z[i] = (-winmat[3][2] / -pix_z[i]) - winmat[2][2];
|
||||
pix_z[i] = clamp_f(pix_z[i] * 0.5f + 0.5f, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Keep in mind, near and far distance are negatives. */
|
||||
float near = DRW_view_near_distance_get(view);
|
||||
float far = DRW_view_far_distance_get(view);
|
||||
float range_inv = 1.0f / fabsf(far - near);
|
||||
for (int i = 0; i < pix_ct; i++) {
|
||||
pix_z[i] = (pix_z[i] + near) * range_inv;
|
||||
pix_z[i] = clamp_f(pix_z[i], 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool do_region = (scene->r.mode & R_BORDER) != 0;
|
||||
const bool do_clear_z = !pix_z || do_region;
|
||||
const bool do_clear_col = !pix_col || do_region;
|
||||
|
||||
/* FIXME(fclem): we have a precision loss in the depth buffer because of this reupload.
|
||||
* Find where it comes from! */
|
||||
txl->render_depth_tx = DRW_texture_create_2d(
|
||||
size[0], size[1], GPU_DEPTH_COMPONENT24, 0, do_region ? NULL : pix_z);
|
||||
txl->render_color_tx = DRW_texture_create_2d(
|
||||
size[0], size[1], GPU_RGBA16F, 0, do_region ? NULL : pix_col);
|
||||
|
||||
GPU_framebuffer_ensure_config(&fbl->render_fb,
|
||||
{
|
||||
GPU_ATTACHMENT_TEXTURE(txl->render_depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(txl->render_color_tx),
|
||||
});
|
||||
|
||||
if (do_clear_z || do_clear_col) {
|
||||
/* To avoid unpredictable result, clear buffers that have not be initialized. */
|
||||
GPU_framebuffer_bind(fbl->render_fb);
|
||||
if (do_clear_col) {
|
||||
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_clear_color(fbl->render_fb, clear_col);
|
||||
}
|
||||
if (do_clear_z) {
|
||||
GPU_framebuffer_clear_depth(fbl->render_fb, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (do_region) {
|
||||
int x = rect->xmin;
|
||||
int y = rect->ymin;
|
||||
int w = BLI_rcti_size_x(rect);
|
||||
int h = BLI_rcti_size_y(rect);
|
||||
if (pix_col) {
|
||||
GPU_texture_update_sub(txl->render_color_tx, GPU_DATA_FLOAT, pix_col, x, y, 0, w, h, 0);
|
||||
}
|
||||
if (pix_z) {
|
||||
GPU_texture_update_sub(txl->render_depth_tx, GPU_DATA_FLOAT, pix_z, x, y, 0, w, h, 0);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(pix_z);
|
||||
}
|
||||
|
||||
/* render all objects and select only grease pencil */
|
||||
static void GPENCIL_render_cache(void *vedata,
|
||||
struct Object *ob,
|
||||
struct RenderEngine *UNUSED(engine),
|
||||
struct Depsgraph *UNUSED(depsgraph))
|
||||
Depsgraph *UNUSED(depsgraph))
|
||||
{
|
||||
if (ob && ob->type == OB_GPENCIL) {
|
||||
if (ob && ELEM(ob->type, OB_GPENCIL, OB_LAMP)) {
|
||||
if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
|
||||
GPENCIL_cache_populate(vedata, ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Reuse Eevee code in shared module instead to duplicate here */
|
||||
static void GPENCIL_render_update_viewvecs(float invproj[4][4],
|
||||
const float winmat[4][4],
|
||||
float (*r_viewvecs)[4])
|
||||
{
|
||||
/* view vectors for the corners of the view frustum.
|
||||
* Can be used to recreate the world space position easily */
|
||||
float view_vecs[4][4] = {
|
||||
{-1.0f, -1.0f, -1.0f, 1.0f},
|
||||
{1.0f, -1.0f, -1.0f, 1.0f},
|
||||
{-1.0f, 1.0f, -1.0f, 1.0f},
|
||||
{-1.0f, -1.0f, 1.0f, 1.0f},
|
||||
};
|
||||
|
||||
/* convert the view vectors to view space */
|
||||
const bool is_persp = (winmat[3][3] == 0.0f);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mul_project_m4_v3(invproj, view_vecs[i]);
|
||||
/* normalized trick see:
|
||||
* http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
|
||||
if (is_persp) {
|
||||
/* Divide XY by Z. */
|
||||
mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and
|
||||
* view_vecs[1] is the vector going from the near-bottom-left corner to
|
||||
* the far-top-right corner.
|
||||
* If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner
|
||||
* when Z = 1, and top-left corner if Z = 1.
|
||||
* view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed)
|
||||
* distance from the near plane to the far clip plane.
|
||||
*/
|
||||
copy_v4_v4(r_viewvecs[0], view_vecs[0]);
|
||||
|
||||
/* we need to store the differences */
|
||||
r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0];
|
||||
r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
|
||||
r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2];
|
||||
}
|
||||
|
||||
/* Update view_vecs */
|
||||
static void GPENCIL_render_update_vecs(GPENCIL_Data *vedata)
|
||||
{
|
||||
GPENCIL_StorageList *stl = vedata->stl;
|
||||
|
||||
float invproj[4][4], winmat[4][4];
|
||||
DRW_view_winmat_get(NULL, winmat, false);
|
||||
DRW_view_winmat_get(NULL, invproj, true);
|
||||
|
||||
/* this is separated to keep function equal to Eevee for future reuse of same code */
|
||||
GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs);
|
||||
}
|
||||
|
||||
/* read z-depth render result */
|
||||
static void GPENCIL_render_result_z(struct RenderLayer *rl,
|
||||
const char *viewname,
|
||||
GPENCIL_Data *vedata,
|
||||
@@ -191,45 +163,52 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
ViewLayer *view_layer = draw_ctx->view_layer;
|
||||
GPENCIL_StorageList *stl = vedata->stl;
|
||||
|
||||
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
|
||||
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
|
||||
|
||||
GPU_framebuffer_read_depth(vedata->fbl->main,
|
||||
GPU_framebuffer_read_depth(vedata->fbl->render_fb,
|
||||
rect->xmin,
|
||||
rect->ymin,
|
||||
BLI_rcti_size_x(rect),
|
||||
BLI_rcti_size_y(rect),
|
||||
rp->rect);
|
||||
|
||||
bool is_persp = DRW_view_is_persp_get(NULL);
|
||||
|
||||
GPENCIL_render_update_vecs(vedata);
|
||||
|
||||
float winmat[4][4];
|
||||
DRW_view_winmat_get(NULL, winmat, false);
|
||||
|
||||
int pix_ct = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
|
||||
|
||||
/* Convert ogl depth [0..1] to view Z [near..far] */
|
||||
for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
if (is_persp) {
|
||||
if (DRW_view_is_persp_get(NULL)) {
|
||||
for (int i = 0; i < pix_ct; i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
|
||||
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Keep in mind, near and far distance are negatives. */
|
||||
float near = DRW_view_near_distance_get(NULL);
|
||||
float far = DRW_view_far_distance_get(NULL);
|
||||
float range = fabsf(far - near);
|
||||
|
||||
for (int i = 0; i < pix_ct; i++) {
|
||||
if (rp->rect[i] == 1.0f) {
|
||||
rp->rect[i] = 1e10f; /* Background */
|
||||
}
|
||||
else {
|
||||
rp->rect[i] = -stl->storage->view_vecs[0][2] +
|
||||
rp->rect[i] * -stl->storage->view_vecs[1][2];
|
||||
rp->rect[i] = -rp->rect[i] * range + near;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* read combined render result */
|
||||
static void GPENCIL_render_result_combined(struct RenderLayer *rl,
|
||||
const char *viewname,
|
||||
GPENCIL_Data *vedata,
|
||||
@@ -238,8 +217,8 @@ static void GPENCIL_render_result_combined(struct RenderLayer *rl,
|
||||
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
|
||||
GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
|
||||
|
||||
GPU_framebuffer_bind(fbl->main);
|
||||
GPU_framebuffer_read_color(vedata->fbl->main,
|
||||
GPU_framebuffer_bind(fbl->render_fb);
|
||||
GPU_framebuffer_read_color(vedata->fbl->render_fb,
|
||||
rect->xmin,
|
||||
rect->ymin,
|
||||
BLI_rcti_size_x(rect),
|
||||
@@ -249,135 +228,31 @@ static void GPENCIL_render_result_combined(struct RenderLayer *rl,
|
||||
rp->rect);
|
||||
}
|
||||
|
||||
/* helper to blend pixels */
|
||||
static void blend_pixel(float top_color[4], float bottom_color[4], float dst_color[4])
|
||||
{
|
||||
float alpha = top_color[3];
|
||||
|
||||
/* use blend: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA */
|
||||
dst_color[0] = (top_color[0] * alpha) + (bottom_color[0] * (1.0f - alpha));
|
||||
dst_color[1] = (top_color[1] * alpha) + (bottom_color[1] * (1.0f - alpha));
|
||||
dst_color[2] = (top_color[2] * alpha) + (bottom_color[2] * (1.0f - alpha));
|
||||
}
|
||||
|
||||
/* render grease pencil to image */
|
||||
void GPENCIL_render_to_image(void *vedata,
|
||||
void GPENCIL_render_to_image(void *ved,
|
||||
RenderEngine *engine,
|
||||
struct RenderLayer *render_layer,
|
||||
const rcti *rect)
|
||||
{
|
||||
GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
|
||||
const char *viewname = RE_GetActiveRenderView(engine->re);
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
int imgsize = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
|
||||
|
||||
/* save previous render data */
|
||||
RenderPass *rpass_color_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
|
||||
RenderPass *rpass_depth_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
|
||||
float *src_rect_color_data = NULL;
|
||||
float *src_rect_depth_data = NULL;
|
||||
if ((rpass_color_src) && (rpass_depth_src) && (rpass_color_src->rect) &&
|
||||
(rpass_depth_src->rect)) {
|
||||
src_rect_color_data = MEM_dupallocN(rpass_color_src->rect);
|
||||
src_rect_depth_data = MEM_dupallocN(rpass_depth_src->rect);
|
||||
}
|
||||
else {
|
||||
/* TODO: put this message in a better place */
|
||||
printf("Warning: To render grease pencil, enable Combined and Z passes.\n");
|
||||
}
|
||||
Depsgraph *depsgraph = draw_ctx->depsgraph;
|
||||
|
||||
GPENCIL_render_init(vedata, engine, render_layer, depsgraph, rect);
|
||||
GPENCIL_engine_init(vedata);
|
||||
GPENCIL_render_init(vedata, engine, draw_ctx->depsgraph);
|
||||
|
||||
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
|
||||
Object *camera = DEG_get_evaluated_object(draw_ctx->depsgraph, RE_GetCamera(engine->re));
|
||||
stl->storage->camera = camera; /* save current camera */
|
||||
|
||||
GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
|
||||
if (fbl->main) {
|
||||
GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx, 0, 0);
|
||||
GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx, 0, 0);
|
||||
/* clean first time the buffer */
|
||||
float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GPU_framebuffer_bind(fbl->main);
|
||||
GPU_framebuffer_clear_color_depth(fbl->main, clearcol, 1.0f);
|
||||
}
|
||||
|
||||
/* loop all objects and draw */
|
||||
DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, GPENCIL_render_cache);
|
||||
vedata->stl->pd->camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
|
||||
|
||||
/* Loop over all objects and create draw structure. */
|
||||
GPENCIL_cache_init(vedata);
|
||||
DRW_render_object_iter(vedata, engine, depsgraph, GPENCIL_render_cache);
|
||||
GPENCIL_cache_finish(vedata);
|
||||
|
||||
DRW_render_instance_buffer_finish();
|
||||
|
||||
/* Render the gpencil object and merge the result to the underlying render. */
|
||||
GPENCIL_draw_scene(vedata);
|
||||
|
||||
/* combined data */
|
||||
GPENCIL_render_result_combined(render_layer, viewname, vedata, rect);
|
||||
/* z-depth data */
|
||||
GPENCIL_render_result_z(render_layer, viewname, vedata, rect);
|
||||
|
||||
/* detach textures */
|
||||
if (fbl->main) {
|
||||
GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx);
|
||||
GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx);
|
||||
}
|
||||
|
||||
/* merge previous render image with new GP image */
|
||||
if (src_rect_color_data) {
|
||||
RenderPass *rpass_color_gp = RE_pass_find_by_name(
|
||||
render_layer, RE_PASSNAME_COMBINED, viewname);
|
||||
RenderPass *rpass_depth_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname);
|
||||
float *gp_rect_color_data = rpass_color_gp->rect;
|
||||
float *gp_rect_depth_data = rpass_depth_gp->rect;
|
||||
float *gp_pixel_rgba;
|
||||
float *gp_pixel_depth;
|
||||
float *src_pixel_rgba;
|
||||
float *src_pixel_depth;
|
||||
|
||||
for (int i = 0; i < imgsize; i++) {
|
||||
gp_pixel_rgba = &gp_rect_color_data[i * 4];
|
||||
gp_pixel_depth = &gp_rect_depth_data[i];
|
||||
|
||||
src_pixel_rgba = &src_rect_color_data[i * 4];
|
||||
src_pixel_depth = &src_rect_depth_data[i];
|
||||
|
||||
/* check grease pencil render transparency */
|
||||
if (gp_pixel_rgba[3] > 0.0f) {
|
||||
if (src_pixel_rgba[3] > 0.0f) {
|
||||
/* check z-depth */
|
||||
if (gp_pixel_depth[0] > src_pixel_depth[0]) {
|
||||
/* copy source z-depth */
|
||||
gp_pixel_depth[0] = src_pixel_depth[0];
|
||||
/* blend object on top */
|
||||
if (src_pixel_rgba[3] < 1.0f) {
|
||||
blend_pixel(src_pixel_rgba, gp_pixel_rgba, gp_pixel_rgba);
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(gp_pixel_rgba, src_pixel_rgba);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* blend gp render */
|
||||
if (gp_pixel_rgba[3] < 1.0f) {
|
||||
/* premult alpha factor to remove double blend effects */
|
||||
mul_v3_fl(gp_pixel_rgba, 1.0f / gp_pixel_rgba[3]);
|
||||
|
||||
blend_pixel(gp_pixel_rgba, src_pixel_rgba, gp_pixel_rgba);
|
||||
|
||||
gp_pixel_rgba[3] = gp_pixel_rgba[3] > src_pixel_rgba[3] ? gp_pixel_rgba[3] :
|
||||
src_pixel_rgba[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
copy_v4_v4(gp_pixel_rgba, src_pixel_rgba);
|
||||
gp_pixel_depth[0] = src_pixel_depth[0];
|
||||
}
|
||||
}
|
||||
|
||||
/* free memory */
|
||||
MEM_SAFE_FREE(src_rect_color_data);
|
||||
MEM_SAFE_FREE(src_rect_depth_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2019, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw
|
||||
*/
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "gpencil_engine.h"
|
||||
|
||||
extern char datatoc_gpencil_common_lib_glsl[];
|
||||
extern char datatoc_gpencil_frag_glsl[];
|
||||
extern char datatoc_gpencil_vert_glsl[];
|
||||
extern char datatoc_gpencil_antialiasing_frag_glsl[];
|
||||
extern char datatoc_gpencil_antialiasing_vert_glsl[];
|
||||
extern char datatoc_gpencil_layer_blend_frag_glsl[];
|
||||
extern char datatoc_gpencil_mask_invert_frag_glsl[];
|
||||
extern char datatoc_gpencil_depth_merge_frag_glsl[];
|
||||
extern char datatoc_gpencil_depth_merge_vert_glsl[];
|
||||
extern char datatoc_gpencil_vfx_frag_glsl[];
|
||||
|
||||
extern char datatoc_common_colormanagement_lib_glsl[];
|
||||
extern char datatoc_common_fullscreen_vert_glsl[];
|
||||
extern char datatoc_common_smaa_lib_glsl[];
|
||||
extern char datatoc_common_view_lib_glsl[];
|
||||
|
||||
static struct {
|
||||
/* SMAA antialiasing */
|
||||
GPUShader *antialiasing_sh[3];
|
||||
/* GPencil Object rendering */
|
||||
GPUShader *gpencil_sh;
|
||||
/* Final Compositing over rendered background. */
|
||||
GPUShader *composite_sh;
|
||||
/* All layer blend types in one shader! */
|
||||
GPUShader *layer_blend_sh;
|
||||
/* Merge the final object depth to the depth buffer. */
|
||||
GPUShader *depth_merge_sh;
|
||||
/* Invert the content of the mask buffer. */
|
||||
GPUShader *mask_invert_sh;
|
||||
/* Effects. */
|
||||
GPUShader *fx_composite_sh;
|
||||
GPUShader *fx_colorize_sh;
|
||||
GPUShader *fx_blur_sh;
|
||||
GPUShader *fx_glow_sh;
|
||||
GPUShader *fx_pixel_sh;
|
||||
GPUShader *fx_rim_sh;
|
||||
GPUShader *fx_shadow_sh;
|
||||
GPUShader *fx_transform_sh;
|
||||
/* general drawing shaders */
|
||||
GPUShader *gpencil_fill_sh;
|
||||
GPUShader *gpencil_stroke_sh;
|
||||
GPUShader *gpencil_point_sh;
|
||||
GPUShader *gpencil_edit_point_sh;
|
||||
GPUShader *gpencil_line_sh;
|
||||
GPUShader *gpencil_drawing_fill_sh;
|
||||
GPUShader *gpencil_fullscreen_sh;
|
||||
GPUShader *gpencil_simple_fullscreen_sh;
|
||||
GPUShader *gpencil_blend_fullscreen_sh;
|
||||
GPUShader *gpencil_background_sh;
|
||||
GPUShader *gpencil_paper_sh;
|
||||
} g_shaders = {{NULL}};
|
||||
|
||||
void GPENCIL_shader_free(void)
|
||||
{
|
||||
GPUShader **sh_data_as_array = (GPUShader **)&g_shaders;
|
||||
for (int i = 0; i < (sizeof(g_shaders) / sizeof(GPUShader *)); i++) {
|
||||
DRW_SHADER_FREE_SAFE(sh_data_as_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_antialiasing(int stage)
|
||||
{
|
||||
BLI_assert(stage < 3);
|
||||
|
||||
if (!g_shaders.antialiasing_sh[stage]) {
|
||||
char stage_define[32];
|
||||
BLI_snprintf(stage_define, sizeof(stage_define), "#define SMAA_STAGE %d\n", stage);
|
||||
|
||||
g_shaders.antialiasing_sh[stage] = GPU_shader_create_from_arrays({
|
||||
.vert =
|
||||
(const char *[]){
|
||||
"#define SMAA_INCLUDE_VS 1\n",
|
||||
"#define SMAA_INCLUDE_PS 0\n",
|
||||
"uniform vec4 viewportMetrics;\n",
|
||||
datatoc_common_smaa_lib_glsl,
|
||||
datatoc_gpencil_antialiasing_vert_glsl,
|
||||
NULL,
|
||||
},
|
||||
.frag =
|
||||
(const char *[]){
|
||||
"#define SMAA_INCLUDE_VS 0\n",
|
||||
"#define SMAA_INCLUDE_PS 1\n",
|
||||
"uniform vec4 viewportMetrics;\n",
|
||||
datatoc_common_smaa_lib_glsl,
|
||||
datatoc_gpencil_antialiasing_frag_glsl,
|
||||
NULL,
|
||||
},
|
||||
.defs =
|
||||
(const char *[]){
|
||||
"#define SMAA_GLSL_3\n",
|
||||
"#define SMAA_RT_METRICS viewportMetrics\n",
|
||||
"#define SMAA_PRESET_HIGH\n",
|
||||
"#define SMAA_LUMA_WEIGHT float4(1.0, 1.0, 1.0, 0.0)\n",
|
||||
"#define SMAA_NO_DISCARD\n",
|
||||
stage_define,
|
||||
NULL,
|
||||
},
|
||||
});
|
||||
}
|
||||
return g_shaders.antialiasing_sh[stage];
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_geometry_get(void)
|
||||
{
|
||||
if (!g_shaders.gpencil_sh) {
|
||||
g_shaders.gpencil_sh = GPU_shader_create_from_arrays({
|
||||
.vert =
|
||||
(const char *[]){
|
||||
datatoc_common_view_lib_glsl,
|
||||
datatoc_gpencil_common_lib_glsl,
|
||||
datatoc_gpencil_vert_glsl,
|
||||
NULL,
|
||||
},
|
||||
.frag =
|
||||
(const char *[]){
|
||||
datatoc_common_colormanagement_lib_glsl,
|
||||
datatoc_gpencil_common_lib_glsl,
|
||||
datatoc_gpencil_frag_glsl,
|
||||
NULL,
|
||||
},
|
||||
.defs =
|
||||
(const char *[]){
|
||||
"#define GP_MATERIAL_BUFFER_LEN " STRINGIFY(GP_MATERIAL_BUFFER_LEN) "\n",
|
||||
"#define GPENCIL_LIGHT_BUFFER_LEN " STRINGIFY(GPENCIL_LIGHT_BUFFER_LEN) "\n",
|
||||
"#define UNIFORM_RESOURCE_ID\n",
|
||||
NULL,
|
||||
},
|
||||
});
|
||||
}
|
||||
return g_shaders.gpencil_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_layer_blend_get(void)
|
||||
{
|
||||
if (!g_shaders.layer_blend_sh) {
|
||||
g_shaders.layer_blend_sh = GPU_shader_create_from_arrays({
|
||||
.vert =
|
||||
(const char *[]){
|
||||
datatoc_common_fullscreen_vert_glsl,
|
||||
NULL,
|
||||
},
|
||||
.frag =
|
||||
(const char *[]){
|
||||
datatoc_gpencil_common_lib_glsl,
|
||||
datatoc_gpencil_layer_blend_frag_glsl,
|
||||
NULL,
|
||||
},
|
||||
});
|
||||
}
|
||||
return g_shaders.layer_blend_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_mask_invert_get(void)
|
||||
{
|
||||
if (!g_shaders.mask_invert_sh) {
|
||||
g_shaders.mask_invert_sh = DRW_shader_create_fullscreen(datatoc_gpencil_mask_invert_frag_glsl,
|
||||
NULL);
|
||||
}
|
||||
return g_shaders.mask_invert_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_depth_merge_get(void)
|
||||
{
|
||||
if (!g_shaders.depth_merge_sh) {
|
||||
g_shaders.depth_merge_sh = GPU_shader_create_from_arrays({
|
||||
.vert =
|
||||
(const char *[]){
|
||||
datatoc_common_view_lib_glsl,
|
||||
datatoc_gpencil_depth_merge_vert_glsl,
|
||||
NULL,
|
||||
},
|
||||
.frag =
|
||||
(const char *[]){
|
||||
datatoc_gpencil_depth_merge_frag_glsl,
|
||||
NULL,
|
||||
},
|
||||
});
|
||||
}
|
||||
return g_shaders.depth_merge_sh;
|
||||
}
|
||||
|
||||
/* ------- FX Shaders --------- */
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_blur_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_blur_sh) {
|
||||
g_shaders.fx_blur_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
|
||||
"#define BLUR\n");
|
||||
}
|
||||
return g_shaders.fx_blur_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_colorize_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_colorize_sh) {
|
||||
g_shaders.fx_colorize_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
|
||||
"#define COLORIZE\n");
|
||||
}
|
||||
return g_shaders.fx_colorize_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_composite_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_composite_sh) {
|
||||
g_shaders.fx_composite_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
|
||||
"#define COMPOSITE\n");
|
||||
}
|
||||
return g_shaders.fx_composite_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_glow_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_glow_sh) {
|
||||
g_shaders.fx_glow_sh = GPU_shader_create_from_arrays({
|
||||
.vert =
|
||||
(const char *[]){
|
||||
datatoc_common_fullscreen_vert_glsl,
|
||||
NULL,
|
||||
},
|
||||
.frag =
|
||||
(const char *[]){
|
||||
datatoc_gpencil_common_lib_glsl,
|
||||
datatoc_gpencil_vfx_frag_glsl,
|
||||
NULL,
|
||||
},
|
||||
.defs =
|
||||
(const char *[]){
|
||||
"#define GLOW\n",
|
||||
NULL,
|
||||
},
|
||||
});
|
||||
}
|
||||
return g_shaders.fx_glow_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_pixelize_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_pixel_sh) {
|
||||
g_shaders.fx_pixel_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
|
||||
"#define PIXELIZE\n");
|
||||
}
|
||||
return g_shaders.fx_pixel_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_rim_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_rim_sh) {
|
||||
g_shaders.fx_rim_sh = GPU_shader_create_from_arrays({
|
||||
.vert =
|
||||
(const char *[]){
|
||||
datatoc_common_fullscreen_vert_glsl,
|
||||
NULL,
|
||||
},
|
||||
.frag =
|
||||
(const char *[]){
|
||||
datatoc_gpencil_common_lib_glsl,
|
||||
datatoc_gpencil_vfx_frag_glsl,
|
||||
NULL,
|
||||
},
|
||||
.defs =
|
||||
(const char *[]){
|
||||
"#define RIM\n",
|
||||
NULL,
|
||||
},
|
||||
});
|
||||
}
|
||||
return g_shaders.fx_rim_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_shadow_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_shadow_sh) {
|
||||
g_shaders.fx_shadow_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
|
||||
"#define SHADOW\n");
|
||||
}
|
||||
return g_shaders.fx_shadow_sh;
|
||||
}
|
||||
|
||||
GPUShader *GPENCIL_shader_fx_transform_get(void)
|
||||
{
|
||||
if (!g_shaders.fx_transform_sh) {
|
||||
g_shaders.fx_transform_sh = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
|
||||
"#define TRANSFORM\n");
|
||||
}
|
||||
return g_shaders.fx_transform_sh;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,85 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform vec2 Viewport;
|
||||
|
||||
uniform int blur[2];
|
||||
|
||||
uniform vec3 loc;
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform float pixfactor;
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
vec2 noffset = vec2(blur[0], blur[1]);
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
float get_zdepth(ivec2 poxy)
|
||||
{
|
||||
/* if outside viewport set as infinite depth */
|
||||
if ((poxy.x < 0) || (poxy.x > Viewport.x)) {
|
||||
return 1.0f;
|
||||
}
|
||||
if ((poxy.y < 0) || (poxy.y > Viewport.y)) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float zdepth = texelFetch(strokeDepth, poxy, 0).r;
|
||||
return zdepth;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
|
||||
vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
|
||||
|
||||
float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) :
|
||||
(noffset[0] / defaultpixsize);
|
||||
float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) :
|
||||
(noffset[1] / defaultpixsize);
|
||||
|
||||
/* round to avoid shift when add more samples */
|
||||
dx = floor(dx) + 1.0;
|
||||
dy = floor(dy) + 1.0;
|
||||
|
||||
/* apply blurring, using a 9-tap filter with predefined gaussian weights */
|
||||
/* depth (get the value of the surrounding pixels) */
|
||||
float outdepth = get_zdepth(ivec2(uv.x, uv.y));
|
||||
for (int x = -1; x < 2; x++) {
|
||||
for (int y = -1; y < 2; y++) {
|
||||
float depth = get_zdepth(ivec2(uv.x + x * dx, uv.y + y * dy));
|
||||
if (depth < outdepth) {
|
||||
outdepth = depth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
gl_FragDepth = outdepth;
|
||||
|
||||
/* color */
|
||||
vec4 outcolor = vec4(0.0);
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416;
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x - 0.0 * dx, uv.y + 1.0 * dy), 0) * 0.118318;
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416;
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318;
|
||||
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x, uv.y), 0) * 0.147761;
|
||||
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318;
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416;
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x + 0.0 * dx, uv.y - 1.0 * dy), 0) * 0.118318;
|
||||
outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416;
|
||||
|
||||
FragColor = clamp(outcolor, 0, 1.0);
|
||||
|
||||
/* discar extreme values */
|
||||
if (outcolor.a < 0.02f) {
|
||||
discard;
|
||||
}
|
||||
if ((outdepth <= 0.000001) || (outdepth >= 0.999999)) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
|
||||
uniform vec4 low_color;
|
||||
uniform vec4 high_color;
|
||||
uniform int mode;
|
||||
uniform float factor;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
#define MODE_GRAYSCALE 0
|
||||
#define MODE_SEPIA 1
|
||||
#define MODE_DUOTONE 2
|
||||
#define MODE_CUSTOM 3
|
||||
#define MODE_TRANSPARENT 4
|
||||
|
||||
float get_luminance(vec4 color)
|
||||
{
|
||||
float lum = (color.r * 0.2126) + (color.g * 0.7152) + (color.b * 0.723);
|
||||
return lum;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
|
||||
vec4 src_pixel = texelFetch(strokeColor, uv.xy, 0);
|
||||
float luminance = get_luminance(src_pixel);
|
||||
vec4 outcolor;
|
||||
|
||||
/* is transparent */
|
||||
if (src_pixel.a == 0.0f) {
|
||||
discard;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case MODE_GRAYSCALE: {
|
||||
outcolor = vec4(luminance, luminance, luminance, src_pixel.a);
|
||||
break;
|
||||
}
|
||||
case MODE_SEPIA: {
|
||||
float Red = (src_pixel.r * 0.393) + (src_pixel.g * 0.769) + (src_pixel.b * 0.189);
|
||||
float Green = (src_pixel.r * 0.349) + (src_pixel.g * 0.686) + (src_pixel.b * 0.168);
|
||||
float Blue = (src_pixel.r * 0.272) + (src_pixel.g * 0.534) + (src_pixel.b * 0.131);
|
||||
outcolor = vec4(Red, Green, Blue, src_pixel.a);
|
||||
break;
|
||||
}
|
||||
case MODE_DUOTONE: {
|
||||
if (luminance <= factor) {
|
||||
outcolor = low_color;
|
||||
}
|
||||
else {
|
||||
outcolor = high_color;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MODE_CUSTOM: {
|
||||
/* if below umbral, force custom color */
|
||||
if (luminance <= factor) {
|
||||
outcolor = low_color;
|
||||
}
|
||||
else {
|
||||
outcolor = vec4(luminance * low_color.r,
|
||||
luminance * low_color.b,
|
||||
luminance * low_color.b,
|
||||
src_pixel.a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MODE_TRANSPARENT: {
|
||||
outcolor = vec4(src_pixel.rgb, src_pixel.a * factor);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
outcolor = src_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform vec2 wsize;
|
||||
uniform int flipmode;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 mode = vec2(0, 0);
|
||||
/* horz. */
|
||||
if (flipmode >= 110) {
|
||||
mode[0] = 1;
|
||||
}
|
||||
/* vert. */
|
||||
if ((flipmode == 101) || (flipmode == 111)) {
|
||||
mode[1] = 1;
|
||||
}
|
||||
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
float stroke_depth;
|
||||
vec4 outcolor;
|
||||
|
||||
if (mode[0] > 0) {
|
||||
uv.x = wsize.x - uv.x;
|
||||
}
|
||||
if (mode[1] > 0) {
|
||||
uv.y = wsize.y - uv.y;
|
||||
}
|
||||
|
||||
ivec2 iuv = ivec2(uv.x, uv.y);
|
||||
stroke_depth = texelFetch(strokeDepth, iuv, 0).r;
|
||||
outcolor = texelFetch(strokeColor, iuv, 0);
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
/* ******************************************************************* */
|
||||
/* create glow mask */
|
||||
/* ******************************************************************* */
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
|
||||
uniform vec3 glow_color;
|
||||
uniform vec3 select_color;
|
||||
uniform float threshold;
|
||||
uniform int mode;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
#define MODE_LUMINANCE 0
|
||||
#define MODE_COLOR 1
|
||||
|
||||
/* calc luminance */
|
||||
float luma(vec3 color)
|
||||
{
|
||||
/* the color is linear, so do not apply tonemapping */
|
||||
return (color.r + color.g + color.b) / 3.0;
|
||||
}
|
||||
|
||||
bool check_color(vec3 color_a, vec3 color_b)
|
||||
{
|
||||
/* need round the number to avoid precision errors */
|
||||
if ((floor(color_a.r * 100) == floor(color_b.r * 100)) &&
|
||||
(floor(color_a.g * 100) == floor(color_b.g * 100)) &&
|
||||
(floor(color_a.b * 100) == floor(color_b.b * 100))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r;
|
||||
vec4 src_pixel = texelFetch(strokeColor, ivec2(uv.xy), 0);
|
||||
vec4 outcolor;
|
||||
|
||||
/* is transparent */
|
||||
if (src_pixel.a == 0.0f) {
|
||||
discard;
|
||||
}
|
||||
|
||||
if (mode == MODE_LUMINANCE) {
|
||||
if (luma(src_pixel.rgb) < threshold) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
else if (mode == MODE_COLOR) {
|
||||
if (!check_color(src_pixel.rgb, select_color.rgb)) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
else {
|
||||
discard;
|
||||
}
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = vec4(glow_color.rgb, 1.0);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/* ******************************************************************* */
|
||||
/* Resolve GLOW pass */
|
||||
/* ******************************************************************* */
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform sampler2D glowColor;
|
||||
uniform sampler2D glowDepth;
|
||||
uniform int alpha_mode;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 outcolor;
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
|
||||
vec4 src_pixel = texelFetch(strokeColor, uv.xy, 0);
|
||||
vec4 glow_pixel = texelFetch(glowColor, uv.xy, 0);
|
||||
float glow_depth = texelFetch(glowDepth, uv.xy, 0).r;
|
||||
|
||||
if (alpha_mode == 0) {
|
||||
outcolor = src_pixel + glow_pixel;
|
||||
}
|
||||
else {
|
||||
if ((src_pixel.a < 0.1) || (glow_pixel.a < 0.1)) {
|
||||
outcolor = src_pixel + glow_pixel;
|
||||
}
|
||||
else {
|
||||
outcolor = src_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
if (src_pixel.a < glow_pixel.a) {
|
||||
gl_FragDepth = glow_depth;
|
||||
}
|
||||
else {
|
||||
gl_FragDepth = stroke_depth;
|
||||
}
|
||||
|
||||
if (outcolor.a < 0.001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform vec2 Viewport;
|
||||
uniform vec4 loc;
|
||||
uniform float energy;
|
||||
uniform float ambient;
|
||||
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform float pixfactor;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
|
||||
#define height loc.w
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 vertex)
|
||||
{
|
||||
/* need to calculate ndc because this is not done by vertex shader */
|
||||
vec3 ndc = vec3(vertex).xyz / vertex.w;
|
||||
|
||||
vec2 sc;
|
||||
sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x;
|
||||
sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float stroke_depth;
|
||||
vec4 objcolor;
|
||||
|
||||
vec4 light_loc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
|
||||
vec2 light2d = toScreenSpace(light_loc);
|
||||
|
||||
/* calc pixel scale */
|
||||
float pxscale = (ProjectionMatrix[3][3] == 0.0) ? (10.0 / (light_loc.z * defaultpixsize)) :
|
||||
(10.0 / defaultpixsize);
|
||||
pxscale = max(pxscale, 0.000001);
|
||||
|
||||
/* the height over plane is received in the w component of the loc
|
||||
* and needs a factor to adapt to pixels
|
||||
*/
|
||||
float peak = height * 10.0 * pxscale;
|
||||
vec3 light3d = vec3(light2d.x, light2d.y, peak);
|
||||
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
vec3 frag_loc = vec3(uv.x, uv.y, 0);
|
||||
vec3 norm = vec3(0, 0, 1.0); /* always z-up */
|
||||
|
||||
ivec2 iuv = ivec2(uv.x, uv.y);
|
||||
stroke_depth = texelFetch(strokeDepth, iuv, 0).r;
|
||||
objcolor = texelFetch(strokeColor, iuv, 0);
|
||||
|
||||
/* diffuse light */
|
||||
vec3 lightdir = normalize(light3d - frag_loc);
|
||||
float diff = max(dot(norm, lightdir), 0.0);
|
||||
float dist = length(light3d - frag_loc) / pxscale;
|
||||
float factor = diff * ((energy * 100.0) / (dist * dist));
|
||||
|
||||
vec3 result = factor * max(ambient, 0.1) * vec3(objcolor);
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = vec4(result.r, result.g, result.b, objcolor.a);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
|
||||
uniform int size[3];
|
||||
uniform vec4 color;
|
||||
|
||||
uniform vec3 loc;
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform float pixfactor;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
int uselines = size[2];
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
vec2 nsize = max(vec2(size[0], size[1]), 3.0);
|
||||
|
||||
/* This pixelation shader is a modified version of original Geeks3d.com code */
|
||||
void main()
|
||||
{
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
|
||||
|
||||
float dx = (ProjectionMatrix[3][3] == 0.0) ? (nsize[0] / (nloc.z * defaultpixsize)) :
|
||||
(nsize[0] / defaultpixsize);
|
||||
float dy = (ProjectionMatrix[3][3] == 0.0) ? (nsize[1] / (nloc.z * defaultpixsize)) :
|
||||
(nsize[1] / defaultpixsize);
|
||||
|
||||
dx = max(abs(dx), 3.0);
|
||||
dy = max(abs(dy), 3.0);
|
||||
|
||||
vec2 coord = vec2(dx * floor(uv.x / dx), dy * floor(uv.y / dy));
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, ivec2(coord), 0).r;
|
||||
vec4 outcolor = texelFetch(strokeColor, ivec2(coord), 0);
|
||||
|
||||
if (uselines == 1) {
|
||||
float difx = uv.x - (floor(uv.x / nsize[0]) * nsize[0]);
|
||||
if ((difx == 0.5) && (outcolor.a > 0)) {
|
||||
outcolor = color;
|
||||
}
|
||||
float dify = uv.y - (floor(uv.y / nsize[1]) * nsize[1]);
|
||||
if ((dify == 0.5) && (outcolor.a > 0)) {
|
||||
outcolor = color;
|
||||
}
|
||||
}
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
/* ******************************************************************* */
|
||||
/* create rim and mask */
|
||||
/* ******************************************************************* */
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform vec2 Viewport;
|
||||
|
||||
uniform int offset[2];
|
||||
uniform vec3 rim_color;
|
||||
uniform vec3 mask_color;
|
||||
|
||||
uniform vec3 loc;
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform float pixfactor;
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
vec2 noffset = vec2(offset[0], offset[1]);
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
|
||||
|
||||
float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) :
|
||||
(noffset[0] / defaultpixsize);
|
||||
float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) :
|
||||
(noffset[1] / defaultpixsize);
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r;
|
||||
vec4 src_pixel = texelFetch(strokeColor, ivec2(uv.xy), 0);
|
||||
vec4 offset_pixel = texelFetch(strokeColor, ivec2(uv.x - dx, uv.y - dy), 0);
|
||||
vec4 outcolor;
|
||||
|
||||
/* is transparent */
|
||||
if (src_pixel.a == 0.0f) {
|
||||
discard;
|
||||
}
|
||||
/* check inside viewport */
|
||||
else if ((uv.x - dx < 0) || (uv.x - dx > Viewport[0])) {
|
||||
discard;
|
||||
}
|
||||
else if ((uv.y - dy < 0) || (uv.y - dy > Viewport[1])) {
|
||||
discard;
|
||||
}
|
||||
/* pixel is equal to mask color, keep */
|
||||
else if (src_pixel.rgb == mask_color.rgb) {
|
||||
discard;
|
||||
}
|
||||
else {
|
||||
if ((src_pixel.a > 0) && (offset_pixel.a > 0)) {
|
||||
discard;
|
||||
}
|
||||
else {
|
||||
outcolor = vec4(rim_color, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/* ******************************************************************* */
|
||||
/* Resolve RIM pass and add blur if needed */
|
||||
/* ******************************************************************* */
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform sampler2D strokeRim;
|
||||
|
||||
uniform vec3 mask_color;
|
||||
uniform int mode;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
#define MODE_NORMAL 0
|
||||
#define MODE_OVERLAY 1
|
||||
#define MODE_ADD 2
|
||||
#define MODE_SUB 3
|
||||
#define MODE_MULTIPLY 4
|
||||
#define MODE_DIVIDE 5
|
||||
|
||||
float overlay_color(float a, float b)
|
||||
{
|
||||
float rtn;
|
||||
if (a < 0.5) {
|
||||
rtn = 2.0 * a * b;
|
||||
}
|
||||
else {
|
||||
rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
vec4 get_blend_color(int mode, vec4 src_color, vec4 mix_color)
|
||||
{
|
||||
vec4 outcolor;
|
||||
if (mode == MODE_NORMAL) {
|
||||
outcolor = mix_color;
|
||||
}
|
||||
else if (mode == MODE_OVERLAY) {
|
||||
outcolor.r = overlay_color(src_color.r, mix_color.r);
|
||||
outcolor.g = overlay_color(src_color.g, mix_color.g);
|
||||
outcolor.b = overlay_color(src_color.b, mix_color.b);
|
||||
}
|
||||
else if (mode == MODE_ADD) {
|
||||
outcolor = src_color + mix_color;
|
||||
}
|
||||
else if (mode == MODE_SUB) {
|
||||
outcolor = src_color - mix_color;
|
||||
}
|
||||
else if (mode == MODE_MULTIPLY) {
|
||||
outcolor = src_color * mix_color;
|
||||
}
|
||||
else if (mode == MODE_DIVIDE) {
|
||||
outcolor = src_color / mix_color;
|
||||
}
|
||||
else {
|
||||
outcolor = mix_color;
|
||||
}
|
||||
|
||||
/* use always the alpha of source color */
|
||||
|
||||
outcolor.a = src_color.a;
|
||||
/* use alpha to calculate the weight of the mixed color */
|
||||
outcolor = mix(src_color, outcolor, mix_color.a);
|
||||
|
||||
return outcolor;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
|
||||
vec4 src_pixel = texelFetch(strokeColor, uv.xy, 0);
|
||||
vec4 rim_pixel = texelFetch(strokeRim, uv.xy, 0);
|
||||
|
||||
vec4 outcolor = src_pixel;
|
||||
|
||||
/* is transparent */
|
||||
if (src_pixel.a == 0.0f) {
|
||||
discard;
|
||||
}
|
||||
/* pixel is equal to mask color, keep */
|
||||
else if (src_pixel.rgb == mask_color.rgb) {
|
||||
outcolor = src_pixel;
|
||||
}
|
||||
else {
|
||||
if (rim_pixel.a == 0.0f) {
|
||||
outcolor = src_pixel;
|
||||
}
|
||||
else {
|
||||
outcolor = get_blend_color(mode, src_pixel, rim_pixel);
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
/* ******************************************************************* */
|
||||
/* create shadow */
|
||||
/* ******************************************************************* */
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform vec2 Viewport;
|
||||
|
||||
uniform int offset[2];
|
||||
uniform float scale[2];
|
||||
uniform float rotation;
|
||||
uniform vec4 shadow_color;
|
||||
|
||||
uniform float amplitude;
|
||||
uniform float period;
|
||||
uniform float phase;
|
||||
uniform int orientation;
|
||||
|
||||
uniform vec3 loc;
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform float pixfactor;
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
#define HORIZONTAL 0
|
||||
#define VERTICAL 1
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
vec2 noffset = vec2(offset[0], offset[1]);
|
||||
float cosv = cos(rotation);
|
||||
float sinv = sin(rotation);
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 vertex)
|
||||
{
|
||||
/* need to calculate ndc because this is not done by vertex shader */
|
||||
vec3 ndc = vec3(vertex).xyz / vertex.w;
|
||||
|
||||
vec2 sc;
|
||||
sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x;
|
||||
sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
|
||||
vec2 loc2d = toScreenSpace(nloc);
|
||||
|
||||
float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) :
|
||||
(noffset[0] / defaultpixsize);
|
||||
float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) :
|
||||
(noffset[1] / defaultpixsize);
|
||||
|
||||
/* move point to new coords system */
|
||||
vec2 tpos = vec2(uv.x, uv.y) - loc2d;
|
||||
|
||||
/* rotation */
|
||||
if (rotation != 0) {
|
||||
vec2 rotpoint = vec2((tpos.x * cosv) - (tpos.y * sinv), (tpos.x * sinv) + (tpos.y * cosv));
|
||||
tpos = rotpoint;
|
||||
}
|
||||
|
||||
/* apply offset */
|
||||
tpos = vec2(tpos.x - dx, tpos.y - dy);
|
||||
|
||||
/* apply scale */
|
||||
tpos.x *= 1.0 / scale[0];
|
||||
tpos.y *= 1.0 / scale[1];
|
||||
|
||||
/* back to original coords system */
|
||||
vec2 texpos = tpos + loc2d;
|
||||
|
||||
/* wave */
|
||||
if (orientation == HORIZONTAL) {
|
||||
float pval = (uv.x * M_PI) / Viewport[0];
|
||||
texpos.y += amplitude * sin((period * pval) + phase);
|
||||
}
|
||||
else if (orientation == VERTICAL) {
|
||||
float pval = (uv.y * M_PI) / Viewport[1];
|
||||
texpos.x += amplitude * sin((period * pval) + phase);
|
||||
}
|
||||
|
||||
vec4 src_pixel = texelFetch(strokeColor, ivec2(texpos.x, texpos.y), 0);
|
||||
/* is transparent */
|
||||
if (src_pixel.a == 0.0f) {
|
||||
discard;
|
||||
}
|
||||
|
||||
gl_FragDepth = texelFetch(strokeDepth, ivec2(texpos.x, texpos.y), 0).r;
|
||||
FragColor = shadow_color;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* ******************************************************************* */
|
||||
/* Resolve Shadow pass */
|
||||
/* ******************************************************************* */
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform sampler2D shadowColor;
|
||||
uniform sampler2D shadowDepth;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r;
|
||||
float shadow_depth = texelFetch(shadowDepth, uv.xy, 0).r;
|
||||
vec4 stroke_pixel = texelFetch(strokeColor, uv.xy, 0);
|
||||
vec4 shadow_pixel = texelFetch(shadowColor, uv.xy, 0);
|
||||
|
||||
/* copy original pixel */
|
||||
vec4 outcolor = stroke_pixel;
|
||||
float outdepth = stroke_depth;
|
||||
|
||||
/* if stroke is not on top, copy shadow */
|
||||
if ((stroke_pixel.a <= 0.2) && (shadow_pixel.a > 0.0)) {
|
||||
outcolor = shadow_pixel;
|
||||
outdepth = shadow_depth;
|
||||
}
|
||||
|
||||
gl_FragDepth = outdepth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
uniform mat4 ProjectionMatrix;
|
||||
uniform mat4 ViewMatrix;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
|
||||
uniform vec2 Viewport;
|
||||
uniform vec3 loc;
|
||||
uniform int radius;
|
||||
uniform float angle;
|
||||
uniform int transparent;
|
||||
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform float pixfactor;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 vertex)
|
||||
{
|
||||
/* need to calculate ndc because this is not done by vertex shader */
|
||||
vec3 ndc = vec3(vertex).xyz / vertex.w;
|
||||
|
||||
vec2 sc;
|
||||
sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x;
|
||||
sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
/* This swirl shader is a modified version of original Geeks3d.com code */
|
||||
void main()
|
||||
{
|
||||
vec2 uv = vec2(gl_FragCoord.xy);
|
||||
float stroke_depth;
|
||||
vec4 outcolor;
|
||||
|
||||
vec4 center3d = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0);
|
||||
vec2 center = toScreenSpace(center3d);
|
||||
vec2 tc = uv - center;
|
||||
|
||||
float dist = length(tc);
|
||||
float locpixsize = abs((loc.z * defaultpixsize));
|
||||
if (locpixsize == 0) {
|
||||
locpixsize = 1;
|
||||
}
|
||||
float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / locpixsize) :
|
||||
(radius / defaultpixsize);
|
||||
pxradius = max(pxradius, 1);
|
||||
|
||||
if (dist <= pxradius) {
|
||||
float percent = (pxradius - dist) / pxradius;
|
||||
float theta = percent * percent * angle * 8.0;
|
||||
float s = sin(theta);
|
||||
float c = cos(theta);
|
||||
tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c)));
|
||||
tc += center;
|
||||
|
||||
stroke_depth = texelFetch(strokeDepth, ivec2(tc), 0).r;
|
||||
outcolor = texelFetch(strokeColor, ivec2(tc), 0);
|
||||
}
|
||||
else {
|
||||
if (transparent == 1) {
|
||||
discard;
|
||||
}
|
||||
stroke_depth = texelFetch(strokeDepth, ivec2(uv), 0).r;
|
||||
outcolor = texelFetch(strokeColor, ivec2(uv), 0);
|
||||
}
|
||||
|
||||
gl_FragDepth = stroke_depth;
|
||||
FragColor = outcolor;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
|
||||
uniform float amplitude;
|
||||
uniform float period;
|
||||
uniform float phase;
|
||||
uniform int orientation;
|
||||
uniform vec2 wsize;
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
#define HORIZONTAL 0
|
||||
#define VERTICAL 1
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 outcolor;
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
float stroke_depth;
|
||||
|
||||
float value;
|
||||
if (orientation == HORIZONTAL) {
|
||||
float pval = (uv.x * M_PI) / wsize[0];
|
||||
value = amplitude * sin((period * pval) + phase);
|
||||
outcolor = texelFetch(strokeColor, ivec2(uv.x, uv.y + value), 0);
|
||||
stroke_depth = texelFetch(strokeDepth, ivec2(uv.x, uv.y + value), 0).r;
|
||||
}
|
||||
else {
|
||||
float pval = (uv.y * M_PI) / wsize[1];
|
||||
value = amplitude * sin((period * pval) + phase);
|
||||
outcolor = texelFetch(strokeColor, ivec2(uv.x + value, uv.y), 0);
|
||||
stroke_depth = texelFetch(strokeDepth, ivec2(uv.x + value, uv.y), 0).r;
|
||||
}
|
||||
|
||||
FragColor = outcolor;
|
||||
gl_FragDepth = stroke_depth;
|
||||
|
||||
if (outcolor.a < 0.02f) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
uniform sampler2D edgesTex;
|
||||
uniform sampler2D areaTex;
|
||||
uniform sampler2D searchTex;
|
||||
uniform sampler2D blendTex;
|
||||
uniform sampler2D colorTex;
|
||||
uniform sampler2D revealTex;
|
||||
uniform bool onlyAlpha;
|
||||
uniform bool doAntiAliasing;
|
||||
|
||||
in vec2 uvs;
|
||||
in vec2 pixcoord;
|
||||
in vec4 offset[3];
|
||||
|
||||
#if SMAA_STAGE == 0
|
||||
out vec2 fragColor;
|
||||
#elif SMAA_STAGE == 1
|
||||
out vec4 fragColor;
|
||||
#elif SMAA_STAGE == 2
|
||||
/* Reminder: Blending func is fragRevealage * DST + fragColor .*/
|
||||
layout(location = 0, index = 0) out vec4 outColor;
|
||||
layout(location = 0, index = 1) out vec4 outReveal;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#if SMAA_STAGE == 0
|
||||
/* Detect edges in color and revealage buffer. */
|
||||
fragColor = SMAALumaEdgeDetectionPS(uvs, offset, colorTex);
|
||||
fragColor = max(fragColor, SMAALumaEdgeDetectionPS(uvs, offset, revealTex));
|
||||
/* Discard if there is no edge. */
|
||||
if (dot(fragColor, float2(1.0, 1.0)) == 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
#elif SMAA_STAGE == 1
|
||||
fragColor = SMAABlendingWeightCalculationPS(
|
||||
uvs, pixcoord, offset, edgesTex, areaTex, searchTex, vec4(0));
|
||||
|
||||
#elif SMAA_STAGE == 2
|
||||
/* Resolve both buffers. */
|
||||
if (doAntiAliasing) {
|
||||
outColor = SMAANeighborhoodBlendingPS(uvs, offset[0], colorTex, blendTex);
|
||||
outReveal = SMAANeighborhoodBlendingPS(uvs, offset[0], revealTex, blendTex);
|
||||
}
|
||||
else {
|
||||
outColor = texture(colorTex, uvs);
|
||||
outReveal = texture(revealTex, uvs);
|
||||
}
|
||||
|
||||
/* Revealage, how much light passes through. */
|
||||
/* Average for alpha channel. */
|
||||
outReveal.a = clamp(dot(outReveal.rgb, vec3(0.333334)), 0.0, 1.0);
|
||||
/* Color buf is already premultiplied. Just add it to the color. */
|
||||
/* Add the alpha. */
|
||||
outColor.a = 1.0 - outReveal.a;
|
||||
|
||||
if (onlyAlpha) {
|
||||
/* Special case in wireframe xray mode. */
|
||||
outColor = vec4(0.0);
|
||||
outReveal.rgb = outReveal.aaa;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
out vec2 uvs;
|
||||
out vec2 pixcoord;
|
||||
out vec4 offset[3];
|
||||
|
||||
void main()
|
||||
{
|
||||
int v = gl_VertexID % 3;
|
||||
float x = -1.0 + float((v & 1) << 2);
|
||||
float y = -1.0 + float((v & 2) << 1);
|
||||
gl_Position = vec4(x, y, 1.0, 1.0);
|
||||
uvs = (gl_Position.xy + 1.0) * 0.5;
|
||||
|
||||
#if SMAA_STAGE == 0
|
||||
SMAAEdgeDetectionVS(uvs, offset);
|
||||
#elif SMAA_STAGE == 1
|
||||
SMAABlendingWeightCalculationVS(uvs, pixcoord, offset);
|
||||
#elif SMAA_STAGE == 2
|
||||
SMAANeighborhoodBlendingVS(uvs, offset[0]);
|
||||
#endif
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
|
||||
gl_FragDepth = texelFetch(strokeDepth, uv, 0).r;
|
||||
FragColor = texelFetch(strokeColor, uv, 0);
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform sampler2D blendColor;
|
||||
uniform sampler2D blendDepth;
|
||||
uniform int mode;
|
||||
uniform int mask_layer;
|
||||
uniform int tonemapping;
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
|
||||
#define MODE_REGULAR 0
|
||||
#define MODE_OVERLAY 1
|
||||
#define MODE_ADD 2
|
||||
#define MODE_SUB 3
|
||||
#define MODE_MULTIPLY 4
|
||||
#define MODE_DIVIDE 5
|
||||
|
||||
float overlay_color(float a, float b)
|
||||
{
|
||||
float rtn;
|
||||
if (a < 0.5) {
|
||||
rtn = 2.0 * a * b;
|
||||
}
|
||||
else {
|
||||
rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
vec4 get_blend_color(int mode, vec4 src_color, vec4 mix_color)
|
||||
{
|
||||
vec4 outcolor;
|
||||
|
||||
if (mix_color.a == 0) {
|
||||
return src_color;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case MODE_REGULAR: {
|
||||
/* premult */
|
||||
src_color = vec4(vec3(src_color.rgb / src_color.a), src_color.a);
|
||||
mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
|
||||
|
||||
outcolor = vec4(mix(src_color.rgb, mix_color.rgb, mix_color.a), src_color.a);
|
||||
break;
|
||||
}
|
||||
case MODE_OVERLAY: {
|
||||
src_color = vec4(vec3(src_color.rgb / src_color.a), src_color.a);
|
||||
mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
|
||||
|
||||
mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
|
||||
outcolor.r = overlay_color(src_color.r, mix_color.r);
|
||||
outcolor.g = overlay_color(src_color.g, mix_color.g);
|
||||
outcolor.b = overlay_color(src_color.b, mix_color.b);
|
||||
outcolor.a = src_color.a;
|
||||
break;
|
||||
}
|
||||
case MODE_ADD: {
|
||||
mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
|
||||
outcolor = src_color + mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
break;
|
||||
}
|
||||
case MODE_SUB: {
|
||||
mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
|
||||
outcolor = src_color - mix_color;
|
||||
outcolor.a = clamp(src_color.a - mix_color.a, 0.0, 1.0);
|
||||
break;
|
||||
}
|
||||
case MODE_MULTIPLY: {
|
||||
src_color = vec4(vec3(src_color.rgb / src_color.a), src_color.a);
|
||||
mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
|
||||
|
||||
mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
|
||||
outcolor = src_color * mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
break;
|
||||
}
|
||||
case MODE_DIVIDE: {
|
||||
mix_color.rgb = mix(src_color.rgb, mix_color.rgb, mix_color.a);
|
||||
outcolor = src_color / mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
outcolor = mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return clamp(outcolor, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float linearrgb_to_srgb(float c)
|
||||
{
|
||||
if (c < 0.0031308) {
|
||||
return (c < 0.0) ? 0.0 : c * 12.92;
|
||||
}
|
||||
else {
|
||||
return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 tone(vec4 stroke_color)
|
||||
{
|
||||
if (tonemapping == 1) {
|
||||
vec4 color = vec4(0, 0, 0, stroke_color.a);
|
||||
color.r = linearrgb_to_srgb(stroke_color.r);
|
||||
color.g = linearrgb_to_srgb(stroke_color.g);
|
||||
color.b = linearrgb_to_srgb(stroke_color.b);
|
||||
return color;
|
||||
}
|
||||
else {
|
||||
return stroke_color;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 outcolor;
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
|
||||
float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
|
||||
|
||||
vec4 mix_color = texelFetch(blendColor, uv, 0).rgba;
|
||||
float mix_depth = texelFetch(blendDepth, uv, 0).r;
|
||||
|
||||
if (stroke_color.a > 0) {
|
||||
if (mix_color.a > 0) {
|
||||
/* apply blend mode */
|
||||
FragColor = get_blend_color(mode, stroke_color, mix_color);
|
||||
}
|
||||
else {
|
||||
FragColor = stroke_color;
|
||||
}
|
||||
gl_FragDepth = min(stroke_depth, mix_depth);
|
||||
}
|
||||
else {
|
||||
if (mask_layer == ON) {
|
||||
discard;
|
||||
}
|
||||
else {
|
||||
/* if not using mask, return mix color */
|
||||
FragColor = mix_color;
|
||||
gl_FragDepth = mix_depth;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply tone mapping */
|
||||
FragColor = tone(FragColor);
|
||||
}
|
||||
@@ -0,0 +1,593 @@
|
||||
|
||||
/* Must match C declaration. */
|
||||
struct gpMaterial {
|
||||
vec4 stroke_color;
|
||||
vec4 fill_color;
|
||||
vec4 fill_mix_color;
|
||||
vec4 fill_uv_rot_scale;
|
||||
vec4 fill_uv_offset;
|
||||
/* Put float/int at the end to avoid padding error */
|
||||
float stroke_texture_mix;
|
||||
float stroke_u_scale;
|
||||
float fill_texture_mix;
|
||||
int flag;
|
||||
/* Please ensure 16 byte alignment (multiple of vec4). */
|
||||
};
|
||||
|
||||
/* flag */
|
||||
#define GP_STROKE_ALIGNMENT_STROKE 1
|
||||
#define GP_STROKE_ALIGNMENT_OBJECT 2
|
||||
#define GP_STROKE_ALIGNMENT_FIXED 3
|
||||
#define GP_STROKE_ALIGNMENT 0x3
|
||||
#define GP_STROKE_OVERLAP (1 << 2)
|
||||
#define GP_STROKE_TEXTURE_USE (1 << 3)
|
||||
#define GP_STROKE_TEXTURE_STENCIL (1 << 4)
|
||||
#define GP_STROKE_TEXTURE_PREMUL (1 << 5)
|
||||
#define GP_STROKE_DOTS (1 << 6)
|
||||
#define GP_FILL_TEXTURE_USE (1 << 10)
|
||||
#define GP_FILL_TEXTURE_PREMUL (1 << 11)
|
||||
#define GP_FILL_TEXTURE_CLIP (1 << 12)
|
||||
#define GP_FILL_GRADIENT_USE (1 << 13)
|
||||
#define GP_FILL_GRADIENT_RADIAL (1 << 14)
|
||||
/* High bits are used to pass material ID to fragment shader. */
|
||||
#define GP_MATID_SHIFT 16
|
||||
|
||||
/* Multiline defines can crash blender with certain GPU drivers. */
|
||||
/* clang-format off */
|
||||
#define GP_FILL_FLAGS (GP_FILL_TEXTURE_USE | GP_FILL_TEXTURE_PREMUL | GP_FILL_TEXTURE_CLIP | GP_FILL_GRADIENT_USE | GP_FILL_GRADIENT_RADIAL)
|
||||
/* clang-format on */
|
||||
|
||||
#define GP_FLAG_TEST(flag, val) (((flag) & (val)) != 0)
|
||||
|
||||
/* Must match C declaration. */
|
||||
struct gpLight {
|
||||
vec4 color_type;
|
||||
vec4 right;
|
||||
vec4 up;
|
||||
vec4 forward;
|
||||
vec4 position;
|
||||
/* Please ensure 16 byte alignment (multiple of vec4). */
|
||||
};
|
||||
|
||||
#define spot_size right.w
|
||||
#define spot_blend up.w
|
||||
|
||||
#define GP_LIGHT_TYPE_POINT 0.0
|
||||
#define GP_LIGHT_TYPE_SPOT 1.0
|
||||
#define GP_LIGHT_TYPE_SUN 2.0
|
||||
#define GP_LIGHT_TYPE_AMBIENT 3.0
|
||||
|
||||
#ifdef GP_MATERIAL_BUFFER_LEN
|
||||
|
||||
layout(std140) uniform gpMaterialBlock
|
||||
{
|
||||
gpMaterial materials[GP_MATERIAL_BUFFER_LEN];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GPENCIL_LIGHT_BUFFER_LEN
|
||||
|
||||
layout(std140) uniform gpLightBlock
|
||||
{
|
||||
gpLight lights[GPENCIL_LIGHT_BUFFER_LEN];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Must match eGPLayerBlendModes */
|
||||
#define MODE_REGULAR 0
|
||||
#define MODE_OVERLAY 1
|
||||
#define MODE_ADD 2
|
||||
#define MODE_SUB 3
|
||||
#define MODE_MULTIPLY 4
|
||||
#define MODE_DIVIDE 5
|
||||
#define MODE_OVERLAY_SECOND_PASS 999
|
||||
|
||||
void blend_mode_output(
|
||||
int blend_mode, vec4 color, float opacity, out vec4 frag_color, out vec4 frag_revealage)
|
||||
{
|
||||
switch (blend_mode) {
|
||||
case MODE_REGULAR:
|
||||
/* Reminder: Blending func is premult alpha blend (dst.rgba * (1 - src.a) + src.rgb).*/
|
||||
color *= opacity;
|
||||
frag_color = color;
|
||||
frag_revealage = vec4(0.0, 0.0, 0.0, color.a);
|
||||
break;
|
||||
case MODE_MULTIPLY:
|
||||
/* Reminder: Blending func is multiply blend (dst.rgba * src.rgba).*/
|
||||
color.a *= opacity;
|
||||
frag_revealage = frag_color = (1.0 - color.a) + color.a * color;
|
||||
break;
|
||||
case MODE_DIVIDE:
|
||||
/* Reminder: Blending func is multiply blend (dst.rgba * src.rgba).*/
|
||||
color.a *= opacity;
|
||||
frag_revealage = frag_color = clamp(1.0 / max(vec4(1e-6), 1.0 - color * color.a), 0.0, 1e18);
|
||||
break;
|
||||
case MODE_OVERLAY:
|
||||
/* Reminder: Blending func is multiply blend (dst.rgba * src.rgba).*/
|
||||
/**
|
||||
* We need to separate the overlay equation into 2 term (one mul and one add).
|
||||
* This is the standard overlay equation (per channel):
|
||||
* rtn = (src < 0.5) ? (2.0 * src * dst) : (1.0 - 2.0 * (1.0 - src) * (1.0 - dst));
|
||||
* We rewrite the second branch like this:
|
||||
* rtn = 1 - 2 * (1 - src) * (1 - dst);
|
||||
* rtn = 1 - 2 (1 - dst + src * dst - src);
|
||||
* rtn = 1 - 2 (1 - dst * (1 - src) - src);
|
||||
* rtn = 1 - 2 + dst * (2 - 2 * src) + 2 * src;
|
||||
* rtn = (- 1 + 2 * src) + dst * (2 - 2 * src);
|
||||
**/
|
||||
color = mix(vec4(0.5), color, color.a * opacity);
|
||||
vec4 s = step(-0.5, -color);
|
||||
frag_revealage = frag_color = 2.0 * s + 2.0 * color * (1.0 - s * 2.0);
|
||||
break;
|
||||
case MODE_OVERLAY_SECOND_PASS:
|
||||
/* Reminder: Blending func is additive blend (dst.rgba + src.rgba).*/
|
||||
color = mix(vec4(0.5), color, color.a * opacity);
|
||||
frag_revealage = frag_color = (-1.0 + 2.0 * color) * step(-0.5, -color);
|
||||
break;
|
||||
case MODE_SUB:
|
||||
case MODE_ADD:
|
||||
/* Reminder: Blending func is additive / subtractive blend (dst.rgba +/- src.rgba).*/
|
||||
frag_color = color * color.a * opacity;
|
||||
frag_revealage = vec4(0.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GPU_VERTEX_SHADER
|
||||
# define IN_OUT out
|
||||
#else
|
||||
# define IN_OUT in
|
||||
#endif
|
||||
|
||||
/* Shader interface. */
|
||||
IN_OUT vec4 finalColorMul;
|
||||
IN_OUT vec4 finalColorAdd;
|
||||
IN_OUT vec3 finalPos;
|
||||
IN_OUT vec2 finalUvs;
|
||||
noperspective IN_OUT float strokeThickness;
|
||||
noperspective IN_OUT float strokeHardeness;
|
||||
flat IN_OUT vec2 strokeAspect;
|
||||
flat IN_OUT vec2 strokePt1;
|
||||
flat IN_OUT vec2 strokePt2;
|
||||
flat IN_OUT int matFlag;
|
||||
flat IN_OUT float depth;
|
||||
|
||||
#ifdef GPU_FRAGMENT_SHADER
|
||||
|
||||
# define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0))
|
||||
|
||||
float stroke_round_cap_mask(vec2 p1, vec2 p2, vec2 aspect, float thickness, float hardfac)
|
||||
{
|
||||
/* We create our own uv space to avoid issues with triangulation and linear
|
||||
* interpolation artifacts. */
|
||||
vec2 line = p2.xy - p1.xy;
|
||||
vec2 pos = gl_FragCoord.xy - p1.xy;
|
||||
float line_len = length(line);
|
||||
float half_line_len = line_len * 0.5;
|
||||
/* Normalize */
|
||||
line = (line_len > 0.0) ? (line / line_len) : vec2(1.0, 0.0);
|
||||
/* Create a uv space that englobe the whole segment into a capsule. */
|
||||
vec2 uv_end;
|
||||
uv_end.x = max(abs(dot(line, pos) - half_line_len) - half_line_len, 0.0);
|
||||
uv_end.y = dot(vec2(-line.y, line.x), pos);
|
||||
/* Divide by stroke radius. */
|
||||
uv_end /= thickness;
|
||||
uv_end *= aspect;
|
||||
|
||||
float dist = clamp(1.0 - length(uv_end) * 2.0, 0.0, 1.0);
|
||||
if (hardfac > 0.999) {
|
||||
return step(1e-8, dist);
|
||||
}
|
||||
else {
|
||||
/* Modulate the falloff profile */
|
||||
float hardness = 1.0 - hardfac;
|
||||
dist = pow(dist, mix(0.01, 10.0, hardness));
|
||||
return smoothstep(0.0, 1.0, dist);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uniform vec2 sizeViewport;
|
||||
uniform vec2 sizeViewportInv;
|
||||
|
||||
/* Per Object */
|
||||
uniform bool strokeOrder3d;
|
||||
uniform int gpMaterialOffset;
|
||||
uniform float thicknessScale;
|
||||
uniform float thicknessWorldScale;
|
||||
#define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
|
||||
#define MATERIAL(m) materials[m + gpMaterialOffset]
|
||||
|
||||
#ifdef GPU_VERTEX_SHADER
|
||||
|
||||
/* Per Layer */
|
||||
uniform float thicknessOffset;
|
||||
uniform float vertexColorOpacity;
|
||||
uniform vec4 layerTint;
|
||||
uniform float layerOpacity; /* Used for onion skin. */
|
||||
uniform float strokeIndexOffset = 0.0;
|
||||
|
||||
/* All of these attribs are quad loaded the same way
|
||||
* as GL_LINES_ADJACENCY would feed a geometry shader:
|
||||
* - ma reference the previous adjacency point.
|
||||
* - ma1 reference the current line first point.
|
||||
* - ma2 reference the current line second point.
|
||||
* - ma3 reference the next adjacency point.
|
||||
* Note that we are rendering quad instances and not using any index buffer (except for fills).
|
||||
*/
|
||||
in vec4 ma;
|
||||
in vec4 ma1;
|
||||
in vec4 ma2;
|
||||
in vec4 ma3;
|
||||
# define strength1 ma1.y
|
||||
# define strength2 ma2.y
|
||||
# define stroke_id1 ma1.z
|
||||
# define point_id1 ma1.w
|
||||
/* Position contains thickness in 4th component. */
|
||||
in vec4 pos; /* Prev adj vert */
|
||||
in vec4 pos1; /* Current edge */
|
||||
in vec4 pos2; /* Current edge */
|
||||
in vec4 pos3; /* Next adj vert */
|
||||
# define thickness1 pos1.w
|
||||
# define thickness2 pos2.w
|
||||
/* xy is UV for fills, z is U of stroke, w is cosine of UV angle with sign of sine. */
|
||||
in vec4 uv1;
|
||||
in vec4 uv2;
|
||||
|
||||
in vec4 col1;
|
||||
in vec4 col2;
|
||||
|
||||
in vec4 fcol1;
|
||||
|
||||
/* hard.x is aspect. */
|
||||
in vec2 hard1;
|
||||
in vec2 hard2;
|
||||
# define aspect1 hard1.x
|
||||
# define aspect2 hard2.x
|
||||
|
||||
void discard_vert()
|
||||
{
|
||||
/* We set the vertex at the camera origin to generate 0 fragments. */
|
||||
gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
|
||||
}
|
||||
|
||||
vec2 project_to_screenspace(vec4 v)
|
||||
{
|
||||
return ((v.xy / v.w) * 0.5 + 0.5) * sizeViewport;
|
||||
}
|
||||
|
||||
vec2 rotate_90deg(vec2 v)
|
||||
{
|
||||
/* Counter Clock-Wise. */
|
||||
return vec2(-v.y, v.x);
|
||||
}
|
||||
|
||||
mat4 model_matrix_get()
|
||||
{
|
||||
return ModelMatrix;
|
||||
}
|
||||
|
||||
vec3 transform_point(mat4 m, vec3 v)
|
||||
{
|
||||
return (m * vec4(v, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec2 safe_normalize(vec2 v)
|
||||
{
|
||||
float len_sqr = dot(v, v);
|
||||
if (len_sqr > 0.0) {
|
||||
return v / sqrt(len_sqr);
|
||||
}
|
||||
else {
|
||||
return vec2(1.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 safe_normalize_len(vec2 v, out float len)
|
||||
{
|
||||
len = sqrt(dot(v, v));
|
||||
if (len > 0.0) {
|
||||
return v / len;
|
||||
}
|
||||
else {
|
||||
return vec2(1.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
float stroke_thickness_modulate(float thickness)
|
||||
{
|
||||
/* Modify stroke thickness by object and layer factors.-*/
|
||||
thickness *= thicknessScale;
|
||||
thickness += thicknessOffset;
|
||||
thickness = max(1.0, thickness);
|
||||
|
||||
if (thicknessIsScreenSpace) {
|
||||
/* Multiply offset by view Z so that offset is constant in screenspace.
|
||||
* (e.i: does not change with the distance to camera) */
|
||||
thickness *= gl_Position.w;
|
||||
}
|
||||
else {
|
||||
/* World space point size. */
|
||||
thickness *= thicknessWorldScale * ProjectionMatrix[1][1] * sizeViewport.y;
|
||||
}
|
||||
return thickness;
|
||||
}
|
||||
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
void color_output(vec4 stroke_col, vec4 vert_col, float vert_strength, float mix_tex)
|
||||
{
|
||||
/* Mix stroke with other colors. */
|
||||
vec4 mixed_col = stroke_col;
|
||||
mixed_col.rgb = mix(mixed_col.rgb, vert_col.rgb, vert_col.a * vertexColorOpacity);
|
||||
mixed_col.rgb = mix(mixed_col.rgb, layerTint.rgb, layerTint.a);
|
||||
mixed_col.a *= vert_strength * layerOpacity;
|
||||
/**
|
||||
* This is what the fragment shader looks like.
|
||||
* out = col * finalColorMul + col.a * finalColorAdd.
|
||||
* finalColorMul is how much of the texture color to keep.
|
||||
* finalColorAdd is how much of the mixed color to add.
|
||||
* Note that we never add alpha. This is to keep the texture act as a stencil.
|
||||
* We do however, modulate the alpha (reduce it).
|
||||
**/
|
||||
/* We add the mixed color. This is 100% mix (no texture visible). */
|
||||
finalColorMul = vec4(mixed_col.aaa, mixed_col.a);
|
||||
finalColorAdd = vec4(mixed_col.rgb * mixed_col.a, 0.0);
|
||||
/* Then we blend according to the texture mix factor.
|
||||
* Note that we keep the alpha modulation. */
|
||||
finalColorMul.rgb *= mix_tex;
|
||||
finalColorAdd.rgb *= 1.0 - mix_tex;
|
||||
}
|
||||
# endif
|
||||
|
||||
void stroke_vertex()
|
||||
{
|
||||
int m = int(ma1.x);
|
||||
bool is_dot = false;
|
||||
bool is_squares = false;
|
||||
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
if (m != -1.0) {
|
||||
is_dot = GP_FLAG_TEST(MATERIAL(m).flag, GP_STROKE_ALIGNMENT);
|
||||
is_squares = !GP_FLAG_TEST(MATERIAL(m).flag, GP_STROKE_DOTS);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Special Case. Stroke with single vert are rendered as dots. Do not discard them. */
|
||||
if (!is_dot && ma.x == -1.0 && ma2.x == -1.0) {
|
||||
is_dot = true;
|
||||
is_squares = false;
|
||||
}
|
||||
|
||||
/* Enpoints, we discard the vertices. */
|
||||
if (ma1.x == -1.0 || (!is_dot && ma2.x == -1.0)) {
|
||||
discard_vert();
|
||||
return;
|
||||
}
|
||||
|
||||
mat4 model_mat = model_matrix_get();
|
||||
|
||||
/* Avoid using a vertex attrib for quad positioning. */
|
||||
float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
|
||||
float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
|
||||
|
||||
bool use_curr = is_dot || (x == -1.0);
|
||||
|
||||
vec3 wpos_adj = transform_point(model_mat, (use_curr) ? pos.xyz : pos3.xyz);
|
||||
vec3 wpos1 = transform_point(model_mat, pos1.xyz);
|
||||
vec3 wpos2 = transform_point(model_mat, pos2.xyz);
|
||||
|
||||
vec4 ndc_adj = point_world_to_ndc(wpos_adj);
|
||||
vec4 ndc1 = point_world_to_ndc(wpos1);
|
||||
vec4 ndc2 = point_world_to_ndc(wpos2);
|
||||
|
||||
gl_Position = (use_curr) ? ndc1 : ndc2;
|
||||
finalPos = (use_curr) ? wpos1 : wpos2;
|
||||
|
||||
vec2 ss_adj = project_to_screenspace(ndc_adj);
|
||||
vec2 ss1 = project_to_screenspace(ndc1);
|
||||
vec2 ss2 = project_to_screenspace(ndc2);
|
||||
/* Screenspace Lines tangents. */
|
||||
float line_len;
|
||||
vec2 line = safe_normalize_len(ss2 - ss1, line_len);
|
||||
vec2 line_adj = safe_normalize((use_curr) ? (ss1 - ss_adj) : (ss_adj - ss2));
|
||||
|
||||
float thickness = abs((use_curr) ? thickness1 : thickness2);
|
||||
thickness = stroke_thickness_modulate(thickness);
|
||||
|
||||
finalUvs = vec2(x, y) * 0.5 + 0.5;
|
||||
strokeHardeness = (use_curr) ? hard1.y : hard2.y;
|
||||
|
||||
if (is_dot) {
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
int alignement = MATERIAL(m).flag & GP_STROKE_ALIGNMENT;
|
||||
# endif
|
||||
|
||||
vec2 x_axis;
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
if (alignement == GP_STROKE_ALIGNMENT_STROKE) {
|
||||
x_axis = (ma2.x == -1.0) ? line_adj : line;
|
||||
}
|
||||
else if (alignement == GP_STROKE_ALIGNMENT_FIXED) {
|
||||
/* Default for no-material drawing. */
|
||||
x_axis = vec2(1.0, 0.0);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{ /* GP_STROKE_ALIGNMENT_OBJECT */
|
||||
vec4 ndc_x = point_world_to_ndc(wpos1 + model_mat[0].xyz);
|
||||
vec2 ss_x = project_to_screenspace(ndc_x);
|
||||
x_axis = safe_normalize(ss_x - ss1);
|
||||
}
|
||||
|
||||
/* Rotation: Encoded as Cos + Sin sign. */
|
||||
float rot_sin = sqrt(1.0 - uv1.w * uv1.w) * sign(uv1.w);
|
||||
float rot_cos = abs(uv1.w);
|
||||
x_axis = mat2(rot_cos, -rot_sin, rot_sin, rot_cos) * x_axis;
|
||||
|
||||
vec2 y_axis = rotate_90deg(x_axis);
|
||||
|
||||
strokeAspect.x = aspect1;
|
||||
|
||||
if (strokeAspect.x > 1.0) {
|
||||
strokeAspect.y = strokeAspect.x;
|
||||
strokeAspect.x = 1.0;
|
||||
}
|
||||
else {
|
||||
strokeAspect.x = 1.0 / strokeAspect.x;
|
||||
strokeAspect.y = 1.0;
|
||||
}
|
||||
|
||||
x /= strokeAspect.x;
|
||||
y /= strokeAspect.y;
|
||||
|
||||
gl_Position.xy += (x * x_axis + y * y_axis) * sizeViewportInv.xy * thickness;
|
||||
|
||||
strokePt1 = ss1;
|
||||
strokePt2 = ss1 + x_axis * 0.5;
|
||||
strokeThickness = (is_squares) ? 1e18 : (thickness / gl_Position.w);
|
||||
}
|
||||
else {
|
||||
bool is_stroke_start = (ma.x == -1.0 && x == -1.0);
|
||||
bool is_stroke_end = (ma3.x == -1.0 && x == 1.0);
|
||||
|
||||
/* Mitter tangent vector. */
|
||||
vec2 miter_tan = safe_normalize(line_adj + line);
|
||||
float miter_dot = dot(miter_tan, line_adj);
|
||||
/* Break corners after a certain angle to avoid really thick corners. */
|
||||
const float miter_limit = 0.5; /* cos(60°) */
|
||||
bool miter_break = (miter_dot < miter_limit) || is_stroke_start || is_stroke_end;
|
||||
miter_tan = (miter_break) ? line : (miter_tan / miter_dot);
|
||||
|
||||
vec2 miter = rotate_90deg(miter_tan);
|
||||
|
||||
strokePt1.xy = ss1;
|
||||
strokePt2.xy = ss2;
|
||||
strokeThickness = thickness / gl_Position.w;
|
||||
strokeAspect = vec2(1.0);
|
||||
|
||||
vec2 screen_ofs = miter * y;
|
||||
|
||||
/* Reminder: we packed the cap flag into the sign of stength and thickness sign. */
|
||||
if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) ||
|
||||
miter_break) {
|
||||
screen_ofs += line * x;
|
||||
}
|
||||
|
||||
gl_Position.xy += screen_ofs * sizeViewportInv.xy * thickness;
|
||||
|
||||
finalUvs.x = (use_curr) ? uv1.z : uv2.z;
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
finalUvs.x *= MATERIAL(m).stroke_u_scale;
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
vec4 vert_col = (use_curr) ? col1 : col2;
|
||||
float vert_strength = abs((use_curr) ? strength1 : strength2);
|
||||
vec4 stroke_col = MATERIAL(m).stroke_color;
|
||||
float mix_tex = MATERIAL(m).stroke_texture_mix;
|
||||
|
||||
color_output(stroke_col, vert_col, vert_strength, mix_tex);
|
||||
|
||||
matFlag = MATERIAL(m).flag & ~GP_FILL_FLAGS;
|
||||
# endif
|
||||
|
||||
if (strokeOrder3d) {
|
||||
/* Use the fragment depth (see fragment shader). */
|
||||
depth = -1.0;
|
||||
}
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
else if (GP_FLAG_TEST(MATERIAL(m).flag, GP_STROKE_OVERLAP)) {
|
||||
/* Use the index of the point as depth.
|
||||
* This means the stroke can overlap itself. */
|
||||
depth = (point_id1 + strokeIndexOffset + 1.0) * 0.0000002;
|
||||
}
|
||||
# endif
|
||||
else {
|
||||
/* Use the index of first point of the stroke as depth.
|
||||
* We render using a greater depth test this means the stroke
|
||||
* cannot overlap itself.
|
||||
* We offset by one so that the fill can be overlapped by its stroke.
|
||||
* The offset is ok since we pad the strokes data because of adjacency infos. */
|
||||
depth = (stroke_id1 + strokeIndexOffset + 1.0) * 0.0000002;
|
||||
}
|
||||
}
|
||||
|
||||
void fill_vertex()
|
||||
{
|
||||
mat4 model_mat = model_matrix_get();
|
||||
|
||||
vec3 wpos = transform_point(model_mat, pos1.xyz);
|
||||
gl_Position = point_world_to_ndc(wpos);
|
||||
finalPos = wpos;
|
||||
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
int m = int(ma1.x);
|
||||
|
||||
vec4 fill_col = MATERIAL(m).fill_color;
|
||||
float mix_tex = MATERIAL(m).fill_texture_mix;
|
||||
|
||||
/* Special case: We don't modulate alpha in gradient mode. */
|
||||
if (GP_FLAG_TEST(MATERIAL(m).flag, GP_FILL_GRADIENT_USE)) {
|
||||
fill_col.a = 1.0;
|
||||
}
|
||||
|
||||
/* Decode fill opacity. */
|
||||
vec4 fcol_decode = vec4(fcol1.rgb, floor(fcol1.a / 10.0));
|
||||
float fill_opacity = fcol1.a - (fcol_decode.a * 10);
|
||||
fcol_decode.a /= 10000.0f;
|
||||
|
||||
/* Apply opacity. */
|
||||
fill_col.a *= fill_opacity;
|
||||
/* If factor is > 1 force opacity. */
|
||||
if (fill_opacity > 1.0) {
|
||||
fill_col.a += fill_opacity - 1.0f;
|
||||
}
|
||||
|
||||
fill_col.a = clamp(fill_col.a, 0.0, 1.0);
|
||||
|
||||
color_output(fill_col, fcol_decode, 1.0, mix_tex);
|
||||
|
||||
matFlag = MATERIAL(m).flag & GP_FILL_FLAGS;
|
||||
matFlag |= m << GP_MATID_SHIFT;
|
||||
|
||||
vec2 loc = MATERIAL(m).fill_uv_offset.xy;
|
||||
mat2x2 rot_scale = mat2x2(MATERIAL(m).fill_uv_rot_scale.xy, MATERIAL(m).fill_uv_rot_scale.zw);
|
||||
finalUvs = rot_scale * uv1.xy + loc;
|
||||
# endif
|
||||
|
||||
strokeThickness = 1e18;
|
||||
strokeAspect = vec2(1.0);
|
||||
strokePt1 = strokePt2 = vec2(0.0);
|
||||
|
||||
if (strokeOrder3d) {
|
||||
/* Use the fragment depth (see fragment shader). */
|
||||
depth = -1.0;
|
||||
/* We still offset the fills a little to avoid overlaps */
|
||||
gl_Position.z += 0.000002;
|
||||
}
|
||||
else {
|
||||
/* Use the index of first point of the stroke as depth. */
|
||||
depth = (stroke_id1 + strokeIndexOffset) * 0.0000002;
|
||||
}
|
||||
}
|
||||
|
||||
void gpencil_vertex()
|
||||
{
|
||||
/* Trick to detect if a drawcall is stroke or fill.
|
||||
* This does mean that we need to draw an empty stroke segment before starting
|
||||
* to draw the real stroke segments. */
|
||||
bool is_fill = (gl_InstanceID == 0);
|
||||
|
||||
if (!is_fill) {
|
||||
stroke_vertex();
|
||||
}
|
||||
else {
|
||||
fill_vertex();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
uniform sampler2D depthBuf;
|
||||
uniform float strokeDepth2d;
|
||||
uniform bool strokeOrder3d;
|
||||
|
||||
noperspective in vec4 uvcoordsvar;
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = textureLod(depthBuf, uvcoordsvar.xy, 0).r;
|
||||
if (strokeOrder3d) {
|
||||
gl_FragDepth = depth;
|
||||
}
|
||||
else {
|
||||
gl_FragDepth = (depth != 0.0) ? gl_FragCoord.z : 1.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
uniform vec4 gpModelMatrix[4];
|
||||
|
||||
noperspective out vec4 uvcoordsvar;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 model_matrix = mat4(gpModelMatrix[0], gpModelMatrix[1], gpModelMatrix[2], gpModelMatrix[3]);
|
||||
int v = gl_VertexID % 3;
|
||||
float x = -1.0 + float((v & 1) << 2);
|
||||
float y = -1.0 + float((v & 2) << 1);
|
||||
gl_Position = ViewProjectionMatrix * (model_matrix * vec4(x, y, 0.0, 1.0));
|
||||
uvcoordsvar = vec4((gl_Position.xy / gl_Position.w + 1.0) * 0.5, 0.0, 0.0);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
in vec4 mColor;
|
||||
in vec2 mTexCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 centered = mTexCoord - vec2(0.5);
|
||||
float dist_squared = dot(centered, centered);
|
||||
const float rad_squared = 0.25;
|
||||
|
||||
// round point with jaggy edges
|
||||
if (dist_squared > rad_squared) {
|
||||
discard;
|
||||
}
|
||||
|
||||
fragColor = mColor;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
uniform vec2 Viewport;
|
||||
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
in vec4 finalColor[1];
|
||||
in float finalThickness[1];
|
||||
|
||||
out vec4 mColor;
|
||||
out vec2 mTexCoord;
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 vertex)
|
||||
{
|
||||
return vec2(vertex.xy / vertex.w) * Viewport;
|
||||
}
|
||||
|
||||
/* get zdepth value */
|
||||
float getZdepth(vec4 point)
|
||||
{
|
||||
return min(-0.05, (point.z / point.w));
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 P0 = gl_in[0].gl_Position;
|
||||
vec2 sp0 = toScreenSpace(P0);
|
||||
|
||||
float size = finalThickness[0];
|
||||
|
||||
/* generate the triangle strip */
|
||||
mTexCoord = vec2(0, 1);
|
||||
mColor = finalColor[0];
|
||||
gl_Position = vec4(vec2(sp0.x - size, sp0.y + size) / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0, 0);
|
||||
mColor = finalColor[0];
|
||||
gl_Position = vec4(vec2(sp0.x - size, sp0.y - size) / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(1, 1);
|
||||
mColor = finalColor[0];
|
||||
gl_Position = vec4(vec2(sp0.x + size, sp0.y + size) / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(1, 0);
|
||||
mColor = finalColor[0];
|
||||
gl_Position = vec4(vec2(sp0.x + size, sp0.y - size) / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
uniform mat4 gpModelMatrix;
|
||||
|
||||
in vec3 pos;
|
||||
in vec4 color;
|
||||
in float size;
|
||||
|
||||
out vec4 finalColor;
|
||||
out float finalThickness;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
|
||||
finalColor = color;
|
||||
finalThickness = size;
|
||||
|
||||
/* Dirty fix waiting for new GPencil engine. */
|
||||
finalColor.rgb = pow(finalColor.rgb, vec3(2.2));
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
uniform vec4 color2;
|
||||
uniform int fill_type;
|
||||
uniform float mix_factor;
|
||||
|
||||
uniform float gradient_angle;
|
||||
uniform float gradient_radius;
|
||||
uniform float pattern_gridsize;
|
||||
uniform vec2 gradient_scale;
|
||||
uniform vec2 gradient_shift;
|
||||
|
||||
uniform float texture_angle;
|
||||
uniform vec2 texture_scale;
|
||||
uniform vec2 texture_offset;
|
||||
uniform int texture_mix;
|
||||
uniform int texture_flip;
|
||||
uniform float texture_opacity;
|
||||
uniform int xraymode;
|
||||
uniform int drawmode;
|
||||
uniform float layer_opacity;
|
||||
|
||||
uniform sampler2D myTexture;
|
||||
uniform bool myTexturePremultiplied;
|
||||
uniform int texture_clamp;
|
||||
|
||||
uniform int viewport_xray;
|
||||
uniform int shading_type[2];
|
||||
uniform vec4 wire_color;
|
||||
|
||||
uniform int fade_layer;
|
||||
uniform float fade_layer_factor;
|
||||
uniform bool fade_ob;
|
||||
uniform vec3 fade_color;
|
||||
uniform float fade_ob_factor;
|
||||
|
||||
/* keep this list synchronized with list in gpencil_draw_utils.c */
|
||||
#define SOLID 0
|
||||
#define GRADIENT 1
|
||||
#define RADIAL 2
|
||||
#define CHECKER 3
|
||||
#define TEXTURE 4
|
||||
#define PATTERN 5
|
||||
|
||||
#define GP_XRAY_FRONT 0
|
||||
#define GP_XRAY_3DSPACE 1
|
||||
|
||||
#define GP_DRAWMODE_2D 0
|
||||
#define GP_DRAWMODE_3D 1
|
||||
|
||||
#define OB_WIRE 2
|
||||
#define OB_SOLID 3
|
||||
|
||||
#define V3D_SHADING_MATERIAL_COLOR 0
|
||||
#define V3D_SHADING_TEXTURE_COLOR 3
|
||||
#define V3D_SHADING_VERTEX_COLOR 5
|
||||
|
||||
in vec4 finalColor;
|
||||
in vec2 texCoord_interp;
|
||||
out vec4 fragColor;
|
||||
#define texture2D texture
|
||||
|
||||
void set_color(in vec4 color,
|
||||
in vec4 color2,
|
||||
in vec4 tcolor,
|
||||
in float mixv,
|
||||
in float factor,
|
||||
in int tmix,
|
||||
in int flip,
|
||||
out vec4 ocolor)
|
||||
{
|
||||
/* full color A */
|
||||
if (mixv == 1.0) {
|
||||
if (tmix == 1) {
|
||||
ocolor = (flip == 0) ? color : tcolor;
|
||||
}
|
||||
else {
|
||||
ocolor = (flip == 0) ? color : color2;
|
||||
}
|
||||
}
|
||||
/* full color B */
|
||||
else if (mixv == 0.0) {
|
||||
if (tmix == 1) {
|
||||
ocolor = (flip == 0) ? tcolor : color;
|
||||
}
|
||||
else {
|
||||
ocolor = (flip == 0) ? color2 : color;
|
||||
}
|
||||
}
|
||||
/* mix of colors */
|
||||
else {
|
||||
if (tmix == 1) {
|
||||
ocolor = (flip == 0) ? mix(color, tcolor, factor) : mix(tcolor, color, factor);
|
||||
}
|
||||
else {
|
||||
ocolor = (flip == 0) ? mix(color, color2, factor) : mix(color2, color, factor);
|
||||
}
|
||||
}
|
||||
ocolor.a *= layer_opacity;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 t_center = vec2(0.5, 0.5);
|
||||
mat2 matrot_tex = mat2(
|
||||
cos(texture_angle), -sin(texture_angle), sin(texture_angle), cos(texture_angle));
|
||||
vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + texture_offset;
|
||||
vec4 tmp_color;
|
||||
tmp_color = (texture_clamp == 0) ?
|
||||
texture_read_as_srgb(
|
||||
myTexture, myTexturePremultiplied, rot_tex * texture_scale) :
|
||||
texture_read_as_srgb(
|
||||
myTexture, myTexturePremultiplied, clamp(rot_tex * texture_scale, 0.0, 1.0));
|
||||
vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * texture_opacity);
|
||||
vec4 checker_color;
|
||||
|
||||
/* wireframe with x-ray discard */
|
||||
if ((viewport_xray == 1) && (shading_type[0] == OB_WIRE)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* solid fill */
|
||||
if (fill_type == SOLID) {
|
||||
fragColor = finalColor;
|
||||
}
|
||||
else {
|
||||
vec2 center = vec2(0.5, 0.5) + gradient_shift;
|
||||
mat2 matrot = mat2(
|
||||
cos(gradient_angle), -sin(gradient_angle), sin(gradient_angle), cos(gradient_angle));
|
||||
vec2 rot = (((matrot * (texCoord_interp - center)) + center) * gradient_scale) +
|
||||
gradient_shift;
|
||||
/* gradient */
|
||||
if (fill_type == GRADIENT) {
|
||||
set_color(finalColor,
|
||||
color2,
|
||||
text_color,
|
||||
mix_factor,
|
||||
rot.x - mix_factor + 0.5,
|
||||
texture_mix,
|
||||
texture_flip,
|
||||
fragColor);
|
||||
}
|
||||
/* radial gradient */
|
||||
if (fill_type == RADIAL) {
|
||||
float in_rad = gradient_radius * mix_factor;
|
||||
float ex_rad = gradient_radius - in_rad;
|
||||
float intensity = 0;
|
||||
float distance = length((center - texCoord_interp) * gradient_scale);
|
||||
if (distance > gradient_radius) {
|
||||
discard;
|
||||
}
|
||||
if (distance > in_rad) {
|
||||
intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0);
|
||||
}
|
||||
set_color(finalColor,
|
||||
color2,
|
||||
text_color,
|
||||
mix_factor,
|
||||
intensity,
|
||||
texture_mix,
|
||||
texture_flip,
|
||||
fragColor);
|
||||
}
|
||||
/* Checkerboard */
|
||||
if (fill_type == CHECKER) {
|
||||
vec2 pos = rot / pattern_gridsize;
|
||||
if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) ||
|
||||
(fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) {
|
||||
checker_color = (texture_flip == 0) ? finalColor : color2;
|
||||
}
|
||||
else {
|
||||
checker_color = (texture_flip == 0) ? color2 : finalColor;
|
||||
}
|
||||
/* mix with texture */
|
||||
fragColor = (texture_mix == 1) ? mix(checker_color, text_color, mix_factor) : checker_color;
|
||||
fragColor.a *= layer_opacity;
|
||||
}
|
||||
/* texture */
|
||||
if (fill_type == TEXTURE) {
|
||||
fragColor = (texture_mix == 1) ? mix(text_color, finalColor, mix_factor) : text_color;
|
||||
fragColor.a *= layer_opacity;
|
||||
}
|
||||
/* pattern */
|
||||
if (fill_type == PATTERN) {
|
||||
fragColor = finalColor;
|
||||
fragColor.a = min(text_color.a, finalColor.a) * layer_opacity;
|
||||
}
|
||||
}
|
||||
|
||||
/* set zdepth */
|
||||
if (xraymode == GP_XRAY_FRONT) {
|
||||
gl_FragDepth = min(-0.05, (gl_FragCoord.z / gl_FragCoord.w));
|
||||
}
|
||||
else if (xraymode == GP_XRAY_3DSPACE) {
|
||||
/* if 3D mode, move slightly the fill to avoid z-fighting between stroke and fill on same
|
||||
* stroke */
|
||||
if (drawmode == GP_DRAWMODE_3D) {
|
||||
gl_FragDepth = gl_FragCoord.z * 1.0001;
|
||||
}
|
||||
else {
|
||||
gl_FragDepth = gl_FragCoord.z;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gl_FragDepth = 0.000001;
|
||||
}
|
||||
|
||||
/* if wireframe override colors */
|
||||
if (shading_type[0] == OB_WIRE) {
|
||||
fragColor = wire_color;
|
||||
}
|
||||
|
||||
/* for solid override color */
|
||||
if (shading_type[0] == OB_SOLID) {
|
||||
if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) &&
|
||||
(shading_type[1] != V3D_SHADING_TEXTURE_COLOR) &&
|
||||
(shading_type[1] != V3D_SHADING_VERTEX_COLOR)) {
|
||||
fragColor = wire_color;
|
||||
}
|
||||
if (viewport_xray == 1) {
|
||||
fragColor.a *= 0.5;
|
||||
}
|
||||
}
|
||||
/* Apply paper opacity */
|
||||
if (fade_layer == 1) {
|
||||
/* Layer is below, mix with background. */
|
||||
fragColor.rgb = mix(fade_color.rgb, fragColor.rgb, fade_layer_factor);
|
||||
}
|
||||
else if (fade_layer == 2) {
|
||||
/* Layer is above, change opacity. */
|
||||
fragColor.a *= fade_layer_factor;
|
||||
}
|
||||
else if (fade_ob == true) {
|
||||
fragColor.rgb = mix(fade_color.rgb, fragColor.rgb, fade_ob_factor);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
uniform mat4 gpModelMatrix;
|
||||
|
||||
in vec3 pos;
|
||||
in vec4 color;
|
||||
in vec2 texCoord;
|
||||
|
||||
out vec4 finalColor;
|
||||
out vec2 texCoord_interp;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
|
||||
finalColor = color;
|
||||
texCoord_interp = texCoord;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
uniform sampler2D gpFillTexture;
|
||||
uniform sampler2D gpStrokeTexture;
|
||||
uniform sampler2D gpSceneDepthTexture;
|
||||
uniform sampler2D gpMaskTexture;
|
||||
uniform vec3 gpNormal;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(location = 1) out vec4 revealColor;
|
||||
|
||||
float length_squared(vec2 v)
|
||||
{
|
||||
return dot(v, v);
|
||||
}
|
||||
float length_squared(vec3 v)
|
||||
{
|
||||
return dot(v, v);
|
||||
}
|
||||
|
||||
vec3 gpencil_lighting(void)
|
||||
{
|
||||
vec3 light_accum = vec3(0.0);
|
||||
for (int i = 0; i < GPENCIL_LIGHT_BUFFER_LEN; i++) {
|
||||
if (lights[i].color_type.x == -1.0) {
|
||||
break;
|
||||
}
|
||||
vec3 L = lights[i].position.xyz - finalPos;
|
||||
float vis = 1.0;
|
||||
/* Spot Attenuation. */
|
||||
if (lights[i].color_type.w == GP_LIGHT_TYPE_SPOT) {
|
||||
mat3 rot_scale = mat3(lights[i].right.xyz, lights[i].up.xyz, lights[i].forward.xyz);
|
||||
vec3 local_L = rot_scale * L;
|
||||
local_L /= abs(local_L.z);
|
||||
float ellipse = inversesqrt(length_squared(local_L));
|
||||
vis *= smoothstep(0.0, 1.0, (ellipse - lights[i].spot_size) / lights[i].spot_blend);
|
||||
/* Also mask +Z cone. */
|
||||
vis *= step(0.0, local_L.z);
|
||||
}
|
||||
/* Inverse square decay. Skip for suns. */
|
||||
float L_len_sqr = length_squared(L);
|
||||
if (lights[i].color_type.w < GP_LIGHT_TYPE_SUN) {
|
||||
vis /= L_len_sqr;
|
||||
}
|
||||
else {
|
||||
L = lights[i].forward.xyz;
|
||||
L_len_sqr = 1.0;
|
||||
}
|
||||
/* Lambertian falloff */
|
||||
if (lights[i].color_type.w != GP_LIGHT_TYPE_AMBIENT) {
|
||||
L /= sqrt(L_len_sqr);
|
||||
vis *= clamp(dot(gpNormal, L), 0.0, 1.0);
|
||||
}
|
||||
light_accum += vis * lights[i].color_type.rgb;
|
||||
}
|
||||
/* Clamp to avoid NaNs. */
|
||||
return clamp(light_accum, 0.0, 1e10);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col;
|
||||
if (GP_FLAG_TEST(matFlag, GP_STROKE_TEXTURE_USE)) {
|
||||
bool premul = GP_FLAG_TEST(matFlag, GP_STROKE_TEXTURE_PREMUL);
|
||||
col = texture_read_as_linearrgb(gpStrokeTexture, premul, finalUvs);
|
||||
}
|
||||
else if (GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_USE)) {
|
||||
bool use_clip = GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_CLIP);
|
||||
vec2 uvs = (use_clip) ? clamp(finalUvs, 0.0, 1.0) : finalUvs;
|
||||
bool premul = GP_FLAG_TEST(matFlag, GP_FILL_TEXTURE_PREMUL);
|
||||
col = texture_read_as_linearrgb(gpFillTexture, premul, uvs);
|
||||
}
|
||||
else if (GP_FLAG_TEST(matFlag, GP_FILL_GRADIENT_USE)) {
|
||||
bool radial = GP_FLAG_TEST(matFlag, GP_FILL_GRADIENT_RADIAL);
|
||||
float fac = clamp(radial ? length(finalUvs * 2.0 - 1.0) : finalUvs.x, 0.0, 1.0);
|
||||
int matid = matFlag >> GP_MATID_SHIFT;
|
||||
col = mix(MATERIAL(matid).fill_color, MATERIAL(matid).fill_mix_color, fac);
|
||||
}
|
||||
else /* SOLID */ {
|
||||
col = vec4(1.0);
|
||||
}
|
||||
col.rgb *= col.a;
|
||||
|
||||
/* Composite all other colors on top of texture color.
|
||||
* Everything is premult by col.a to have the stencil effect. */
|
||||
fragColor = col * finalColorMul + col.a * finalColorAdd;
|
||||
|
||||
fragColor.rgb *= gpencil_lighting();
|
||||
|
||||
fragColor *= stroke_round_cap_mask(
|
||||
strokePt1, strokePt2, strokeAspect, strokeThickness, strokeHardeness);
|
||||
|
||||
/* For compatibility with colored alpha buffer.
|
||||
* Note that we are limited to mono-chromatic alpha blending here
|
||||
* because of the blend equation and the limit of 1 color target
|
||||
* when using custom color blending. */
|
||||
revealColor = vec4(0.0, 0.0, 0.0, fragColor.a);
|
||||
|
||||
if (fragColor.a < 0.001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* Manual depth test */
|
||||
vec2 uvs = gl_FragCoord.xy / vec2(textureSize(gpSceneDepthTexture, 0).xy);
|
||||
float scene_depth = texture(gpSceneDepthTexture, uvs).r;
|
||||
if (gl_FragCoord.z > scene_depth) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* FIXME(fclem) Grrr. This is bad for performance but it's the easiest way to not get
|
||||
* depth written where the mask obliterate the layer. */
|
||||
float mask = texture(gpMaskTexture, uvs).r;
|
||||
if (mask < 0.001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* We override the fragment depth using the fragment shader to ensure a constant value.
|
||||
* This has a cost as the depth test cannot happen early.
|
||||
* We could do this in the vertex shader but then perspective interpolation of uvs and
|
||||
* fragment clipping gets really complicated. */
|
||||
if (depth >= 0.0) {
|
||||
gl_FragDepth = depth;
|
||||
}
|
||||
else {
|
||||
gl_FragDepth = gl_FragCoord.z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
uniform sampler2D colorBuf;
|
||||
uniform sampler2D revealBuf;
|
||||
uniform sampler2D maskBuf;
|
||||
uniform int blendMode;
|
||||
uniform float blendOpacity;
|
||||
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
/* Reminder: This is considered SRC color in blend equations.
|
||||
* Same operation on all buffers. */
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(location = 1) out vec4 fragRevealage;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color;
|
||||
|
||||
/* Remember, this is associated alpha (aka. premult). */
|
||||
color.rgb = textureLod(colorBuf, uvcoordsvar.xy, 0).rgb;
|
||||
/* Stroke only render mono-chromatic revealage. We convert to alpha. */
|
||||
color.a = 1.0 - textureLod(revealBuf, uvcoordsvar.xy, 0).r;
|
||||
|
||||
float mask = textureLod(maskBuf, uvcoordsvar.xy, 0).r;
|
||||
mask *= blendOpacity;
|
||||
|
||||
fragColor = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
fragRevealage = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
|
||||
blend_mode_output(blendMode, color, mask, fragColor, fragRevealage);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(location = 1) out vec4 fragRevealage;
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Blend mode does the inversion. */
|
||||
fragRevealage = fragColor = vec4(1.0);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
uniform vec3 color;
|
||||
uniform float opacity;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = vec4(color, 1.0 - opacity);
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
uniform int color_type;
|
||||
uniform int mode;
|
||||
uniform sampler2D myTexture;
|
||||
uniform bool myTexturePremultiplied;
|
||||
|
||||
uniform float gradient_f;
|
||||
uniform vec2 gradient_s;
|
||||
|
||||
uniform vec4 colormix;
|
||||
uniform float mix_stroke_factor;
|
||||
uniform int shading_type[2];
|
||||
|
||||
in vec4 mColor;
|
||||
in vec2 mTexCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform int fade_layer;
|
||||
uniform float fade_layer_factor;
|
||||
uniform bool fade_ob;
|
||||
uniform vec3 fade_color;
|
||||
uniform float fade_ob_factor;
|
||||
|
||||
#define texture2D texture
|
||||
|
||||
#define GPENCIL_MODE_LINE 0
|
||||
#define GPENCIL_MODE_DOTS 1
|
||||
#define GPENCIL_MODE_BOX 2
|
||||
|
||||
/* keep this list synchronized with list in gpencil_engine.h */
|
||||
#define GPENCIL_COLOR_SOLID 0
|
||||
#define GPENCIL_COLOR_TEXTURE 1
|
||||
#define GPENCIL_COLOR_PATTERN 2
|
||||
|
||||
#define OB_SOLID 3
|
||||
#define V3D_SHADING_TEXTURE_COLOR 3
|
||||
|
||||
bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR);
|
||||
|
||||
/* Function to check the point inside ellipse */
|
||||
float check_ellipse_point(vec2 pt, vec2 radius)
|
||||
{
|
||||
float p = (pow(pt.x, 2) / pow(radius.x, 2)) + (pow(pt.y, 2) / pow(radius.y, 2));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Function to check the point inside box */
|
||||
vec2 check_box_point(vec2 pt, vec2 radius)
|
||||
{
|
||||
vec2 rtn;
|
||||
rtn.x = abs(pt.x) / radius.x;
|
||||
rtn.y = abs(pt.y) / radius.y;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 centered = mTexCoord - vec2(0.5);
|
||||
float ellip = check_ellipse_point(centered, vec2(gradient_s / 2.0));
|
||||
vec2 box;
|
||||
|
||||
if (mode != GPENCIL_MODE_BOX) {
|
||||
if (ellip > 1.0) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
else {
|
||||
box = check_box_point(centered, vec2(gradient_s / 2.0));
|
||||
if ((box.x > 1.0) || (box.y > 1.0)) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
/* Solid */
|
||||
if ((color_type == GPENCIL_COLOR_SOLID) || (no_texture)) {
|
||||
fragColor = mColor;
|
||||
}
|
||||
/* texture */
|
||||
if ((color_type == GPENCIL_COLOR_TEXTURE) && (!no_texture)) {
|
||||
vec4 text_color = texture_read_as_srgb(myTexture, myTexturePremultiplied, mTexCoord);
|
||||
if (mix_stroke_factor > 0.0) {
|
||||
fragColor.rgb = mix(text_color.rgb, colormix.rgb, mix_stroke_factor);
|
||||
fragColor.a = text_color.a;
|
||||
}
|
||||
else {
|
||||
fragColor = text_color;
|
||||
}
|
||||
|
||||
/* mult both alpha factor to use strength factor with texture */
|
||||
fragColor.a = min(fragColor.a * mColor.a, fragColor.a);
|
||||
}
|
||||
/* pattern */
|
||||
if ((color_type == GPENCIL_COLOR_PATTERN) && (!no_texture)) {
|
||||
vec4 text_color = texture_read_as_srgb(myTexture, myTexturePremultiplied, mTexCoord);
|
||||
fragColor = mColor;
|
||||
/* mult both alpha factor to use strength factor with color alpha limit */
|
||||
fragColor.a = min(text_color.a * mColor.a, mColor.a);
|
||||
}
|
||||
|
||||
if (gradient_f < 1.0) {
|
||||
float dist = length(centered) * 2.0;
|
||||
float decay = dist * (1.0 - gradient_f) * fragColor.a;
|
||||
fragColor.a = clamp(fragColor.a - decay, 0.0, 1.0);
|
||||
if (mode == GPENCIL_MODE_DOTS) {
|
||||
fragColor.a = fragColor.a * (1.0 - ellip);
|
||||
}
|
||||
}
|
||||
|
||||
if (fragColor.a < 0.0035) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* Apply paper opacity */
|
||||
if (fade_layer == 1) {
|
||||
/* Layer is below, mix with background. */
|
||||
fragColor.rgb = mix(fade_color.rgb, fragColor.rgb, fade_layer_factor);
|
||||
}
|
||||
else if (fade_layer == 2) {
|
||||
/* Layer is above, change opacity. */
|
||||
fragColor.a *= fade_layer_factor;
|
||||
}
|
||||
else if (fade_ob == true) {
|
||||
fragColor.rgb = mix(fade_color.rgb, fragColor.rgb, fade_ob_factor);
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
uniform vec2 Viewport;
|
||||
uniform int xraymode;
|
||||
uniform int alignment_mode;
|
||||
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
in vec4 finalColor[1];
|
||||
in float finalThickness[1];
|
||||
in vec2 finaluvdata[1];
|
||||
in vec4 finalprev_pos[1];
|
||||
|
||||
out vec4 mColor;
|
||||
out vec2 mTexCoord;
|
||||
|
||||
#define GP_XRAY_FRONT 0
|
||||
#define GP_XRAY_3DSPACE 1
|
||||
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_2PI 6.28318530717958647692 /* 2*pi */
|
||||
#define FALSE 0
|
||||
|
||||
/* keep this definition equals to GP_STYLE_FOLLOW_FIXED value */
|
||||
#define FIXED 2
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 vertex)
|
||||
{
|
||||
return vec2(vertex.xy / vertex.w) * Viewport;
|
||||
}
|
||||
|
||||
/* get zdepth value */
|
||||
float getZdepth(vec4 point)
|
||||
{
|
||||
if (xraymode == GP_XRAY_FRONT) {
|
||||
return min(-0.05, (point.z / point.w));
|
||||
}
|
||||
if (xraymode == GP_XRAY_3DSPACE) {
|
||||
return (point.z / point.w);
|
||||
}
|
||||
|
||||
/* in front by default */
|
||||
return 0.000001;
|
||||
}
|
||||
|
||||
vec2 rotateUV(vec2 uv, float angle)
|
||||
{
|
||||
/* translate center of rotation to the center of texture */
|
||||
vec2 new_uv = uv - vec2(0.5f, 0.5f);
|
||||
vec2 rot_uv;
|
||||
rot_uv.x = new_uv.x * cos(angle) - new_uv.y * sin(angle);
|
||||
rot_uv.y = new_uv.y * cos(angle) + new_uv.x * sin(angle);
|
||||
return rot_uv + vec2(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
vec2 rotatePoint(vec2 center, vec2 point, float angle)
|
||||
{
|
||||
/* translate center of rotation to the center */
|
||||
vec2 new_point = point - center;
|
||||
vec2 rot_point;
|
||||
rot_point.x = new_point.x * cos(angle) - new_point.y * sin(angle);
|
||||
rot_point.y = new_point.y * cos(angle) + new_point.x * sin(angle);
|
||||
return rot_point + center;
|
||||
}
|
||||
|
||||
/* Calculate angle of the stroke using previous point as reference.
|
||||
* The angle is calculated using the x axis (1, 0) as 0 degrees */
|
||||
float getAngle(vec2 pt0, vec2 pt1)
|
||||
{
|
||||
/* do not rotate one point only (no reference to rotate) */
|
||||
if (pt0 == pt1) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (alignment_mode == FIXED) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* default horizontal line (x-axis) in screen space */
|
||||
vec2 v0 = vec2(1.0, 0.0);
|
||||
|
||||
/* vector of direction */
|
||||
vec2 vn = vec2(normalize(pt1 - pt0));
|
||||
|
||||
/* angle signed (function ported from angle_signed_v2v2) */
|
||||
float perp_dot = (v0[1] * vn[0]) - (v0[0] * vn[1]);
|
||||
float angle = atan(perp_dot, dot(v0, vn));
|
||||
|
||||
/* get full circle rotation */
|
||||
if (angle > 0.0) {
|
||||
angle = M_PI + (M_PI - angle);
|
||||
}
|
||||
else {
|
||||
angle *= -1.0;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
/* receive points */
|
||||
vec4 P0 = gl_in[0].gl_Position;
|
||||
vec2 sp0 = toScreenSpace(P0);
|
||||
|
||||
vec4 P1 = finalprev_pos[0];
|
||||
vec2 sp1 = toScreenSpace(P1);
|
||||
vec2 point;
|
||||
|
||||
float size = finalThickness[0];
|
||||
vec2 center = vec2(sp0.x, sp0.y);
|
||||
|
||||
/* get angle of stroke to rotate texture */
|
||||
float angle = getAngle(sp0, sp1);
|
||||
|
||||
/* generate the triangle strip */
|
||||
mTexCoord = rotateUV(vec2(0, 1), finaluvdata[0].y);
|
||||
mColor = finalColor[0];
|
||||
point = rotatePoint(center, vec2(sp0.x - size, sp0.y + size), angle);
|
||||
gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = rotateUV(vec2(0, 0), finaluvdata[0].y);
|
||||
mColor = finalColor[0];
|
||||
point = rotatePoint(center, vec2(sp0.x - size, sp0.y - size), angle);
|
||||
gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = rotateUV(vec2(1, 1), finaluvdata[0].y);
|
||||
mColor = finalColor[0];
|
||||
point = rotatePoint(center, vec2(sp0.x + size, sp0.y + size), angle);
|
||||
gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = rotateUV(vec2(1, 0), finaluvdata[0].y);
|
||||
mColor = finalColor[0];
|
||||
point = rotatePoint(center, vec2(sp0.x + size, sp0.y - size), angle);
|
||||
gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform int keep_size;
|
||||
uniform float objscale;
|
||||
uniform float pixfactor;
|
||||
uniform int viewport_xray;
|
||||
uniform int shading_type[2];
|
||||
uniform vec4 wire_color;
|
||||
uniform mat4 gpModelMatrix;
|
||||
|
||||
in vec3 pos;
|
||||
in vec4 color;
|
||||
in float thickness;
|
||||
in vec2 uvdata;
|
||||
in vec3 prev_pos;
|
||||
|
||||
out vec4 finalColor;
|
||||
out float finalThickness;
|
||||
out vec2 finaluvdata;
|
||||
out vec4 finalprev_pos;
|
||||
|
||||
#define TRUE 1
|
||||
|
||||
#define OB_WIRE 2
|
||||
#define OB_SOLID 3
|
||||
|
||||
#define V3D_SHADING_MATERIAL_COLOR 0
|
||||
#define V3D_SHADING_TEXTURE_COLOR 3
|
||||
#define V3D_SHADING_VERTEX_COLOR 5
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
|
||||
finalprev_pos = point_world_to_ndc((gpModelMatrix * vec4(prev_pos, 1.0)).xyz);
|
||||
finalColor = color;
|
||||
|
||||
if (keep_size == TRUE) {
|
||||
finalThickness = thickness;
|
||||
}
|
||||
else {
|
||||
float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) :
|
||||
(thickness / defaultpixsize);
|
||||
finalThickness = max(size * objscale, 0.5); /* set a minimum size */
|
||||
}
|
||||
|
||||
/* for wireframe override size and color */
|
||||
if (shading_type[0] == OB_WIRE) {
|
||||
finalThickness = 2.0;
|
||||
finalColor = wire_color;
|
||||
}
|
||||
/* for solid override color */
|
||||
if (shading_type[0] == OB_SOLID) {
|
||||
if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) &&
|
||||
(shading_type[1] != V3D_SHADING_TEXTURE_COLOR) &&
|
||||
(shading_type[1] != V3D_SHADING_VERTEX_COLOR)) {
|
||||
finalColor = wire_color;
|
||||
}
|
||||
if (viewport_xray == 1) {
|
||||
finalColor.a *= 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
finaluvdata = uvdata;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
|
||||
vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
|
||||
|
||||
FragColor = stroke_color;
|
||||
gl_FragDepth = stroke_depth;
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
uniform int color_type;
|
||||
uniform sampler2D myTexture;
|
||||
uniform bool myTexturePremultiplied;
|
||||
|
||||
uniform float gradient_f;
|
||||
|
||||
uniform vec4 colormix;
|
||||
uniform float mix_stroke_factor;
|
||||
uniform int shading_type[2];
|
||||
|
||||
uniform int fade_layer;
|
||||
uniform float fade_layer_factor;
|
||||
uniform bool fade_ob;
|
||||
uniform vec3 fade_color;
|
||||
uniform float fade_ob_factor;
|
||||
|
||||
in vec4 mColor;
|
||||
in vec2 mTexCoord;
|
||||
in vec2 uvfac;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
#define texture2D texture
|
||||
|
||||
/* keep this list synchronized with list in gpencil_engine.h */
|
||||
#define GPENCIL_COLOR_SOLID 0
|
||||
#define GPENCIL_COLOR_TEXTURE 1
|
||||
#define GPENCIL_COLOR_PATTERN 2
|
||||
|
||||
#define ENDCAP 1.0
|
||||
|
||||
#define OB_SOLID 3
|
||||
#define V3D_SHADING_TEXTURE_COLOR 3
|
||||
|
||||
bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
vec4 tColor = vec4(mColor);
|
||||
/* if uvfac[1] == 1, then encap */
|
||||
if (uvfac[1] == ENDCAP) {
|
||||
vec2 center = vec2(uvfac[0], 0.5);
|
||||
float dist = length(mTexCoord - center);
|
||||
if (dist > 0.50) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
if ((color_type == GPENCIL_COLOR_SOLID) || (no_texture)) {
|
||||
fragColor = tColor;
|
||||
}
|
||||
|
||||
/* texture for endcaps */
|
||||
vec4 text_color;
|
||||
if (uvfac[1] == ENDCAP) {
|
||||
text_color = texture_read_as_srgb(
|
||||
myTexture, myTexturePremultiplied, vec2(mTexCoord.x, mTexCoord.y));
|
||||
}
|
||||
else {
|
||||
text_color = texture_read_as_srgb(myTexture, myTexturePremultiplied, mTexCoord);
|
||||
}
|
||||
|
||||
/* texture */
|
||||
if ((color_type == GPENCIL_COLOR_TEXTURE) && (!no_texture)) {
|
||||
if (mix_stroke_factor > 0.0) {
|
||||
fragColor.rgb = mix(text_color.rgb, colormix.rgb, mix_stroke_factor);
|
||||
fragColor.a = text_color.a;
|
||||
}
|
||||
else {
|
||||
fragColor = text_color;
|
||||
}
|
||||
|
||||
/* mult both alpha factor to use strength factor */
|
||||
fragColor.a = min(fragColor.a * tColor.a, fragColor.a);
|
||||
}
|
||||
/* pattern */
|
||||
if ((color_type == GPENCIL_COLOR_PATTERN) && (!no_texture)) {
|
||||
fragColor = tColor;
|
||||
/* mult both alpha factor to use strength factor with color alpha limit */
|
||||
fragColor.a = min(text_color.a * tColor.a, tColor.a);
|
||||
}
|
||||
|
||||
/* gradient */
|
||||
/* keep this disabled while the line glitch bug exists
|
||||
if (gradient_f < 1.0) {
|
||||
float d = abs(mTexCoord.y - 0.5) * (1.1 - gradient_f);
|
||||
float alpha = 1.0 - clamp((fragColor.a - (d * 2.0)), 0.03, 1.0);
|
||||
fragColor.a = smoothstep(fragColor.a, 0.0, alpha);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
if (fragColor.a < 0.0035) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* Apply paper opacity */
|
||||
if (fade_layer == 1) {
|
||||
/* Layer is below, mix with background. */
|
||||
fragColor.rgb = mix(fade_color.rgb, fragColor.rgb, fade_layer_factor);
|
||||
}
|
||||
else if (fade_layer == 2) {
|
||||
/* Layer is above, change opacity. */
|
||||
fragColor.a *= fade_layer_factor;
|
||||
}
|
||||
else if (fade_ob == true) {
|
||||
fragColor.rgb = mix(fade_color.rgb, fragColor.rgb, fade_ob_factor);
|
||||
}
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
uniform vec2 Viewport;
|
||||
uniform int xraymode;
|
||||
uniform int color_type;
|
||||
uniform int caps_mode[2];
|
||||
|
||||
layout(lines_adjacency) in;
|
||||
layout(triangle_strip, max_vertices = 13) out;
|
||||
|
||||
in vec4 finalColor[4];
|
||||
in float finalThickness[4];
|
||||
in vec2 finaluvdata[4];
|
||||
|
||||
out vec4 mColor;
|
||||
out vec2 mTexCoord;
|
||||
out vec2 uvfac;
|
||||
|
||||
#define GP_XRAY_FRONT 0
|
||||
#define GP_XRAY_3DSPACE 1
|
||||
|
||||
/* keep this list synchronized with list in gpencil_engine.h */
|
||||
#define GPENCIL_COLOR_SOLID 0
|
||||
#define GPENCIL_COLOR_TEXTURE 1
|
||||
#define GPENCIL_COLOR_PATTERN 2
|
||||
|
||||
#define GPENCIL_FLATCAP 1
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 vertex)
|
||||
{
|
||||
return vec2(vertex.xy / vertex.w) * Viewport;
|
||||
}
|
||||
|
||||
/* get zdepth value */
|
||||
float getZdepth(vec4 point)
|
||||
{
|
||||
if (xraymode == GP_XRAY_FRONT) {
|
||||
return min(-0.05, (point.z / point.w));
|
||||
}
|
||||
if (xraymode == GP_XRAY_3DSPACE) {
|
||||
return (point.z / point.w);
|
||||
}
|
||||
|
||||
/* in front by default */
|
||||
return 0.000001;
|
||||
}
|
||||
|
||||
/* check equality but with a small tolerance */
|
||||
bool is_equal(vec4 p1, vec4 p2)
|
||||
{
|
||||
float limit = 0.0001;
|
||||
float x = abs(p1.x - p2.x);
|
||||
float y = abs(p1.y - p2.y);
|
||||
float z = abs(p1.z - p2.z);
|
||||
|
||||
if ((x < limit) && (y < limit) && (z < limit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
float MiterLimit = 0.75;
|
||||
uvfac = vec2(0.0, 0.0);
|
||||
|
||||
/* receive 4 points */
|
||||
vec4 P0 = gl_in[0].gl_Position;
|
||||
vec4 P1 = gl_in[1].gl_Position;
|
||||
vec4 P2 = gl_in[2].gl_Position;
|
||||
vec4 P3 = gl_in[3].gl_Position;
|
||||
|
||||
/* get the four vertices passed to the shader */
|
||||
vec2 sp0 = toScreenSpace(P0); // start of previous segment
|
||||
vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment
|
||||
vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment
|
||||
vec2 sp3 = toScreenSpace(P3); // end of next segment
|
||||
|
||||
/* culling outside viewport */
|
||||
vec2 area = Viewport * 4.0;
|
||||
if (sp1.x < -area.x || sp1.x > area.x) {
|
||||
return;
|
||||
}
|
||||
if (sp1.y < -area.y || sp1.y > area.y) {
|
||||
return;
|
||||
}
|
||||
if (sp2.x < -area.x || sp2.x > area.x) {
|
||||
return;
|
||||
}
|
||||
if (sp2.y < -area.y || sp2.y > area.y) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* culling behind camera */
|
||||
if (P1.w < 0 || P2.w < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* determine the direction of each of the 3 segments (previous, current, next) */
|
||||
vec2 v0 = normalize(sp1 - sp0);
|
||||
vec2 v1 = normalize(sp2 - sp1);
|
||||
vec2 v2 = normalize(sp3 - sp2);
|
||||
|
||||
/* determine the normal of each of the 3 segments (previous, current, next) */
|
||||
vec2 n0 = vec2(-v0.y, v0.x);
|
||||
vec2 n1 = vec2(-v1.y, v1.x);
|
||||
vec2 n2 = vec2(-v2.y, v2.x);
|
||||
|
||||
/* determine miter lines by averaging the normals of the 2 segments */
|
||||
vec2 miter_a = normalize(n0 + n1); // miter at start of current segment
|
||||
vec2 miter_b = normalize(n1 + n2); // miter at end of current segment
|
||||
|
||||
/* determine the length of the miter by projecting it onto normal and then inverse it */
|
||||
float an1 = dot(miter_a, n1);
|
||||
float bn1 = dot(miter_b, n2);
|
||||
if (an1 == 0) {
|
||||
an1 = 1;
|
||||
}
|
||||
if (bn1 == 0) {
|
||||
bn1 = 1;
|
||||
}
|
||||
float length_a = finalThickness[1] / an1;
|
||||
float length_b = finalThickness[2] / bn1;
|
||||
if (length_a <= 0.0) {
|
||||
length_a = 0.01;
|
||||
}
|
||||
if (length_b <= 0.0) {
|
||||
length_b = 0.01;
|
||||
}
|
||||
|
||||
/* prevent excessively long miters at sharp corners */
|
||||
if (dot(v0, v1) < -MiterLimit) {
|
||||
miter_a = n1;
|
||||
length_a = finalThickness[1];
|
||||
|
||||
/* close the gap */
|
||||
if (dot(v0, n1) > 0) {
|
||||
mTexCoord = vec2(0, 0);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0, 0);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0, 0.5);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
else {
|
||||
mTexCoord = vec2(0, 1);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0, 1);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0, 0.5);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
}
|
||||
|
||||
if (dot(v1, v2) < -MiterLimit) {
|
||||
miter_b = n1;
|
||||
length_b = finalThickness[2];
|
||||
}
|
||||
|
||||
/* generate the start endcap */
|
||||
if ((caps_mode[0] != GPENCIL_FLATCAP) && is_equal(P0, P2)) {
|
||||
vec4 cap_color = finalColor[1];
|
||||
|
||||
mTexCoord = vec2(2.0, 0.5);
|
||||
mColor = cap_color;
|
||||
vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0;
|
||||
uvfac = vec2(0.0, 1.0);
|
||||
gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0.0, -0.5);
|
||||
mColor = cap_color;
|
||||
uvfac = vec2(0.0, 1.0);
|
||||
gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(0.0, 1.5);
|
||||
mColor = cap_color;
|
||||
uvfac = vec2(0.0, 1.0);
|
||||
gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
float y_a = 0.0;
|
||||
float y_b = 1.0;
|
||||
|
||||
/* invert uv (vertical) */
|
||||
if (finaluvdata[2].x > 1.0) {
|
||||
if ((finaluvdata[1].y != 0.0) && (finaluvdata[2].y != 0.0)) {
|
||||
float d = ceil(finaluvdata[2].x) - 1.0;
|
||||
if (floor(d / 2.0) == (d / 2.0)) {
|
||||
y_a = 1.0;
|
||||
y_b = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* generate the triangle strip */
|
||||
uvfac = vec2(0.0, 0.0);
|
||||
mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 0) : vec2(finaluvdata[1].x, y_a);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 1) : vec2(finaluvdata[1].x, y_b);
|
||||
mColor = finalColor[1];
|
||||
gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 0) : vec2(finaluvdata[2].x, y_a);
|
||||
mColor = finalColor[2];
|
||||
gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 1) : vec2(finaluvdata[2].x, y_b);
|
||||
mColor = finalColor[2];
|
||||
gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
/* generate the end endcap */
|
||||
if ((caps_mode[1] != GPENCIL_FLATCAP) && is_equal(P1, P3) && (finaluvdata[2].x > 0)) {
|
||||
vec4 cap_color = finalColor[2];
|
||||
|
||||
mTexCoord = vec2(finaluvdata[2].x, 1.5);
|
||||
mColor = cap_color;
|
||||
uvfac = vec2(finaluvdata[2].x, 1.0);
|
||||
gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(finaluvdata[2].x, -0.5);
|
||||
mColor = cap_color;
|
||||
uvfac = vec2(finaluvdata[2].x, 1.0);
|
||||
gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
|
||||
EmitVertex();
|
||||
|
||||
mTexCoord = vec2(finaluvdata[2].x + 2, 0.5);
|
||||
mColor = cap_color;
|
||||
uvfac = vec2(finaluvdata[2].x, 1.0);
|
||||
vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0;
|
||||
gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0);
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
|
||||
uniform float pixsize; /* rv3d->pixsize */
|
||||
uniform int keep_size;
|
||||
uniform float objscale;
|
||||
uniform float pixfactor;
|
||||
uniform int viewport_xray;
|
||||
uniform int shading_type[2];
|
||||
uniform vec4 wire_color;
|
||||
uniform mat4 gpModelMatrix;
|
||||
|
||||
in vec3 pos;
|
||||
in vec4 color;
|
||||
in float thickness;
|
||||
in vec2 uvdata;
|
||||
|
||||
out vec4 finalColor;
|
||||
out float finalThickness;
|
||||
out vec2 finaluvdata;
|
||||
|
||||
#define TRUE 1
|
||||
|
||||
#define OB_WIRE 2
|
||||
#define OB_SOLID 3
|
||||
|
||||
#define V3D_SHADING_MATERIAL_COLOR 0
|
||||
#define V3D_SHADING_TEXTURE_COLOR 3
|
||||
#define V3D_SHADING_VERTEX_COLOR 5
|
||||
|
||||
float defaultpixsize = pixsize * (1000.0 / pixfactor);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = point_world_to_ndc((gpModelMatrix * vec4(pos, 1.0)).xyz);
|
||||
finalColor = color;
|
||||
|
||||
if (keep_size == TRUE) {
|
||||
finalThickness = thickness;
|
||||
}
|
||||
else {
|
||||
float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) :
|
||||
(thickness / defaultpixsize);
|
||||
finalThickness = max(size * objscale, 1.0);
|
||||
}
|
||||
|
||||
/* for wireframe override size and color */
|
||||
if (shading_type[0] == OB_WIRE) {
|
||||
finalThickness = 1.0;
|
||||
finalColor = wire_color;
|
||||
}
|
||||
/* for solid override color */
|
||||
if (shading_type[0] == OB_SOLID) {
|
||||
if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) &&
|
||||
(shading_type[1] != V3D_SHADING_TEXTURE_COLOR) &&
|
||||
(shading_type[1] != V3D_SHADING_VERTEX_COLOR)) {
|
||||
finalColor = wire_color;
|
||||
}
|
||||
if (viewport_xray == 1) {
|
||||
finalColor.a *= 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
finaluvdata = uvdata;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
gpencil_vertex();
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
|
||||
uniform sampler2D colorBuf;
|
||||
uniform sampler2D revealBuf;
|
||||
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
/* Reminder: This is considered SRC color in blend equations.
|
||||
* Same operation on all buffers. */
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(location = 1) out vec4 fragRevealage;
|
||||
|
||||
float gaussian_weight(float x)
|
||||
{
|
||||
return exp(-x * x / (2.0 * 0.35 * 0.35));
|
||||
}
|
||||
|
||||
#if defined(COMPOSITE)
|
||||
|
||||
uniform bool isFirstPass;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (isFirstPass) {
|
||||
/* Blend mode is multiply. */
|
||||
fragColor.rgb = fragRevealage.rgb = texture(revealBuf, uvcoordsvar.xy).rgb;
|
||||
fragColor.a = fragRevealage.a = 1.0;
|
||||
}
|
||||
else {
|
||||
/* Blend mode is additive. */
|
||||
fragRevealage = vec4(0.0);
|
||||
fragColor.rgb = texture(colorBuf, uvcoordsvar.xy).rgb;
|
||||
fragColor.a = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(COLORIZE)
|
||||
|
||||
uniform vec3 lowColor;
|
||||
uniform vec3 highColor;
|
||||
uniform float factor;
|
||||
uniform int mode;
|
||||
|
||||
const mat3 sepia_mat = mat3(
|
||||
vec3(0.393, 0.349, 0.272), vec3(0.769, 0.686, 0.534), vec3(0.189, 0.168, 0.131));
|
||||
|
||||
# define MODE_GRAYSCALE 0
|
||||
# define MODE_SEPIA 1
|
||||
# define MODE_DUOTONE 2
|
||||
# define MODE_CUSTOM 3
|
||||
# define MODE_TRANSPARENT 4
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = texture(colorBuf, uvcoordsvar.xy);
|
||||
fragRevealage = texture(revealBuf, uvcoordsvar.xy);
|
||||
|
||||
float luma = dot(fragColor.rgb, vec3(0.2126, 0.7152, 0.723));
|
||||
|
||||
/* No blending. */
|
||||
switch (mode) {
|
||||
case MODE_GRAYSCALE:
|
||||
fragColor.rgb = mix(fragColor.rgb, vec3(luma), factor);
|
||||
break;
|
||||
case MODE_SEPIA:
|
||||
fragColor.rgb = mix(fragColor.rgb, sepia_mat * fragColor.rgb, factor);
|
||||
break;
|
||||
case MODE_DUOTONE:
|
||||
fragColor.rgb = luma * ((luma <= factor) ? lowColor : highColor);
|
||||
break;
|
||||
case MODE_CUSTOM:
|
||||
fragColor.rgb = mix(fragColor.rgb, luma * lowColor, factor);
|
||||
break;
|
||||
case MODE_TRANSPARENT:
|
||||
default:
|
||||
fragColor.rgb *= factor;
|
||||
fragRevealage.rgb = mix(vec3(1.0), fragRevealage.rgb, factor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(BLUR)
|
||||
|
||||
uniform vec2 offset;
|
||||
uniform int sampCount;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pixel_size = 1.0 / vec2(textureSize(revealBuf, 0).xy);
|
||||
vec2 ofs = offset * pixel_size;
|
||||
|
||||
fragColor = vec4(0.0);
|
||||
fragRevealage = vec4(0.0);
|
||||
|
||||
/* No blending. */
|
||||
float weight_accum = 0.0;
|
||||
for (int i = -sampCount; i <= sampCount; i++) {
|
||||
float x = float(i) / float(sampCount);
|
||||
float weight = gaussian_weight(x);
|
||||
weight_accum += weight;
|
||||
vec2 uv = uvcoordsvar.xy + ofs * x;
|
||||
fragColor.rgb += texture(colorBuf, uv).rgb * weight;
|
||||
fragRevealage.rgb += texture(revealBuf, uv).rgb * weight;
|
||||
}
|
||||
|
||||
fragColor /= weight_accum;
|
||||
fragRevealage /= weight_accum;
|
||||
}
|
||||
|
||||
#elif defined(TRANSFORM)
|
||||
|
||||
uniform vec2 axisFlip = vec2(1.0);
|
||||
uniform vec2 waveDir = vec2(0.0);
|
||||
uniform vec2 waveOffset = vec2(0.0);
|
||||
uniform float wavePhase = 0.0;
|
||||
uniform vec2 swirlCenter = vec2(0.0);
|
||||
uniform float swirlAngle = 0.0;
|
||||
uniform float swirlRadius = 0.0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = (uvcoordsvar.xy - 0.5) * axisFlip + 0.5;
|
||||
|
||||
/* Wave deform. */
|
||||
float wave_time = dot(uv, waveDir.xy);
|
||||
uv += sin(wave_time + wavePhase) * waveOffset;
|
||||
/* Swirl deform. */
|
||||
if (swirlRadius > 0.0) {
|
||||
vec2 tex_size = vec2(textureSize(colorBuf, 0).xy);
|
||||
vec2 pix_coord = uv * tex_size - swirlCenter;
|
||||
float dist = length(pix_coord);
|
||||
float percent = clamp((swirlRadius - dist) / swirlRadius, 0.0, 1.0);
|
||||
float theta = percent * percent * swirlAngle;
|
||||
float s = sin(theta);
|
||||
float c = cos(theta);
|
||||
mat2 rot = mat2(vec2(c, -s), vec2(s, c));
|
||||
uv = (rot * pix_coord + swirlCenter) / tex_size;
|
||||
}
|
||||
|
||||
fragColor = texture(colorBuf, uv);
|
||||
fragRevealage = texture(revealBuf, uv);
|
||||
}
|
||||
|
||||
#elif defined(GLOW)
|
||||
|
||||
uniform vec4 glowColor;
|
||||
uniform vec2 offset;
|
||||
uniform int sampCount;
|
||||
uniform vec3 threshold;
|
||||
uniform bool firstPass;
|
||||
uniform bool glowUnder;
|
||||
uniform int blendMode;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pixel_size = 1.0 / vec2(textureSize(revealBuf, 0).xy);
|
||||
vec2 ofs = offset * pixel_size;
|
||||
|
||||
fragColor = vec4(0.0);
|
||||
fragRevealage = vec4(0.0);
|
||||
|
||||
float weight_accum = 0.0;
|
||||
for (int i = -sampCount; i <= sampCount; i++) {
|
||||
float x = float(i) / float(sampCount);
|
||||
float weight = gaussian_weight(x);
|
||||
weight_accum += weight;
|
||||
vec2 uv = uvcoordsvar.xy + ofs * x;
|
||||
vec3 col = texture(colorBuf, uv).rgb;
|
||||
vec3 rev = texture(revealBuf, uv).rgb;
|
||||
if (threshold.x > -1.0) {
|
||||
if (threshold.y > -1.0) {
|
||||
if (all(lessThan(abs(col - threshold), vec3(0.05)))) {
|
||||
weight = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dot(col, vec3(1.0 / 3.0)) < threshold.x) {
|
||||
weight = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
fragColor.rgb += col * weight;
|
||||
fragRevealage.rgb += (1.0 - rev) * weight;
|
||||
}
|
||||
|
||||
if (weight_accum > 0.0) {
|
||||
fragColor *= glowColor.rgbb / weight_accum;
|
||||
fragRevealage = fragRevealage / weight_accum;
|
||||
}
|
||||
fragRevealage = 1.0 - fragRevealage;
|
||||
|
||||
if (glowUnder) {
|
||||
if (firstPass) {
|
||||
/* In first pass we copy the revealage buffer in the alpha channel.
|
||||
* This let us do the alpha under in second pass. */
|
||||
vec3 original_revealage = texture(revealBuf, uvcoordsvar.xy).rgb;
|
||||
fragRevealage.a = clamp(dot(original_revealage.rgb, vec3(0.333334)), 0.0, 1.0);
|
||||
}
|
||||
else {
|
||||
/* Recover original revealage. */
|
||||
fragRevealage.a = texture(revealBuf, uvcoordsvar.xy).a;
|
||||
}
|
||||
}
|
||||
|
||||
if (!firstPass) {
|
||||
fragColor.a = clamp(1.0 - dot(fragRevealage.rgb, vec3(0.333334)), 0.0, 1.0);
|
||||
fragRevealage.a *= glowColor.a;
|
||||
blend_mode_output(blendMode, fragColor, fragRevealage.a, fragColor, fragRevealage);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(RIM)
|
||||
|
||||
uniform vec2 blurDir;
|
||||
uniform vec2 uvOffset;
|
||||
uniform vec3 rimColor;
|
||||
uniform vec3 maskColor;
|
||||
uniform int sampCount;
|
||||
uniform int blendMode;
|
||||
uniform bool isFirstPass;
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Blur revealage buffer. */
|
||||
fragRevealage = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
for (int i = -sampCount; i <= sampCount; i++) {
|
||||
float x = float(i) / float(sampCount);
|
||||
float weight = gaussian_weight(x);
|
||||
weight_accum += weight;
|
||||
vec2 uv = uvcoordsvar.xy + blurDir * x + uvOffset;
|
||||
vec3 col = texture(revealBuf, uv).rgb;
|
||||
if (any(not(equal(vec2(0.0), floor(uv))))) {
|
||||
col = vec3(0.0);
|
||||
}
|
||||
fragRevealage.rgb += col * weight;
|
||||
}
|
||||
fragRevealage /= weight_accum;
|
||||
|
||||
if (isFirstPass) {
|
||||
/* In first pass we copy the reveal buffer. This let us do alpha masking in second pass. */
|
||||
fragColor = texture(revealBuf, uvcoordsvar.xy);
|
||||
/* Also add the masked color to the reveal buffer. */
|
||||
vec3 col = texture(colorBuf, uvcoordsvar.xy).rgb;
|
||||
if (all(lessThan(abs(col - maskColor), vec3(0.05)))) {
|
||||
fragColor = vec4(1.0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Premult by foreground alpha (alpha mask). */
|
||||
float mask = 1.0 - clamp(dot(vec3(0.333334), texture(colorBuf, uvcoordsvar.xy).rgb), 0.0, 1.0);
|
||||
|
||||
/* fragRevealage is blurred shadow. */
|
||||
float rim = clamp(dot(vec3(0.333334), fragRevealage.rgb), 0.0, 1.0);
|
||||
|
||||
vec4 color = vec4(rimColor, 1.0);
|
||||
|
||||
blend_mode_output(blendMode, color, rim * mask, fragColor, fragRevealage);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(SHADOW)
|
||||
|
||||
uniform vec4 shadowColor;
|
||||
uniform vec2 uvRotX;
|
||||
uniform vec2 uvRotY;
|
||||
uniform vec2 uvOffset;
|
||||
uniform vec2 blurDir;
|
||||
uniform vec2 waveDir;
|
||||
uniform vec2 waveOffset;
|
||||
uniform float wavePhase;
|
||||
uniform int sampCount;
|
||||
uniform bool isFirstPass;
|
||||
|
||||
vec2 compute_uvs(float x)
|
||||
{
|
||||
vec2 uv = uvcoordsvar.xy;
|
||||
/* Tranform UV (loc, rot, scale) */
|
||||
uv = uv.x * uvRotX + uv.y * uvRotY + uvOffset;
|
||||
uv += blurDir * x;
|
||||
/* Wave deform. */
|
||||
float wave_time = dot(uv, waveDir.xy);
|
||||
uv += sin(wave_time + wavePhase) * waveOffset;
|
||||
return uv;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Blur revealage buffer. */
|
||||
fragRevealage = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
for (int i = -sampCount; i <= sampCount; i++) {
|
||||
float x = float(i) / float(sampCount);
|
||||
float weight = gaussian_weight(x);
|
||||
weight_accum += weight;
|
||||
vec2 uv = compute_uvs(x);
|
||||
vec3 col = texture(revealBuf, uv).rgb;
|
||||
if (any(not(equal(vec2(0.0), floor(uv))))) {
|
||||
col = vec3(1.0);
|
||||
}
|
||||
fragRevealage.rgb += col * weight;
|
||||
}
|
||||
fragRevealage /= weight_accum;
|
||||
|
||||
/* No blending in first pass, alpha over premult in second pass. */
|
||||
if (isFirstPass) {
|
||||
/* In first pass we copy the reveal buffer. This let us do alpha under in second pass. */
|
||||
fragColor = texture(revealBuf, uvcoordsvar.xy);
|
||||
}
|
||||
else {
|
||||
/* fragRevealage is blurred shadow. */
|
||||
float shadow_fac = 1.0 - clamp(dot(vec3(0.333334), fragRevealage.rgb), 0.0, 1.0);
|
||||
/* Premult by foreground revealage (alpha under). */
|
||||
vec3 original_revealage = texture(colorBuf, uvcoordsvar.xy).rgb;
|
||||
shadow_fac *= clamp(dot(vec3(0.333334), original_revealage), 0.0, 1.0);
|
||||
/* Modulate by opacity */
|
||||
shadow_fac *= shadowColor.a;
|
||||
/* Apply shadow color. */
|
||||
fragColor.rgb = mix(vec3(0.0), shadowColor.rgb, shadow_fac);
|
||||
/* Alpha over (mask behind the shadow). */
|
||||
fragColor.a = shadow_fac;
|
||||
|
||||
fragRevealage.rgb = original_revealage * (1.0 - shadow_fac);
|
||||
/* Replace the whole revealage buffer. */
|
||||
fragRevealage.a = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(PIXELIZE)
|
||||
|
||||
uniform vec2 targetPixelSize;
|
||||
uniform vec2 targetPixelOffset;
|
||||
uniform vec2 accumOffset;
|
||||
uniform int sampCount;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pixel = floor((uvcoordsvar.xy - targetPixelOffset) / targetPixelSize);
|
||||
vec2 uv = (pixel + 0.5) * targetPixelSize + targetPixelOffset;
|
||||
|
||||
fragColor = vec4(0.0);
|
||||
fragRevealage = vec4(0.0);
|
||||
|
||||
for (int i = -sampCount; i <= sampCount; i++) {
|
||||
float x = float(i) / float(sampCount + 1);
|
||||
vec2 uv_ofs = uv + accumOffset * 0.5 * x;
|
||||
fragColor += texture(colorBuf, uv_ofs);
|
||||
fragRevealage += texture(revealBuf, uv_ofs);
|
||||
}
|
||||
|
||||
fragColor /= float(sampCount) * 2.0 + 1.0;
|
||||
fragRevealage /= float(sampCount) * 2.0 + 1.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform int tonemapping;
|
||||
uniform vec4 select_color;
|
||||
uniform int do_select;
|
||||
|
||||
float srgb_to_linearrgb(float c)
|
||||
{
|
||||
if (c < 0.04045) {
|
||||
return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
|
||||
}
|
||||
else {
|
||||
return pow((c + 0.055) * (1.0 / 1.055), 2.4);
|
||||
}
|
||||
}
|
||||
|
||||
float linearrgb_to_srgb(float c)
|
||||
{
|
||||
if (c < 0.0031308) {
|
||||
return (c < 0.0) ? 0.0 : c * 12.92;
|
||||
}
|
||||
else {
|
||||
return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_borders(ivec2 uv, int size)
|
||||
{
|
||||
for (int x = -size; x <= size; x++) {
|
||||
for (int y = -size; y <= size; y++) {
|
||||
vec4 stroke_color = texelFetch(strokeColor, ivec2(uv.x + x, uv.y + y), 0).rgba;
|
||||
if (stroke_color.a > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
|
||||
vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
|
||||
|
||||
/* premult alpha factor to remove double blend effects */
|
||||
if (stroke_color.a > 0) {
|
||||
stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a);
|
||||
}
|
||||
|
||||
/* apply color correction for render only */
|
||||
if (tonemapping == 1) {
|
||||
stroke_color.r = srgb_to_linearrgb(stroke_color.r);
|
||||
stroke_color.g = srgb_to_linearrgb(stroke_color.g);
|
||||
stroke_color.b = srgb_to_linearrgb(stroke_color.b);
|
||||
}
|
||||
|
||||
FragColor = clamp(stroke_color, 0.0, 1.0);
|
||||
gl_FragDepth = clamp(stroke_depth, 0.0, 1.0);
|
||||
|
||||
if (do_select == 1) {
|
||||
if (stroke_color.a == 0) {
|
||||
if (check_borders(uv, 2)) {
|
||||
FragColor = select_color;
|
||||
gl_FragDepth = 0.000001;
|
||||
/* Dirty fix waiting for new GPencil engine. */
|
||||
FragColor.rgb = pow(FragColor.rgb, vec3(2.2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user