Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h118
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h21
-rw-r--r--source/blender/blenkernel/intern/brush.c85
-rw-r--r--source/blender/blenkernel/intern/gpencil.c690
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c332
-rw-r--r--source/blender/blenkernel/intern/material.c3
-rw-r--r--source/blender/blenkernel/intern/object.c14
-rw-r--r--source/blender/blenkernel/intern/object_update.c11
-rw-r--r--source/blender/blenlib/intern/BLI_memblock.c11
-rw-r--r--source/blender/blenloader/intern/readfile.c25
-rw-r--r--source/blender/blenloader/intern/versioning_270.c8
-rw-r--r--source/blender/blenloader/intern/versioning_280.c8300
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c6
-rw-r--r--source/blender/blenloader/intern/writefile.c7
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc9
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc4
-rw-r--r--source/blender/draw/CMakeLists.txt51
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_antialiasing.c155
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c468
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c1144
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_data.c506
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c2128
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c1774
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h764
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_render.c333
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader.c305
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c1375
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl85
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl82
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl37
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl68
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl46
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl70
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl51
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl65
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl98
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl98
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl32
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl74
-rw-r--r--source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl44
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_frag.glsl43
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl21
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl12
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl157
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl549
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_composite_frag.glsl41
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_frag.glsl17
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl14
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl17
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl53
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl16
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl234
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl16
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl117
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl27
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_layer_mask_frag.glsl37
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl9
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl126
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl142
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl66
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl15
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl107
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl264
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl63
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl5
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl339
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl74
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c25
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c83
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c391
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c158
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h19
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c103
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c6
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl35
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl14
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl103
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl37
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl14
-rw-r--r--source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl6
-rw-r--r--source/blender/draw/engines/workbench/workbench_render.c60
-rw-r--r--source/blender/draw/intern/DRW_render.h22
-rw-r--r--source/blender/draw/intern/draw_cache.c27
-rw-r--r--source/blender/draw/intern/draw_cache.h17
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c747
-rw-r--r--source/blender/draw/intern/draw_common.c2
-rw-r--r--source/blender/draw/intern/draw_common.h2
-rw-r--r--source/blender/draw/intern/draw_manager.c9
-rw-r--r--source/blender/draw/intern/draw_manager.h18
-rw-r--r--source/blender/draw/intern/draw_manager_data.c65
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c90
-rw-r--r--source/blender/draw/intern/shaders/common_globals_lib.glsl2
-rw-r--r--source/blender/draw/intern/shaders/common_smaa_lib.glsl11
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl13
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c42
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c2
-rw-r--r--source/blender/editors/armature/armature_naming.c2
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c37
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c15
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c203
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c48
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c93
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c8
-rw-r--r--source/blender/editors/gpencil/gpencil_armature.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c14
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c151
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c236
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c50
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h32
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c139
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c24
-rw-r--r--source/blender/editors/gpencil/gpencil_ops_versioning.c17
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c343
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c112
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c385
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c31
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c271
-rw-r--r--source/blender/editors/gpencil/gpencil_uv.c19
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_ops.c120
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c149
-rw-r--r--source/blender/editors/gpencil/gpencil_weight_paint.c58
-rw-r--r--source/blender/editors/include/ED_gpencil.h38
-rw-r--r--source/blender/editors/interface/interface_eyedropper_gpencil_color.c29
-rw-r--r--source/blender/editors/object/object_add.c2
-rw-r--r--source/blender/editors/object/object_transform.c10
-rw-r--r--source/blender/editors/screen/screen_context.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c8
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/space_action/action_select.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c7
-rw-r--r--source/blender/editors/transform/transform_convert.c2
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c6
-rw-r--r--source/blender/editors/transform/transform_generics.c7
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c41
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c70
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c13
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c77
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c15
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c15
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c70
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c17
-rw-r--r--source/blender/gpu/GPU_framebuffer.h2
-rw-r--r--source/blender/gpu/GPU_shader_interface.h1
-rw-r--r--source/blender/gpu/GPU_texture.h2
-rw-r--r--source/blender/gpu/GPU_vertex_format.h2
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c15
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c1
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c41
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h7
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h109
-rw-r--r--source/blender/makesdna/DNA_material_types.h65
-rw-r--r--source/blender/makesdna/DNA_object_types.h22
-rw-r--r--source/blender/makesdna/DNA_scene_types.h6
-rw-r--r--source/blender/makesdna/DNA_shader_fx_types.h15
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h5
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c154
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c32
-rw-r--r--source/blender/makesrna/intern/rna_material.c121
-rw-r--r--source/blender/makesrna/intern/rna_object.c19
-rw-r--r--source/blender/makesrna/intern/rna_scene.c30
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c7
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c54
-rw-r--r--source/blender/makesrna/intern/rna_space.c30
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c19
-rw-r--r--source/blender/shader_fx/CMakeLists.txt1
-rw-r--r--source/blender/shader_fx/FX_shader_types.h1
-rw-r--r--source/blender/shader_fx/intern/FX_shader_blur.c6
-rw-r--r--source/blender/shader_fx/intern/FX_shader_flip.c2
-rw-r--r--source/blender/shader_fx/intern/FX_shader_pixel.c2
-rw-r--r--source/blender/shader_fx/intern/FX_shader_shadow.c2
-rw-r--r--source/blender/shader_fx/intern/FX_shader_util.c1
-rw-r--r--source/blender/shader_fx/intern/FX_shader_wave.c2
189 files changed, 12678 insertions, 15409 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 8dc19ed32e5..495fe4eb7f6 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -42,7 +42,7 @@ struct bGPDlayer;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
-
+struct MaterialGPencilStyle;
struct MDeformVert;
#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
@@ -52,18 +52,15 @@ 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) \
@@ -91,8 +88,8 @@ 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_batch_cache_dirty_tag(struct bGPdata *gpd);
void BKE_gpencil_batch_cache_free(struct bGPdata *gpd);
@@ -107,10 +104,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);
@@ -145,12 +143,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,
@@ -161,7 +158,7 @@ struct bGPDstroke *BKE_gpencil_add_stroke_existing_style(struct bGPDframe *gpf,
#define GPENCIL_STRENGTH_MIN 0.003f
#define GP_VERTEX_MASK_ATTENUATE 0.3f
-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.
@@ -176,14 +173,14 @@ 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_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);
@@ -205,9 +202,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);
@@ -228,6 +225,7 @@ 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_collision_get(struct bGPDstroke *gps);
/* vertex groups */
void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps);
@@ -239,11 +237,11 @@ void BKE_gpencil_eval_geometry(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(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 flag);
+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);
@@ -259,27 +257,29 @@ 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);
@@ -302,7 +302,39 @@ bool BKE_gpencil_from_image(struct SpaceImage *sima,
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);
+#ifdef __cplusplus
+extern "C" {
+#endif
+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
+
#endif /* __BKE_GPENCIL_H__ */
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index 9cbc7d05ac2..07cc041cc51 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -293,24 +293,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);
@@ -318,4 +300,7 @@ 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);
#endif /* __BKE_GPENCIL_MODIFIER_H__ */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 2879905795b..c38c4a44d54 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -326,6 +326,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
/* Pin the matterial to the brush. */
brush->gpencil_settings->flag |= GP_BRUSH_MATERIAL_PINNED;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_INK_PEN: {
@@ -362,6 +367,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_INK_PEN_ROUGH: {
@@ -399,6 +409,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_MARKER_BOLD: {
@@ -436,6 +451,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_MARKER_CHISEL: {
@@ -466,6 +486,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_CHISEL;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_PEN: {
@@ -497,6 +522,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_PENCIL_SOFT: {
@@ -528,6 +558,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_PENCIL: {
@@ -558,6 +593,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_FILL_AREA: {
@@ -580,6 +620,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_tool = GPAINT_TOOL_FILL;
brush->gpencil_settings->vertex_mode = GPPAINT_MODE_FILL;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_ERASER_SOFT: {
@@ -635,12 +680,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.8f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->rgb[0] = 0.757f;
- brush->rgb[1] = 0.659f;
- brush->rgb[2] = 0.824f;
- zero_v3(brush->secondary_rgb);
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_VERTEX_DRAW: {
@@ -652,9 +697,10 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.8f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->rgb[0] = 0.757f;
- brush->rgb[1] = 0.659f;
- brush->rgb[2] = 0.824f;
+
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
zero_v3(brush->secondary_rgb);
break;
@@ -668,6 +714,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.8f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_VERTEX_AVERAGE: {
@@ -679,6 +731,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.8f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_VERTEX_SMEAR: {
@@ -690,6 +748,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.8f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_VERTEX_REPLACE: {
@@ -702,6 +766,11 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->draw_strength = 0.8f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->rgb[0] = 1.0f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 1.0f;
+
+ zero_v3(brush->secondary_rgb);
break;
}
case GP_BRUSH_PRESET_SMOOTH_STROKE: {
@@ -843,7 +912,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
static Brush *gpencil_brush_ensure(Main *bmain,
ToolSettings *ts,
- char *brush_name,
+ const char *brush_name,
eObjectMode mode)
{
Brush *brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 8612973fd11..610c8b4280c 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -69,6 +69,7 @@
#include "BLI_math_color.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
static CLG_LogRef LOG = {"bke.gpencil"};
@@ -158,24 +159,6 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf)
return changed;
}
-/* Free strokes and colors belonging to a gp-frame */
-bool BKE_gpencil_free_frame_runtime_data(bGPDframe *gpf_eval)
-{
- bGPDstroke *gps_next;
- if (!gpf_eval) {
- return false;
- }
-
- /* free strokes */
- for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps_next) {
- gps_next = gps->next;
- BKE_gpencil_free_stroke(gps);
- }
- BLI_listbase_clear(&gpf_eval->strokes);
-
- return true;
-}
-
/* Free all of a gp-layer's frames */
void BKE_gpencil_free_frames(bGPDlayer *gpl)
{
@@ -236,6 +219,13 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_all)
}
}
+void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
+{
+ BKE_gpencil_free(gpd_eval, true);
+ BKE_libblock_free_data(&gpd_eval->id, false);
+ MEM_freeN(gpd_eval);
+}
+
/* ************************************************** */
/* Container Creation */
@@ -313,7 +303,7 @@ bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
/* Find frame to insert it before */
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->framenum > cframe) {
/* Add it here */
BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
@@ -362,7 +352,7 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
/* allocate memory for frame and add to end of list */
gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
- gpl_active = BKE_gpencil_layer_getactive(gpd);
+ gpl_active = BKE_gpencil_layer_active_get(gpd);
/* add to datablock */
if (gpl_active == NULL) {
@@ -405,9 +395,12 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
offsetof(bGPDlayer, info),
sizeof(gpl->info));
+ /* Enable always affected by scene lights. */
+ gpl->flag |= GP_LAYER_USE_LIGHTS;
+ gpl->mask_layer[0] = '\0';
/* make this one the active one */
if (setactive) {
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
}
/* return layer */
@@ -427,7 +420,6 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
/* general flags */
gpd->flag |= GP_DATA_VIEWALIGN;
- gpd->flag |= GP_DATA_STROKE_FORCE_RECALC;
/* always enable object onion skin switch */
gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
/* GP object specific settings */
@@ -482,13 +474,14 @@ void BKE_gpencil_stroke_add_points(bGPDstroke *gps,
}
}
-/* Create a new stroke, with pre-allocated data buffers */
-bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, short thickness)
+/* Create a new stroke, with pre-allocated data buffers. */
+bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
{
/* allocate memory for a new stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
gps->thickness = thickness;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_f = 1.0f;
gps->gradient_s[0] = 1.0f;
gps->gradient_s[1] = 1.0f;
@@ -497,30 +490,44 @@ bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, s
gps->inittime = 0;
- /* enable recalculation flag by default */
- gps->flag = GP_STROKE_RECALC_GEOMETRY | GP_STROKE_3DSPACE;
+ gps->flag = GP_STROKE_3DSPACE;
gps->totpoints = totpoints;
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
/* initialize triangle memory to dummy data */
gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
gps->tot_triangles = 0;
gps->mat_nr = mat_idx;
- /* add to frame */
- BLI_addtail(&gpf->strokes, gps);
+ return gps;
+}
+
+/* Create a new stroke and add to frame. */
+bGPDstroke *BKE_gpencil_stroke_add(
+ bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
+{
+ bGPDstroke *gps = BKE_gpencil_stroke_new(mat_idx, totpoints, thickness);
+
+ /* Add to frame. */
+ if ((gps != NULL) && (gpf != NULL)) {
+ if (!insert_at_head) {
+ BLI_addtail(&gpf->strokes, gps);
+ }
+ else {
+ BLI_addhead(&gpf->strokes, gps);
+ }
+ }
return gps;
}
/* Add a stroke and copy the temporary drawing color value from one of the existing stroke */
-bGPDstroke *BKE_gpencil_add_stroke_existing_style(
+bGPDstroke *BKE_gpencil_stroke_add_existing_style(
bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
{
- bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, mat_idx, totpoints, thickness);
+ bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, mat_idx, totpoints, thickness, false);
/* Copy run-time color data so that strokes added in the modifier has the style.
* There are depsgraph reference pointers inside,
* change the copy function if interfere with future drawing implementation. */
@@ -543,30 +550,26 @@ void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_d
}
/* make a copy of a given gpencil stroke */
-bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src)
+bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points)
{
bGPDstroke *gps_dst = NULL;
gps_dst = MEM_dupallocN(gps_src);
gps_dst->prev = gps_dst->next = NULL;
+ gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
- gps_dst->points = MEM_dupallocN(gps_src->points);
+ if (dup_points) {
+ gps_dst->points = MEM_dupallocN(gps_src->points);
- if (gps_src->dvert != NULL) {
- gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
- }
- else {
- gps_dst->dvert = NULL;
+ if (gps_src->dvert != NULL) {
+ gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
+ }
+ else {
+ gps_dst->dvert = NULL;
+ }
}
- /* Don't clear triangles, so that modifier evaluation can just use
- * this without extra work first. Most places that need to force
- * this data to get recalculated will destroy the data anyway though.
- */
- gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
- /* gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY; */
-
/* return new stroke */
return gps_dst;
}
@@ -590,7 +593,7 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
BLI_listbase_clear(&gpf_dst->strokes);
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* make copy of source stroke */
- gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
@@ -611,7 +614,7 @@ void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_ds
BLI_listbase_clear(&gpf_dst->strokes);
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* make copy of source stroke */
- gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
}
@@ -668,7 +671,7 @@ void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int U
/* copy layers */
BLI_listbase_clear(&gpd_dst->layers);
- for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
/* make a copy of source layer and its data */
/* TODO here too could add unused flags... */
@@ -776,8 +779,8 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
/* if frame has no strokes after this, delete it */
if (BLI_listbase_is_empty(&gpf->strokes)) {
- BKE_gpencil_layer_delframe(gpl, gpf);
- BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
+ BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_USE_PREV);
}
}
@@ -785,7 +788,7 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
/* GP Layer API */
/* Check if the given layer is able to be edited or not */
-bool gpencil_layer_is_editable(const bGPDlayer *gpl)
+bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
{
/* Sanity check */
if (gpl == NULL) {
@@ -807,7 +810,7 @@ bool gpencil_layer_is_editable(const bGPDlayer *gpl)
}
/* Look up the gp-frame on the requested frame number, but don't add a new one */
-bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
+bGPDframe *BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
{
bGPDframe *gpf;
@@ -827,7 +830,7 @@ bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
* - this sets the layer's actframe var (if allowed to)
* - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
*/
-bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
+bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
{
bGPDframe *gpf = NULL;
bool found = false;
@@ -976,7 +979,7 @@ bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_M
}
/* delete the given frame from a layer */
-bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
+bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
{
bool changed = false;
@@ -1000,17 +1003,15 @@ bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
}
/* get the active gp-layer for editing */
-bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
+bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
{
- bGPDlayer *gpl;
-
/* error checking */
if (ELEM(NULL, gpd, gpd->layers.first)) {
return NULL;
}
/* loop over layers until found (assume only one active) */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_ACTIVE) {
return gpl;
}
@@ -1021,17 +1022,15 @@ bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
}
/* set the active gp-layer */
-void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
+void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
{
- bGPDlayer *gpl;
-
/* error checking */
if (ELEM(NULL, gpd, gpd->layers.first, active)) {
return;
}
/* loop over layers deactivating all */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_ACTIVE;
if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
gpl->flag |= GP_LAYER_LOCKED;
@@ -1050,13 +1049,11 @@ void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
{
BLI_assert(gpd != NULL);
- bGPDlayer *gpl;
-
if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
- bGPDlayer *layer_active = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *layer_active = BKE_gpencil_layer_active_get(gpd);
/* Lock all other layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* unlock active layer */
if (gpl == layer_active) {
gpl->flag &= ~GP_LAYER_LOCKED;
@@ -1071,7 +1068,7 @@ void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
* a problem in the UI because the user expects all layers will be unlocked
*/
if (unlock) {
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_LOCKED;
}
}
@@ -1129,7 +1126,7 @@ Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob,
Material *ma = BKE_gpencil_brush_material_get(brush);
/* check if the material is already on object material slots and add it if missing */
- if (ma && BKE_gpencil_object_material_get_index(ob, ma) < 0) {
+ if (ma && BKE_gpencil_object_material_index_get(ob, ma) < 0) {
BKE_object_material_slot_add(bmain, ob);
BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
}
@@ -1148,7 +1145,7 @@ int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *materi
if (!material) {
return -1;
}
- int index = BKE_gpencil_object_material_get_index(ob, material);
+ int index = BKE_gpencil_object_material_index_get(ob, material);
if (index < 0) {
BKE_object_material_slot_add(bmain, ob);
BKE_object_material_assign(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
@@ -1177,7 +1174,7 @@ Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *n
}
/* Returns the material for a brush with respect to its pinned state. */
-Material *BKE_gpencil_object_material_get_from_brush(Object *ob, Brush *brush)
+Material *BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush)
{
if ((brush) && (brush->gpencil_settings) &&
(brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
@@ -1193,7 +1190,7 @@ Material *BKE_gpencil_object_material_get_from_brush(Object *ob, Brush *brush)
int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
{
if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
- return BKE_gpencil_object_material_get_index(ob, brush->gpencil_settings->material);
+ return BKE_gpencil_object_material_index_get(ob, brush->gpencil_settings->material);
}
else {
return ob->actcol - 1;
@@ -1304,11 +1301,11 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
return changed;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf != NULL) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
}
}
@@ -1340,6 +1337,13 @@ void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
mul_v3_v3fl(r_centroid, tot, 0.5f);
}
+/* Compute stroke collision detection center and radius. */
+void BKE_gpencil_stroke_collision_get(bGPDstroke *gps)
+{
+ INIT_MINMAX(gps->collision_min, gps->collision_max);
+ BKE_gpencil_stroke_minmax(gps, false, gps->collision_min, gps->collision_max);
+}
+
/* create bounding box values */
static void boundbox_gpencil(Object *ob)
{
@@ -1391,7 +1395,7 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
}
const float scalef = mat4_to_scale(mat);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* FIXME: For now, we just skip parented layers.
* Otherwise, we have to update each frame to find
* the current parent position/effects.
@@ -1400,8 +1404,8 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
continue;
}
- 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) {
bGPDspoint *pt;
int i;
@@ -1410,9 +1414,8 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
pt->pressure *= scalef;
}
- /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Distortion may mean we need to re-triangulate. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
}
@@ -1431,9 +1434,9 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
/* Remove points data */
if (gpd) {
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->dvert != NULL) {
for (int i = 0; i < gps->totpoints; i++) {
dvert = &gps->dvert[i];
@@ -1547,7 +1550,7 @@ static int stroke_march_next_point(const bGPDstroke *gps,
float *result,
float *pressure,
float *strength,
- float *mix_color,
+ float *vert_color,
float *ratio_result,
int *index_from,
int *index_to)
@@ -1587,7 +1590,7 @@ static int stroke_march_next_point(const bGPDstroke *gps,
copy_v3_v3(result, &pt->x);
*pressure = gps->points[next_point_index].pressure;
*strength = gps->points[next_point_index].strength;
- memcpy(mix_color, gps->points[next_point_index].mix_color, sizeof(float) * 4);
+ memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float) * 4);
*index_from = next_point_index - 1;
*index_to = next_point_index;
@@ -1602,9 +1605,9 @@ static int stroke_march_next_point(const bGPDstroke *gps,
gps->points[next_point_index].pressure, gps->points[next_point_index - 1].pressure, ratio);
*strength = interpf(
gps->points[next_point_index].strength, gps->points[next_point_index - 1].strength, ratio);
- interp_v4_v4v4(mix_color,
- gps->points[next_point_index - 1].mix_color,
- gps->points[next_point_index].mix_color,
+ interp_v4_v4v4(vert_color,
+ gps->points[next_point_index - 1].vert_color,
+ gps->points[next_point_index].vert_color,
ratio);
*index_from = next_point_index - 1;
@@ -1689,7 +1692,7 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist)
* \param gps: Stroke to sample
* \param dist: Distance of one segment
*/
-bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool select)
+bool BKE_gpencil_stroke_sample(bGPDstroke *gps, const float dist, const bool select)
{
bGPDspoint *pt = gps->points;
bGPDspoint *pt1 = NULL;
@@ -1717,7 +1720,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
int next_point_index = 1;
i = 0;
float pressure, strength, ratio_result;
- float mix_color[4];
+ float vert_color[4];
int index_from, index_to;
float last_coord[3];
@@ -1728,7 +1731,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
copy_v3_v3(&pt2->x, last_coord);
new_pt[i].pressure = pt[0].pressure;
new_pt[i].strength = pt[0].strength;
- memcpy(new_pt[i].mix_color, pt[0].mix_color, sizeof(float) * 4);
+ memcpy(new_pt[i].vert_color, pt[0].vert_color, sizeof(float) * 4);
if (select) {
new_pt[i].flag |= GP_SPOINT_SELECT;
}
@@ -1746,7 +1749,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
last_coord,
&pressure,
&strength,
- mix_color,
+ vert_color,
&ratio_result,
&index_from,
&index_to)) > -1) {
@@ -1754,7 +1757,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
copy_v3_v3(&pt2->x, last_coord);
new_pt[i].pressure = pressure;
new_pt[i].strength = strength;
- memcpy(new_pt[i].mix_color, mix_color, sizeof(float) * 4);
+ memcpy(new_pt[i].vert_color, vert_color, sizeof(float) * 4);
if (select) {
new_pt[i].flag |= GP_SPOINT_SELECT;
}
@@ -1786,8 +1789,8 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
gps->totpoints = i;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
return true;
}
@@ -1798,7 +1801,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
* \param dist: Distance of one segment
* \param tip_length: Ignore tip jittering, set zero to use default value.
*/
-bool BKE_gpencil_stretch_stroke(bGPDstroke *gps, const float dist, const float tip_length)
+bool BKE_gpencil_stroke_stretch(bGPDstroke *gps, const float dist, const float tip_length)
{
bGPDspoint *pt = gps->points, *last_pt, *second_last, *next_pt;
int i;
@@ -1849,7 +1852,7 @@ bool BKE_gpencil_stretch_stroke(bGPDstroke *gps, const float dist, const float t
* \param index_from: the index of the first point to be used in the trimmed result
* \param index_to: the index of the last point to be used in the trimmed result
*/
-bool BKE_gpencil_trim_stroke_points(bGPDstroke *gps, const int index_from, const int index_to)
+bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const int index_to)
{
bGPDspoint *pt = gps->points, *new_pt;
MDeformVert *dv, *new_dv;
@@ -1899,7 +1902,7 @@ bool BKE_gpencil_trim_stroke_points(bGPDstroke *gps, const int index_from, const
return true;
}
-bool BKE_gpencil_split_stroke(bGPDframe *gpf,
+bool BKE_gpencil_stroke_split(bGPDframe *gpf,
bGPDstroke *gps,
const int before_index,
bGPDstroke **remaining_gps)
@@ -1917,7 +1920,7 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
/* Handle remaining segments first. */
- new_gps = BKE_gpencil_add_stroke_existing_style(
+ new_gps = BKE_gpencil_stroke_add_existing_style(
gpf, gps, gps->mat_nr, new_count, gps->thickness);
new_pt = new_gps->points; /* Allocated from above. */
@@ -1947,8 +1950,8 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
/* Trim the original stroke into a shorter one.
* Keep the end point. */
- BKE_gpencil_trim_stroke_points(gps, 0, old_count);
-
+ BKE_gpencil_stroke_trim_points(gps, 0, old_count);
+ BKE_gpencil_stroke_geometry_update(gps);
return true;
}
@@ -1957,7 +1960,7 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
* \param gps: Stroke to shrink
* \param dist: delta length
*/
-bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
+bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist)
{
bGPDspoint *pt = gps->points, *second_last;
int i;
@@ -2001,7 +2004,7 @@ bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
index_start = index_end = 0; /* no length left to cut */
}
- BKE_gpencil_trim_stroke_points(gps, index_start, index_end);
+ BKE_gpencil_stroke_trim_points(gps, index_start, index_end);
if (gps->totpoints == 0) {
return false;
@@ -2029,7 +2032,7 @@ bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
* \param i: Point index
* \param inf: Amount of smoothing to apply
*/
-bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
+bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf)
{
bGPDspoint *pt = &gps->points[i];
float sco[3] = {0.0f};
@@ -2088,7 +2091,7 @@ bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
/**
* Apply smooth for strength to stroke point */
-bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -2148,7 +2151,7 @@ bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float
/**
* Apply smooth for thickness to stroke point (use pressure) */
-bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -2208,7 +2211,7 @@ bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float
/**
* Apply smooth for UV rotation to stroke point (use pressure).
*/
-bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -2258,7 +2261,7 @@ void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_end
*r_initframe = gpl->actframe->framenum;
*r_endframe = gpl->actframe->framenum;
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
if (gpf->framenum < *r_initframe) {
*r_initframe = gpf->framenum;
@@ -2311,9 +2314,9 @@ float BKE_gpencil_multiframe_falloff_calc(
/* reassign strokes using a material */
void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
{
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* reassign strokes */
if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) {
gps->mat_nr--;
@@ -2327,9 +2330,9 @@ void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
/* remove strokes using a material */
bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
{
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->mat_nr == index) {
return true;
}
@@ -2353,9 +2356,9 @@ void BKE_gpencil_material_remap(struct bGPdata *gpd,
} \
((void)0)
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* reassign strokes */
MAT_NR_REMAP(gps->mat_nr);
}
@@ -2402,7 +2405,7 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
gp_style_secondary = ma_secondary->gp_style;
if ((gp_style_primary == NULL) || (gp_style_secondary == NULL) ||
- (gp_style_secondary->flag & GP_STYLE_COLOR_LOCKED)) {
+ (gp_style_secondary->flag & GP_MATERIAL_LOCKED)) {
continue;
}
@@ -2412,13 +2415,13 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
}
/* Check materials have same stroke and fill attributes. */
- if ((gp_style_primary->flag & GP_STYLE_STROKE_SHOW) !=
- (gp_style_secondary->flag & GP_STYLE_STROKE_SHOW)) {
+ if ((gp_style_primary->flag & GP_MATERIAL_STROKE_SHOW) !=
+ (gp_style_secondary->flag & GP_MATERIAL_STROKE_SHOW)) {
continue;
}
- if ((gp_style_primary->flag & GP_STYLE_FILL_SHOW) !=
- (gp_style_secondary->flag & GP_STYLE_FILL_SHOW)) {
+ if ((gp_style_primary->flag & GP_MATERIAL_FILL_SHOW) !=
+ (gp_style_secondary->flag & GP_MATERIAL_FILL_SHOW)) {
continue;
}
@@ -2469,11 +2472,11 @@ void BKE_gpencil_stats_update(bGPdata *gpd)
gpd->totstroke = 0;
gpd->totpoint = 0;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpd->totlayer++;
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
gpd->totframe++;
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
gpd->totstroke++;
gpd->totpoint += gps->totpoints;
}
@@ -2482,7 +2485,7 @@ void BKE_gpencil_stats_update(bGPdata *gpd)
}
/* get material index (0-based like mat_nr not actcol) */
-int BKE_gpencil_object_material_get_index(Object *ob, Material *ma)
+int BKE_gpencil_object_material_index_get(Object *ob, Material *ma)
{
short *totcol = BKE_object_material_num(ob);
Material *read_ma = NULL;
@@ -2717,7 +2720,7 @@ static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2],
/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was
* modified) */
-void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
+void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
{
BLI_assert(gps->totpoints >= 3);
@@ -2739,36 +2742,25 @@ void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
float minv[2];
float maxv[2];
/* first needs bounding box data */
- if (gpd->flag & GP_DATA_UV_ADAPTIVE) {
- gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
- }
- else {
- ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
- ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
- }
+ ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
+ ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
/* calc uv data */
gpencil_calc_stroke_fill_uv(points2d, gps, minv, maxv, uv);
- /* Number of triangles */
- gps->tot_triangles = gps->totpoints - 2;
- /* save triangulation data in stroke cache */
+ /* Save triangulation data. */
if (gps->tot_triangles > 0) {
- if (gps->triangles == NULL) {
- gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
- "GP Stroke triangulation");
- }
- else {
- gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
- }
+ MEM_SAFE_FREE(gps->triangles);
+ gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
+ "GP Stroke triangulation");
for (int i = 0; i < gps->tot_triangles; i++) {
- bGPDtriangle *stroke_triangle = &gps->triangles[i];
memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
- /* copy texture coordinates */
- copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
- copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
- copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
+ }
+
+ /* Copy UVs to bGPDspoint. */
+ for (int i = 0; i < gps->totpoints; i++) {
+ copy_v2_v2(gps->points[i].uv_fill, uv[i]);
}
}
else {
@@ -2780,17 +2772,50 @@ void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
gps->triangles = NULL;
}
- /* disable recalculation flag */
- if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
- gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
- }
-
/* clear memory */
MEM_SAFE_FREE(tmp_triangles);
MEM_SAFE_FREE(points2d);
MEM_SAFE_FREE(uv);
}
+/* texture coordinate utilities */
+void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
+{
+ if (gps == NULL || gps->totpoints == 0) {
+ return;
+ }
+
+ bGPDspoint *pt = gps->points;
+ float totlen = 0.0f;
+ pt[0].uv_fac = totlen;
+ for (int i = 1; i < gps->totpoints; i++) {
+ totlen += len_v3v3(&pt[i - 1].x, &pt[i].x);
+ pt[i].uv_fac = totlen;
+ }
+}
+
+/* Recalc the internal geometry caches for fill and uvs. */
+void BKE_gpencil_stroke_geometry_update(bGPDstroke *gps)
+{
+ if (gps == NULL) {
+ return;
+ }
+
+ if (gps->totpoints > 2) {
+ BKE_gpencil_stroke_fill_triangulate(gps);
+ }
+ else {
+ gps->tot_triangles = 0;
+ MEM_SAFE_FREE(gps->triangles);
+ }
+
+ /* calc uv data along the stroke */
+ BKE_gpencil_stroke_uv_update(gps);
+
+ /* Calc collision center and radius. */
+ BKE_gpencil_stroke_collision_get(gps);
+}
+
float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
{
if (!gps->points || gps->totpoints < 2) {
@@ -2817,7 +2842,7 @@ float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
* Trim stroke to the first intersection or loop
* \param gps: Stroke data
*/
-bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
+bool BKE_gpencil_stroke_trim(bGPDstroke *gps)
{
if (gps->totpoints < 4) {
return false;
@@ -2898,13 +2923,14 @@ bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
}
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
gps->totpoints = newtot;
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
}
+
+ BKE_gpencil_stroke_geometry_update(gps);
+
return intersect;
}
@@ -2912,7 +2938,7 @@ bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
* Close stroke
* \param gps: Stroke to close
*/
-bool BKE_gpencil_close_stroke(bGPDstroke *gps)
+bool BKE_gpencil_stroke_close(bGPDstroke *gps)
{
bGPDspoint *pt1 = NULL;
bGPDspoint *pt2 = NULL;
@@ -2970,7 +2996,7 @@ bool BKE_gpencil_close_stroke(bGPDstroke *gps)
pt->pressure = interpf(pt2->pressure, pt1->pressure, step);
pt->strength = interpf(pt2->strength, pt1->strength, step);
pt->flag = 0;
- interp_v4_v4v4(pt->mix_color, pt1->mix_color, pt2->mix_color, step);
+ interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step);
/* Set weights. */
if (gps->dvert != NULL) {
@@ -3073,8 +3099,7 @@ void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short ta
gps->totpoints = tot;
/* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
@@ -3087,7 +3112,7 @@ void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short ta
* \param threshold: Distance between points
* \param use_unselected: Set to true to analyze all stroke and not only selected points
*/
-void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf,
+void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf,
bGPDstroke *gps,
const float threshold,
const bool use_unselected)
@@ -3154,6 +3179,9 @@ void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf,
if (tagged) {
BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG);
}
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* Helper: Check materials with same color. */
@@ -3173,7 +3201,8 @@ static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Mate
float hsv2[4];
rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
hsv2[3] = gp_style->fill_rgba[3];
- if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_SOLID) && (compare_v4v4(hsv1, hsv2, 0.01f))) {
+ if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) &&
+ (compare_v4v4(hsv1, hsv2, 0.01f))) {
*r_mat = ma;
return i - 1;
}
@@ -3198,24 +3227,24 @@ static Material *gpencil_add_from_curve_material(Main *bmain,
/* Stroke color. */
if (gpencil_lines) {
ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
else {
linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color);
- gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
/* Fill color. */
linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color);
/* Fill is false if the original curve hasn't material assigned, so enable it. */
if (fill) {
- gp_style->flag |= GP_STYLE_FILL_SHOW;
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
/* Check at least one is enabled. */
- if (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) &&
- ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) &&
+ ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
return mat_gp;
@@ -3280,6 +3309,7 @@ static void gpencil_convert_spline(Main *bmain,
/* Create Stroke. */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
gps->thickness = 1.0f;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_f = 1.0f;
gps->uv_scale = 1.0f;
@@ -3287,8 +3317,6 @@ static void gpencil_convert_spline(Main *bmain,
ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND);
gps->inittime = 0.0f;
- /* Enable recalculation flag by default. */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
gps->flag &= ~GP_STROKE_SELECT;
gps->flag |= GP_STROKE_3DSPACE;
@@ -3307,10 +3335,6 @@ static void gpencil_convert_spline(Main *bmain,
}
totpoints = (resolu * segments) - (segments - 1);
- /* Initialize triangle memory to dummy data. */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
-
/* Materials
* Notice: The color of the material is the color of viewport and not the final shader color.
*/
@@ -3370,16 +3394,16 @@ static void gpencil_convert_spline(Main *bmain,
if (ob_cu->totcol > 0) {
mat_curve = BKE_object_material_get(ob_cu, 1);
if (mat_curve) {
- linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
+ copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
/* Set fill and stroke depending of curve type (3D or 2D). */
if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
- mat_gp->gp_style->flag |= GP_STYLE_STROKE_SHOW;
- mat_gp->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
}
else {
- mat_gp->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
- mat_gp->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
}
}
@@ -3491,8 +3515,11 @@ static void gpencil_convert_spline(Main *bmain,
}
/* Cyclic curve, close stroke. */
if ((cyclic) && (!do_stroke)) {
- BKE_gpencil_close_stroke(gps);
+ BKE_gpencil_stroke_close(gps);
}
+
+ /* Recalc fill geometry. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* Convert a curve object to grease pencil stroke.
@@ -3538,14 +3565,14 @@ void BKE_gpencil_convert_curve(Main *bmain,
}
if (gpl == NULL) {
- gpl = BKE_gpencil_layer_getactive(gpd);
+ gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl == NULL) {
gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
}
}
/* Check if there is an active frame and add if needed. */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY);
/* Read all splines of the curve and create a stroke for each. */
for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
@@ -3560,7 +3587,7 @@ void BKE_gpencil_convert_curve(Main *bmain,
void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
{
const int totcol = 120;
- static char *hexcol[] = {
+ const char *hexcol[] = {
"FFFFFF", "F2F2F2", "E6E6E6", "D9D9D9", "CCCCCC", "BFBFBF", "B2B2B2", "A6A6A6", "999999",
"8C8C8C", "808080", "737373", "666666", "595959", "4C4C4C", "404040", "333333", "262626",
"1A1A1A", "000000", "F2FC24", "FFEA00", "FEA711", "FE8B68", "FB3B02", "FE3521", "D00000",
@@ -3589,7 +3616,7 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
for (int i = 0; i < totcol; i++) {
PaletteColor *palcol = BKE_palette_color_add(paint->palette);
if (palcol) {
- hex_to_rgb(hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
+ hex_to_rgb((char *)hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
}
}
}
@@ -3614,27 +3641,26 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size,
int img_x = ibuf->x;
int img_y = ibuf->y;
- // space = 0.005 pixels = image.pixels
float color[4];
bGPDspoint *pt;
for (int row = 0; row < img_y; row++) {
/* Create new stroke */
- bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, 0, img_x, size * 1000);
+ bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, 0, img_x, size * 1000, false);
done = true;
for (int col = 0; col < img_x; col++) {
- IMB_sampleImageAtLocation(ibuf, col, row, false, color);
+ IMB_sampleImageAtLocation(ibuf, col, row, true, color);
pt = &gps->points[col];
pt->pressure = 1.0f;
pt->x = col * size;
pt->z = row * size;
if (!mask) {
- copy_v3_v3(pt->mix_color, color);
- pt->mix_color[3] = 1.0f;
+ copy_v3_v3(pt->vert_color, color);
+ pt->vert_color[3] = 1.0f;
pt->strength = color[3];
}
else {
- zero_v3(pt->mix_color);
- pt->mix_color[3] = 1.0f;
+ zero_v3(pt->vert_color);
+ pt->vert_color[3] = 1.0f;
pt->strength = 1.0f - color[3];
}
@@ -3644,6 +3670,7 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size,
pt->flag |= GP_SPOINT_SELECT;
}
}
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
@@ -3652,3 +3679,282 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size,
return done;
}
+
+/* -------------------------------------------------------------------- */
+/** \name Iterators
+ *
+ * Iterate over all visible stroke of all visible layers inside a gpObject.
+ * Also take into account onion skining.
+ *
+ * \{ */
+
+void BKE_gpencil_visible_stroke_iter(
+ Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
+
+ /* Onion skinning. */
+ const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE);
+ const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED);
+ const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0;
+ const short onion_keytype = gpd->onion_keytype;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+
+ bGPDframe *act_gpf = gpl->actframe;
+ bGPDframe *sta_gpf = act_gpf;
+ bGPDframe *end_gpf = act_gpf ? act_gpf->next : NULL;
+
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+
+ if (is_multiedit) {
+ sta_gpf = end_gpf = NULL;
+ /* Check the whole range and tag the editable frames. */
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ if (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT)) {
+ gpf->runtime.onion_id = 0;
+ if (sta_gpf == NULL) {
+ sta_gpf = gpf;
+ }
+ end_gpf = gpf->next;
+ }
+ else {
+ gpf->runtime.onion_id = INT_MAX;
+ }
+ }
+ }
+ else if (is_onion && (gpl->onion_flag & GP_LAYER_ONIONSKIN)) {
+ if (act_gpf) {
+ bGPDframe *last_gpf = gpl->frames.last;
+
+ int frame_len = 0;
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ gpf->runtime.frameid = frame_len++;
+ }
+
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ bool is_wrong_keytype = (onion_keytype > -1) && (gpf->key_type != onion_keytype);
+ bool is_in_range;
+ int delta = (onion_mode_abs) ? (gpf->framenum - cfra) :
+ (gpf->runtime.frameid - act_gpf->runtime.frameid);
+
+ if (onion_mode_sel) {
+ is_in_range = (gpf->flag & GP_FRAME_SELECT) != 0;
+ }
+ else {
+ is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
+
+ if (onion_loop && !is_in_range) {
+ /* We wrap the value using the last frame and 0 as reference. */
+ /* FIXME: This might not be good for animations not starting at 0. */
+ int shift = (onion_mode_abs) ? last_gpf->framenum : last_gpf->runtime.frameid;
+ delta += (delta < 0) ? (shift + 1) : -(shift + 1);
+ /* Test again with wrapped value. */
+ is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
+ }
+ }
+ /* Mask frames that have wrong keytype of are not in range. */
+ gpf->runtime.onion_id = (is_wrong_keytype || !is_in_range) ? INT_MAX : delta;
+ }
+ /* Active frame is always shown. */
+ act_gpf->runtime.onion_id = 0;
+ }
+
+ sta_gpf = gpl->frames.first;
+ end_gpf = NULL;
+ }
+ else {
+ /* Bypass multiedit/onion skinning. */
+ end_gpf = sta_gpf = NULL;
+ }
+
+ if (sta_gpf == NULL && act_gpf == NULL) {
+ if (layer_cb) {
+ layer_cb(gpl, act_gpf, NULL, thunk);
+ }
+ continue;
+ }
+
+ /* Draw multiedit/onion skinning first */
+ for (bGPDframe *gpf = sta_gpf; gpf && gpf != end_gpf; gpf = gpf->next) {
+ if (gpf->runtime.onion_id == INT_MAX || gpf == act_gpf) {
+ continue;
+ }
+
+ if (layer_cb) {
+ layer_cb(gpl, gpf, NULL, thunk);
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ stroke_cb(gpl, gpf, gps, thunk);
+ }
+ }
+ /* Draw Active frame on top. */
+ /* Use evaluated frame (with modifiers for active stroke)/ */
+ act_gpf = gpl->actframe;
+ act_gpf->runtime.onion_id = 0;
+ if (act_gpf) {
+ if (layer_cb) {
+ layer_cb(gpl, act_gpf, NULL, thunk);
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
+ stroke_cb(gpl, act_gpf, gps, thunk);
+ }
+ }
+ }
+}
+
+void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
+ const struct bGPDframe *gpf_eval)
+{
+ bGPDstroke *gps_eval = gpf_eval->strokes.first;
+ LISTBASE_FOREACH (bGPDstroke *, gps_orig, &gpf_orig->strokes) {
+
+ /* Assign original stroke pointer. */
+ if (gps_eval != NULL) {
+ gps_eval->runtime.gps_orig = gps_orig;
+
+ /* Assign original point pointer. */
+ for (int i = 0; i < gps_orig->totpoints; i++) {
+ bGPDspoint *pt_eval = &gps_eval->points[i];
+ pt_eval->runtime.pt_orig = &gps_orig->points[i];
+ pt_eval->runtime.idx_orig = i;
+ }
+ /* Increase pointer. */
+ gps_eval = gps_eval->next;
+ }
+ }
+}
+
+void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
+{
+ bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
+ bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
+
+ /* Assign pointers to the original stroke and points to the evaluated data. This must
+ * be done before applying any modifier because at this moment the structure is equals,
+ * so we can assume the layer index is the same in both datablocks.
+ * This data will be used by operators. */
+
+ bGPDlayer *gpl_eval = gpd_eval->layers.first;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
+ if (gpl_eval != NULL) {
+ /* Update layer reference pointers. */
+ gpl_eval->runtime.gpl_orig = (bGPDlayer *)gpl;
+
+ bGPDframe *gpf_eval = gpl_eval->frames.first;
+ LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl->frames) {
+ if (gpf_eval != NULL) {
+ /* Update frame reference pointers. */
+ gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
+ gpf_eval = gpf_eval->next;
+ }
+ }
+ gpl_eval = gpl_eval->next;
+ }
+ }
+}
+
+void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
+ Object *obact,
+ bGPDlayer *gpl,
+ float diff_mat[4][4])
+{
+ Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
+ Object *obparent = gpl->parent;
+ Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
+ obparent;
+
+ /* if not layer parented, try with object parented */
+ if (obparent_eval == NULL) {
+ if (ob_eval != NULL) {
+ if (ob_eval->type == OB_GPENCIL) {
+ copy_m4_m4(diff_mat, ob_eval->obmat);
+ return;
+ }
+ }
+ /* not gpencil object */
+ unit_m4(diff_mat);
+ return;
+ }
+ else {
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ return;
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
+ mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ }
+ else {
+ /* if bone not found use object (armature) */
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ }
+ return;
+ }
+ else {
+ unit_m4(diff_mat); /* not defined type */
+ }
+ }
+}
+
+void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob)
+{
+ if (ob->type != OB_GPENCIL) {
+ return;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDspoint *pt;
+ int i;
+ float diff_mat[4][4];
+ float cur_mat[4][4];
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if ((gpl->parent != NULL) && (gpl->actframe != NULL)) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, gpl->parent);
+
+ /* calculate new matrix */
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ invert_m4_m4(cur_mat, ob_eval->obmat);
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, ob_eval->obmat, pchan->pose_mat);
+ invert_m4_m4(cur_mat, tmp_mat);
+ }
+ }
+ /* only redo if any change */
+ if (!equals_m4m4(gpl->inverse, cur_mat)) {
+
+ /* first apply current transformation to all strokes */
+ BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat);
+ /* undo local object */
+ sub_v3_v3(diff_mat[3], ob->obmat[3]);
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ mul_m4_v3(diff_mat, &pt->x);
+ }
+ }
+ /* set new parent matrix */
+ copy_m4_m4(gpl->inverse, cur_mat);
+ }
+ }
+ }
+}
+/** \} */
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 444ba8b4db3..6eb4c4ea36d 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -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(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;
@@ -460,8 +395,8 @@ void BKE_gpencil_eval_geometry(Depsgraph *depsgraph, bGPdata *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 flag)
{
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,7 +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->mix_color, pt->mix_color);
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@@ -750,7 +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->mix_color, pt->mix_color, next->mix_color, 0.5f);
+ interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@@ -795,145 +728,174 @@ 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;
- }
+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;
- BLI_addtail(&gpf_eval->strokes, gps_dst);
+ 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);
}
-/* Calculate gpencil modifiers */
-void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
+static bGPdata *gpencil_copy_for_eval(bGPdata *gpd)
{
- /* use original data to set reference pointers to original data */
- Object *ob_orig = DEG_get_original_object(ob);
- bGPdata *gpd = (bGPdata *)ob_orig->data;
- 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);
+ 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;
- /* 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);
+ /* 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;
}
}
- /* 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__);
+ 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;
}
- else {
- ob->runtime.gpencil_evaluated_frames = MEM_recallocN(ob->runtime.gpencil_evaluated_frames,
- sizeof(struct bGPDframe) *
- ob->runtime.gpencil_tot_layers);
+ 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;
}
- /* Init general modifiers data. */
- if (ob->greasepencil_modifiers.first) {
- BKE_gpencil_lattice_init(ob);
+ /* 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)
+{
+ 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 is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
+ (!GPENCIL_SIMPLIFY_MODIF(scene)));
+ if (!do_modifiers) {
+ return;
+ }
+
+ /* Init general modifiers data. */
+ 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) {
+ /* Loop all layers and apply modifiers. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* 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);
- }
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
+ 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);
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);
+ LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
- /* Skip all if some disable flag is enabled. */
- if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) {
- idx++;
- continue;
- }
+ if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
- /* Apply geometry modifiers (create new geometry). */
- if (BKE_gpencil_has_geometry_modifiers(ob)) {
- BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, gpf_eval, is_render);
- }
+ if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
+ continue;
+ }
- /* 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);
- }
+ /* Apply geometry modifiers (add new geometry). */
+ if (mti->generateStrokes) {
+ mti->generateStrokes(md, depsgraph, ob, gpl, gpf);
+ }
- idx++;
+ /* Apply deform modifiers (only change geometry). */
+ if (mti && mti->deformStroke) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ mti->deformStroke(md, depsgraph, ob, gpl, gpf, gps);
+ }
+ }
+ }
+ }
}
/* Clear any lattice data. */
- if (ob->greasepencil_modifiers.first) {
- BKE_gpencil_lattice_clear(ob);
- }
+ BKE_gpencil_lattice_clear(ob);
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 84b3ea27025..e0b7f3114eb 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -106,7 +106,6 @@ 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);
@@ -114,7 +113,7 @@ void BKE_gpencil_material_attr_init(Material *ma)
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;
}
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index cf43dec132a..d666565956e 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -452,7 +452,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 */
+ /* Clear grease pencil data. */
+ if (ob->runtime.gpd_eval != NULL) {
+ BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
+ ob->runtime.gpd_eval = NULL;
+ }
DRW_gpencil_freecache(ob);
}
@@ -580,6 +584,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;
}
@@ -857,6 +864,10 @@ void BKE_object_init(Object *ob, const short ob_type)
ob->upflag = OB_POSZ;
}
+ if (ob->type == OB_GPENCIL) {
+ ob->dtx |= OB_USE_GPENCIL_LIGHTS;
+ }
+
/* Animation Visualization defaults */
animviz_settings_init(&ob->avs);
}
@@ -3928,7 +3939,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
runtime->mesh_eval = NULL;
runtime->mesh_deform_eval = NULL;
runtime->curve_cache = NULL;
- runtime->gpencil_cache = NULL;
}
/*
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 366fd0950fa..dbed508bc91 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -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 */
diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c
index f7239f1b9d1..ee9ea15835b 100644
--- a/source/blender/blenlib/intern/BLI_memblock.c
+++ b/source/blender/blenlib/intern/BLI_memblock.c
@@ -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]);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9c7e4a35e1f..37fcf10e553 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6928,7 +6928,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);
}
@@ -6942,9 +6942,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! */
@@ -6986,7 +6983,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);
@@ -6994,24 +6991,21 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
gpl->runtime.icon_id = 0;
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ 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;
}
}
}
@@ -9332,11 +9326,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;
@@ -10879,7 +10868,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);
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index a04a2a99c94..87957b550c5 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1130,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;
}
@@ -1358,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) {
@@ -1386,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;
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 8ff82407e1c..ff5b98d13a4 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -14,11 +14,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/** \file
- * \ingroup blenloader
- */
+ /** \file
+ * \ingroup blenloader
+ */
-/* allow readfile to use deprecated functionality */
+ /* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
#include <string.h>
@@ -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"
@@ -73,6 +74,7 @@
#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_library.h"
@@ -106,73 +108,73 @@
/* Make preferences read-only, use versioning_userdef.c. */
#define U (*((const UserDef *)&U))
-static bScreen *screen_parent_find(const bScreen *screen)
+static bScreen* screen_parent_find(const bScreen* screen)
{
- /* Can avoid lookup if screen state isn't maximized/full
- * (parent and child store the same state). */
- if (ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL)) {
- for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->full && sa->full != screen) {
- BLI_assert(sa->full->state == screen->state);
- return sa->full;
- }
- }
- }
-
- return NULL;
+ /* Can avoid lookup if screen state isn't maximized/full
+ * (parent and child store the same state). */
+ if (ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL)) {
+ for (const ScrArea* sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->full && sa->full != screen) {
+ BLI_assert(sa->full->state == screen->state);
+ return sa->full;
+ }
+ }
+ }
+
+ return NULL;
}
-static void do_version_workspaces_create_from_screens(Main *bmain)
+static void do_version_workspaces_create_from_screens(Main* bmain)
{
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- const bScreen *screen_parent = screen_parent_find(screen);
- WorkSpace *workspace;
- if (screen->temp) {
- continue;
- }
-
- if (screen_parent) {
- /* Full-screen with "Back to Previous" option, don't create
- * a new workspace, add layout workspace containing parent. */
- workspace = BLI_findstring(
- &bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2);
- }
- else {
- workspace = BKE_workspace_add(bmain, screen->id.name + 2);
- }
- if (workspace == NULL) {
- continue; /* Not much we can do.. */
- }
- BKE_workspace_layout_add(bmain, workspace, screen, screen->id.name + 2);
- }
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ const bScreen* screen_parent = screen_parent_find(screen);
+ WorkSpace* workspace;
+ if (screen->temp) {
+ continue;
+ }
+
+ if (screen_parent) {
+ /* Full-screen with "Back to Previous" option, don't create
+ * a new workspace, add layout workspace containing parent. */
+ workspace = BLI_findstring(
+ &bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2);
+ }
+ else {
+ workspace = BKE_workspace_add(bmain, screen->id.name + 2);
+ }
+ if (workspace == NULL) {
+ continue; /* Not much we can do.. */
+ }
+ BKE_workspace_layout_add(bmain, workspace, screen, screen->id.name + 2);
+ }
}
-static void do_version_area_change_space_to_space_action(ScrArea *area, const Scene *scene)
+static void do_version_area_change_space_to_space_action(ScrArea* area, const Scene* scene)
{
- SpaceType *stype = BKE_spacetype_from_id(SPACE_ACTION);
- SpaceAction *saction = (SpaceAction *)stype->new (area, scene);
- ARegion *region_channels;
-
- /* Properly free current regions */
- for (ARegion *region = area->regionbase.first; region; region = region->next) {
- BKE_area_region_free(area->type, region);
- }
- BLI_freelistN(&area->regionbase);
-
- area->type = stype;
- area->spacetype = stype->spaceid;
-
- BLI_addhead(&area->spacedata, saction);
- area->regionbase = saction->regionbase;
- BLI_listbase_clear(&saction->regionbase);
-
- /* Different defaults for timeline */
- region_channels = BKE_area_find_region_type(area, RGN_TYPE_CHANNELS);
- region_channels->flag |= RGN_FLAG_HIDDEN;
-
- saction->mode = SACTCONT_TIMELINE;
- saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED;
- saction->ads.filterflag |= ADS_FILTER_SUMMARY;
+ SpaceType* stype = BKE_spacetype_from_id(SPACE_ACTION);
+ SpaceAction* saction = (SpaceAction*)stype->new (area, scene);
+ ARegion* region_channels;
+
+ /* Properly free current regions */
+ for (ARegion* region = area->regionbase.first; region; region = region->next) {
+ BKE_area_region_free(area->type, region);
+ }
+ BLI_freelistN(&area->regionbase);
+
+ area->type = stype;
+ area->spacetype = stype->spaceid;
+
+ BLI_addhead(&area->spacedata, saction);
+ area->regionbase = saction->regionbase;
+ BLI_listbase_clear(&saction->regionbase);
+
+ /* Different defaults for timeline */
+ region_channels = BKE_area_find_region_type(area, RGN_TYPE_CHANNELS);
+ region_channels->flag |= RGN_FLAG_HIDDEN;
+
+ saction->mode = SACTCONT_TIMELINE;
+ saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED;
+ saction->ads.filterflag |= ADS_FILTER_SUMMARY;
}
/**
@@ -187,1961 +189,1961 @@ static void do_version_area_change_space_to_space_action(ScrArea *area, const Sc
* \note Some of the created workspaces might be deleted again
* in case of reading the default `startup.blend`.
*/
-static void do_version_workspaces_after_lib_link(Main *bmain)
+static void do_version_workspaces_after_lib_link(Main* bmain)
{
- BLI_assert(BLI_listbase_is_empty(&bmain->workspaces));
-
- do_version_workspaces_create_from_screens(bmain);
-
- for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- bScreen *screen_parent = screen_parent_find(win->screen);
- bScreen *screen = screen_parent ? screen_parent : win->screen;
-
- if (screen->temp) {
- /* We do not generate a new workspace for those screens...
- * still need to set some data in win. */
- win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
- win->scene = screen->scene;
- /* Deprecated from now on! */
- win->screen = NULL;
- continue;
- }
-
- WorkSpace *workspace = BLI_findstring(
- &bmain->workspaces, screen->id.name + 2, offsetof(ID, name) + 2);
- BLI_assert(workspace != NULL);
- WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, win->screen);
- BLI_assert(layout != NULL);
-
- win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
-
- BKE_workspace_active_set(win->workspace_hook, workspace);
- BKE_workspace_active_layout_set(win->workspace_hook, layout);
-
- /* Move scene and view layer to window. */
- Scene *scene = screen->scene;
- ViewLayer *layer = BLI_findlink(&scene->view_layers, scene->r.actlay);
- if (!layer) {
- layer = BKE_view_layer_default_view(scene);
- }
-
- win->scene = scene;
- STRNCPY(win->view_layer_name, layer->name);
-
- /* Deprecated from now on! */
- win->screen = NULL;
- }
- }
-
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- /* Deprecated from now on! */
- BLI_freelistN(&screen->scene->transform_spaces);
- screen->scene = NULL;
- }
+ BLI_assert(BLI_listbase_is_empty(&bmain->workspaces));
+
+ do_version_workspaces_create_from_screens(bmain);
+
+ for (wmWindowManager* wm = bmain->wm.first; wm; wm = wm->id.next) {
+ for (wmWindow* win = wm->windows.first; win; win = win->next) {
+ bScreen* screen_parent = screen_parent_find(win->screen);
+ bScreen* screen = screen_parent ? screen_parent : win->screen;
+
+ if (screen->temp) {
+ /* We do not generate a new workspace for those screens...
+ * still need to set some data in win. */
+ win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
+ win->scene = screen->scene;
+ /* Deprecated from now on! */
+ win->screen = NULL;
+ continue;
+ }
+
+ WorkSpace* workspace = BLI_findstring(
+ &bmain->workspaces, screen->id.name + 2, offsetof(ID, name) + 2);
+ BLI_assert(workspace != NULL);
+ WorkSpaceLayout* layout = BKE_workspace_layout_find(workspace, win->screen);
+ BLI_assert(layout != NULL);
+
+ win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
+
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+ BKE_workspace_active_layout_set(win->workspace_hook, layout);
+
+ /* Move scene and view layer to window. */
+ Scene* scene = screen->scene;
+ ViewLayer* layer = BLI_findlink(&scene->view_layers, scene->r.actlay);
+ if (!layer) {
+ layer = BKE_view_layer_default_view(scene);
+ }
+
+ win->scene = scene;
+ STRNCPY(win->view_layer_name, layer->name);
+
+ /* Deprecated from now on! */
+ win->screen = NULL;
+ }
+ }
+
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ /* Deprecated from now on! */
+ BLI_freelistN(&screen->scene->transform_spaces);
+ screen->scene = NULL;
+ }
}
#ifdef USE_COLLECTION_COMPAT_28
enum {
- COLLECTION_DEPRECATED_VISIBLE = (1 << 0),
- COLLECTION_DEPRECATED_VIEWPORT = (1 << 0),
- COLLECTION_DEPRECATED_SELECTABLE = (1 << 1),
- COLLECTION_DEPRECATED_DISABLED = (1 << 2),
- COLLECTION_DEPRECATED_RENDER = (1 << 3),
+ COLLECTION_DEPRECATED_VISIBLE = (1 << 0),
+ COLLECTION_DEPRECATED_VIEWPORT = (1 << 0),
+ COLLECTION_DEPRECATED_SELECTABLE = (1 << 1),
+ COLLECTION_DEPRECATED_DISABLED = (1 << 2),
+ COLLECTION_DEPRECATED_RENDER = (1 << 3),
};
-static void do_version_view_layer_visibility(ViewLayer *view_layer)
+static void do_version_view_layer_visibility(ViewLayer* view_layer)
{
- /* Convert from deprecated VISIBLE flag to DISABLED */
- LayerCollection *lc;
- for (lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- if (lc->flag & COLLECTION_DEPRECATED_DISABLED) {
- lc->flag &= ~COLLECTION_DEPRECATED_DISABLED;
- }
-
- if ((lc->flag & COLLECTION_DEPRECATED_VISIBLE) == 0) {
- lc->flag |= COLLECTION_DEPRECATED_DISABLED;
- }
-
- lc->flag |= COLLECTION_DEPRECATED_VIEWPORT | COLLECTION_DEPRECATED_RENDER;
- }
+ /* Convert from deprecated VISIBLE flag to DISABLED */
+ LayerCollection* lc;
+ for (lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ if (lc->flag & COLLECTION_DEPRECATED_DISABLED) {
+ lc->flag &= ~COLLECTION_DEPRECATED_DISABLED;
+ }
+
+ if ((lc->flag & COLLECTION_DEPRECATED_VISIBLE) == 0) {
+ lc->flag |= COLLECTION_DEPRECATED_DISABLED;
+ }
+
+ lc->flag |= COLLECTION_DEPRECATED_VIEWPORT | COLLECTION_DEPRECATED_RENDER;
+ }
}
-static void do_version_layer_collection_pre(ViewLayer *view_layer,
- ListBase *lb,
- GSet *enabled_set,
- GSet *selectable_set)
+static void do_version_layer_collection_pre(ViewLayer* view_layer,
+ ListBase* lb,
+ GSet* enabled_set,
+ GSet* selectable_set)
{
- /* Convert from deprecated DISABLED to new layer collection and collection flags */
- for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
- if (lc->scene_collection) {
- if (!(lc->flag & COLLECTION_DEPRECATED_DISABLED)) {
- BLI_gset_insert(enabled_set, lc->scene_collection);
- }
- if (lc->flag & COLLECTION_DEPRECATED_SELECTABLE) {
- BLI_gset_insert(selectable_set, lc->scene_collection);
- }
- }
-
- do_version_layer_collection_pre(
- view_layer, &lc->layer_collections, enabled_set, selectable_set);
- }
+ /* Convert from deprecated DISABLED to new layer collection and collection flags */
+ for (LayerCollection* lc = lb->first; lc; lc = lc->next) {
+ if (lc->scene_collection) {
+ if (!(lc->flag & COLLECTION_DEPRECATED_DISABLED)) {
+ BLI_gset_insert(enabled_set, lc->scene_collection);
+ }
+ if (lc->flag & COLLECTION_DEPRECATED_SELECTABLE) {
+ BLI_gset_insert(selectable_set, lc->scene_collection);
+ }
+ }
+
+ do_version_layer_collection_pre(
+ view_layer, &lc->layer_collections, enabled_set, selectable_set);
+ }
}
-static void do_version_layer_collection_post(ViewLayer *view_layer,
- ListBase *lb,
- GSet *enabled_set,
- GSet *selectable_set,
- GHash *collection_map)
+static void do_version_layer_collection_post(ViewLayer* view_layer,
+ ListBase* lb,
+ GSet* enabled_set,
+ GSet* selectable_set,
+ GHash* collection_map)
{
- /* Apply layer collection exclude flags. */
- for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
- if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
- SceneCollection *sc = BLI_ghash_lookup(collection_map, lc->collection);
- const bool enabled = (sc && BLI_gset_haskey(enabled_set, sc));
- const bool selectable = (sc && BLI_gset_haskey(selectable_set, sc));
-
- if (!enabled) {
- lc->flag |= LAYER_COLLECTION_EXCLUDE;
- }
- if (enabled && !selectable) {
- lc->collection->flag |= COLLECTION_RESTRICT_SELECT;
- }
- }
-
- do_version_layer_collection_post(
- view_layer, &lc->layer_collections, enabled_set, selectable_set, collection_map);
- }
+ /* Apply layer collection exclude flags. */
+ for (LayerCollection* lc = lb->first; lc; lc = lc->next) {
+ if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ SceneCollection* sc = BLI_ghash_lookup(collection_map, lc->collection);
+ const bool enabled = (sc && BLI_gset_haskey(enabled_set, sc));
+ const bool selectable = (sc && BLI_gset_haskey(selectable_set, sc));
+
+ if (!enabled) {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ if (enabled && !selectable) {
+ lc->collection->flag |= COLLECTION_RESTRICT_SELECT;
+ }
+ }
+
+ do_version_layer_collection_post(
+ view_layer, &lc->layer_collections, enabled_set, selectable_set, collection_map);
+ }
}
static void do_version_scene_collection_convert(
- Main *bmain, ID *id, SceneCollection *sc, Collection *collection, GHash *collection_map)
+ Main* bmain, ID* id, SceneCollection* sc, Collection* collection, GHash* collection_map)
{
- if (collection_map) {
- BLI_ghash_insert(collection_map, collection, sc);
- }
-
- for (SceneCollection *nsc = sc->scene_collections.first; nsc;) {
- SceneCollection *nsc_next = nsc->next;
- Collection *ncollection = BKE_collection_add(bmain, collection, nsc->name);
- ncollection->id.lib = id->lib;
- do_version_scene_collection_convert(bmain, id, nsc, ncollection, collection_map);
- nsc = nsc_next;
- }
-
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- Object *ob = link->data;
- if (ob) {
- BKE_collection_object_add(bmain, collection, ob);
- id_us_min(&ob->id);
- }
- }
-
- BLI_freelistN(&sc->objects);
- MEM_freeN(sc);
+ if (collection_map) {
+ BLI_ghash_insert(collection_map, collection, sc);
+ }
+
+ for (SceneCollection* nsc = sc->scene_collections.first; nsc;) {
+ SceneCollection* nsc_next = nsc->next;
+ Collection* ncollection = BKE_collection_add(bmain, collection, nsc->name);
+ ncollection->id.lib = id->lib;
+ do_version_scene_collection_convert(bmain, id, nsc, ncollection, collection_map);
+ nsc = nsc_next;
+ }
+
+ for (LinkData* link = sc->objects.first; link; link = link->next) {
+ Object* ob = link->data;
+ if (ob) {
+ BKE_collection_object_add(bmain, collection, ob);
+ id_us_min(&ob->id);
+ }
+ }
+
+ BLI_freelistN(&sc->objects);
+ MEM_freeN(sc);
}
-static void do_version_group_collection_to_collection(Main *bmain, Collection *group)
+static void do_version_group_collection_to_collection(Main* bmain, Collection* group)
{
- /* Convert old 2.8 group collections to new unified collections. */
- if (group->collection) {
- do_version_scene_collection_convert(bmain, &group->id, group->collection, group, NULL);
- }
-
- group->collection = NULL;
- group->view_layer = NULL;
- id_fake_user_set(&group->id);
+ /* Convert old 2.8 group collections to new unified collections. */
+ if (group->collection) {
+ do_version_scene_collection_convert(bmain, &group->id, group->collection, group, NULL);
+ }
+
+ group->collection = NULL;
+ group->view_layer = NULL;
+ id_fake_user_set(&group->id);
}
-static void do_version_scene_collection_to_collection(Main *bmain, Scene *scene)
+static void do_version_scene_collection_to_collection(Main* bmain, Scene* scene)
{
- /* Convert old 2.8 scene collections to new unified collections. */
+ /* Convert old 2.8 scene collections to new unified collections. */
- /* Temporarily clear view layers so we don't do any layer collection syncing
- * and destroy old flags that we want to restore. */
- ListBase view_layers = scene->view_layers;
- BLI_listbase_clear(&scene->view_layers);
+ /* Temporarily clear view layers so we don't do any layer collection syncing
+ * and destroy old flags that we want to restore. */
+ ListBase view_layers = scene->view_layers;
+ BLI_listbase_clear(&scene->view_layers);
- if (!scene->master_collection) {
- scene->master_collection = BKE_collection_master_add();
- }
+ if (!scene->master_collection) {
+ scene->master_collection = BKE_collection_master_add();
+ }
- /* Convert scene collections. */
- GHash *collection_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- if (scene->collection) {
- do_version_scene_collection_convert(
- bmain, &scene->id, scene->collection, scene->master_collection, collection_map);
- scene->collection = NULL;
- }
+ /* Convert scene collections. */
+ GHash* collection_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ if (scene->collection) {
+ do_version_scene_collection_convert(
+ bmain, &scene->id, scene->collection, scene->master_collection, collection_map);
+ scene->collection = NULL;
+ }
- scene->view_layers = view_layers;
+ scene->view_layers = view_layers;
- /* Convert layer collections. */
- ViewLayer *view_layer;
- for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- GSet *enabled_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- GSet *selectable_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ /* Convert layer collections. */
+ ViewLayer* view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ GSet* enabled_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ GSet* selectable_set = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- do_version_layer_collection_pre(
- view_layer, &view_layer->layer_collections, enabled_set, selectable_set);
+ do_version_layer_collection_pre(
+ view_layer, &view_layer->layer_collections, enabled_set, selectable_set);
- BKE_layer_collection_sync(scene, view_layer);
+ BKE_layer_collection_sync(scene, view_layer);
- do_version_layer_collection_post(
- view_layer, &view_layer->layer_collections, enabled_set, selectable_set, collection_map);
+ do_version_layer_collection_post(
+ view_layer, &view_layer->layer_collections, enabled_set, selectable_set, collection_map);
- BLI_gset_free(enabled_set, NULL);
- BLI_gset_free(selectable_set, NULL);
+ BLI_gset_free(enabled_set, NULL);
+ BLI_gset_free(selectable_set, NULL);
- BKE_layer_collection_sync(scene, view_layer);
- }
+ BKE_layer_collection_sync(scene, view_layer);
+ }
- BLI_ghash_free(collection_map, NULL, NULL);
+ BLI_ghash_free(collection_map, NULL, NULL);
}
#endif
-static void do_version_layers_to_collections(Main *bmain, Scene *scene)
+static void do_version_layers_to_collections(Main* bmain, Scene* scene)
{
- /* Since we don't have access to FileData we check the (always valid) first
- * render layer instead. */
- if (!scene->master_collection) {
- scene->master_collection = BKE_collection_master_add();
- }
-
- if (scene->view_layers.first) {
- return;
- }
-
- /* Create collections from layers. */
- Collection *collection_master = scene->master_collection;
- Collection *collections[20] = {NULL};
-
- for (int layer = 0; layer < 20; layer++) {
- for (Base *base = scene->base.first; base; base = base->next) {
- if (base->lay & (1 << layer)) {
- /* Create collections when needed only. */
- if (collections[layer] == NULL) {
- char name[MAX_NAME];
-
- BLI_snprintf(
- name, sizeof(collection_master->id.name), DATA_("Collection %d"), layer + 1);
-
- Collection *collection = BKE_collection_add(bmain, collection_master, name);
- collection->id.lib = scene->id.lib;
- if (collection->id.lib != NULL) {
- collection->id.tag |= LIB_TAG_INDIRECT;
- }
- collections[layer] = collection;
-
- if (!(scene->lay & (1 << layer))) {
- collection->flag |= COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER;
- }
- }
-
- /* Note usually this would do slow collection syncing for view layers,
- * but since no view layers exists yet at this point it's fast. */
- BKE_collection_object_add(bmain, collections[layer], base->object);
- }
-
- if (base->flag & SELECT) {
- base->object->flag |= SELECT;
- }
- else {
- base->object->flag &= ~SELECT;
- }
- }
- }
-
- /* Handle legacy render layers. */
- bool have_override = false;
- const bool need_default_renderlayer = scene->r.layers.first == NULL;
-
- for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
- ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name);
-
- if (srl->layflag & SCE_LAY_DISABLE) {
- view_layer->flag &= ~VIEW_LAYER_RENDER;
- }
-
- if ((srl->layflag & SCE_LAY_FRS) == 0) {
- view_layer->flag &= ~VIEW_LAYER_FREESTYLE;
- }
-
- view_layer->layflag = srl->layflag;
- view_layer->passflag = srl->passflag;
- view_layer->pass_alpha_threshold = srl->pass_alpha_threshold;
- view_layer->samples = srl->samples;
- view_layer->mat_override = srl->mat_override;
-
- BKE_freestyle_config_free(&view_layer->freestyle_config, true);
- view_layer->freestyle_config = srl->freestyleConfig;
- view_layer->id_properties = srl->prop;
-
- /* Set exclusion and overrides. */
- for (int layer = 0; layer < 20; layer++) {
- Collection *collection = collections[layer];
- if (collection) {
- LayerCollection *lc = BKE_layer_collection_first_from_scene_collection(view_layer,
- collection);
-
- if (srl->lay_exclude & (1 << layer)) {
- /* Disable excluded layer. */
- have_override = true;
- lc->flag |= LAYER_COLLECTION_EXCLUDE;
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- nlc->flag |= LAYER_COLLECTION_EXCLUDE;
- }
- }
- else {
- if (srl->lay_zmask & (1 << layer)) {
- have_override = true;
- lc->flag |= LAYER_COLLECTION_HOLDOUT;
- }
-
- if ((srl->lay & (1 << layer)) == 0) {
- have_override = true;
- lc->flag |= LAYER_COLLECTION_INDIRECT_ONLY;
- }
- }
- }
- }
-
- /* for convenience set the same active object in all the layers */
- if (scene->basact) {
- view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
- }
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLE) && (base->object->flag & SELECT)) {
- base->flag |= BASE_SELECTED;
- }
- }
- }
-
- BLI_freelistN(&scene->r.layers);
-
- /* If render layers included overrides, or there are no render layers,
- * we also create a vanilla viewport layer. */
- if (have_override || need_default_renderlayer) {
- ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport");
-
- /* If we ported all the original render layers,
- * we don't need to make the viewport layer renderable. */
- if (!BLI_listbase_is_single(&scene->view_layers)) {
- view_layer->flag &= ~VIEW_LAYER_RENDER;
- }
-
- /* convert active base */
- if (scene->basact) {
- view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
- }
-
- /* convert selected bases */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLE) && (base->object->flag & SELECT)) {
- base->flag |= BASE_SELECTED;
- }
-
- /* keep lay around for forward compatibility (open those files in 2.79) */
- base->lay = base->object->lay;
- }
- }
-
- /* remove bases once and for all */
- for (Base *base = scene->base.first; base; base = base->next) {
- id_us_min(&base->object->id);
- }
-
- BLI_freelistN(&scene->base);
- scene->basact = NULL;
+ /* Since we don't have access to FileData we check the (always valid) first
+ * render layer instead. */
+ if (!scene->master_collection) {
+ scene->master_collection = BKE_collection_master_add();
+ }
+
+ if (scene->view_layers.first) {
+ return;
+ }
+
+ /* Create collections from layers. */
+ Collection* collection_master = scene->master_collection;
+ Collection* collections[20] = { NULL };
+
+ for (int layer = 0; layer < 20; layer++) {
+ for (Base* base = scene->base.first; base; base = base->next) {
+ if (base->lay & (1 << layer)) {
+ /* Create collections when needed only. */
+ if (collections[layer] == NULL) {
+ char name[MAX_NAME];
+
+ BLI_snprintf(
+ name, sizeof(collection_master->id.name), DATA_("Collection %d"), layer + 1);
+
+ Collection* collection = BKE_collection_add(bmain, collection_master, name);
+ collection->id.lib = scene->id.lib;
+ if (collection->id.lib != NULL) {
+ collection->id.tag |= LIB_TAG_INDIRECT;
+ }
+ collections[layer] = collection;
+
+ if (!(scene->lay & (1 << layer))) {
+ collection->flag |= COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER;
+ }
+ }
+
+ /* Note usually this would do slow collection syncing for view layers,
+ * but since no view layers exists yet at this point it's fast. */
+ BKE_collection_object_add(bmain, collections[layer], base->object);
+ }
+
+ if (base->flag & SELECT) {
+ base->object->flag |= SELECT;
+ }
+ else {
+ base->object->flag &= ~SELECT;
+ }
+ }
+ }
+
+ /* Handle legacy render layers. */
+ bool have_override = false;
+ const bool need_default_renderlayer = scene->r.layers.first == NULL;
+
+ for (SceneRenderLayer* srl = scene->r.layers.first; srl; srl = srl->next) {
+ ViewLayer* view_layer = BKE_view_layer_add(scene, srl->name);
+
+ if (srl->layflag & SCE_LAY_DISABLE) {
+ view_layer->flag &= ~VIEW_LAYER_RENDER;
+ }
+
+ if ((srl->layflag & SCE_LAY_FRS) == 0) {
+ view_layer->flag &= ~VIEW_LAYER_FREESTYLE;
+ }
+
+ view_layer->layflag = srl->layflag;
+ view_layer->passflag = srl->passflag;
+ view_layer->pass_alpha_threshold = srl->pass_alpha_threshold;
+ view_layer->samples = srl->samples;
+ view_layer->mat_override = srl->mat_override;
+
+ BKE_freestyle_config_free(&view_layer->freestyle_config, true);
+ view_layer->freestyle_config = srl->freestyleConfig;
+ view_layer->id_properties = srl->prop;
+
+ /* Set exclusion and overrides. */
+ for (int layer = 0; layer < 20; layer++) {
+ Collection* collection = collections[layer];
+ if (collection) {
+ LayerCollection* lc = BKE_layer_collection_first_from_scene_collection(view_layer,
+ collection);
+
+ if (srl->lay_exclude & (1 << layer)) {
+ /* Disable excluded layer. */
+ have_override = true;
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ for (LayerCollection* nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ }
+ else {
+ if (srl->lay_zmask & (1 << layer)) {
+ have_override = true;
+ lc->flag |= LAYER_COLLECTION_HOLDOUT;
+ }
+
+ if ((srl->lay & (1 << layer)) == 0) {
+ have_override = true;
+ lc->flag |= LAYER_COLLECTION_INDIRECT_ONLY;
+ }
+ }
+ }
+ }
+
+ /* for convenience set the same active object in all the layers */
+ if (scene->basact) {
+ view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
+ }
+
+ for (Base* base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLE) && (base->object->flag & SELECT)) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+ }
+
+ BLI_freelistN(&scene->r.layers);
+
+ /* If render layers included overrides, or there are no render layers,
+ * we also create a vanilla viewport layer. */
+ if (have_override || need_default_renderlayer) {
+ ViewLayer* view_layer = BKE_view_layer_add(scene, "Viewport");
+
+ /* If we ported all the original render layers,
+ * we don't need to make the viewport layer renderable. */
+ if (!BLI_listbase_is_single(&scene->view_layers)) {
+ view_layer->flag &= ~VIEW_LAYER_RENDER;
+ }
+
+ /* convert active base */
+ if (scene->basact) {
+ view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
+ }
+
+ /* convert selected bases */
+ for (Base* base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLE) && (base->object->flag & SELECT)) {
+ base->flag |= BASE_SELECTED;
+ }
+
+ /* keep lay around for forward compatibility (open those files in 2.79) */
+ base->lay = base->object->lay;
+ }
+ }
+
+ /* remove bases once and for all */
+ for (Base* base = scene->base.first; base; base = base->next) {
+ id_us_min(&base->object->id);
+ }
+
+ BLI_freelistN(&scene->base);
+ scene->basact = NULL;
}
-static void do_version_collection_propagate_lib_to_children(Collection *collection)
+static void do_version_collection_propagate_lib_to_children(Collection* collection)
{
- if (collection->id.lib != NULL) {
- for (CollectionChild *collection_child = collection->children.first; collection_child != NULL;
- collection_child = collection_child->next) {
- if (collection_child->collection->id.lib == NULL) {
- collection_child->collection->id.lib = collection->id.lib;
- }
- do_version_collection_propagate_lib_to_children(collection_child->collection);
- }
- }
+ if (collection->id.lib != NULL) {
+ for (CollectionChild* collection_child = collection->children.first; collection_child != NULL;
+ collection_child = collection_child->next) {
+ if (collection_child->collection->id.lib == NULL) {
+ collection_child->collection->id.lib = collection->id.lib;
+ }
+ do_version_collection_propagate_lib_to_children(collection_child->collection);
+ }
+ }
}
/** convert old annotations colors */
-static void do_versions_fix_annotations(bGPdata *gpd)
+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) {
- /* unlock/unhide layer */
- gpl->flag &= ~GP_LAYER_LOCKED;
- gpl->flag &= ~GP_LAYER_HIDE;
- /* set opacity to 1 */
- gpl->opacity = 1.0f;
- /* 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) {
- if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
- /* copy color settings */
- copy_v4_v4(gpl->color, palcolor->color);
- }
- }
- }
- }
- }
- }
+ for (const bGPDpalette* palette = gpd->palettes.first; palette; palette = palette->next) {
+ for (bGPDpalettecolor* palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) {
+ /* fix layers */
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ /* unlock/unhide layer */
+ gpl->flag &= ~GP_LAYER_LOCKED;
+ gpl->flag &= ~GP_LAYER_HIDE;
+ /* set opacity to 1 */
+ gpl->opacity = 1.0f;
+ /* disable tint */
+ gpl->tintcolor[3] = 0.0f;
+
+ 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);
+ }
+ }
+ }
+ }
+ }
+ }
}
-static void do_versions_remove_region(ListBase *regionbase, ARegion *ar)
+static void do_versions_remove_region(ListBase* regionbase, ARegion* ar)
{
- BLI_freelinkN(regionbase, ar);
+ BLI_freelinkN(regionbase, ar);
}
-static void do_versions_remove_regions_by_type(ListBase *regionbase, int regiontype)
+static void do_versions_remove_regions_by_type(ListBase* regionbase, int regiontype)
{
- ARegion *ar, *ar_next;
- for (ar = regionbase->first; ar; ar = ar_next) {
- ar_next = ar->next;
- if (ar->regiontype == regiontype) {
- do_versions_remove_region(regionbase, ar);
- }
- }
+ ARegion* ar, * ar_next;
+ for (ar = regionbase->first; ar; ar = ar_next) {
+ ar_next = ar->next;
+ if (ar->regiontype == regiontype) {
+ do_versions_remove_region(regionbase, ar);
+ }
+ }
}
-static ARegion *do_versions_find_region_or_null(ListBase *regionbase, int regiontype)
+static ARegion* do_versions_find_region_or_null(ListBase* regionbase, int regiontype)
{
- for (ARegion *ar = regionbase->first; ar; ar = ar->next) {
- if (ar->regiontype == regiontype) {
- return ar;
- }
- }
- return NULL;
+ for (ARegion* ar = regionbase->first; ar; ar = ar->next) {
+ if (ar->regiontype == regiontype) {
+ return ar;
+ }
+ }
+ return NULL;
}
-static ARegion *do_versions_find_region(ListBase *regionbase, int regiontype)
+static ARegion* do_versions_find_region(ListBase* regionbase, int regiontype)
{
- ARegion *ar = do_versions_find_region_or_null(regionbase, regiontype);
- if (ar == NULL) {
- BLI_assert(!"Did not find expected region in versioning");
- }
- return ar;
+ ARegion* ar = do_versions_find_region_or_null(regionbase, regiontype);
+ if (ar == NULL) {
+ BLI_assert(!"Did not find expected region in versioning");
+ }
+ return ar;
}
-static ARegion *do_versions_add_region(int regiontype, const char *name)
+static ARegion* do_versions_add_region(int regiontype, const char* name)
{
- ARegion *ar = MEM_callocN(sizeof(ARegion), name);
- ar->regiontype = regiontype;
- return ar;
+ ARegion* ar = MEM_callocN(sizeof(ARegion), name);
+ ar->regiontype = regiontype;
+ return ar;
}
-static void do_versions_area_ensure_tool_region(Main *bmain,
- const short space_type,
- const short region_flag)
+static void do_versions_area_ensure_tool_region(Main* bmain,
+ const short space_type,
+ const short region_flag)
{
- 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) {
- if (sl->spacetype == space_type) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
- if (!ar) {
- ARegion *header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- ar = do_versions_add_region(RGN_TYPE_TOOLS, "tools region");
- BLI_insertlinkafter(regionbase, header, ar);
- ar->alignment = RGN_ALIGN_LEFT;
- ar->flag = region_flag;
- }
- }
- }
- }
- }
+ 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) {
+ if (sl->spacetype == space_type) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion* ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
+ if (!ar) {
+ ARegion* header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ ar = do_versions_add_region(RGN_TYPE_TOOLS, "tools region");
+ BLI_insertlinkafter(regionbase, header, ar);
+ ar->alignment = RGN_ALIGN_LEFT;
+ ar->flag = region_flag;
+ }
+ }
+ }
+ }
+ }
}
-static void do_version_bones_split_bbone_scale(ListBase *lb)
+static void do_version_bones_split_bbone_scale(ListBase* lb)
{
- for (Bone *bone = lb->first; bone; bone = bone->next) {
- bone->scale_in_y = bone->scale_in_x;
- bone->scale_out_y = bone->scale_out_x;
+ for (Bone* bone = lb->first; bone; bone = bone->next) {
+ bone->scale_in_y = bone->scale_in_x;
+ bone->scale_out_y = bone->scale_out_x;
- do_version_bones_split_bbone_scale(&bone->childbase);
- }
+ do_version_bones_split_bbone_scale(&bone->childbase);
+ }
}
-static void do_version_bones_inherit_scale(ListBase *lb)
+static void do_version_bones_inherit_scale(ListBase* lb)
{
- for (Bone *bone = lb->first; bone; bone = bone->next) {
- if (bone->flag & BONE_NO_SCALE) {
- bone->inherit_scale_mode = BONE_INHERIT_SCALE_NONE_LEGACY;
- bone->flag &= ~BONE_NO_SCALE;
- }
-
- do_version_bones_inherit_scale(&bone->childbase);
- }
+ for (Bone* bone = lb->first; bone; bone = bone->next) {
+ if (bone->flag & BONE_NO_SCALE) {
+ bone->inherit_scale_mode = BONE_INHERIT_SCALE_NONE_LEGACY;
+ bone->flag &= ~BONE_NO_SCALE;
+ }
+
+ do_version_bones_inherit_scale(&bone->childbase);
+ }
}
-static bool replace_bbone_scale_rnapath(char **p_old_path)
+static bool replace_bbone_scale_rnapath(char** p_old_path)
{
- char *old_path = *p_old_path;
+ char* old_path = *p_old_path;
- if (old_path == NULL) {
- return false;
- }
+ if (old_path == NULL) {
+ return false;
+ }
- if (BLI_str_endswith(old_path, "bbone_scalein") ||
- BLI_str_endswith(old_path, "bbone_scaleout")) {
- *p_old_path = BLI_strdupcat(old_path, "x");
+ if (BLI_str_endswith(old_path, "bbone_scalein") ||
+ BLI_str_endswith(old_path, "bbone_scaleout")) {
+ *p_old_path = BLI_strdupcat(old_path, "x");
- MEM_freeN(old_path);
- return true;
- }
+ MEM_freeN(old_path);
+ return true;
+ }
- return false;
+ return false;
}
-static void do_version_bbone_scale_fcurve_fix(ListBase *curves, FCurve *fcu)
+static void do_version_bbone_scale_fcurve_fix(ListBase* curves, FCurve* fcu)
{
- /* Update driver variable paths. */
- if (fcu->driver) {
- LISTBASE_FOREACH (DriverVar *, dvar, &fcu->driver->variables) {
- DRIVER_TARGETS_LOOPER_BEGIN (dvar) {
- replace_bbone_scale_rnapath(&dtar->rna_path);
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
-
- /* Update F-Curve's path. */
- if (replace_bbone_scale_rnapath(&fcu->rna_path)) {
- /* If matched, duplicate the curve and tweak name. */
- FCurve *second = copy_fcurve(fcu);
-
- second->rna_path[strlen(second->rna_path) - 1] = 'y';
-
- BLI_insertlinkafter(curves, fcu, second);
-
- /* Add to the curve group. */
- second->grp = fcu->grp;
-
- if (fcu->grp != NULL && fcu->grp->channels.last == fcu) {
- fcu->grp->channels.last = second;
- }
- }
+ /* Update driver variable paths. */
+ if (fcu->driver) {
+ LISTBASE_FOREACH(DriverVar*, dvar, &fcu->driver->variables) {
+ DRIVER_TARGETS_LOOPER_BEGIN(dvar) {
+ replace_bbone_scale_rnapath(&dtar->rna_path);
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+ }
+
+ /* Update F-Curve's path. */
+ if (replace_bbone_scale_rnapath(&fcu->rna_path)) {
+ /* If matched, duplicate the curve and tweak name. */
+ FCurve* second = copy_fcurve(fcu);
+
+ second->rna_path[strlen(second->rna_path) - 1] = 'y';
+
+ BLI_insertlinkafter(curves, fcu, second);
+
+ /* Add to the curve group. */
+ second->grp = fcu->grp;
+
+ if (fcu->grp != NULL && fcu->grp->channels.last == fcu) {
+ fcu->grp->channels.last = second;
+ }
+ }
}
-static void do_version_bbone_scale_animdata_cb(ID *UNUSED(id),
- AnimData *adt,
- void *UNUSED(wrapper_data))
+static void do_version_bbone_scale_animdata_cb(ID* UNUSED(id),
+ AnimData* adt,
+ void* UNUSED(wrapper_data))
{
- LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &adt->drivers) {
- do_version_bbone_scale_fcurve_fix(&adt->drivers, fcu);
- }
+ LISTBASE_FOREACH_MUTABLE(FCurve*, fcu, &adt->drivers) {
+ do_version_bbone_scale_fcurve_fix(&adt->drivers, fcu);
+ }
}
-static void do_version_constraints_maintain_volume_mode_uniform(ListBase *lb)
+static void do_version_constraints_maintain_volume_mode_uniform(ListBase* lb)
{
- for (bConstraint *con = lb->first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_SAMEVOL) {
- bSameVolumeConstraint *data = (bSameVolumeConstraint *)con->data;
- data->mode = SAMEVOL_UNIFORM;
- }
- }
+ for (bConstraint* con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SAMEVOL) {
+ bSameVolumeConstraint* data = (bSameVolumeConstraint*)con->data;
+ data->mode = SAMEVOL_UNIFORM;
+ }
+ }
}
-static void do_version_constraints_copy_scale_power(ListBase *lb)
+static void do_version_constraints_copy_scale_power(ListBase* lb)
{
- for (bConstraint *con = lb->first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_SIZELIKE) {
- bSizeLikeConstraint *data = (bSizeLikeConstraint *)con->data;
- data->power = 1.0f;
- }
- }
+ for (bConstraint* con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SIZELIKE) {
+ bSizeLikeConstraint* data = (bSizeLikeConstraint*)con->data;
+ data->power = 1.0f;
+ }
+ }
}
-static void do_version_constraints_copy_rotation_mix_mode(ListBase *lb)
+static void do_version_constraints_copy_rotation_mix_mode(ListBase* lb)
{
- for (bConstraint *con = lb->first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
- bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
- data->mix_mode = (data->flag & ROTLIKE_OFFSET) ? ROTLIKE_MIX_OFFSET : ROTLIKE_MIX_REPLACE;
- data->flag &= ~ROTLIKE_OFFSET;
- }
- }
+ for (bConstraint* con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
+ bRotateLikeConstraint* data = (bRotateLikeConstraint*)con->data;
+ data->mix_mode = (data->flag & ROTLIKE_OFFSET) ? ROTLIKE_MIX_OFFSET : ROTLIKE_MIX_REPLACE;
+ data->flag &= ~ROTLIKE_OFFSET;
+ }
+ }
}
-static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase)
+static void do_versions_seq_alloc_transform_and_crop(ListBase* seqbase)
{
- for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) {
- if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD) == 0) {
- if (seq->strip->transform == NULL) {
- seq->strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform");
- }
-
- if (seq->strip->crop == NULL) {
- seq->strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop");
- }
-
- if (seq->seqbase.first != NULL) {
- do_versions_seq_alloc_transform_and_crop(&seq->seqbase);
- }
- }
- }
+ for (Sequence* seq = seqbase->first; seq != NULL; seq = seq->next) {
+ if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD) == 0) {
+ if (seq->strip->transform == NULL) {
+ seq->strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform");
+ }
+
+ if (seq->strip->crop == NULL) {
+ seq->strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop");
+ }
+
+ if (seq->seqbase.first != NULL) {
+ do_versions_seq_alloc_transform_and_crop(&seq->seqbase);
+ }
+ }
+ }
}
/* Return true if there is something to convert. */
-static void do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, char blend_method)
+static void do_versions_material_convert_legacy_blend_mode(bNodeTree* ntree, char blend_method)
{
- bool need_update = false;
+ bool need_update = false;
- /* Iterate backwards from end so we don't encounter newly added links. */
- bNodeLink *prevlink;
- for (bNodeLink *link = ntree->links.last; link; link = prevlink) {
- prevlink = link->prev;
+ /* Iterate backwards from end so we don't encounter newly added links. */
+ bNodeLink* prevlink;
+ for (bNodeLink* link = ntree->links.last; link; link = prevlink) {
+ prevlink = link->prev;
- /* Detect link to replace. */
- bNode *fromnode = link->fromnode;
- bNodeSocket *fromsock = link->fromsock;
- bNode *tonode = link->tonode;
- bNodeSocket *tosock = link->tosock;
+ /* Detect link to replace. */
+ bNode* fromnode = link->fromnode;
+ bNodeSocket* fromsock = link->fromsock;
+ bNode* tonode = link->tonode;
+ bNodeSocket* tosock = link->tosock;
- if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && STREQ(tosock->identifier, "Surface"))) {
- continue;
- }
+ if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && STREQ(tosock->identifier, "Surface"))) {
+ continue;
+ }
- /* Only do outputs that are enabled for EEVEE */
- if (!ELEM(tonode->custom1, SHD_OUTPUT_ALL, SHD_OUTPUT_EEVEE)) {
- continue;
- }
+ /* Only do outputs that are enabled for EEVEE */
+ if (!ELEM(tonode->custom1, SHD_OUTPUT_ALL, SHD_OUTPUT_EEVEE)) {
+ continue;
+ }
- if (blend_method == 1 /* MA_BM_ADD */) {
- nodeRemLink(ntree, link);
+ if (blend_method == 1 /* MA_BM_ADD */) {
+ nodeRemLink(ntree, link);
- bNode *add_node = nodeAddStaticNode(NULL, ntree, SH_NODE_ADD_SHADER);
- add_node->locx = 0.5f * (fromnode->locx + tonode->locx);
- add_node->locy = 0.5f * (fromnode->locy + tonode->locy);
+ bNode* add_node = nodeAddStaticNode(NULL, ntree, SH_NODE_ADD_SHADER);
+ add_node->locx = 0.5f * (fromnode->locx + tonode->locx);
+ add_node->locy = 0.5f * (fromnode->locy + tonode->locy);
- bNodeSocket *shader1_socket = add_node->inputs.first;
- bNodeSocket *shader2_socket = add_node->inputs.last;
- bNodeSocket *add_socket = nodeFindSocket(add_node, SOCK_OUT, "Shader");
+ bNodeSocket* shader1_socket = add_node->inputs.first;
+ bNodeSocket* shader2_socket = add_node->inputs.last;
+ bNodeSocket* add_socket = nodeFindSocket(add_node, SOCK_OUT, "Shader");
- bNode *transp_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT);
- transp_node->locx = add_node->locx;
- transp_node->locy = add_node->locy - 110.0f;
+ bNode* transp_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT);
+ transp_node->locx = add_node->locx;
+ transp_node->locy = add_node->locy - 110.0f;
- bNodeSocket *transp_socket = nodeFindSocket(transp_node, SOCK_OUT, "BSDF");
+ bNodeSocket* transp_socket = nodeFindSocket(transp_node, SOCK_OUT, "BSDF");
- /* Link to input and material output node. */
- nodeAddLink(ntree, fromnode, fromsock, add_node, shader1_socket);
- nodeAddLink(ntree, transp_node, transp_socket, add_node, shader2_socket);
- nodeAddLink(ntree, add_node, add_socket, tonode, tosock);
+ /* Link to input and material output node. */
+ nodeAddLink(ntree, fromnode, fromsock, add_node, shader1_socket);
+ nodeAddLink(ntree, transp_node, transp_socket, add_node, shader2_socket);
+ nodeAddLink(ntree, add_node, add_socket, tonode, tosock);
- need_update = true;
- }
- else if (blend_method == 2 /* MA_BM_MULTIPLY */) {
- nodeRemLink(ntree, link);
+ need_update = true;
+ }
+ else if (blend_method == 2 /* MA_BM_MULTIPLY */) {
+ nodeRemLink(ntree, link);
- bNode *transp_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT);
+ bNode* transp_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT);
- bNodeSocket *color_socket = nodeFindSocket(transp_node, SOCK_IN, "Color");
- bNodeSocket *transp_socket = nodeFindSocket(transp_node, SOCK_OUT, "BSDF");
+ bNodeSocket* color_socket = nodeFindSocket(transp_node, SOCK_IN, "Color");
+ bNodeSocket* transp_socket = nodeFindSocket(transp_node, SOCK_OUT, "BSDF");
- /* If incomming link is from a closure socket, we need to convert it. */
- if (fromsock->type == SOCK_SHADER) {
- transp_node->locx = 0.33f * fromnode->locx + 0.66f * tonode->locx;
- transp_node->locy = 0.33f * fromnode->locy + 0.66f * tonode->locy;
+ /* If incomming link is from a closure socket, we need to convert it. */
+ if (fromsock->type == SOCK_SHADER) {
+ transp_node->locx = 0.33f * fromnode->locx + 0.66f * tonode->locx;
+ transp_node->locy = 0.33f * fromnode->locy + 0.66f * tonode->locy;
- bNode *shtorgb_node = nodeAddStaticNode(NULL, ntree, SH_NODE_SHADERTORGB);
- shtorgb_node->locx = 0.66f * fromnode->locx + 0.33f * tonode->locx;
- shtorgb_node->locy = 0.66f * fromnode->locy + 0.33f * tonode->locy;
+ bNode* shtorgb_node = nodeAddStaticNode(NULL, ntree, SH_NODE_SHADERTORGB);
+ shtorgb_node->locx = 0.66f * fromnode->locx + 0.33f * tonode->locx;
+ shtorgb_node->locy = 0.66f * fromnode->locy + 0.33f * tonode->locy;
- bNodeSocket *shader_socket = nodeFindSocket(shtorgb_node, SOCK_IN, "Shader");
- bNodeSocket *rgba_socket = nodeFindSocket(shtorgb_node, SOCK_OUT, "Color");
+ bNodeSocket* shader_socket = nodeFindSocket(shtorgb_node, SOCK_IN, "Shader");
+ bNodeSocket* rgba_socket = nodeFindSocket(shtorgb_node, SOCK_OUT, "Color");
- nodeAddLink(ntree, fromnode, fromsock, shtorgb_node, shader_socket);
- nodeAddLink(ntree, shtorgb_node, rgba_socket, transp_node, color_socket);
- }
- else {
- transp_node->locx = 0.5f * (fromnode->locx + tonode->locx);
- transp_node->locy = 0.5f * (fromnode->locy + tonode->locy);
+ nodeAddLink(ntree, fromnode, fromsock, shtorgb_node, shader_socket);
+ nodeAddLink(ntree, shtorgb_node, rgba_socket, transp_node, color_socket);
+ }
+ else {
+ transp_node->locx = 0.5f * (fromnode->locx + tonode->locx);
+ transp_node->locy = 0.5f * (fromnode->locy + tonode->locy);
- nodeAddLink(ntree, fromnode, fromsock, transp_node, color_socket);
- }
+ nodeAddLink(ntree, fromnode, fromsock, transp_node, color_socket);
+ }
- /* Link to input and material output node. */
- nodeAddLink(ntree, transp_node, transp_socket, tonode, tosock);
+ /* Link to input and material output node. */
+ nodeAddLink(ntree, transp_node, transp_socket, tonode, tosock);
- need_update = true;
- }
- }
+ need_update = true;
+ }
+ }
- if (need_update) {
- ntreeUpdateTree(NULL, ntree);
- }
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
}
-static void do_versions_local_collection_bits_set(LayerCollection *layer_collection)
+static void do_versions_local_collection_bits_set(LayerCollection* layer_collection)
{
- layer_collection->local_collections_bits = ~(0);
- LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
- do_versions_local_collection_bits_set(child);
- }
+ layer_collection->local_collections_bits = ~(0);
+ LISTBASE_FOREACH(LayerCollection*, child, &layer_collection->layer_collections) {
+ do_versions_local_collection_bits_set(child);
+ }
}
-static void do_version_curvemapping_flag_extend_extrapolate(CurveMapping *cumap)
+static void do_version_curvemapping_flag_extend_extrapolate(CurveMapping* cumap)
{
#define CUMA_EXTEND_EXTRAPOLATE_OLD 1
- for (int curve_map_index = 0; curve_map_index < 4; curve_map_index++) {
- CurveMap *cuma = &cumap->cm[curve_map_index];
- if (cuma->flag & CUMA_EXTEND_EXTRAPOLATE_OLD) {
- cumap->flag |= CUMA_EXTEND_EXTRAPOLATE;
- return;
- }
- }
+ for (int curve_map_index = 0; curve_map_index < 4; curve_map_index++) {
+ CurveMap* cuma = &cumap->cm[curve_map_index];
+ if (cuma->flag & CUMA_EXTEND_EXTRAPOLATE_OLD) {
+ cumap->flag |= CUMA_EXTEND_EXTRAPOLATE;
+ return;
+ }
+ }
#undef CUMA_EXTEND_EXTRAPOLATE_OLD
}
/* Util version to walk over all CurveMappings in the given `bmain` */
-static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMapping *cumap))
+static void do_version_curvemapping_walker(Main* bmain, void (*callback)(CurveMapping* cumap))
{
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- callback(&scene->r.mblur_shutter_curve);
-
- if (scene->view_settings.curve_mapping) {
- callback(scene->view_settings.curve_mapping);
- }
-
- if (scene->ed != NULL) {
- LISTBASE_FOREACH (Sequence *, seq, &scene->ed->seqbase) {
- LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) {
- const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
-
- if (smti) {
- if (smd->type == seqModifierType_Curves) {
- CurvesModifierData *cmd = (CurvesModifierData *)smd;
- callback(&cmd->curve_mapping);
- }
- else if (smd->type == seqModifierType_HueCorrect) {
- HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd;
- callback(&hcmd->curve_mapping);
- }
- }
- }
- }
- }
-
- // toolsettings
- ToolSettings *ts = scene->toolsettings;
- if (ts->vpaint) {
- callback(ts->vpaint->paint.cavity_curve);
- }
- if (ts->wpaint) {
- callback(ts->wpaint->paint.cavity_curve);
- }
- if (ts->sculpt) {
- callback(ts->sculpt->paint.cavity_curve);
- }
- if (ts->uvsculpt) {
- callback(ts->uvsculpt->paint.cavity_curve);
- }
- if (ts->gp_paint) {
- callback(ts->gp_paint->paint.cavity_curve);
- }
- if (ts->gp_interpolate.custom_ipo) {
- callback(ts->gp_interpolate.custom_ipo);
- }
- if (ts->gp_sculpt.cur_falloff) {
- callback(ts->gp_sculpt.cur_falloff);
- }
- if (ts->gp_sculpt.cur_primitive) {
- callback(ts->gp_sculpt.cur_primitive);
- }
- callback(ts->imapaint.paint.cavity_curve);
- }
-
- FOREACH_NODETREE_BEGIN (bmain, node_tree, id) {
- LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) {
- if (ELEM(node->type,
- SH_NODE_CURVE_VEC,
- SH_NODE_CURVE_RGB,
- CMP_NODE_CURVE_VEC,
- CMP_NODE_CURVE_RGB,
- CMP_NODE_TIME,
- CMP_NODE_HUECORRECT,
- TEX_NODE_CURVE_RGB,
- TEX_NODE_CURVE_TIME)) {
- callback((CurveMapping *)node->storage);
- }
- }
- }
- FOREACH_NODETREE_END;
-
- LISTBASE_FOREACH (Light *, light, &bmain->lights) {
- if (light->curfalloff) {
- callback(light->curfalloff);
- }
- }
-
- LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
- if (brush->curve) {
- callback(brush->curve);
- }
- if (brush->gpencil_settings) {
- if (brush->gpencil_settings->curve_sensitivity) {
- callback(brush->gpencil_settings->curve_sensitivity);
- }
- if (brush->gpencil_settings->curve_strength) {
- callback(brush->gpencil_settings->curve_strength);
- }
- if (brush->gpencil_settings->curve_jitter) {
- callback(brush->gpencil_settings->curve_jitter);
- }
- }
- }
-
- LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
- if (part->clumpcurve) {
- callback(part->clumpcurve);
- }
- if (part->roughcurve) {
- callback(part->roughcurve);
- }
- if (part->twistcurve) {
- callback(part->twistcurve);
- }
- }
-
- /* Object */
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- /* Object modifiers */
- LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
- if (md->type == eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData *)md;
-
- if (hmd->curfalloff) {
- callback(hmd->curfalloff);
- }
- }
- else if (md->type == eModifierType_Warp) {
- WarpModifierData *tmd = (WarpModifierData *)md;
- if (tmd->curfalloff) {
- callback(tmd->curfalloff);
- }
- }
- else if (md->type == eModifierType_WeightVGEdit) {
- WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md;
-
- if (wmd->cmap_curve) {
- callback(wmd->cmap_curve);
- }
- }
- }
- /* Grease pencil modifiers */
- LISTBASE_FOREACH (ModifierData *, md, &ob->greasepencil_modifiers) {
- if (md->type == eGpencilModifierType_Thick) {
- ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md;
-
- if (gpmd->curve_thickness) {
- callback(gpmd->curve_thickness);
- }
- }
- else if (md->type == eGpencilModifierType_Hook) {
- HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
-
- if (gpmd->curfalloff) {
- callback(gpmd->curfalloff);
- }
- }
- }
- }
-
- /* Free Style */
- LISTBASE_FOREACH (struct FreestyleLineStyle *, linestyle, &bmain->linestyles) {
- LISTBASE_FOREACH (LineStyleModifier *, m, &linestyle->alpha_modifiers) {
- switch (m->type) {
- case LS_MODIFIER_ALONG_STROKE:
- callback(((LineStyleAlphaModifier_AlongStroke *)m)->curve);
- break;
- case LS_MODIFIER_DISTANCE_FROM_CAMERA:
- callback(((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve);
- break;
- case LS_MODIFIER_DISTANCE_FROM_OBJECT:
- callback(((LineStyleAlphaModifier_DistanceFromObject *)m)->curve);
- break;
- case LS_MODIFIER_MATERIAL:
- callback(((LineStyleAlphaModifier_Material *)m)->curve);
- break;
- case LS_MODIFIER_TANGENT:
- callback(((LineStyleAlphaModifier_Tangent *)m)->curve);
- break;
- case LS_MODIFIER_NOISE:
- callback(((LineStyleAlphaModifier_Noise *)m)->curve);
- break;
- case LS_MODIFIER_CREASE_ANGLE:
- callback(((LineStyleAlphaModifier_CreaseAngle *)m)->curve);
- break;
- case LS_MODIFIER_CURVATURE_3D:
- callback(((LineStyleAlphaModifier_Curvature_3D *)m)->curve);
- break;
- }
- }
-
- LISTBASE_FOREACH (LineStyleModifier *, m, &linestyle->thickness_modifiers) {
- switch (m->type) {
- case LS_MODIFIER_ALONG_STROKE:
- callback(((LineStyleThicknessModifier_AlongStroke *)m)->curve);
- break;
- case LS_MODIFIER_DISTANCE_FROM_CAMERA:
- callback(((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve);
- break;
- case LS_MODIFIER_DISTANCE_FROM_OBJECT:
- callback(((LineStyleThicknessModifier_DistanceFromObject *)m)->curve);
- break;
- case LS_MODIFIER_MATERIAL:
- callback(((LineStyleThicknessModifier_Material *)m)->curve);
- break;
- case LS_MODIFIER_TANGENT:
- callback(((LineStyleThicknessModifier_Tangent *)m)->curve);
- break;
- case LS_MODIFIER_CREASE_ANGLE:
- callback(((LineStyleThicknessModifier_CreaseAngle *)m)->curve);
- break;
- case LS_MODIFIER_CURVATURE_3D:
- callback(((LineStyleThicknessModifier_Curvature_3D *)m)->curve);
- break;
- }
- }
- }
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ callback(&scene->r.mblur_shutter_curve);
+
+ if (scene->view_settings.curve_mapping) {
+ callback(scene->view_settings.curve_mapping);
+ }
+
+ if (scene->ed != NULL) {
+ LISTBASE_FOREACH(Sequence*, seq, &scene->ed->seqbase) {
+ LISTBASE_FOREACH(SequenceModifierData*, smd, &seq->modifiers) {
+ const SequenceModifierTypeInfo* smti = BKE_sequence_modifier_type_info_get(smd->type);
+
+ if (smti) {
+ if (smd->type == seqModifierType_Curves) {
+ CurvesModifierData* cmd = (CurvesModifierData*)smd;
+ callback(&cmd->curve_mapping);
+ }
+ else if (smd->type == seqModifierType_HueCorrect) {
+ HueCorrectModifierData* hcmd = (HueCorrectModifierData*)smd;
+ callback(&hcmd->curve_mapping);
+ }
+ }
+ }
+ }
+ }
+
+ // toolsettings
+ ToolSettings* ts = scene->toolsettings;
+ if (ts->vpaint) {
+ callback(ts->vpaint->paint.cavity_curve);
+ }
+ if (ts->wpaint) {
+ callback(ts->wpaint->paint.cavity_curve);
+ }
+ if (ts->sculpt) {
+ callback(ts->sculpt->paint.cavity_curve);
+ }
+ if (ts->uvsculpt) {
+ callback(ts->uvsculpt->paint.cavity_curve);
+ }
+ if (ts->gp_paint) {
+ callback(ts->gp_paint->paint.cavity_curve);
+ }
+ if (ts->gp_interpolate.custom_ipo) {
+ callback(ts->gp_interpolate.custom_ipo);
+ }
+ if (ts->gp_sculpt.cur_falloff) {
+ callback(ts->gp_sculpt.cur_falloff);
+ }
+ if (ts->gp_sculpt.cur_primitive) {
+ callback(ts->gp_sculpt.cur_primitive);
+ }
+ callback(ts->imapaint.paint.cavity_curve);
+ }
+
+ FOREACH_NODETREE_BEGIN(bmain, node_tree, id) {
+ LISTBASE_FOREACH(bNode*, node, &node_tree->nodes) {
+ if (ELEM(node->type,
+ SH_NODE_CURVE_VEC,
+ SH_NODE_CURVE_RGB,
+ CMP_NODE_CURVE_VEC,
+ CMP_NODE_CURVE_RGB,
+ CMP_NODE_TIME,
+ CMP_NODE_HUECORRECT,
+ TEX_NODE_CURVE_RGB,
+ TEX_NODE_CURVE_TIME)) {
+ callback((CurveMapping*)node->storage);
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ LISTBASE_FOREACH(Light*, light, &bmain->lights) {
+ if (light->curfalloff) {
+ callback(light->curfalloff);
+ }
+ }
+
+ LISTBASE_FOREACH(Brush*, brush, &bmain->brushes) {
+ if (brush->curve) {
+ callback(brush->curve);
+ }
+ if (brush->gpencil_settings) {
+ if (brush->gpencil_settings->curve_sensitivity) {
+ callback(brush->gpencil_settings->curve_sensitivity);
+ }
+ if (brush->gpencil_settings->curve_strength) {
+ callback(brush->gpencil_settings->curve_strength);
+ }
+ if (brush->gpencil_settings->curve_jitter) {
+ callback(brush->gpencil_settings->curve_jitter);
+ }
+ }
+ }
+
+ LISTBASE_FOREACH(ParticleSettings*, part, &bmain->particles) {
+ if (part->clumpcurve) {
+ callback(part->clumpcurve);
+ }
+ if (part->roughcurve) {
+ callback(part->roughcurve);
+ }
+ if (part->twistcurve) {
+ callback(part->twistcurve);
+ }
+ }
+
+ /* Object */
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ /* Object modifiers */
+ LISTBASE_FOREACH(ModifierData*, md, &ob->modifiers) {
+ if (md->type == eModifierType_Hook) {
+ HookModifierData* hmd = (HookModifierData*)md;
+
+ if (hmd->curfalloff) {
+ callback(hmd->curfalloff);
+ }
+ }
+ else if (md->type == eModifierType_Warp) {
+ WarpModifierData* tmd = (WarpModifierData*)md;
+ if (tmd->curfalloff) {
+ callback(tmd->curfalloff);
+ }
+ }
+ else if (md->type == eModifierType_WeightVGEdit) {
+ WeightVGEditModifierData* wmd = (WeightVGEditModifierData*)md;
+
+ if (wmd->cmap_curve) {
+ callback(wmd->cmap_curve);
+ }
+ }
+ }
+ /* Grease pencil modifiers */
+ LISTBASE_FOREACH(ModifierData*, md, &ob->greasepencil_modifiers) {
+ if (md->type == eGpencilModifierType_Thick) {
+ ThickGpencilModifierData* gpmd = (ThickGpencilModifierData*)md;
+
+ if (gpmd->curve_thickness) {
+ callback(gpmd->curve_thickness);
+ }
+ }
+ else if (md->type == eGpencilModifierType_Hook) {
+ HookGpencilModifierData* gpmd = (HookGpencilModifierData*)md;
+
+ if (gpmd->curfalloff) {
+ callback(gpmd->curfalloff);
+ }
+ }
+ }
+ }
+
+ /* Free Style */
+ LISTBASE_FOREACH(struct FreestyleLineStyle*, linestyle, &bmain->linestyles) {
+ LISTBASE_FOREACH(LineStyleModifier*, m, &linestyle->alpha_modifiers) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ callback(((LineStyleAlphaModifier_AlongStroke*)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ callback(((LineStyleAlphaModifier_DistanceFromCamera*)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ callback(((LineStyleAlphaModifier_DistanceFromObject*)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ callback(((LineStyleAlphaModifier_Material*)m)->curve);
+ break;
+ case LS_MODIFIER_TANGENT:
+ callback(((LineStyleAlphaModifier_Tangent*)m)->curve);
+ break;
+ case LS_MODIFIER_NOISE:
+ callback(((LineStyleAlphaModifier_Noise*)m)->curve);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ callback(((LineStyleAlphaModifier_CreaseAngle*)m)->curve);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ callback(((LineStyleAlphaModifier_Curvature_3D*)m)->curve);
+ break;
+ }
+ }
+
+ LISTBASE_FOREACH(LineStyleModifier*, m, &linestyle->thickness_modifiers) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ callback(((LineStyleThicknessModifier_AlongStroke*)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ callback(((LineStyleThicknessModifier_DistanceFromCamera*)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ callback(((LineStyleThicknessModifier_DistanceFromObject*)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ callback(((LineStyleThicknessModifier_Material*)m)->curve);
+ break;
+ case LS_MODIFIER_TANGENT:
+ callback(((LineStyleThicknessModifier_Tangent*)m)->curve);
+ break;
+ case LS_MODIFIER_CREASE_ANGLE:
+ callback(((LineStyleThicknessModifier_CreaseAngle*)m)->curve);
+ break;
+ case LS_MODIFIER_CURVATURE_3D:
+ callback(((LineStyleThicknessModifier_Curvature_3D*)m)->curve);
+ break;
+ }
+ }
+ }
}
-static void do_version_fcurve_hide_viewport_fix(struct ID *UNUSED(id),
- struct FCurve *fcu,
- void *UNUSED(user_data))
+static void do_version_fcurve_hide_viewport_fix(struct ID* UNUSED(id),
+ struct FCurve* fcu,
+ void* UNUSED(user_data))
{
- if (strcmp(fcu->rna_path, "hide")) {
- return;
- }
+ if (strcmp(fcu->rna_path, "hide")) {
+ return;
+ }
- MEM_freeN(fcu->rna_path);
- fcu->rna_path = BLI_strdupn("hide_viewport", 13);
+ MEM_freeN(fcu->rna_path);
+ fcu->rna_path = BLI_strdupn("hide_viewport", 13);
}
-void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
+void do_versions_after_linking_280(Main* bmain, ReportList* UNUSED(reports))
{
- bool use_collection_compat_28 = true;
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- use_collection_compat_28 = false;
-
- /* Convert group layer visibility flags to hidden nested collection. */
- for (Collection *collection = bmain->collections.first; collection;
- collection = collection->id.next) {
- /* Add fake user for all existing groups. */
- id_fake_user_set(&collection->id);
-
- if (collection->flag & (COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER)) {
- continue;
- }
-
- Collection *hidden_collection_array[20] = {NULL};
- for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob;
- cob = cob_next) {
- cob_next = cob->next;
- Object *ob = cob->ob;
-
- if (!(ob->lay & collection->layer)) {
- /* Find or create hidden collection matching object's first layer. */
- Collection **collection_hidden = NULL;
- int coll_idx = 0;
- for (; coll_idx < 20; coll_idx++) {
- if (ob->lay & (1 << coll_idx)) {
- collection_hidden = &hidden_collection_array[coll_idx];
- break;
- }
- }
- BLI_assert(collection_hidden != NULL);
-
- if (*collection_hidden == NULL) {
- char name[MAX_ID_NAME];
- BLI_snprintf(name, sizeof(name), DATA_("Hidden %d"), coll_idx + 1);
- *collection_hidden = BKE_collection_add(bmain, collection, name);
- (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEWPORT |
- COLLECTION_RESTRICT_RENDER;
- }
-
- BKE_collection_object_add(bmain, *collection_hidden, ob);
- BKE_collection_object_remove(bmain, collection, ob, true);
- }
- }
- }
-
- /* We need to assign lib pointer to generated hidden collections *after* all have been
- * created, otherwise we'll end up with several data-blocks sharing same name/library,
- * which is FORBIDDEN! Note: we need this to be recursive, since a child collection may be
- * sorted before its parent in bmain. */
- for (Collection *collection = bmain->collections.first; collection != NULL;
- collection = collection->id.next) {
- do_version_collection_propagate_lib_to_children(collection);
- }
-
- /* Convert layers to collections. */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- do_version_layers_to_collections(bmain, scene);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- /* same render-layer as do_version_workspaces_after_lib_link will activate,
- * so same layer as BKE_view_layer_default_view would return */
- ViewLayer *layer = screen->scene->view_layers.first;
-
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *space = sa->spacedata.first; space; space = space->next) {
- if (space->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *soutliner = (SpaceOutliner *)space;
-
- soutliner->outlinevis = SO_VIEW_LAYER;
-
- if (BLI_listbase_count_at_most(&layer->layer_collections, 2) == 1) {
- if (soutliner->treestore == NULL) {
- soutliner->treestore = BLI_mempool_create(
- sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
- }
-
- /* Create a tree store element for the collection. This is normally
- * done in check_persistent (outliner_tree.c), but we need to access
- * it here :/ (expand element if it's the only one) */
- TreeStoreElem *tselem = BLI_mempool_calloc(soutliner->treestore);
- tselem->type = TSE_LAYER_COLLECTION;
- tselem->id = layer->layer_collections.first;
- tselem->nr = tselem->used = 0;
- tselem->flag &= ~TSE_CLOSED;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *space = sa->spacedata.first; space; space = space->next) {
- if (space->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)space;
- if ((sima) && (sima->gpd)) {
- sima->gpd->flag |= GP_DATA_ANNOTATIONS;
- do_versions_fix_annotations(sima->gpd);
- }
- }
- if (space->spacetype == SPACE_CLIP) {
- SpaceClip *spclip = (SpaceClip *)space;
- MovieClip *clip = spclip->clip;
- if ((clip) && (clip->gpd)) {
- clip->gpd->flag |= GP_DATA_ANNOTATIONS;
- do_versions_fix_annotations(clip->gpd);
- }
- }
- }
- }
- }
- }
-
- /* New workspace design */
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 1)) {
- do_version_workspaces_after_lib_link(bmain);
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 2)) {
- /* Cleanup any remaining SceneRenderLayer data for files that were created
- * with Blender 2.8 before the SceneRenderLayer > RenderLayer refactor. */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
- if (srl->prop) {
- IDP_FreeProperty(srl->prop);
- }
- BKE_freestyle_config_free(&srl->freestyleConfig, true);
- }
- BLI_freelistN(&scene->r.layers);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
- /* Due to several changes to particle RNA and draw code particles from older files may
- * no longer be visible.
- * Here we correct this by setting a default draw size for those files. */
- for (Object *object = bmain->objects.first; object; object = object->id.next) {
- for (ParticleSystem *psys = object->particlesystem.first; psys; psys = psys->next) {
- if (psys->part->draw_size == 0.0f) {
- psys->part->draw_size = 0.1f;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 4)) {
- for (Object *object = bmain->objects.first; object; object = object->id.next) {
- if (object->particlesystem.first) {
- object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
- for (ParticleSystem *psys = object->particlesystem.first; psys; psys = psys->next) {
- if (psys->part->draw & PART_DRAW_EMITTER) {
- object->duplicator_visibility_flag |= OB_DUPLI_FLAG_RENDER;
- break;
- }
- }
- }
- else if (object->transflag & OB_DUPLI) {
- object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
- }
- else {
- object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER;
- }
- }
-
- /* Cleanup deprecated flag from particlesettings data-blocks. */
- for (ParticleSettings *part = bmain->particles.first; part; part = part->id.next) {
- part->draw &= ~PART_DRAW_EMITTER;
- }
- }
-
- /* SpaceTime & SpaceLogic removal/replacing */
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 9)) {
- const wmWindowManager *wm = bmain->wm.first;
- const Scene *scene = bmain->scenes.first;
-
- if (wm != NULL) {
- /* Action editors need a scene for creation. First, update active
- * screens using the active scene of the window they're displayed in.
- * Next, update remaining screens using first scene in main listbase. */
-
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
- for (ScrArea *area = screen->areabase.first; area; area = area->next) {
- if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
- do_version_area_change_space_to_space_action(area, win->scene);
-
- /* Don't forget to unset! */
- area->butspacetype = SPACE_EMPTY;
- }
- }
- }
- }
- if (scene != NULL) {
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (ScrArea *area = screen->areabase.first; area; area = area->next) {
- if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
- /* Areas that were already handled won't be handled again */
- do_version_area_change_space_to_space_action(area, scene);
-
- /* Don't forget to unset! */
- area->butspacetype = SPACE_EMPTY;
- }
- }
- }
- }
- }
+ bool use_collection_compat_28 = true;
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ use_collection_compat_28 = false;
+
+ /* Convert group layer visibility flags to hidden nested collection. */
+ for (Collection* collection = bmain->collections.first; collection;
+ collection = collection->id.next) {
+ /* Add fake user for all existing groups. */
+ id_fake_user_set(&collection->id);
+
+ if (collection->flag & (COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER)) {
+ continue;
+ }
+
+ Collection* hidden_collection_array[20] = { NULL };
+ for (CollectionObject* cob = collection->gobject.first, *cob_next = NULL; cob;
+ cob = cob_next) {
+ cob_next = cob->next;
+ Object* ob = cob->ob;
+
+ if (!(ob->lay & collection->layer)) {
+ /* Find or create hidden collection matching object's first layer. */
+ Collection** collection_hidden = NULL;
+ int coll_idx = 0;
+ for (; coll_idx < 20; coll_idx++) {
+ if (ob->lay & (1 << coll_idx)) {
+ collection_hidden = &hidden_collection_array[coll_idx];
+ break;
+ }
+ }
+ BLI_assert(collection_hidden != NULL);
+
+ if (*collection_hidden == NULL) {
+ char name[MAX_ID_NAME];
+ BLI_snprintf(name, sizeof(name), DATA_("Hidden %d"), coll_idx + 1);
+ *collection_hidden = BKE_collection_add(bmain, collection, name);
+ (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEWPORT |
+ COLLECTION_RESTRICT_RENDER;
+ }
+
+ BKE_collection_object_add(bmain, *collection_hidden, ob);
+ BKE_collection_object_remove(bmain, collection, ob, true);
+ }
+ }
+ }
+
+ /* We need to assign lib pointer to generated hidden collections *after* all have been
+ * created, otherwise we'll end up with several data-blocks sharing same name/library,
+ * which is FORBIDDEN! Note: we need this to be recursive, since a child collection may be
+ * sorted before its parent in bmain. */
+ for (Collection* collection = bmain->collections.first; collection != NULL;
+ collection = collection->id.next) {
+ do_version_collection_propagate_lib_to_children(collection);
+ }
+
+ /* Convert layers to collections. */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ do_version_layers_to_collections(bmain, scene);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ /* same render-layer as do_version_workspaces_after_lib_link will activate,
+ * so same layer as BKE_view_layer_default_view would return */
+ ViewLayer* layer = screen->scene->view_layers.first;
+
+ for (ScrArea* sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink* space = sa->spacedata.first; space; space = space->next) {
+ if (space->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner* soutliner = (SpaceOutliner*)space;
+
+ soutliner->outlinevis = SO_VIEW_LAYER;
+
+ if (BLI_listbase_count_at_most(&layer->layer_collections, 2) == 1) {
+ if (soutliner->treestore == NULL) {
+ soutliner->treestore = BLI_mempool_create(
+ sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
+ }
+
+ /* Create a tree store element for the collection. This is normally
+ * done in check_persistent (outliner_tree.c), but we need to access
+ * it here :/ (expand element if it's the only one) */
+ TreeStoreElem* tselem = BLI_mempool_calloc(soutliner->treestore);
+ tselem->type = TSE_LAYER_COLLECTION;
+ tselem->id = layer->layer_collections.first;
+ tselem->nr = tselem->used = 0;
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea* sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink* space = sa->spacedata.first; space; space = space->next) {
+ if (space->spacetype == SPACE_IMAGE) {
+ SpaceImage* sima = (SpaceImage*)space;
+ if ((sima) && (sima->gpd)) {
+ sima->gpd->flag |= GP_DATA_ANNOTATIONS;
+ do_versions_fix_annotations(sima->gpd);
+ }
+ }
+ if (space->spacetype == SPACE_CLIP) {
+ SpaceClip* spclip = (SpaceClip*)space;
+ MovieClip* clip = spclip->clip;
+ if ((clip) && (clip->gpd)) {
+ clip->gpd->flag |= GP_DATA_ANNOTATIONS;
+ do_versions_fix_annotations(clip->gpd);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* New workspace design */
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 1)) {
+ do_version_workspaces_after_lib_link(bmain);
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 2)) {
+ /* Cleanup any remaining SceneRenderLayer data for files that were created
+ * with Blender 2.8 before the SceneRenderLayer > RenderLayer refactor. */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ for (SceneRenderLayer* srl = scene->r.layers.first; srl; srl = srl->next) {
+ if (srl->prop) {
+ IDP_FreeProperty(srl->prop);
+ }
+ BKE_freestyle_config_free(&srl->freestyleConfig, true);
+ }
+ BLI_freelistN(&scene->r.layers);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
+ /* Due to several changes to particle RNA and draw code particles from older files may
+ * no longer be visible.
+ * Here we correct this by setting a default draw size for those files. */
+ for (Object* object = bmain->objects.first; object; object = object->id.next) {
+ for (ParticleSystem* psys = object->particlesystem.first; psys; psys = psys->next) {
+ if (psys->part->draw_size == 0.0f) {
+ psys->part->draw_size = 0.1f;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 4)) {
+ for (Object* object = bmain->objects.first; object; object = object->id.next) {
+ if (object->particlesystem.first) {
+ object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
+ for (ParticleSystem* psys = object->particlesystem.first; psys; psys = psys->next) {
+ if (psys->part->draw & PART_DRAW_EMITTER) {
+ object->duplicator_visibility_flag |= OB_DUPLI_FLAG_RENDER;
+ break;
+ }
+ }
+ }
+ else if (object->transflag & OB_DUPLI) {
+ object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
+ }
+ else {
+ object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER;
+ }
+ }
+
+ /* Cleanup deprecated flag from particlesettings data-blocks. */
+ for (ParticleSettings* part = bmain->particles.first; part; part = part->id.next) {
+ part->draw &= ~PART_DRAW_EMITTER;
+ }
+ }
+
+ /* SpaceTime & SpaceLogic removal/replacing */
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 9)) {
+ const wmWindowManager* wm = bmain->wm.first;
+ const Scene* scene = bmain->scenes.first;
+
+ if (wm != NULL) {
+ /* Action editors need a scene for creation. First, update active
+ * screens using the active scene of the window they're displayed in.
+ * Next, update remaining screens using first scene in main listbase. */
+
+ for (wmWindow* win = wm->windows.first; win; win = win->next) {
+ const bScreen* screen = BKE_workspace_active_screen_get(win->workspace_hook);
+ for (ScrArea* area = screen->areabase.first; area; area = area->next) {
+ if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
+ do_version_area_change_space_to_space_action(area, win->scene);
+
+ /* Don't forget to unset! */
+ area->butspacetype = SPACE_EMPTY;
+ }
+ }
+ }
+ }
+ if (scene != NULL) {
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea* area = screen->areabase.first; area; area = area->next) {
+ if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
+ /* Areas that were already handled won't be handled again */
+ do_version_area_change_space_to_space_action(area, scene);
+
+ /* Don't forget to unset! */
+ area->butspacetype = SPACE_EMPTY;
+ }
+ }
+ }
+ }
+ }
#ifdef USE_COLLECTION_COMPAT_28
- if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(bmain, 280, 14)) {
- for (Collection *group = bmain->collections.first; group; group = group->id.next) {
- do_version_group_collection_to_collection(bmain, group);
- }
-
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- do_version_scene_collection_to_collection(bmain, scene);
- }
- }
+ if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(bmain, 280, 14)) {
+ for (Collection* group = bmain->collections.first; group; group = group->id.next) {
+ do_version_group_collection_to_collection(bmain, group);
+ }
+
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ do_version_scene_collection_to_collection(bmain, scene);
+ }
+ }
#endif
- /* Update Curve object Shape Key data layout to include the Radius property */
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 23)) {
- for (Curve *cu = bmain->curves.first; cu; cu = cu->id.next) {
- if (!cu->key || cu->key->elemsize != sizeof(float[4])) {
- continue;
- }
-
- cu->key->elemstr[0] = 3; /*KEYELEM_ELEM_SIZE_CURVE*/
- cu->key->elemsize = sizeof(float[3]);
-
- int new_count = BKE_keyblock_curve_element_count(&cu->nurb);
-
- for (KeyBlock *block = cu->key->block.first; block; block = block->next) {
- int old_count = block->totelem;
- void *old_data = block->data;
-
- if (!old_data || old_count <= 0) {
- continue;
- }
-
- block->totelem = new_count;
- block->data = MEM_callocN(sizeof(float[3]) * new_count, __func__);
-
- float *oldptr = old_data;
- float(*newptr)[3] = block->data;
-
- for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->bezt) {
- BezTriple *bezt = nu->bezt;
-
- for (int a = 0; a < nu->pntsu; a++, bezt++) {
- if ((old_count -= 3) < 0) {
- memcpy(newptr, bezt->vec, sizeof(float[3][3]));
- newptr[3][0] = bezt->tilt;
- }
- else {
- memcpy(newptr, oldptr, sizeof(float[3][4]));
- }
-
- newptr[3][1] = bezt->radius;
-
- oldptr += 3 * 4;
- newptr += 4; /*KEYELEM_ELEM_LEN_BEZTRIPLE*/
- }
- }
- else if (nu->bp) {
- BPoint *bp = nu->bp;
-
- for (int a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (--old_count < 0) {
- copy_v3_v3(newptr[0], bp->vec);
- newptr[1][0] = bp->tilt;
- }
- else {
- memcpy(newptr, oldptr, sizeof(float[4]));
- }
-
- newptr[1][1] = bp->radius;
-
- oldptr += 4;
- newptr += 2; /*KEYELEM_ELEM_LEN_BPOINT*/
- }
- }
- }
-
- MEM_freeN(old_data);
- }
- }
- }
-
- /* Move B-Bone custom handle settings from bPoseChannel to Bone. */
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 25)) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- bArmature *arm = ob->data;
-
- /* If it is an armature from the same file. */
- if (ob->pose && arm && arm->id.lib == ob->id.lib) {
- bool rebuild = false;
-
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* If the 2.7 flag is enabled, processing is needed. */
- if (pchan->bone && (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES)) {
- /* If the settings in the Bone are not set, copy. */
- if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO &&
- pchan->bone->bbone_next_type == BBONE_HANDLE_AUTO &&
- pchan->bone->bbone_prev == NULL && pchan->bone->bbone_next == NULL) {
- pchan->bone->bbone_prev_type = (pchan->bboneflag & PCHAN_BBONE_CUSTOM_START_REL) ?
- BBONE_HANDLE_RELATIVE :
- BBONE_HANDLE_ABSOLUTE;
- pchan->bone->bbone_next_type = (pchan->bboneflag & PCHAN_BBONE_CUSTOM_END_REL) ?
- BBONE_HANDLE_RELATIVE :
- BBONE_HANDLE_ABSOLUTE;
-
- if (pchan->bbone_prev) {
- pchan->bone->bbone_prev = pchan->bbone_prev->bone;
- }
- if (pchan->bbone_next) {
- pchan->bone->bbone_next = pchan->bbone_next->bone;
- }
- }
-
- rebuild = true;
- pchan->bboneflag = 0;
- }
- }
-
- /* Tag pose rebuild for all objects that use this armature. */
- if (rebuild) {
- for (Object *ob2 = bmain->objects.first; ob2; ob2 = ob2->id.next) {
- if (ob2->pose && ob2->data == arm) {
- ob2->pose->flag |= POSE_RECALC;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 30)) {
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if (brush->gpencil_settings != NULL) {
- brush->gpencil_tool = brush->gpencil_settings->brush_type;
- }
- }
- BKE_paint_toolslots_init_from_main(bmain);
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 38)) {
- /* Ensure we get valid rigidbody object/constraint data in relevant collections' objects.
- */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- RigidBodyWorld *rbw = scene->rigidbody_world;
-
- if (rbw == NULL) {
- continue;
- }
-
- BKE_rigidbody_objects_collection_validate(scene, rbw);
- BKE_rigidbody_constraints_collection_validate(scene, rbw);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
- /* Unify DOF settings (EEVEE part only) */
- const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
- if (scene->eevee.flag & SCE_EEVEE_DOF_ENABLED) {
- Object *cam_ob = scene->camera;
- if (cam_ob && cam_ob->type == OB_CAMERA) {
- Camera *cam = cam_ob->data;
- cam->dof.flag |= CAM_DOF_ENABLED;
- }
- }
- }
- }
-
- LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
- camera->dof.focus_object = camera->dof_ob;
- camera->dof.focus_distance = camera->dof_distance;
- camera->dof.aperture_fstop = camera->gpu_dof.fstop;
- camera->dof.aperture_rotation = camera->gpu_dof.rotation;
- camera->dof.aperture_ratio = camera->gpu_dof.ratio;
- camera->dof.aperture_blades = camera->gpu_dof.num_blades;
- camera->dof_ob = NULL;
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
- /* Replace Multiply and Additive blend mode by Alpha Blend
- * now that we use dualsource blending. */
- /* We take care of doing only nodetrees that are always part of materials
- * with old blending modes. */
- for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) {
- bNodeTree *ntree = ma->nodetree;
- if (ma->blend_method == 1 /* MA_BM_ADD */) {
- if (ma->use_nodes) {
- do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */);
- }
- ma->blend_method = MA_BM_BLEND;
- }
- else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) {
- if (ma->use_nodes) {
- do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */);
- }
- ma->blend_method = MA_BM_BLEND;
- }
- }
-
- /* Update all ruler layers to set new flag. */
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- bGPdata *gpd = scene->gpd;
- if (gpd == NULL) {
- continue;
- }
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (STREQ(gpl->info, "RulerData3D")) {
- gpl->flag |= GP_LAYER_IS_RULER;
- break;
- }
- }
- }
-
- /* This versionning could probably be done only on earlier versions, not sure however
- * which exact version fully deprecated tessfaces, so think we can keep that one here, no
- * harm to be expected anyway for being over-conservative. */
- for (Mesh *me = bmain->meshes.first; me != NULL; me = me->id.next) {
- /*check if we need to convert mfaces to mpolys*/
- if (me->totface && !me->totpoly) {
- /* temporarily switch main so that reading from
- * external CustomData works */
- Main *gmain = G_MAIN;
- G_MAIN = bmain;
-
- BKE_mesh_do_versions_convert_mfaces_to_mpolys(me);
-
- G_MAIN = gmain;
- }
-
- /* Deprecated, only kept for conversion. */
- BKE_mesh_tessface_clear(me);
-
- /* Moved from do_versions because we need updated polygons for calculating normals. */
- if (MAIN_VERSION_OLDER(bmain, 256, 6)) {
- BKE_mesh_calc_normals(me);
- }
- }
- }
-
- 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. */
- 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.
- *
- * \note Be sure to check when bumping the version:
- * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
- * - "versioning_userdef.c", #do_versions_theme
- *
- * \note Keep this message at the bottom of the function.
- */
- {
- /* Keep this block, even when empty. */
-
- /* During development of Blender 2.80 the "Object.hide" property was
- * removed, and reintroduced in 5e968a996a53 as "Object.hide_viewport". */
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- BKE_fcurves_id_cb(&ob->id, do_version_fcurve_hide_viewport_fix, NULL);
- }
- }
+ /* Update Curve object Shape Key data layout to include the Radius property */
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 23)) {
+ for (Curve* cu = bmain->curves.first; cu; cu = cu->id.next) {
+ if (!cu->key || cu->key->elemsize != sizeof(float[4])) {
+ continue;
+ }
+
+ cu->key->elemstr[0] = 3; /*KEYELEM_ELEM_SIZE_CURVE*/
+ cu->key->elemsize = sizeof(float[3]);
+
+ int new_count = BKE_keyblock_curve_element_count(&cu->nurb);
+
+ for (KeyBlock* block = cu->key->block.first; block; block = block->next) {
+ int old_count = block->totelem;
+ void* old_data = block->data;
+
+ if (!old_data || old_count <= 0) {
+ continue;
+ }
+
+ block->totelem = new_count;
+ block->data = MEM_callocN(sizeof(float[3]) * new_count, __func__);
+
+ float* oldptr = old_data;
+ float(*newptr)[3] = block->data;
+
+ for (Nurb* nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ BezTriple* bezt = nu->bezt;
+
+ for (int a = 0; a < nu->pntsu; a++, bezt++) {
+ if ((old_count -= 3) < 0) {
+ memcpy(newptr, bezt->vec, sizeof(float[3][3]));
+ newptr[3][0] = bezt->tilt;
+ }
+ else {
+ memcpy(newptr, oldptr, sizeof(float[3][4]));
+ }
+
+ newptr[3][1] = bezt->radius;
+
+ oldptr += 3 * 4;
+ newptr += 4; /*KEYELEM_ELEM_LEN_BEZTRIPLE*/
+ }
+ }
+ else if (nu->bp) {
+ BPoint* bp = nu->bp;
+
+ for (int a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (--old_count < 0) {
+ copy_v3_v3(newptr[0], bp->vec);
+ newptr[1][0] = bp->tilt;
+ }
+ else {
+ memcpy(newptr, oldptr, sizeof(float[4]));
+ }
+
+ newptr[1][1] = bp->radius;
+
+ oldptr += 4;
+ newptr += 2; /*KEYELEM_ELEM_LEN_BPOINT*/
+ }
+ }
+ }
+
+ MEM_freeN(old_data);
+ }
+ }
+ }
+
+ /* Move B-Bone custom handle settings from bPoseChannel to Bone. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 25)) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ bArmature* arm = ob->data;
+
+ /* If it is an armature from the same file. */
+ if (ob->pose && arm && arm->id.lib == ob->id.lib) {
+ bool rebuild = false;
+
+ for (bPoseChannel* pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* If the 2.7 flag is enabled, processing is needed. */
+ if (pchan->bone && (pchan->bboneflag & PCHAN_BBONE_CUSTOM_HANDLES)) {
+ /* If the settings in the Bone are not set, copy. */
+ if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO &&
+ pchan->bone->bbone_next_type == BBONE_HANDLE_AUTO &&
+ pchan->bone->bbone_prev == NULL && pchan->bone->bbone_next == NULL) {
+ pchan->bone->bbone_prev_type = (pchan->bboneflag & PCHAN_BBONE_CUSTOM_START_REL) ?
+ BBONE_HANDLE_RELATIVE :
+ BBONE_HANDLE_ABSOLUTE;
+ pchan->bone->bbone_next_type = (pchan->bboneflag & PCHAN_BBONE_CUSTOM_END_REL) ?
+ BBONE_HANDLE_RELATIVE :
+ BBONE_HANDLE_ABSOLUTE;
+
+ if (pchan->bbone_prev) {
+ pchan->bone->bbone_prev = pchan->bbone_prev->bone;
+ }
+ if (pchan->bbone_next) {
+ pchan->bone->bbone_next = pchan->bbone_next->bone;
+ }
+ }
+
+ rebuild = true;
+ pchan->bboneflag = 0;
+ }
+ }
+
+ /* Tag pose rebuild for all objects that use this armature. */
+ if (rebuild) {
+ for (Object* ob2 = bmain->objects.first; ob2; ob2 = ob2->id.next) {
+ if (ob2->pose && ob2->data == arm) {
+ ob2->pose->flag |= POSE_RECALC;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 30)) {
+ for (Brush* brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ if (brush->gpencil_settings != NULL) {
+ brush->gpencil_tool = brush->gpencil_settings->brush_type;
+ }
+ }
+ BKE_paint_toolslots_init_from_main(bmain);
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 38)) {
+ /* Ensure we get valid rigidbody object/constraint data in relevant collections' objects.
+ */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ RigidBodyWorld* rbw = scene->rigidbody_world;
+
+ if (rbw == NULL) {
+ continue;
+ }
+
+ BKE_rigidbody_objects_collection_validate(scene, rbw);
+ BKE_rigidbody_constraints_collection_validate(scene, rbw);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
+ /* Unify DOF settings (EEVEE part only) */
+ const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
+ if (scene->eevee.flag & SCE_EEVEE_DOF_ENABLED) {
+ Object* cam_ob = scene->camera;
+ if (cam_ob && cam_ob->type == OB_CAMERA) {
+ Camera* cam = cam_ob->data;
+ cam->dof.flag |= CAM_DOF_ENABLED;
+ }
+ }
+ }
+ }
+
+ LISTBASE_FOREACH(Camera*, camera, &bmain->cameras) {
+ camera->dof.focus_object = camera->dof_ob;
+ camera->dof.focus_distance = camera->dof_distance;
+ camera->dof.aperture_fstop = camera->gpu_dof.fstop;
+ camera->dof.aperture_rotation = camera->gpu_dof.rotation;
+ camera->dof.aperture_ratio = camera->gpu_dof.ratio;
+ camera->dof.aperture_blades = camera->gpu_dof.num_blades;
+ camera->dof_ob = NULL;
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
+ /* Replace Multiply and Additive blend mode by Alpha Blend
+ * now that we use dualsource blending. */
+ /* We take care of doing only nodetrees that are always part of materials
+ * with old blending modes. */
+ for (Material* ma = bmain->materials.first; ma; ma = ma->id.next) {
+ bNodeTree* ntree = ma->nodetree;
+ if (ma->blend_method == 1 /* MA_BM_ADD */) {
+ if (ma->use_nodes) {
+ do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */);
+ }
+ ma->blend_method = MA_BM_BLEND;
+ }
+ else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) {
+ if (ma->use_nodes) {
+ do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */);
+ }
+ ma->blend_method = MA_BM_BLEND;
+ }
+ }
+
+ /* Update all ruler layers to set new flag. */
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ bGPdata* gpd = scene->gpd;
+ if (gpd == NULL) {
+ continue;
+ }
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ if (STREQ(gpl->info, "RulerData3D")) {
+ gpl->flag |= GP_LAYER_IS_RULER;
+ break;
+ }
+ }
+ }
+
+ /* This versionning could probably be done only on earlier versions, not sure however
+ * which exact version fully deprecated tessfaces, so think we can keep that one here, no
+ * harm to be expected anyway for being over-conservative. */
+ for (Mesh* me = bmain->meshes.first; me != NULL; me = me->id.next) {
+ /*check if we need to convert mfaces to mpolys*/
+ if (me->totface && !me->totpoly) {
+ /* temporarily switch main so that reading from
+ * external CustomData works */
+ Main* gmain = G_MAIN;
+ G_MAIN = bmain;
+
+ BKE_mesh_do_versions_convert_mfaces_to_mpolys(me);
+
+ G_MAIN = gmain;
+ }
+
+ /* Deprecated, only kept for conversion. */
+ BKE_mesh_tessface_clear(me);
+
+ /* Moved from do_versions because we need updated polygons for calculating normals. */
+ if (MAIN_VERSION_OLDER(bmain, 256, 6)) {
+ BKE_mesh_calc_normals(me);
+ }
+ }
+ }
+
+ 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. */
+ 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.
+ *
+ * \note Be sure to check when bumping the version:
+ * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+
+ /* During development of Blender 2.80 the "Object.hide" property was
+ * removed, and reintroduced in 5e968a996a53 as "Object.hide_viewport". */
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ BKE_fcurves_id_cb(&ob->id, do_version_fcurve_hide_viewport_fix, NULL);
+ }
+ }
}
/* NOTE: This version patch is intended for versions < 2.52.2,
* but was initially introduced in 2.27 already.
* But in 2.79 another case generating non-unique names was discovered
* (see T55668, involving Meta strips). */
-static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep)
+static void do_versions_seq_unique_name_all_strips(Scene* sce, ListBase* seqbasep)
{
- for (Sequence *seq = seqbasep->first; seq != NULL; seq = seq->next) {
- BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq);
- if (seq->seqbase.first != NULL) {
- do_versions_seq_unique_name_all_strips(sce, &seq->seqbase);
- }
- }
+ for (Sequence* seq = seqbasep->first; seq != NULL; seq = seq->next) {
+ BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq);
+ if (seq->seqbase.first != NULL) {
+ do_versions_seq_unique_name_all_strips(sce, &seq->seqbase);
+ }
+ }
}
-static void do_versions_seq_set_cache_defaults(Editing *ed)
+static void do_versions_seq_set_cache_defaults(Editing* ed)
{
- ed->cache_flag = SEQ_CACHE_STORE_FINAL_OUT;
- ed->cache_flag |= SEQ_CACHE_VIEW_FINAL_OUT;
- ed->cache_flag |= SEQ_CACHE_VIEW_ENABLE;
- ed->recycle_max_cost = 10.0f;
+ ed->cache_flag = SEQ_CACHE_STORE_FINAL_OUT;
+ ed->cache_flag |= SEQ_CACHE_VIEW_FINAL_OUT;
+ ed->cache_flag |= SEQ_CACHE_VIEW_ENABLE;
+ ed->recycle_max_cost = 10.0f;
}
-void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
+void blo_do_versions_280(FileData* fd, Library* UNUSED(lib), Main* bmain)
{
- bool use_collection_compat_28 = true;
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- use_collection_compat_28 = false;
-
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->r.gauss = 1.5f;
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 1)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "bleedexp")) {
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- la->bleedexp = 2.5f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
- for (Camera *ca = bmain->cameras.first; ca; ca = ca->id.next) {
- ca->gpu_dof.ratio = 1.0f;
- }
- }
-
- /* MTexPoly now removed. */
- if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
- for (Mesh *me = bmain->meshes.first; me; me = me->id.next) {
- /* If we have UV's, so this file will have MTexPoly layers too! */
- if (me->mloopuv != NULL) {
- CustomData_update_typemap(&me->pdata);
- CustomData_free_layers(&me->pdata, CD_MTEXPOLY, me->totpoly);
- BKE_mesh_update_customdata_pointers(me, false);
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 2)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "cascade_max_dist")) {
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- la->cascade_max_dist = 1000.0f;
- la->cascade_count = 4;
- la->cascade_exponent = 0.8f;
- la->cascade_fade = 0.1f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "contact_dist")) {
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- la->contact_dist = 0.2f;
- la->contact_bias = 0.03f;
- la->contact_spread = 0.2f;
- la->contact_thickness = 0.2f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "vis_bias")) {
- for (LightProbe *probe = bmain->lightprobes.first; probe; probe = probe->id.next) {
- probe->vis_bias = 1.0f;
- probe->vis_blur = 0.2f;
- }
- }
-
- typedef enum eNTreeDoVersionErrors {
- NTREE_DOVERSION_NO_ERROR = 0,
- NTREE_DOVERSION_NEED_OUTPUT = (1 << 0),
- NTREE_DOVERSION_TRANSPARENCY_EMISSION = (1 << 1),
- } eNTreeDoVersionErrors;
-
- /* Eevee shader nodes renamed because of the output node system.
- * Note that a new output node is not being added here, because it would be overkill
- * to handle this case in lib_verify_nodetree.
- *
- * Also, metallic node is now unified into the principled node. */
- eNTreeDoVersionErrors error = NTREE_DOVERSION_NO_ERROR;
-
- FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- if (node->type == 194 /* SH_NODE_EEVEE_METALLIC */ &&
- STREQ(node->idname, "ShaderNodeOutputMetallic")) {
- BLI_strncpy(node->idname, "ShaderNodeEeveeMetallic", sizeof(node->idname));
- error |= NTREE_DOVERSION_NEED_OUTPUT;
- }
-
- else if (node->type == SH_NODE_EEVEE_SPECULAR &&
- STREQ(node->idname, "ShaderNodeOutputSpecular")) {
- BLI_strncpy(node->idname, "ShaderNodeEeveeSpecular", sizeof(node->idname));
- error |= NTREE_DOVERSION_NEED_OUTPUT;
- }
-
- else if (node->type == 196 /* SH_NODE_OUTPUT_EEVEE_MATERIAL */ &&
- STREQ(node->idname, "ShaderNodeOutputEeveeMaterial")) {
- node->type = SH_NODE_OUTPUT_MATERIAL;
- BLI_strncpy(node->idname, "ShaderNodeOutputMaterial", sizeof(node->idname));
- }
-
- else if (node->type == 194 /* SH_NODE_EEVEE_METALLIC */ &&
- STREQ(node->idname, "ShaderNodeEeveeMetallic")) {
- node->type = SH_NODE_BSDF_PRINCIPLED;
- BLI_strncpy(node->idname, "ShaderNodeBsdfPrincipled", sizeof(node->idname));
- node->custom1 = SHD_GLOSSY_MULTI_GGX;
- error |= NTREE_DOVERSION_TRANSPARENCY_EMISSION;
- }
- }
- }
- }
- FOREACH_NODETREE_END;
-
- if (error & NTREE_DOVERSION_NEED_OUTPUT) {
- BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
- printf(
- "You need to connect Principled and Eevee Specular shader nodes to new material "
- "output "
- "nodes.\n");
- }
-
- if (error & NTREE_DOVERSION_TRANSPARENCY_EMISSION) {
- BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
- printf(
- "You need to combine transparency and emission shaders to the converted Principled "
- "shader nodes.\n");
- }
+ bool use_collection_compat_28 = true;
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ use_collection_compat_28 = false;
+
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->r.gauss = 1.5f;
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 1)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "bleedexp")) {
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ la->bleedexp = 2.5f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
+ for (Camera* ca = bmain->cameras.first; ca; ca = ca->id.next) {
+ ca->gpu_dof.ratio = 1.0f;
+ }
+ }
+
+ /* MTexPoly now removed. */
+ if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
+ for (Mesh* me = bmain->meshes.first; me; me = me->id.next) {
+ /* If we have UV's, so this file will have MTexPoly layers too! */
+ if (me->mloopuv != NULL) {
+ CustomData_update_typemap(&me->pdata);
+ CustomData_free_layers(&me->pdata, CD_MTEXPOLY, me->totpoly);
+ BKE_mesh_update_customdata_pointers(me, false);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 2)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "cascade_max_dist")) {
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ la->cascade_max_dist = 1000.0f;
+ la->cascade_count = 4;
+ la->cascade_exponent = 0.8f;
+ la->cascade_fade = 0.1f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "contact_dist")) {
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ la->contact_dist = 0.2f;
+ la->contact_bias = 0.03f;
+ la->contact_spread = 0.2f;
+ la->contact_thickness = 0.2f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "vis_bias")) {
+ for (LightProbe* probe = bmain->lightprobes.first; probe; probe = probe->id.next) {
+ probe->vis_bias = 1.0f;
+ probe->vis_blur = 0.2f;
+ }
+ }
+
+ typedef enum eNTreeDoVersionErrors {
+ NTREE_DOVERSION_NO_ERROR = 0,
+ NTREE_DOVERSION_NEED_OUTPUT = (1 << 0),
+ NTREE_DOVERSION_TRANSPARENCY_EMISSION = (1 << 1),
+ } eNTreeDoVersionErrors;
+
+ /* Eevee shader nodes renamed because of the output node system.
+ * Note that a new output node is not being added here, because it would be overkill
+ * to handle this case in lib_verify_nodetree.
+ *
+ * Also, metallic node is now unified into the principled node. */
+ eNTreeDoVersionErrors error = NTREE_DOVERSION_NO_ERROR;
+
+ FOREACH_NODETREE_BEGIN(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ for (bNode* node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == 194 /* SH_NODE_EEVEE_METALLIC */ &&
+ STREQ(node->idname, "ShaderNodeOutputMetallic")) {
+ BLI_strncpy(node->idname, "ShaderNodeEeveeMetallic", sizeof(node->idname));
+ error |= NTREE_DOVERSION_NEED_OUTPUT;
+ }
+
+ else if (node->type == SH_NODE_EEVEE_SPECULAR &&
+ STREQ(node->idname, "ShaderNodeOutputSpecular")) {
+ BLI_strncpy(node->idname, "ShaderNodeEeveeSpecular", sizeof(node->idname));
+ error |= NTREE_DOVERSION_NEED_OUTPUT;
+ }
+
+ else if (node->type == 196 /* SH_NODE_OUTPUT_EEVEE_MATERIAL */ &&
+ STREQ(node->idname, "ShaderNodeOutputEeveeMaterial")) {
+ node->type = SH_NODE_OUTPUT_MATERIAL;
+ BLI_strncpy(node->idname, "ShaderNodeOutputMaterial", sizeof(node->idname));
+ }
+
+ else if (node->type == 194 /* SH_NODE_EEVEE_METALLIC */ &&
+ STREQ(node->idname, "ShaderNodeEeveeMetallic")) {
+ node->type = SH_NODE_BSDF_PRINCIPLED;
+ BLI_strncpy(node->idname, "ShaderNodeBsdfPrincipled", sizeof(node->idname));
+ node->custom1 = SHD_GLOSSY_MULTI_GGX;
+ error |= NTREE_DOVERSION_TRANSPARENCY_EMISSION;
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ if (error & NTREE_DOVERSION_NEED_OUTPUT) {
+ BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
+ printf(
+ "You need to connect Principled and Eevee Specular shader nodes to new material "
+ "output "
+ "nodes.\n");
+ }
+
+ if (error & NTREE_DOVERSION_TRANSPARENCY_EMISSION) {
+ BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
+ printf(
+ "You need to combine transparency and emission shaders to the converted Principled "
+ "shader nodes.\n");
+ }
#ifdef USE_COLLECTION_COMPAT_28
- if (use_collection_compat_28 &&
- (DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") ==
- false) &&
- DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- ViewLayer *view_layer;
- for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- view_layer->flag |= VIEW_LAYER_FREESTYLE;
- view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */
- view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
- view_layer->pass_alpha_threshold = 0.5f;
- BKE_freestyle_config_init(&view_layer->freestyle_config);
- }
- }
- }
+ if (use_collection_compat_28 &&
+ (DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") ==
+ false) &&
+ DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ ViewLayer* view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ view_layer->flag |= VIEW_LAYER_FREESTYLE;
+ view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */
+ view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
+ view_layer->pass_alpha_threshold = 0.5f;
+ BKE_freestyle_config_init(&view_layer->freestyle_config);
+ }
+ }
+ }
#endif
- {
- /* 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) {
- ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
- }
- }
-
- /* Init grease pencil pixel size factor */
- if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "float", "pixfactor")) {
- for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
- }
- }
-
- /* Grease pencil multiframe falloff curve */
- if (!DNA_struct_elem_find(
- fd->filesdna, "GP_Sculpt_Settings", "CurveMapping", "cur_falloff")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- /* sculpt brushes */
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- if ((gset) && (gset->cur_falloff == NULL)) {
- gset->cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- BKE_curvemapping_initialize(gset->cur_falloff);
- BKE_curvemap_reset(gset->cur_falloff->cm,
- &gset->cur_falloff->clipr,
- CURVE_PRESET_GAUSS,
- CURVEMAP_SLOPE_POSITIVE);
- }
- }
- }
- }
-
- /* 2.79 style Maintain Volume mode. */
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- do_version_constraints_maintain_volume_mode_uniform(&ob->constraints);
- if (ob->pose) {
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- do_version_constraints_maintain_volume_mode_uniform(&pchan->constraints);
- }
- }
- }
- }
+ {
+ /* 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) {
+ ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
+ }
+ }
+
+ /* Init grease pencil pixel size factor */
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "float", "pixfactor")) {
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ }
+ }
+
+ /* Grease pencil multiframe falloff curve */
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "GP_Sculpt_Settings", "CurveMapping", "cur_falloff")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ /* sculpt brushes */
+ GP_Sculpt_Settings* gset = &scene->toolsettings->gp_sculpt;
+ if ((gset) && (gset->cur_falloff == NULL)) {
+ gset->cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ BKE_curvemapping_initialize(gset->cur_falloff);
+ BKE_curvemap_reset(gset->cur_falloff->cm,
+ &gset->cur_falloff->clipr,
+ CURVE_PRESET_GAUSS,
+ CURVEMAP_SLOPE_POSITIVE);
+ }
+ }
+ }
+ }
+
+ /* 2.79 style Maintain Volume mode. */
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ do_version_constraints_maintain_volume_mode_uniform(&ob->constraints);
+ if (ob->pose) {
+ LISTBASE_FOREACH(bPoseChannel*, pchan, &ob->pose->chanbase) {
+ do_version_constraints_maintain_volume_mode_uniform(&pchan->constraints);
+ }
+ }
+ }
+ }
#ifdef USE_COLLECTION_COMPAT_28
- if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- ViewLayer *view_layer;
- for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- do_version_view_layer_visibility(view_layer);
- }
- }
-
- for (Collection *group = bmain->collections.first; group; group = group->id.next) {
- if (group->view_layer != NULL) {
- do_version_view_layer_visibility(group->view_layer);
- }
- }
- }
+ if (use_collection_compat_28 && !MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ ViewLayer* view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ do_version_view_layer_visibility(view_layer);
+ }
+ }
+
+ for (Collection* group = bmain->collections.first; group; group = group->id.next) {
+ if (group->view_layer != NULL) {
+ do_version_view_layer_visibility(group->view_layer);
+ }
+ }
+ }
#endif
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
- /* init grease pencil grids and paper */
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.gpencil_paper_opacity = 0.5f;
- v3d->overlay.gpencil_grid_opacity = 0.9f;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 6)) {
- if (DNA_struct_elem_find(fd->filesdna, "SpaceOutliner", "int", "filter") == false) {
- bScreen *sc;
- ScrArea *sa;
- SpaceLink *sl;
-
- /* Update files using invalid (outdated) outlinevis Outliner values. */
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *so = (SpaceOutliner *)sl;
-
- if (!ELEM(so->outlinevis,
- SO_SCENES,
- SO_LIBRARIES,
- SO_SEQUENCE,
- SO_DATA_API,
- SO_ID_ORPHANS)) {
- so->outlinevis = SO_VIEW_LAYER;
- }
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "intensity")) {
- for (LightProbe *probe = bmain->lightprobes.first; probe; probe = probe->id.next) {
- probe->intensity = 1.0f;
- }
- }
-
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- bConstraint *con, *con_next;
- con = ob->constraints.first;
- while (con) {
- con_next = con->next;
- if (con->type == 17) { /* CONSTRAINT_TYPE_RIGIDBODYJOINT */
- BLI_remlink(&ob->constraints, con);
- BKE_constraint_free_data(con);
- MEM_freeN(con);
- }
- con = con_next;
- }
- }
-
- for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.light = V3D_LIGHTING_STUDIO;
- v3d->shading.flag |= V3D_SHADING_OBJECT_OUTLINE;
-
- /* Assume (demo) files written with 2.8 want to show
- * Eevee renders in the viewport. */
- if (MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- v3d->drawtype = OB_MATERIAL;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 7)) {
- /* Render engine storage moved elsewhere and back during 2.8
- * development, we assume any files saved in 2.8 had Eevee set
- * as scene render engine. */
- if (MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine));
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 8)) {
- /* Blender Internal removal */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- if (STREQ(scene->r.engine, "BLENDER_RENDER") || STREQ(scene->r.engine, "BLENDER_GAME")) {
- BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine));
- }
-
- scene->r.bake_mode = 0;
- }
-
- for (Tex *tex = bmain->textures.first; tex; tex = tex->id.next) {
- /* Removed envmap, pointdensity, voxeldata, ocean textures. */
- if (ELEM(tex->type, 10, 14, 15, 16)) {
- tex->type = 0;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 11)) {
-
- /* Remove info editor, but only if at the top of the window. */
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- /* Calculate window width/height from screen vertices */
- int win_width = 0, win_height = 0;
- for (ScrVert *vert = screen->vertbase.first; vert; vert = vert->next) {
- win_width = MAX2(win_width, vert->vec.x);
- win_height = MAX2(win_height, vert->vec.y);
- }
-
- for (ScrArea *area = screen->areabase.first, *area_next; area; area = area_next) {
- area_next = area->next;
-
- if (area->spacetype == SPACE_INFO) {
- if ((area->v2->vec.y == win_height) && (area->v1->vec.x == 0) &&
- (area->v4->vec.x == win_width)) {
- BKE_screen_area_free(area);
-
- BLI_remlink(&screen->areabase, area);
-
- BKE_screen_remove_double_scredges(screen);
- BKE_screen_remove_unused_scredges(screen);
- BKE_screen_remove_unused_scrverts(screen);
-
- MEM_freeN(area);
- }
- }
- /* AREA_TEMP_INFO is deprecated from now on, it should only be set for info areas
- * which are deleted above, so don't need to unset it. Its slot/bit can be reused */
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 11)) {
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- if (la->mode & (1 << 13)) { /* LA_SHAD_RAY */
- la->mode |= LA_SHADOW;
- la->mode &= ~(1 << 13);
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 12)) {
- /* Remove tool property regions. */
- 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) {
- if (ELEM(sl->spacetype, SPACE_VIEW3D, SPACE_CLIP)) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
-
- for (ARegion *region = regionbase->first, *region_next; region; region = region_next) {
- region_next = region->next;
-
- if (region->regiontype == RGN_TYPE_TOOL_PROPS) {
- BKE_area_region_free(NULL, region);
- BLI_freelinkN(regionbase, region);
- }
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 13)) {
- /* Initialize specular factor. */
- if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "spec_fac")) {
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- la->spec_fac = 1.0f;
- }
- }
-
- /* Initialize new view3D options. */
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.light = V3D_LIGHTING_STUDIO;
- v3d->shading.color_type = V3D_SHADING_MATERIAL_COLOR;
- copy_v3_fl(v3d->shading.single_color, 0.8f);
- v3d->shading.shadow_intensity = 0.5;
-
- v3d->overlay.backwire_opacity = 0.5f;
- v3d->overlay.normals_length = 0.1f;
- v3d->overlay.flag = 0;
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 14)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Scene", "SceneDisplay", "display")) {
- /* Initialize new scene.SceneDisplay */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- copy_v3_v3(scene->display.light_direction, (float[3]){-M_SQRT1_3, -M_SQRT1_3, M_SQRT1_3});
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "float", "shadow_shift")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->display.shadow_shift = 0.1;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "transform_pivot_point")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->toolsettings->transform_pivot_point = V3D_AROUND_CENTER_MEDIAN;
- }
- }
-
- if (!DNA_struct_find(fd->filesdna, "SceneEEVEE")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- /* First set the default for all the properties. */
-
- scene->eevee.gi_diffuse_bounces = 3;
- scene->eevee.gi_cubemap_resolution = 512;
- scene->eevee.gi_visibility_resolution = 32;
-
- scene->eevee.taa_samples = 16;
- scene->eevee.taa_render_samples = 64;
-
- scene->eevee.sss_samples = 7;
- scene->eevee.sss_jitter_threshold = 0.3f;
-
- scene->eevee.ssr_quality = 0.25f;
- scene->eevee.ssr_max_roughness = 0.5f;
- scene->eevee.ssr_thickness = 0.2f;
- scene->eevee.ssr_border_fade = 0.075f;
- scene->eevee.ssr_firefly_fac = 10.0f;
-
- scene->eevee.volumetric_start = 0.1f;
- scene->eevee.volumetric_end = 100.0f;
- scene->eevee.volumetric_tile_size = 8;
- scene->eevee.volumetric_samples = 64;
- scene->eevee.volumetric_sample_distribution = 0.8f;
- scene->eevee.volumetric_light_clamp = 0.0f;
- scene->eevee.volumetric_shadow_samples = 16;
-
- scene->eevee.gtao_distance = 0.2f;
- scene->eevee.gtao_factor = 1.0f;
- scene->eevee.gtao_quality = 0.25f;
-
- scene->eevee.bokeh_max_size = 100.0f;
- scene->eevee.bokeh_threshold = 1.0f;
-
- copy_v3_fl(scene->eevee.bloom_color, 1.0f);
- scene->eevee.bloom_threshold = 0.8f;
- scene->eevee.bloom_knee = 0.5f;
- scene->eevee.bloom_intensity = 0.05f;
- scene->eevee.bloom_radius = 6.5f;
- scene->eevee.bloom_clamp = 0.0f;
-
- scene->eevee.motion_blur_samples = 8;
- scene->eevee.motion_blur_shutter = 0.5f;
-
- scene->eevee.shadow_method = SHADOW_ESM;
- scene->eevee.shadow_cube_size = 512;
- scene->eevee.shadow_cascade_size = 1024;
-
- scene->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | SCE_EEVEE_GTAO_BENT_NORMALS |
- SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION |
- SCE_EEVEE_SSR_HALF_RESOLUTION;
-
- /* If the file is pre-2.80 move on. */
- if (scene->layer_properties == NULL) {
- continue;
- }
-
- /* Now we handle eventual properties that may be set in the file. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 3)) {
+ /* init grease pencil grids and paper */
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.gpencil_paper_opacity = 0.5f;
+ v3d->overlay.gpencil_grid_opacity = 0.9f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 6)) {
+ if (DNA_struct_elem_find(fd->filesdna, "SpaceOutliner", "int", "filter") == false) {
+ bScreen* sc;
+ ScrArea* sa;
+ SpaceLink* sl;
+
+ /* Update files using invalid (outdated) outlinevis Outliner values. */
+ for (sc = bmain->screens.first; sc; sc = sc->id.next) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner* so = (SpaceOutliner*)sl;
+
+ if (!ELEM(so->outlinevis,
+ SO_SCENES,
+ SO_LIBRARIES,
+ SO_SEQUENCE,
+ SO_DATA_API,
+ SO_ID_ORPHANS)) {
+ so->outlinevis = SO_VIEW_LAYER;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "intensity")) {
+ for (LightProbe* probe = bmain->lightprobes.first; probe; probe = probe->id.next) {
+ probe->intensity = 1.0f;
+ }
+ }
+
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ bConstraint* con, * con_next;
+ con = ob->constraints.first;
+ while (con) {
+ con_next = con->next;
+ if (con->type == 17) { /* CONSTRAINT_TYPE_RIGIDBODYJOINT */
+ BLI_remlink(&ob->constraints, con);
+ BKE_constraint_free_data(con);
+ MEM_freeN(con);
+ }
+ con = con_next;
+ }
+ }
+
+ for (bScreen* sc = bmain->screens.first; sc; sc = sc->id.next) {
+ for (ScrArea* sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink* sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.light = V3D_LIGHTING_STUDIO;
+ v3d->shading.flag |= V3D_SHADING_OBJECT_OUTLINE;
+
+ /* Assume (demo) files written with 2.8 want to show
+ * Eevee renders in the viewport. */
+ if (MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ v3d->drawtype = OB_MATERIAL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 7)) {
+ /* Render engine storage moved elsewhere and back during 2.8
+ * development, we assume any files saved in 2.8 had Eevee set
+ * as scene render engine. */
+ if (MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine));
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 8)) {
+ /* Blender Internal removal */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (STREQ(scene->r.engine, "BLENDER_RENDER") || STREQ(scene->r.engine, "BLENDER_GAME")) {
+ BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine));
+ }
+
+ scene->r.bake_mode = 0;
+ }
+
+ for (Tex* tex = bmain->textures.first; tex; tex = tex->id.next) {
+ /* Removed envmap, pointdensity, voxeldata, ocean textures. */
+ if (ELEM(tex->type, 10, 14, 15, 16)) {
+ tex->type = 0;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 11)) {
+
+ /* Remove info editor, but only if at the top of the window. */
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ /* Calculate window width/height from screen vertices */
+ int win_width = 0, win_height = 0;
+ for (ScrVert* vert = screen->vertbase.first; vert; vert = vert->next) {
+ win_width = MAX2(win_width, vert->vec.x);
+ win_height = MAX2(win_height, vert->vec.y);
+ }
+
+ for (ScrArea* area = screen->areabase.first, *area_next; area; area = area_next) {
+ area_next = area->next;
+
+ if (area->spacetype == SPACE_INFO) {
+ if ((area->v2->vec.y == win_height) && (area->v1->vec.x == 0) &&
+ (area->v4->vec.x == win_width)) {
+ BKE_screen_area_free(area);
+
+ BLI_remlink(&screen->areabase, area);
+
+ BKE_screen_remove_double_scredges(screen);
+ BKE_screen_remove_unused_scredges(screen);
+ BKE_screen_remove_unused_scrverts(screen);
+
+ MEM_freeN(area);
+ }
+ }
+ /* AREA_TEMP_INFO is deprecated from now on, it should only be set for info areas
+ * which are deleted above, so don't need to unset it. Its slot/bit can be reused */
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 11)) {
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ if (la->mode & (1 << 13)) { /* LA_SHAD_RAY */
+ la->mode |= LA_SHADOW;
+ la->mode &= ~(1 << 13);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 12)) {
+ /* Remove tool property regions. */
+ 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) {
+ if (ELEM(sl->spacetype, SPACE_VIEW3D, SPACE_CLIP)) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+
+ for (ARegion* region = regionbase->first, *region_next; region; region = region_next) {
+ region_next = region->next;
+
+ if (region->regiontype == RGN_TYPE_TOOL_PROPS) {
+ BKE_area_region_free(NULL, region);
+ BLI_freelinkN(regionbase, region);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 13)) {
+ /* Initialize specular factor. */
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "spec_fac")) {
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ la->spec_fac = 1.0f;
+ }
+ }
+
+ /* Initialize new view3D options. */
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.light = V3D_LIGHTING_STUDIO;
+ v3d->shading.color_type = V3D_SHADING_MATERIAL_COLOR;
+ copy_v3_fl(v3d->shading.single_color, 0.8f);
+ v3d->shading.shadow_intensity = 0.5;
+
+ v3d->overlay.backwire_opacity = 0.5f;
+ v3d->overlay.normals_length = 0.1f;
+ v3d->overlay.flag = 0;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 14)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Scene", "SceneDisplay", "display")) {
+ /* Initialize new scene.SceneDisplay */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ copy_v3_v3(scene->display.light_direction, (float[3]) { -M_SQRT1_3, -M_SQRT1_3, M_SQRT1_3 });
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "float", "shadow_shift")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->display.shadow_shift = 0.1;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "transform_pivot_point")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->toolsettings->transform_pivot_point = V3D_AROUND_CENTER_MEDIAN;
+ }
+ }
+
+ if (!DNA_struct_find(fd->filesdna, "SceneEEVEE")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ /* First set the default for all the properties. */
+
+ scene->eevee.gi_diffuse_bounces = 3;
+ scene->eevee.gi_cubemap_resolution = 512;
+ scene->eevee.gi_visibility_resolution = 32;
+
+ scene->eevee.taa_samples = 16;
+ scene->eevee.taa_render_samples = 64;
+
+ scene->eevee.sss_samples = 7;
+ scene->eevee.sss_jitter_threshold = 0.3f;
+
+ scene->eevee.ssr_quality = 0.25f;
+ scene->eevee.ssr_max_roughness = 0.5f;
+ scene->eevee.ssr_thickness = 0.2f;
+ scene->eevee.ssr_border_fade = 0.075f;
+ scene->eevee.ssr_firefly_fac = 10.0f;
+
+ scene->eevee.volumetric_start = 0.1f;
+ scene->eevee.volumetric_end = 100.0f;
+ scene->eevee.volumetric_tile_size = 8;
+ scene->eevee.volumetric_samples = 64;
+ scene->eevee.volumetric_sample_distribution = 0.8f;
+ scene->eevee.volumetric_light_clamp = 0.0f;
+ scene->eevee.volumetric_shadow_samples = 16;
+
+ scene->eevee.gtao_distance = 0.2f;
+ scene->eevee.gtao_factor = 1.0f;
+ scene->eevee.gtao_quality = 0.25f;
+
+ scene->eevee.bokeh_max_size = 100.0f;
+ scene->eevee.bokeh_threshold = 1.0f;
+
+ copy_v3_fl(scene->eevee.bloom_color, 1.0f);
+ scene->eevee.bloom_threshold = 0.8f;
+ scene->eevee.bloom_knee = 0.5f;
+ scene->eevee.bloom_intensity = 0.05f;
+ scene->eevee.bloom_radius = 6.5f;
+ scene->eevee.bloom_clamp = 0.0f;
+
+ scene->eevee.motion_blur_samples = 8;
+ scene->eevee.motion_blur_shutter = 0.5f;
+
+ scene->eevee.shadow_method = SHADOW_ESM;
+ scene->eevee.shadow_cube_size = 512;
+ scene->eevee.shadow_cascade_size = 1024;
+
+ scene->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | SCE_EEVEE_GTAO_BENT_NORMALS |
+ SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION |
+ SCE_EEVEE_SSR_HALF_RESOLUTION;
+
+ /* If the file is pre-2.80 move on. */
+ if (scene->layer_properties == NULL) {
+ continue;
+ }
+
+ /* Now we handle eventual properties that may be set in the file. */
#define EEVEE_GET_BOOL(_props, _name, _flag) \
{ \
IDProperty *_idprop = IDP_GetPropertyFromGroup(_props, #_name); \
@@ -2186,812 +2188,812 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
} \
} \
((void)0)
- const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
- IDProperty *props = IDP_GetPropertyFromGroup(scene->layer_properties,
- RE_engine_id_BLENDER_EEVEE);
- // EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
- EEVEE_GET_BOOL(props, volumetric_lights, SCE_EEVEE_VOLUMETRIC_LIGHTS);
- EEVEE_GET_BOOL(props, volumetric_shadows, SCE_EEVEE_VOLUMETRIC_SHADOWS);
- EEVEE_GET_BOOL(props, gtao_enable, SCE_EEVEE_GTAO_ENABLED);
- EEVEE_GET_BOOL(props, gtao_use_bent_normals, SCE_EEVEE_GTAO_BENT_NORMALS);
- EEVEE_GET_BOOL(props, gtao_bounce, SCE_EEVEE_GTAO_BOUNCE);
- EEVEE_GET_BOOL(props, dof_enable, SCE_EEVEE_DOF_ENABLED);
- EEVEE_GET_BOOL(props, bloom_enable, SCE_EEVEE_BLOOM_ENABLED);
- EEVEE_GET_BOOL(props, motion_blur_enable, SCE_EEVEE_MOTION_BLUR_ENABLED);
- EEVEE_GET_BOOL(props, shadow_high_bitdepth, SCE_EEVEE_SHADOW_HIGH_BITDEPTH);
- EEVEE_GET_BOOL(props, taa_reprojection, SCE_EEVEE_TAA_REPROJECTION);
- // EEVEE_GET_BOOL(props, sss_enable, SCE_EEVEE_SSS_ENABLED);
- // EEVEE_GET_BOOL(props, sss_separate_albedo, SCE_EEVEE_SSS_SEPARATE_ALBEDO);
- EEVEE_GET_BOOL(props, ssr_enable, SCE_EEVEE_SSR_ENABLED);
- EEVEE_GET_BOOL(props, ssr_refraction, SCE_EEVEE_SSR_REFRACTION);
- EEVEE_GET_BOOL(props, ssr_halfres, SCE_EEVEE_SSR_HALF_RESOLUTION);
-
- EEVEE_GET_INT(props, gi_diffuse_bounces);
- EEVEE_GET_INT(props, gi_diffuse_bounces);
- EEVEE_GET_INT(props, gi_cubemap_resolution);
- EEVEE_GET_INT(props, gi_visibility_resolution);
-
- EEVEE_GET_INT(props, taa_samples);
- EEVEE_GET_INT(props, taa_render_samples);
-
- EEVEE_GET_INT(props, sss_samples);
- EEVEE_GET_FLOAT(props, sss_jitter_threshold);
-
- EEVEE_GET_FLOAT(props, ssr_quality);
- EEVEE_GET_FLOAT(props, ssr_max_roughness);
- EEVEE_GET_FLOAT(props, ssr_thickness);
- EEVEE_GET_FLOAT(props, ssr_border_fade);
- EEVEE_GET_FLOAT(props, ssr_firefly_fac);
-
- EEVEE_GET_FLOAT(props, volumetric_start);
- EEVEE_GET_FLOAT(props, volumetric_end);
- EEVEE_GET_INT(props, volumetric_tile_size);
- EEVEE_GET_INT(props, volumetric_samples);
- EEVEE_GET_FLOAT(props, volumetric_sample_distribution);
- EEVEE_GET_FLOAT(props, volumetric_light_clamp);
- EEVEE_GET_INT(props, volumetric_shadow_samples);
-
- EEVEE_GET_FLOAT(props, gtao_distance);
- EEVEE_GET_FLOAT(props, gtao_factor);
- EEVEE_GET_FLOAT(props, gtao_quality);
-
- EEVEE_GET_FLOAT(props, bokeh_max_size);
- EEVEE_GET_FLOAT(props, bokeh_threshold);
-
- EEVEE_GET_FLOAT_ARRAY(props, bloom_color, 3);
- EEVEE_GET_FLOAT(props, bloom_threshold);
- EEVEE_GET_FLOAT(props, bloom_knee);
- EEVEE_GET_FLOAT(props, bloom_intensity);
- EEVEE_GET_FLOAT(props, bloom_radius);
- EEVEE_GET_FLOAT(props, bloom_clamp);
-
- EEVEE_GET_INT(props, motion_blur_samples);
- EEVEE_GET_FLOAT(props, motion_blur_shutter);
-
- EEVEE_GET_INT(props, shadow_method);
- EEVEE_GET_INT(props, shadow_cube_size);
- EEVEE_GET_INT(props, shadow_cascade_size);
-
- /* Cleanup. */
- IDP_FreeProperty(scene->layer_properties);
- scene->layer_properties = NULL;
+ const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
+ IDProperty* props = IDP_GetPropertyFromGroup(scene->layer_properties,
+ RE_engine_id_BLENDER_EEVEE);
+ // EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
+ EEVEE_GET_BOOL(props, volumetric_lights, SCE_EEVEE_VOLUMETRIC_LIGHTS);
+ EEVEE_GET_BOOL(props, volumetric_shadows, SCE_EEVEE_VOLUMETRIC_SHADOWS);
+ EEVEE_GET_BOOL(props, gtao_enable, SCE_EEVEE_GTAO_ENABLED);
+ EEVEE_GET_BOOL(props, gtao_use_bent_normals, SCE_EEVEE_GTAO_BENT_NORMALS);
+ EEVEE_GET_BOOL(props, gtao_bounce, SCE_EEVEE_GTAO_BOUNCE);
+ EEVEE_GET_BOOL(props, dof_enable, SCE_EEVEE_DOF_ENABLED);
+ EEVEE_GET_BOOL(props, bloom_enable, SCE_EEVEE_BLOOM_ENABLED);
+ EEVEE_GET_BOOL(props, motion_blur_enable, SCE_EEVEE_MOTION_BLUR_ENABLED);
+ EEVEE_GET_BOOL(props, shadow_high_bitdepth, SCE_EEVEE_SHADOW_HIGH_BITDEPTH);
+ EEVEE_GET_BOOL(props, taa_reprojection, SCE_EEVEE_TAA_REPROJECTION);
+ // EEVEE_GET_BOOL(props, sss_enable, SCE_EEVEE_SSS_ENABLED);
+ // EEVEE_GET_BOOL(props, sss_separate_albedo, SCE_EEVEE_SSS_SEPARATE_ALBEDO);
+ EEVEE_GET_BOOL(props, ssr_enable, SCE_EEVEE_SSR_ENABLED);
+ EEVEE_GET_BOOL(props, ssr_refraction, SCE_EEVEE_SSR_REFRACTION);
+ EEVEE_GET_BOOL(props, ssr_halfres, SCE_EEVEE_SSR_HALF_RESOLUTION);
+
+ EEVEE_GET_INT(props, gi_diffuse_bounces);
+ EEVEE_GET_INT(props, gi_diffuse_bounces);
+ EEVEE_GET_INT(props, gi_cubemap_resolution);
+ EEVEE_GET_INT(props, gi_visibility_resolution);
+
+ EEVEE_GET_INT(props, taa_samples);
+ EEVEE_GET_INT(props, taa_render_samples);
+
+ EEVEE_GET_INT(props, sss_samples);
+ EEVEE_GET_FLOAT(props, sss_jitter_threshold);
+
+ EEVEE_GET_FLOAT(props, ssr_quality);
+ EEVEE_GET_FLOAT(props, ssr_max_roughness);
+ EEVEE_GET_FLOAT(props, ssr_thickness);
+ EEVEE_GET_FLOAT(props, ssr_border_fade);
+ EEVEE_GET_FLOAT(props, ssr_firefly_fac);
+
+ EEVEE_GET_FLOAT(props, volumetric_start);
+ EEVEE_GET_FLOAT(props, volumetric_end);
+ EEVEE_GET_INT(props, volumetric_tile_size);
+ EEVEE_GET_INT(props, volumetric_samples);
+ EEVEE_GET_FLOAT(props, volumetric_sample_distribution);
+ EEVEE_GET_FLOAT(props, volumetric_light_clamp);
+ EEVEE_GET_INT(props, volumetric_shadow_samples);
+
+ EEVEE_GET_FLOAT(props, gtao_distance);
+ EEVEE_GET_FLOAT(props, gtao_factor);
+ EEVEE_GET_FLOAT(props, gtao_quality);
+
+ EEVEE_GET_FLOAT(props, bokeh_max_size);
+ EEVEE_GET_FLOAT(props, bokeh_threshold);
+
+ EEVEE_GET_FLOAT_ARRAY(props, bloom_color, 3);
+ EEVEE_GET_FLOAT(props, bloom_threshold);
+ EEVEE_GET_FLOAT(props, bloom_knee);
+ EEVEE_GET_FLOAT(props, bloom_intensity);
+ EEVEE_GET_FLOAT(props, bloom_radius);
+ EEVEE_GET_FLOAT(props, bloom_clamp);
+
+ EEVEE_GET_INT(props, motion_blur_samples);
+ EEVEE_GET_FLOAT(props, motion_blur_shutter);
+
+ EEVEE_GET_INT(props, shadow_method);
+ EEVEE_GET_INT(props, shadow_cube_size);
+ EEVEE_GET_INT(props, shadow_cascade_size);
+
+ /* Cleanup. */
+ IDP_FreeProperty(scene->layer_properties);
+ scene->layer_properties = NULL;
#undef EEVEE_GET_FLOAT_ARRAY
#undef EEVEE_GET_FLOAT
#undef EEVEE_GET_INT
#undef EEVEE_GET_BOOL
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 15)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->display.matcap_ssao_distance = 0.2f;
- scene->display.matcap_ssao_attenuation = 1.0f;
- scene->display.matcap_ssao_samples = 16;
- }
-
- 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) {
- if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *soops = (SpaceOutliner *)sl;
- soops->filter_id_type = ID_GR;
- soops->outlinevis = SO_VIEW_LAYER;
- }
- }
- }
- }
-
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- switch (scene->toolsettings->snap_mode) {
- case 0:
- scene->toolsettings->snap_mode = SCE_SNAP_MODE_INCREMENT;
- break;
- case 1:
- scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX;
- break;
- case 2:
- scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE;
- break;
- case 3:
- scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE;
- break;
- case 4:
- scene->toolsettings->snap_mode = SCE_SNAP_MODE_VOLUME;
- break;
- }
- switch (scene->toolsettings->snap_node_mode) {
- case 5:
- scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_X;
- break;
- case 6:
- scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_Y;
- break;
- case 7:
- scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y;
- break;
- case 8:
- scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
- break;
- }
- switch (scene->toolsettings->snap_uv_mode) {
- case 0:
- scene->toolsettings->snap_uv_mode = SCE_SNAP_MODE_INCREMENT;
- break;
- case 1:
- scene->toolsettings->snap_uv_mode = SCE_SNAP_MODE_VERTEX;
- break;
- }
- }
-
- ParticleSettings *part;
- for (part = bmain->particles.first; part; part = part->id.next) {
- part->shape_flag = PART_SHAPE_CLOSE_TIP;
- part->shape = 0.0f;
- part->rad_root = 1.0f;
- part->rad_tip = 0.0f;
- part->rad_scale = 0.01f;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 18)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Material", "float", "roughness")) {
- for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) {
- if (mat->use_nodes) {
- if (MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
- mat->roughness = mat->gloss_mir;
- }
- else {
- mat->roughness = 0.25f;
- }
- }
- else {
- mat->roughness = 1.0f - mat->gloss_mir;
- }
- mat->metallic = mat->ray_mirror;
- }
-
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.flag |= V3D_SHADING_SPECULAR_HIGHLIGHT;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "xray_alpha")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.xray_alpha = 0.5f;
- }
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "matcap[256]")) {
- StudioLight *default_matcap = BKE_studiolight_find_default(STUDIOLIGHT_TYPE_MATCAP);
- /* when loading the internal file is loaded before the matcaps */
- if (default_matcap) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BLI_strncpy(v3d->shading.matcap, default_matcap->name, FILE_MAXFILE);
- }
- }
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "wireframe_threshold")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.wireframe_threshold = 0.5f;
- }
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "cavity_valley_factor")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.cavity_valley_factor = 1.0f;
- v3d->shading.cavity_ridge_factor = 1.0f;
- }
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "xray_alpha_bone")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.xray_alpha_bone = 0.5f;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 19)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Image", "ListBase", "renderslot")) {
- for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
- if (ima->type == IMA_TYPE_R_RESULT) {
- for (int i = 0; i < 8; i++) {
- RenderSlot *slot = MEM_callocN(sizeof(RenderSlot), "Image Render Slot Init");
- BLI_snprintf(slot->name, sizeof(slot->name), "Slot %d", i + 1);
- BLI_addtail(&ima->renderslots, slot);
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "SpaceAction", "char", "mode_prev")) {
- 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) {
- if (sl->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sl;
- /* "Dopesheet" should be default here,
- * unless it looks like the Action Editor was active instead. */
- if ((saction->mode_prev == 0) && (saction->action == NULL)) {
- saction->mode_prev = SACTCONT_DOPESHEET;
- }
- }
- }
- }
- }
- }
-
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- if (v3d->drawtype == OB_TEXTURE) {
- v3d->drawtype = OB_SOLID;
- v3d->shading.light = V3D_LIGHTING_STUDIO;
- v3d->shading.color_type = V3D_SHADING_TEXTURE_COLOR;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 21)) {
- for (Scene *sce = bmain->scenes.first; sce != NULL; sce = sce->id.next) {
- if (sce->ed != NULL && sce->ed->seqbase.first != NULL) {
- do_versions_seq_unique_name_all_strips(sce, &sce->ed->seqbase);
- }
- }
-
- if (!DNA_struct_elem_find(
- fd->filesdna, "View3DOverlay", "float", "texture_paint_mode_opacity")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- enum {
- V3D_SHOW_MODE_SHADE_OVERRIDE = (1 << 15),
- };
- View3D *v3d = (View3D *)sl;
- float alpha = v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE ? 0.0f : 1.0f;
- v3d->overlay.texture_paint_mode_opacity = alpha;
- v3d->overlay.vertex_paint_mode_opacity = alpha;
- v3d->overlay.weight_paint_mode_opacity = alpha;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "background_type")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- copy_v3_fl(v3d->shading.background_color, 0.05f);
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_cubemap_draw_size")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->eevee.gi_irradiance_draw_size = 0.1f;
- scene->eevee.gi_cubemap_draw_size = 0.3f;
- }
- }
-
- if (!DNA_struct_elem_find(
- fd->filesdna, "RigidBodyWorld", "RigidBodyWorld_Shared", "*shared")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- RigidBodyWorld *rbw = scene->rigidbody_world;
-
- if (rbw == NULL) {
- continue;
- }
-
- if (rbw->shared == NULL) {
- rbw->shared = MEM_callocN(sizeof(*rbw->shared), "RigidBodyWorld_Shared");
- }
-
- /* Move shared pointers from deprecated location to current location */
- rbw->shared->pointcache = rbw->pointcache;
- rbw->shared->ptcaches = rbw->ptcaches;
-
- rbw->pointcache = NULL;
- BLI_listbase_clear(&rbw->ptcaches);
-
- if (rbw->shared->pointcache == NULL) {
- rbw->shared->pointcache = BKE_ptcache_add(&(rbw->shared->ptcaches));
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SoftBody", "SoftBody_Shared", "*shared")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- SoftBody *sb = ob->soft;
- if (sb == NULL) {
- continue;
- }
- if (sb->shared == NULL) {
- sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
- }
-
- /* Move shared pointers from deprecated location to current location */
- sb->shared->pointcache = sb->pointcache;
- sb->shared->ptcaches = sb->ptcaches;
-
- sb->pointcache = NULL;
- BLI_listbase_clear(&sb->ptcaches);
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "short", "type")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- if (v3d->drawtype == OB_RENDER) {
- v3d->drawtype = OB_SOLID;
- }
- v3d->shading.type = v3d->drawtype;
- v3d->shading.prev_type = OB_SOLID;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "View3DShading", "shading")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- BKE_screen_view3d_shading_init(&scene->display.shading);
- }
- }
- /* initialize grease pencil view data */
- if (!DNA_struct_elem_find(fd->filesdna, "SpaceView3D", "float", "vertex_opacity")) {
- for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->vertex_opacity = 1.0f;
- v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 22)) {
- if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "annotate_v3d_align")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->toolsettings->annotate_v3d_align = GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR;
- scene->toolsettings->annotate_thickness = 3;
- }
- }
- 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) {
- gpl->line_change = gpl->thickness;
- if ((gpl->thickness < 1) || (gpl->thickness > 10)) {
- gpl->thickness = 3;
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_paper_opacity")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.gpencil_paper_opacity = 0.5f;
- }
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_grid_opacity")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.gpencil_grid_opacity = 0.5f;
- }
- }
- }
- }
- }
-
- /* default loc axis */
- if (!DNA_struct_elem_find(fd->filesdna, "GP_Sculpt_Settings", "int", "lock_axis")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- /* lock axis */
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- if (gset) {
- gset->lock_axis = GP_LOCKAXIS_Y;
- }
- }
- }
-
- /* Versioning code for Subsurf modifier. */
- if (!DNA_struct_elem_find(fd->filesdna, "SubsurfModifier", "short", "uv_smooth")) {
- for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- for (ModifierData *md = object->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Subsurf) {
- SubsurfModifierData *smd = (SubsurfModifierData *)md;
- if (smd->flags & eSubsurfModifierFlag_SubsurfUv_DEPRECATED) {
- smd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
- }
- else {
- smd->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SubsurfModifier", "short", "quality")) {
- for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- for (ModifierData *md = object->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Subsurf) {
- SubsurfModifierData *smd = (SubsurfModifierData *)md;
- smd->quality = min_ii(smd->renderLevels, 3);
- }
- }
- }
- }
- /* Versioning code for Multires modifier. */
- if (!DNA_struct_elem_find(fd->filesdna, "MultiresModifier", "short", "quality")) {
- for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- for (ModifierData *md = object->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Multires) {
- MultiresModifierData *mmd = (MultiresModifierData *)md;
- mmd->quality = 3;
- if (mmd->flags & eMultiresModifierFlag_PlainUv_DEPRECATED) {
- mmd->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
- }
- else {
- mmd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "short", "bending_model")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- ClothModifierData *clmd = NULL;
- if (md->type == eModifierType_Cloth) {
- clmd = (ClothModifierData *)md;
- }
- else if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
- ParticleSystem *psys = psmd->psys;
- clmd = psys->clmd;
- }
- if (clmd != NULL) {
- clmd->sim_parms->bending_model = CLOTH_BENDING_LINEAR;
- clmd->sim_parms->tension = clmd->sim_parms->structural;
- clmd->sim_parms->compression = clmd->sim_parms->structural;
- clmd->sim_parms->shear = clmd->sim_parms->structural;
- clmd->sim_parms->max_tension = clmd->sim_parms->max_struct;
- clmd->sim_parms->max_compression = clmd->sim_parms->max_struct;
- clmd->sim_parms->max_shear = clmd->sim_parms->max_struct;
- clmd->sim_parms->vgroup_shear = clmd->sim_parms->vgroup_struct;
- clmd->sim_parms->tension_damp = clmd->sim_parms->Cdis;
- clmd->sim_parms->compression_damp = clmd->sim_parms->Cdis;
- clmd->sim_parms->shear_damp = clmd->sim_parms->Cdis;
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "era_strength_f")) {
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if (brush->gpencil_settings != NULL) {
- BrushGpencilSettings *gp = brush->gpencil_settings;
- if (gp->brush_type == GPAINT_TOOL_ERASE) {
- gp->era_strength_f = 100.0f;
- gp->era_thickness_f = 10.0f;
- }
- }
- }
- }
-
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData *)md;
-
- if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) {
- clmd->sim_parms->vgroup_mass = 0;
- }
-
- if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)) {
- clmd->sim_parms->vgroup_struct = 0;
- clmd->sim_parms->vgroup_shear = 0;
- clmd->sim_parms->vgroup_bend = 0;
- }
-
- if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW)) {
- clmd->sim_parms->shrink_min = 0.0f;
- clmd->sim_parms->vgroup_shrink = 0;
- }
-
- if (!(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)) {
- clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 24)) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_FACES | V3D_OVERLAY_EDIT_SEAMS |
- V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE |
- V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES |
- V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS |
- V3D_OVERLAY_EDIT_CU_HANDLES | V3D_OVERLAY_EDIT_CU_NORMALS;
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "ShrinkwrapModifierData", "char", "shrinkMode")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Shrinkwrap) {
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
- if (smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) {
- smd->shrinkMode = MOD_SHRINKWRAP_ABOVE_SURFACE;
- smd->shrinkOpts &= ~MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "pdef_cfrict")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->pd) {
- ob->pd->pdef_cfrict = 5.0f;
- }
-
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData *)md;
-
- clmd->coll_parms->selfepsilon = 0.015f;
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "xray_alpha_wire")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.flag |= V3D_SHADING_XRAY_WIREFRAME;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 25)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- UnitSettings *unit = &scene->unit;
- if (unit->system != USER_UNIT_NONE) {
- unit->length_unit = bUnit_GetBaseUnitOfType(scene->unit.system, B_UNIT_LENGTH);
- unit->mass_unit = bUnit_GetBaseUnitOfType(scene->unit.system, B_UNIT_MASS);
- }
- unit->time_unit = bUnit_GetBaseUnitOfType(USER_UNIT_NONE, B_UNIT_TIME);
- }
-
- /* gpencil grid settings */
- for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); // Color
- ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); // Scale
- gpd->grid.lines = GP_DEFAULT_GRID_LINES; // Number of lines
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 28)) {
- for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
- BKE_mesh_calc_edges_loose(mesh);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 29)) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- enum { V3D_OCCLUDE_WIRE = (1 << 14) };
- View3D *v3d = (View3D *)sl;
- if (v3d->flag2 & V3D_OCCLUDE_WIRE) {
- v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_OCCLUDE_WIRE;
- v3d->flag2 &= ~V3D_OCCLUDE_WIRE;
- }
- }
- }
- }
- }
-
- /* Files stored pre 2.5 (possibly re-saved with newer versions) may have non-visible
- * spaces without a header (visible/active ones are properly versioned).
- * Multiple version patches below assume there's always a header though. So inserting this
- * patch in-between older ones to add a header when needed.
- *
- * From here on it should be fine to assume there always is a header.
- */
- if (!MAIN_VERSION_ATLEAST(bmain, 283, 1)) {
- 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) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- ARegion *ar_header = do_versions_find_region_or_null(regionbase, RGN_TYPE_HEADER);
-
- if (!ar_header) {
- /* Headers should always be first in the region list, except if there's also a
- * tool-header. These were only introduced in later versions though, so should be
- * fine to always insert headers first. */
- BLI_assert(!do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOL_HEADER));
-
- ARegion *ar = do_versions_add_region(RGN_TYPE_HEADER, "header 2.83.1 versioning");
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
- BLI_addhead(regionbase, ar);
- }
- }
- }
- }
- }
-
- 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) {
- if (sl->spacetype == SPACE_PROPERTIES) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- ARegion *ar = MEM_callocN(sizeof(ARegion), "navigation bar for properties");
- ARegion *ar_header = NULL;
-
- for (ar_header = regionbase->first; ar_header; ar_header = ar_header->next) {
- if (ar_header->regiontype == RGN_TYPE_HEADER) {
- break;
- }
- }
- BLI_assert(ar_header);
-
- BLI_insertlinkafter(regionbase, ar_header, ar);
-
- ar->regiontype = RGN_TYPE_NAV_BAR;
- ar->alignment = RGN_ALIGN_LEFT;
- }
- }
- }
- }
-
- /* grease pencil fade layer opacity */
- if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_fade_layer")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.gpencil_fade_layer = 0.5f;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 30)) {
- /* 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;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 33)) {
-
- if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "overscan")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->eevee.overscan = 3.0f;
- }
- }
-
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- /* Removed Hemi lights. */
- if (!ELEM(la->type, LA_LOCAL, LA_SUN, LA_SPOT, LA_AREA)) {
- la->type = LA_SUN;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "light_threshold")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->eevee.light_threshold = 0.01f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_irradiance_smoothing")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->eevee.gi_irradiance_smoothing = 0.1f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_filter_quality")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->eevee.gi_filter_quality = 1.0f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "att_dist")) {
- for (Light *la = bmain->lights.first; la; la = la->id.next) {
- la->att_dist = la->clipend;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "Brush", "char", "weightpaint_tool")) {
- /* Magic defines from old files (2.7x) */
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 15)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->display.matcap_ssao_distance = 0.2f;
+ scene->display.matcap_ssao_attenuation = 1.0f;
+ scene->display.matcap_ssao_samples = 16;
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner* soops = (SpaceOutliner*)sl;
+ soops->filter_id_type = ID_GR;
+ soops->outlinevis = SO_VIEW_LAYER;
+ }
+ }
+ }
+ }
+
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ switch (scene->toolsettings->snap_mode) {
+ case 0:
+ scene->toolsettings->snap_mode = SCE_SNAP_MODE_INCREMENT;
+ break;
+ case 1:
+ scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX;
+ break;
+ case 2:
+ scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE;
+ break;
+ case 3:
+ scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE;
+ break;
+ case 4:
+ scene->toolsettings->snap_mode = SCE_SNAP_MODE_VOLUME;
+ break;
+ }
+ switch (scene->toolsettings->snap_node_mode) {
+ case 5:
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_X;
+ break;
+ case 6:
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_Y;
+ break;
+ case 7:
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y;
+ break;
+ case 8:
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
+ break;
+ }
+ switch (scene->toolsettings->snap_uv_mode) {
+ case 0:
+ scene->toolsettings->snap_uv_mode = SCE_SNAP_MODE_INCREMENT;
+ break;
+ case 1:
+ scene->toolsettings->snap_uv_mode = SCE_SNAP_MODE_VERTEX;
+ break;
+ }
+ }
+
+ ParticleSettings* part;
+ for (part = bmain->particles.first; part; part = part->id.next) {
+ part->shape_flag = PART_SHAPE_CLOSE_TIP;
+ part->shape = 0.0f;
+ part->rad_root = 1.0f;
+ part->rad_tip = 0.0f;
+ part->rad_scale = 0.01f;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 18)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Material", "float", "roughness")) {
+ for (Material* mat = bmain->materials.first; mat; mat = mat->id.next) {
+ if (mat->use_nodes) {
+ if (MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
+ mat->roughness = mat->gloss_mir;
+ }
+ else {
+ mat->roughness = 0.25f;
+ }
+ }
+ else {
+ mat->roughness = 1.0f - mat->gloss_mir;
+ }
+ mat->metallic = mat->ray_mirror;
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.flag |= V3D_SHADING_SPECULAR_HIGHLIGHT;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "xray_alpha")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.xray_alpha = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "matcap[256]")) {
+ StudioLight* default_matcap = BKE_studiolight_find_default(STUDIOLIGHT_TYPE_MATCAP);
+ /* when loading the internal file is loaded before the matcaps */
+ if (default_matcap) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ BLI_strncpy(v3d->shading.matcap, default_matcap->name, FILE_MAXFILE);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "wireframe_threshold")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.wireframe_threshold = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "cavity_valley_factor")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.cavity_valley_factor = 1.0f;
+ v3d->shading.cavity_ridge_factor = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "xray_alpha_bone")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.xray_alpha_bone = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 19)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Image", "ListBase", "renderslot")) {
+ for (Image* ima = bmain->images.first; ima; ima = ima->id.next) {
+ if (ima->type == IMA_TYPE_R_RESULT) {
+ for (int i = 0; i < 8; i++) {
+ RenderSlot* slot = MEM_callocN(sizeof(RenderSlot), "Image Render Slot Init");
+ BLI_snprintf(slot->name, sizeof(slot->name), "Slot %d", i + 1);
+ BLI_addtail(&ima->renderslots, slot);
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "SpaceAction", "char", "mode_prev")) {
+ 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) {
+ if (sl->spacetype == SPACE_ACTION) {
+ SpaceAction* saction = (SpaceAction*)sl;
+ /* "Dopesheet" should be default here,
+ * unless it looks like the Action Editor was active instead. */
+ if ((saction->mode_prev == 0) && (saction->action == NULL)) {
+ saction->mode_prev = SACTCONT_DOPESHEET;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ if (v3d->drawtype == OB_TEXTURE) {
+ v3d->drawtype = OB_SOLID;
+ v3d->shading.light = V3D_LIGHTING_STUDIO;
+ v3d->shading.color_type = V3D_SHADING_TEXTURE_COLOR;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 21)) {
+ for (Scene* sce = bmain->scenes.first; sce != NULL; sce = sce->id.next) {
+ if (sce->ed != NULL && sce->ed->seqbase.first != NULL) {
+ do_versions_seq_unique_name_all_strips(sce, &sce->ed->seqbase);
+ }
+ }
+
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "View3DOverlay", "float", "texture_paint_mode_opacity")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ enum {
+ V3D_SHOW_MODE_SHADE_OVERRIDE = (1 << 15),
+ };
+ View3D* v3d = (View3D*)sl;
+ float alpha = v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE ? 0.0f : 1.0f;
+ v3d->overlay.texture_paint_mode_opacity = alpha;
+ v3d->overlay.vertex_paint_mode_opacity = alpha;
+ v3d->overlay.weight_paint_mode_opacity = alpha;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "background_type")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ copy_v3_fl(v3d->shading.background_color, 0.05f);
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_cubemap_draw_size")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->eevee.gi_irradiance_draw_size = 0.1f;
+ scene->eevee.gi_cubemap_draw_size = 0.3f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "RigidBodyWorld", "RigidBodyWorld_Shared", "*shared")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ RigidBodyWorld* rbw = scene->rigidbody_world;
+
+ if (rbw == NULL) {
+ continue;
+ }
+
+ if (rbw->shared == NULL) {
+ rbw->shared = MEM_callocN(sizeof(*rbw->shared), "RigidBodyWorld_Shared");
+ }
+
+ /* Move shared pointers from deprecated location to current location */
+ rbw->shared->pointcache = rbw->pointcache;
+ rbw->shared->ptcaches = rbw->ptcaches;
+
+ rbw->pointcache = NULL;
+ BLI_listbase_clear(&rbw->ptcaches);
+
+ if (rbw->shared->pointcache == NULL) {
+ rbw->shared->pointcache = BKE_ptcache_add(&(rbw->shared->ptcaches));
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SoftBody", "SoftBody_Shared", "*shared")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ SoftBody* sb = ob->soft;
+ if (sb == NULL) {
+ continue;
+ }
+ if (sb->shared == NULL) {
+ sb->shared = MEM_callocN(sizeof(*sb->shared), "SoftBody_Shared");
+ }
+
+ /* Move shared pointers from deprecated location to current location */
+ sb->shared->pointcache = sb->pointcache;
+ sb->shared->ptcaches = sb->ptcaches;
+
+ sb->pointcache = NULL;
+ BLI_listbase_clear(&sb->ptcaches);
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "short", "type")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ if (v3d->drawtype == OB_RENDER) {
+ v3d->drawtype = OB_SOLID;
+ }
+ v3d->shading.type = v3d->drawtype;
+ v3d->shading.prev_type = OB_SOLID;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "View3DShading", "shading")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ BKE_screen_view3d_shading_init(&scene->display.shading);
+ }
+ }
+ /* initialize grease pencil view data */
+ if (!DNA_struct_elem_find(fd->filesdna, "SpaceView3D", "float", "vertex_opacity")) {
+ for (bScreen* sc = bmain->screens.first; sc; sc = sc->id.next) {
+ for (ScrArea* sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink* sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->vertex_opacity = 1.0f;
+ v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 22)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "annotate_v3d_align")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->toolsettings->annotate_v3d_align = GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR;
+ scene->toolsettings->annotate_thickness = 3;
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "short", "line_change")) {
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ gpl->line_change = gpl->thickness;
+ if ((gpl->thickness < 1) || (gpl->thickness > 10)) {
+ gpl->thickness = 3;
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_paper_opacity")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.gpencil_paper_opacity = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_grid_opacity")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.gpencil_grid_opacity = 0.5f;
+ }
+ }
+ }
+ }
+ }
+
+ /* default loc axis */
+ if (!DNA_struct_elem_find(fd->filesdna, "GP_Sculpt_Settings", "int", "lock_axis")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ /* lock axis */
+ GP_Sculpt_Settings* gset = &scene->toolsettings->gp_sculpt;
+ if (gset) {
+ gset->lock_axis = GP_LOCKAXIS_Y;
+ }
+ }
+ }
+
+ /* Versioning code for Subsurf modifier. */
+ if (!DNA_struct_elem_find(fd->filesdna, "SubsurfModifier", "short", "uv_smooth")) {
+ for (Object* object = bmain->objects.first; object != NULL; object = object->id.next) {
+ for (ModifierData* md = object->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Subsurf) {
+ SubsurfModifierData* smd = (SubsurfModifierData*)md;
+ if (smd->flags & eSubsurfModifierFlag_SubsurfUv_DEPRECATED) {
+ smd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
+ }
+ else {
+ smd->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SubsurfModifier", "short", "quality")) {
+ for (Object* object = bmain->objects.first; object != NULL; object = object->id.next) {
+ for (ModifierData* md = object->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Subsurf) {
+ SubsurfModifierData* smd = (SubsurfModifierData*)md;
+ smd->quality = min_ii(smd->renderLevels, 3);
+ }
+ }
+ }
+ }
+ /* Versioning code for Multires modifier. */
+ if (!DNA_struct_elem_find(fd->filesdna, "MultiresModifier", "short", "quality")) {
+ for (Object* object = bmain->objects.first; object != NULL; object = object->id.next) {
+ for (ModifierData* md = object->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Multires) {
+ MultiresModifierData* mmd = (MultiresModifierData*)md;
+ mmd->quality = 3;
+ if (mmd->flags & eMultiresModifierFlag_PlainUv_DEPRECATED) {
+ mmd->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
+ }
+ else {
+ mmd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "short", "bending_model")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ ClothModifierData* clmd = NULL;
+ if (md->type == eModifierType_Cloth) {
+ clmd = (ClothModifierData*)md;
+ }
+ else if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData* psmd = (ParticleSystemModifierData*)md;
+ ParticleSystem* psys = psmd->psys;
+ clmd = psys->clmd;
+ }
+ if (clmd != NULL) {
+ clmd->sim_parms->bending_model = CLOTH_BENDING_LINEAR;
+ clmd->sim_parms->tension = clmd->sim_parms->structural;
+ clmd->sim_parms->compression = clmd->sim_parms->structural;
+ clmd->sim_parms->shear = clmd->sim_parms->structural;
+ clmd->sim_parms->max_tension = clmd->sim_parms->max_struct;
+ clmd->sim_parms->max_compression = clmd->sim_parms->max_struct;
+ clmd->sim_parms->max_shear = clmd->sim_parms->max_struct;
+ clmd->sim_parms->vgroup_shear = clmd->sim_parms->vgroup_struct;
+ clmd->sim_parms->tension_damp = clmd->sim_parms->Cdis;
+ clmd->sim_parms->compression_damp = clmd->sim_parms->Cdis;
+ clmd->sim_parms->shear_damp = clmd->sim_parms->Cdis;
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "era_strength_f")) {
+ for (Brush* brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ if (brush->gpencil_settings != NULL) {
+ BrushGpencilSettings* gp = brush->gpencil_settings;
+ if (gp->brush_type == GPAINT_TOOL_ERASE) {
+ gp->era_strength_f = 100.0f;
+ gp->era_thickness_f = 10.0f;
+ }
+ }
+ }
+ }
+
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Cloth) {
+ ClothModifierData* clmd = (ClothModifierData*)md;
+
+ if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) {
+ clmd->sim_parms->vgroup_mass = 0;
+ }
+
+ if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)) {
+ clmd->sim_parms->vgroup_struct = 0;
+ clmd->sim_parms->vgroup_shear = 0;
+ clmd->sim_parms->vgroup_bend = 0;
+ }
+
+ if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW)) {
+ clmd->sim_parms->shrink_min = 0.0f;
+ clmd->sim_parms->vgroup_shrink = 0;
+ }
+
+ if (!(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)) {
+ clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 24)) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_FACES | V3D_OVERLAY_EDIT_SEAMS |
+ V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE |
+ V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES |
+ V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS |
+ V3D_OVERLAY_EDIT_CU_HANDLES | V3D_OVERLAY_EDIT_CU_NORMALS;
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ShrinkwrapModifierData", "char", "shrinkMode")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Shrinkwrap) {
+ ShrinkwrapModifierData* smd = (ShrinkwrapModifierData*)md;
+ if (smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) {
+ smd->shrinkMode = MOD_SHRINKWRAP_ABOVE_SURFACE;
+ smd->shrinkOpts &= ~MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "pdef_cfrict")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->pd) {
+ ob->pd->pdef_cfrict = 5.0f;
+ }
+
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Cloth) {
+ ClothModifierData* clmd = (ClothModifierData*)md;
+
+ clmd->coll_parms->selfepsilon = 0.015f;
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "xray_alpha_wire")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.flag |= V3D_SHADING_XRAY_WIREFRAME;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 25)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ UnitSettings* unit = &scene->unit;
+ if (unit->system != USER_UNIT_NONE) {
+ unit->length_unit = bUnit_GetBaseUnitOfType(scene->unit.system, B_UNIT_LENGTH);
+ unit->mass_unit = bUnit_GetBaseUnitOfType(scene->unit.system, B_UNIT_MASS);
+ }
+ unit->time_unit = bUnit_GetBaseUnitOfType(USER_UNIT_NONE, B_UNIT_TIME);
+ }
+
+ /* gpencil grid settings */
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); // Color
+ ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); // Scale
+ gpd->grid.lines = GP_DEFAULT_GRID_LINES; // Number of lines
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 28)) {
+ for (Mesh* mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
+ BKE_mesh_calc_edges_loose(mesh);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 29)) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ enum { V3D_OCCLUDE_WIRE = (1 << 14) };
+ View3D* v3d = (View3D*)sl;
+ if (v3d->flag2 & V3D_OCCLUDE_WIRE) {
+ v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_OCCLUDE_WIRE;
+ v3d->flag2 &= ~V3D_OCCLUDE_WIRE;
+ }
+ }
+ }
+ }
+ }
+
+ /* Files stored pre 2.5 (possibly re-saved with newer versions) may have non-visible
+ * spaces without a header (visible/active ones are properly versioned).
+ * Multiple version patches below assume there's always a header though. So inserting this
+ * patch in-between older ones to add a header when needed.
+ *
+ * From here on it should be fine to assume there always is a header.
+ */
+ if (!MAIN_VERSION_ATLEAST(bmain, 283, 1)) {
+ 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) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion* ar_header = do_versions_find_region_or_null(regionbase, RGN_TYPE_HEADER);
+
+ if (!ar_header) {
+ /* Headers should always be first in the region list, except if there's also a
+ * tool-header. These were only introduced in later versions though, so should be
+ * fine to always insert headers first. */
+ BLI_assert(!do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOL_HEADER));
+
+ ARegion* ar = do_versions_add_region(RGN_TYPE_HEADER, "header 2.83.1 versioning");
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+ BLI_addhead(regionbase, ar);
+ }
+ }
+ }
+ }
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_PROPERTIES) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion* ar = MEM_callocN(sizeof(ARegion), "navigation bar for properties");
+ ARegion* ar_header = NULL;
+
+ for (ar_header = regionbase->first; ar_header; ar_header = ar_header->next) {
+ if (ar_header->regiontype == RGN_TYPE_HEADER) {
+ break;
+ }
+ }
+ BLI_assert(ar_header);
+
+ BLI_insertlinkafter(regionbase, ar_header, ar);
+
+ ar->regiontype = RGN_TYPE_NAV_BAR;
+ ar->alignment = RGN_ALIGN_LEFT;
+ }
+ }
+ }
+ }
+
+ /* grease pencil fade layer opacity */
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "gpencil_fade_layer")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.gpencil_fade_layer = 0.5f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 30)) {
+ /* 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_MATERIAL_STROKE_SHOW;
+ mat->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 33)) {
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "overscan")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->eevee.overscan = 3.0f;
+ }
+ }
+
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ /* Removed Hemi lights. */
+ if (!ELEM(la->type, LA_LOCAL, LA_SUN, LA_SPOT, LA_AREA)) {
+ la->type = LA_SUN;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "light_threshold")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->eevee.light_threshold = 0.01f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_irradiance_smoothing")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->eevee.gi_irradiance_smoothing = 0.1f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "gi_filter_quality")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->eevee.gi_filter_quality = 1.0f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "att_dist")) {
+ for (Light* la = bmain->lights.first; la; la = la->id.next) {
+ la->att_dist = la->clipend;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Brush", "char", "weightpaint_tool")) {
+ /* Magic defines from old files (2.7x) */
#define PAINT_BLEND_MIX 0
#define PAINT_BLEND_ADD 1
@@ -3015,98 +3017,98 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
#define PAINT_BLEND_ALPHA_SUB 19
#define PAINT_BLEND_ALPHA_ADD 20
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if (brush->ob_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- const char tool_init = brush->vertexpaint_tool;
- bool is_blend = false;
-
- {
- char tool = tool_init;
- switch (tool_init) {
- case PAINT_BLEND_MIX:
- tool = VPAINT_TOOL_DRAW;
- break;
- case PAINT_BLEND_BLUR:
- tool = VPAINT_TOOL_BLUR;
- break;
- case PAINT_BLEND_AVERAGE:
- tool = VPAINT_TOOL_AVERAGE;
- break;
- case PAINT_BLEND_SMEAR:
- tool = VPAINT_TOOL_SMEAR;
- break;
- default:
- tool = VPAINT_TOOL_DRAW;
- is_blend = true;
- break;
- }
- brush->vertexpaint_tool = tool;
- }
-
- if (is_blend == false) {
- brush->blend = IMB_BLEND_MIX;
- }
- else {
- short blend = IMB_BLEND_MIX;
- switch (tool_init) {
- case PAINT_BLEND_ADD:
- blend = IMB_BLEND_ADD;
- break;
- case PAINT_BLEND_SUB:
- blend = IMB_BLEND_SUB;
- break;
- case PAINT_BLEND_MUL:
- blend = IMB_BLEND_MUL;
- break;
- case PAINT_BLEND_LIGHTEN:
- blend = IMB_BLEND_LIGHTEN;
- break;
- case PAINT_BLEND_DARKEN:
- blend = IMB_BLEND_DARKEN;
- break;
- case PAINT_BLEND_COLORDODGE:
- blend = IMB_BLEND_COLORDODGE;
- break;
- case PAINT_BLEND_DIFFERENCE:
- blend = IMB_BLEND_DIFFERENCE;
- break;
- case PAINT_BLEND_SCREEN:
- blend = IMB_BLEND_SCREEN;
- break;
- case PAINT_BLEND_HARDLIGHT:
- blend = IMB_BLEND_HARDLIGHT;
- break;
- case PAINT_BLEND_OVERLAY:
- blend = IMB_BLEND_OVERLAY;
- break;
- case PAINT_BLEND_SOFTLIGHT:
- blend = IMB_BLEND_SOFTLIGHT;
- break;
- case PAINT_BLEND_EXCLUSION:
- blend = IMB_BLEND_EXCLUSION;
- break;
- case PAINT_BLEND_LUMINOSITY:
- blend = IMB_BLEND_LUMINOSITY;
- break;
- case PAINT_BLEND_SATURATION:
- blend = IMB_BLEND_SATURATION;
- break;
- case PAINT_BLEND_HUE:
- blend = IMB_BLEND_HUE;
- break;
- case PAINT_BLEND_ALPHA_SUB:
- blend = IMB_BLEND_ERASE_ALPHA;
- break;
- case PAINT_BLEND_ALPHA_ADD:
- blend = IMB_BLEND_ADD_ALPHA;
- break;
- }
- brush->blend = blend;
- }
- }
- /* For now these match, in the future new items may not. */
- brush->weightpaint_tool = brush->vertexpaint_tool;
- }
+ for (Brush* brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ if (brush->ob_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
+ const char tool_init = brush->vertexpaint_tool;
+ bool is_blend = false;
+
+ {
+ char tool = tool_init;
+ switch (tool_init) {
+ case PAINT_BLEND_MIX:
+ tool = VPAINT_TOOL_DRAW;
+ break;
+ case PAINT_BLEND_BLUR:
+ tool = VPAINT_TOOL_BLUR;
+ break;
+ case PAINT_BLEND_AVERAGE:
+ tool = VPAINT_TOOL_AVERAGE;
+ break;
+ case PAINT_BLEND_SMEAR:
+ tool = VPAINT_TOOL_SMEAR;
+ break;
+ default:
+ tool = VPAINT_TOOL_DRAW;
+ is_blend = true;
+ break;
+ }
+ brush->vertexpaint_tool = tool;
+ }
+
+ if (is_blend == false) {
+ brush->blend = IMB_BLEND_MIX;
+ }
+ else {
+ short blend = IMB_BLEND_MIX;
+ switch (tool_init) {
+ case PAINT_BLEND_ADD:
+ blend = IMB_BLEND_ADD;
+ break;
+ case PAINT_BLEND_SUB:
+ blend = IMB_BLEND_SUB;
+ break;
+ case PAINT_BLEND_MUL:
+ blend = IMB_BLEND_MUL;
+ break;
+ case PAINT_BLEND_LIGHTEN:
+ blend = IMB_BLEND_LIGHTEN;
+ break;
+ case PAINT_BLEND_DARKEN:
+ blend = IMB_BLEND_DARKEN;
+ break;
+ case PAINT_BLEND_COLORDODGE:
+ blend = IMB_BLEND_COLORDODGE;
+ break;
+ case PAINT_BLEND_DIFFERENCE:
+ blend = IMB_BLEND_DIFFERENCE;
+ break;
+ case PAINT_BLEND_SCREEN:
+ blend = IMB_BLEND_SCREEN;
+ break;
+ case PAINT_BLEND_HARDLIGHT:
+ blend = IMB_BLEND_HARDLIGHT;
+ break;
+ case PAINT_BLEND_OVERLAY:
+ blend = IMB_BLEND_OVERLAY;
+ break;
+ case PAINT_BLEND_SOFTLIGHT:
+ blend = IMB_BLEND_SOFTLIGHT;
+ break;
+ case PAINT_BLEND_EXCLUSION:
+ blend = IMB_BLEND_EXCLUSION;
+ break;
+ case PAINT_BLEND_LUMINOSITY:
+ blend = IMB_BLEND_LUMINOSITY;
+ break;
+ case PAINT_BLEND_SATURATION:
+ blend = IMB_BLEND_SATURATION;
+ break;
+ case PAINT_BLEND_HUE:
+ blend = IMB_BLEND_HUE;
+ break;
+ case PAINT_BLEND_ALPHA_SUB:
+ blend = IMB_BLEND_ERASE_ALPHA;
+ break;
+ case PAINT_BLEND_ALPHA_ADD:
+ blend = IMB_BLEND_ADD_ALPHA;
+ break;
+ }
+ brush->blend = blend;
+ }
+ }
+ /* For now these match, in the future new items may not. */
+ brush->weightpaint_tool = brush->vertexpaint_tool;
+ }
#undef PAINT_BLEND_MIX
#undef PAINT_BLEND_ADD
@@ -3129,1344 +3131,1468 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
#undef PAINT_BLEND_HUE
#undef PAINT_BLEND_ALPHA_SUB
#undef PAINT_BLEND_ALPHA_ADD
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 34)) {
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (ScrArea *area = screen->areabase.first; area; area = area->next) {
- for (SpaceLink *slink = area->spacedata.first; slink; slink = slink->next) {
- if (slink->spacetype == SPACE_USERPREF) {
- ARegion *navigation_region = BKE_spacedata_find_region_type(
- slink, area, RGN_TYPE_NAV_BAR);
-
- if (!navigation_region) {
- ARegion *main_region = BKE_spacedata_find_region_type(slink, area, RGN_TYPE_WINDOW);
- ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase :
- &slink->regionbase;
-
- navigation_region = MEM_callocN(sizeof(ARegion),
- "userpref navigation-region do_versions");
-
- /* Order matters, addhead not addtail! */
- BLI_insertlinkbefore(regionbase, main_region, navigation_region);
-
- navigation_region->regiontype = RGN_TYPE_NAV_BAR;
- navigation_region->alignment = RGN_ALIGN_LEFT;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 36)) {
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "curvature_ridge_factor")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.curvature_ridge_factor = 1.0f;
- v3d->shading.curvature_valley_factor = 1.0f;
- }
- }
- }
- }
- }
-
- /* Rename OpenGL to Workbench. */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- if (STREQ(scene->r.engine, "BLENDER_OPENGL")) {
- STRNCPY(scene->r.engine, RE_engine_id_BLENDER_WORKBENCH);
- }
- }
-
- /* 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) {
- ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
- ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
- }
- }
- }
-
- /* Move studio_light selection to lookdev_light. */
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "lookdev_light[256]")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- memcpy(v3d->shading.lookdev_light, v3d->shading.studio_light, sizeof(char) * 256);
- }
- }
- }
- }
- }
-
- /* Change Solid mode shadow orientation. */
- if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "float", "shadow_focus")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- float *dir = scene->display.light_direction;
- SWAP(float, dir[2], dir[1]);
- dir[2] = -dir[2];
- dir[0] = -dir[0];
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 37)) {
- for (Camera *ca = bmain->cameras.first; ca; ca = ca->id.next) {
- ca->drawsize *= 2.0f;
- }
-
- /* Grease pencil primitive curve */
- if (!DNA_struct_elem_find(
- fd->filesdna, "GP_Sculpt_Settings", "CurveMapping", "cur_primitive")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- if ((gset) && (gset->cur_primitive == NULL)) {
- gset->cur_primitive = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
- BKE_curvemapping_initialize(gset->cur_primitive);
- BKE_curvemap_reset(gset->cur_primitive->cm,
- &gset->cur_primitive->clipr,
- CURVE_PRESET_BELL,
- CURVEMAP_SLOPE_POSITIVE);
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 38)) {
- if (DNA_struct_elem_find(fd->filesdna, "Object", "char", "empty_image_visibility_flag")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- ob->empty_image_visibility_flag ^= (OB_EMPTY_IMAGE_HIDE_PERSPECTIVE |
- OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC |
- OB_EMPTY_IMAGE_HIDE_BACK);
- }
- }
-
- 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) {
- switch (sl->spacetype) {
- case SPACE_IMAGE: {
- SpaceImage *sima = (SpaceImage *)sl;
- sima->flag &= ~(SI_FLAG_UNUSED_0 | SI_FLAG_UNUSED_1 | SI_FLAG_UNUSED_3 |
- SI_FLAG_UNUSED_6 | SI_FLAG_UNUSED_7 | SI_FLAG_UNUSED_8 |
- SI_FLAG_UNUSED_17 | SI_FLAG_UNUSED_18 | SI_FLAG_UNUSED_23 |
- SI_FLAG_UNUSED_24);
- break;
- }
- case SPACE_VIEW3D: {
- View3D *v3d = (View3D *)sl;
- v3d->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_FLAG_UNUSED_1 | V3D_FLAG_UNUSED_10 |
- V3D_FLAG_UNUSED_12);
- v3d->flag2 &= ~(V3D_FLAG2_UNUSED_3 | V3D_FLAG2_UNUSED_6 | V3D_FLAG2_UNUSED_12 |
- V3D_FLAG2_UNUSED_13 | V3D_FLAG2_UNUSED_14 | V3D_FLAG2_UNUSED_15);
- break;
- }
- case SPACE_OUTLINER: {
- SpaceOutliner *so = (SpaceOutliner *)sl;
- so->filter &= ~(SO_FILTER_UNUSED_1 | SO_FILTER_UNUSED_5 | SO_FILTER_UNUSED_12);
- so->storeflag &= ~(SO_TREESTORE_UNUSED_1);
- break;
- }
- case SPACE_FILE: {
- SpaceFile *sfile = (SpaceFile *)sl;
- if (sfile->params) {
- sfile->params->flag &= ~(FILE_PARAMS_FLAG_UNUSED_1 | FILE_PARAMS_FLAG_UNUSED_6 |
- FILE_PARAMS_FLAG_UNUSED_9);
- }
- break;
- }
- case SPACE_NODE: {
- SpaceNode *snode = (SpaceNode *)sl;
- snode->flag &= ~(SNODE_FLAG_UNUSED_6 | SNODE_FLAG_UNUSED_10 | SNODE_FLAG_UNUSED_11);
- break;
- }
- case SPACE_PROPERTIES: {
- SpaceProperties *sbuts = (SpaceProperties *)sl;
- sbuts->flag &= ~(SB_FLAG_UNUSED_2 | SB_FLAG_UNUSED_3);
- break;
- }
- case SPACE_NLA: {
- SpaceNla *snla = (SpaceNla *)sl;
- snla->flag &= ~(SNLA_FLAG_UNUSED_0 | SNLA_FLAG_UNUSED_1 | SNLA_FLAG_UNUSED_3);
- break;
- }
- }
- }
- }
- }
-
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->r.mode &= ~(R_MODE_UNUSED_1 | R_MODE_UNUSED_2 | R_MODE_UNUSED_3 | R_MODE_UNUSED_4 |
- R_MODE_UNUSED_5 | R_MODE_UNUSED_6 | R_MODE_UNUSED_7 | R_MODE_UNUSED_8 |
- R_MODE_UNUSED_10 | R_MODE_UNUSED_13 | R_MODE_UNUSED_16 |
- R_MODE_UNUSED_17 | R_MODE_UNUSED_18 | R_MODE_UNUSED_19 |
- R_MODE_UNUSED_20 | R_MODE_UNUSED_21 | R_MODE_UNUSED_27);
-
- scene->r.scemode &= ~(R_SCEMODE_UNUSED_8 | R_SCEMODE_UNUSED_11 | R_SCEMODE_UNUSED_13 |
- R_SCEMODE_UNUSED_16 | R_SCEMODE_UNUSED_17 | R_SCEMODE_UNUSED_19);
-
- if (scene->toolsettings->sculpt) {
- scene->toolsettings->sculpt->flags &= ~(SCULPT_FLAG_UNUSED_0 | SCULPT_FLAG_UNUSED_1 |
- SCULPT_FLAG_UNUSED_2);
- }
-
- if (scene->ed) {
- Sequence *seq;
- SEQ_BEGIN (scene->ed, seq) {
- seq->flag &= ~(SEQ_FLAG_UNUSED_6 | SEQ_FLAG_UNUSED_18 | SEQ_FLAG_UNUSED_19 |
- SEQ_FLAG_UNUSED_21);
- if (seq->type == SEQ_TYPE_SPEED) {
- SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
- s->flags &= ~(SEQ_SPEED_UNUSED_1);
- }
- }
- SEQ_END;
- }
- }
-
- for (World *world = bmain->worlds.first; world; world = world->id.next) {
- world->flag &= ~(WO_MODE_UNUSED_1 | WO_MODE_UNUSED_2 | WO_MODE_UNUSED_3 | WO_MODE_UNUSED_4 |
- WO_MODE_UNUSED_5 | WO_MODE_UNUSED_7);
- }
-
- for (Image *image = bmain->images.first; image; image = image->id.next) {
- image->flag &= ~(IMA_FLAG_UNUSED_0 | IMA_FLAG_UNUSED_1 | IMA_FLAG_UNUSED_4 |
- IMA_FLAG_UNUSED_6 | IMA_FLAG_UNUSED_8 | IMA_FLAG_UNUSED_15 |
- IMA_FLAG_UNUSED_16);
- }
-
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- ob->flag &= ~(OB_FLAG_UNUSED_11 | OB_FLAG_UNUSED_12);
- ob->transflag &= ~(OB_TRANSFLAG_UNUSED_0 | OB_TRANSFLAG_UNUSED_1);
- ob->shapeflag &= ~OB_SHAPE_FLAG_UNUSED_1;
- }
-
- for (Mesh *me = bmain->meshes.first; me; me = me->id.next) {
- me->flag &= ~(ME_FLAG_UNUSED_0 | ME_FLAG_UNUSED_1 | ME_FLAG_UNUSED_3 | ME_FLAG_UNUSED_4 |
- ME_FLAG_UNUSED_6 | ME_FLAG_UNUSED_7 | ME_FLAG_UNUSED_8);
- }
-
- for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) {
- mat->blend_flag &= ~(1 << 2); /* UNUSED */
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 40)) {
- if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "snap_transform_mode_flag")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->toolsettings->snap_transform_mode_flag = SCE_SNAP_TRANSFORM_MODE_TRANSLATE;
- }
- }
-
- 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) {
- switch (sl->spacetype) {
- case SPACE_VIEW3D: {
- enum { V3D_BACKFACE_CULLING = (1 << 10) };
- View3D *v3d = (View3D *)sl;
- if (v3d->flag2 & V3D_BACKFACE_CULLING) {
- v3d->flag2 &= ~V3D_BACKFACE_CULLING;
- v3d->shading.flag |= V3D_SHADING_BACKFACE_CULLING;
- }
- break;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_find(fd->filesdna, "TransformOrientationSlot")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
- scene->orientation_slots[i].index_custom = -1;
- }
- }
- }
-
- /* 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) {
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- if (gset) {
- gset->isect_threshold = 0.1f;
- }
- }
- }
-
- /* Fix anamorphic bokeh eevee rna limits.*/
- for (Camera *ca = bmain->cameras.first; ca; ca = ca->id.next) {
- if (ca->gpu_dof.ratio < 0.01f) {
- ca->gpu_dof.ratio = 0.01f;
- }
- }
-
- 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) {
- if (sl->spacetype == SPACE_USERPREF) {
- ARegion *execute_region = BKE_spacedata_find_region_type(sl, area, RGN_TYPE_EXECUTE);
-
- if (!execute_region) {
- ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
- &sl->regionbase;
- ARegion *ar_navbar = BKE_spacedata_find_region_type(sl, area, RGN_TYPE_NAV_BAR);
-
- execute_region = MEM_callocN(sizeof(ARegion), "execute region for properties");
-
- BLI_assert(ar_navbar);
-
- BLI_insertlinkafter(regionbase, ar_navbar, execute_region);
-
- execute_region->regiontype = RGN_TYPE_EXECUTE;
- execute_region->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- execute_region->flag |= RGN_FLAG_DYNAMIC_SIZE;
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 43)) {
- ListBase *lb = which_libbase(bmain, ID_BR);
- BKE_main_id_repair_duplicate_names_listbase(lb);
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 44)) {
- if (!DNA_struct_elem_find(fd->filesdna, "Material", "float", "a")) {
- for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) {
- mat->a = 1.0f;
- }
- }
-
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- enum {
- R_ALPHAKEY = 2,
- };
- scene->r.seq_flag &= ~(R_SEQ_UNUSED_0 | R_SEQ_UNUSED_1 | R_SEQ_UNUSED_2);
- scene->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT_UNUSED_1;
- if (scene->r.alphamode == R_ALPHAKEY) {
- scene->r.alphamode = R_ADDSKY;
- }
- ToolSettings *ts = scene->toolsettings;
- ts->particle.flag &= ~PE_UNUSED_6;
- if (ts->sculpt != NULL) {
- ts->sculpt->flags &= ~SCULPT_FLAG_UNUSED_6;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 46)) {
- /* Add wireframe color. */
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "wire_color_type")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.wire_color_type = V3D_SHADING_SINGLE_COLOR;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "View3DCursor", "short", "rotation_mode")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- if (is_zero_v3(scene->cursor.rotation_axis)) {
- scene->cursor.rotation_mode = ROT_MODE_XYZ;
- scene->cursor.rotation_quaternion[0] = 1.0f;
- scene->cursor.rotation_axis[1] = 1.0f;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 47)) {
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- ParticleEditSettings *pset = &scene->toolsettings->particle;
- if (pset->brushtype < 0) {
- pset->brushtype = PE_BRUSH_COMB;
- }
- }
-
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- {
- enum { PARCURVE = 1, PARKEY = 2, PAR_DEPRECATED = 16 };
- if (ELEM(ob->partype, PARCURVE, PARKEY, PAR_DEPRECATED)) {
- ob->partype = PAROBJECT;
- }
- }
-
- {
- enum { OB_WAVE = 21, OB_LIFE = 23, OB_SECTOR = 24 };
- if (ELEM(ob->type, OB_WAVE, OB_LIFE, OB_SECTOR)) {
- ob->type = OB_EMPTY;
- }
- }
-
- ob->transflag &= ~(OB_TRANSFLAG_UNUSED_0 | OB_TRANSFLAG_UNUSED_1 | OB_TRANSFLAG_UNUSED_3 |
- OB_TRANSFLAG_UNUSED_6 | OB_TRANSFLAG_UNUSED_12);
-
- ob->nlaflag &= ~(OB_ADS_UNUSED_1 | OB_ADS_UNUSED_2);
- }
-
- LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
- arm->flag &= ~(ARM_FLAG_UNUSED_1 | ARM_FLAG_UNUSED_5 | ARM_FLAG_UNUSED_6 |
- ARM_FLAG_UNUSED_7 | ARM_FLAG_UNUSED_12);
- }
-
- LISTBASE_FOREACH (Text *, text, &bmain->texts) {
- text->flags &= ~(TXT_FLAG_UNUSED_8 | TXT_FLAG_UNUSED_9);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 48)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- /* Those are not currently used, but are accessible through RNA API and were not
- * properly initialized previously. This is mere copy of BKE_init_scene() code. */
- if (scene->r.im_format.view_settings.look[0] == '\0') {
- BKE_color_managed_display_settings_init(&scene->r.im_format.display_settings);
- BKE_color_managed_view_settings_init_render(
- &scene->r.im_format.view_settings, &scene->r.im_format.display_settings, "Filmic");
- }
-
- if (scene->r.bake.im_format.view_settings.look[0] == '\0') {
- BKE_color_managed_display_settings_init(&scene->r.bake.im_format.display_settings);
- BKE_color_managed_view_settings_init_render(&scene->r.bake.im_format.view_settings,
- &scene->r.bake.im_format.display_settings,
- "Filmic");
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 49)) {
- /* All tool names changed, reset to defaults. */
- for (WorkSpace *workspace = bmain->workspaces.first; workspace;
- workspace = workspace->id.next) {
- while (!BLI_listbase_is_empty(&workspace->tools)) {
- BKE_workspace_tool_remove(workspace, workspace->tools.first);
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 52)) {
- LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
- /* Replace deprecated PART_DRAW_BB by PART_DRAW_NOT */
- if (part->ren_as == PART_DRAW_BB) {
- part->ren_as = PART_DRAW_NOT;
- }
- if (part->draw_as == PART_DRAW_BB) {
- part->draw_as = PART_DRAW_NOT;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "TriangulateModifierData", "int", "min_vertices")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Triangulate) {
- TriangulateModifierData *smd = (TriangulateModifierData *)md;
- smd->min_vertices = 4;
- }
- }
- }
- }
-
- FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
- if (ntree->type == NTREE_SHADER) {
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- /* Fix missing version patching from earlier changes. */
- if (STREQ(node->idname, "ShaderNodeOutputLamp")) {
- STRNCPY(node->idname, "ShaderNodeOutputLight");
- }
- if (node->type == SH_NODE_BSDF_PRINCIPLED && node->custom2 == 0) {
- node->custom2 = SHD_SUBSURFACE_BURLEY;
- }
- }
- }
- }
- FOREACH_NODETREE_END;
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 53)) {
- for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) {
- /* Eevee: Keep material appearance consistent with previous behavior. */
- if (!mat->use_nodes || !mat->nodetree || mat->blend_method == MA_BM_SOLID) {
- mat->blend_shadow = MA_BS_SOLID;
- }
- }
-
- /* grease pencil default animation channel color */
- {
- for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- if (gpd->flag & GP_DATA_ANNOTATIONS) {
- continue;
- }
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* default channel color */
- ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 54)) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- bool is_first_subdiv = true;
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Subsurf) {
- SubsurfModifierData *smd = (SubsurfModifierData *)md;
- if (is_first_subdiv) {
- smd->flags |= eSubsurfModifierFlag_UseCrease;
- }
- else {
- smd->flags &= ~eSubsurfModifierFlag_UseCrease;
- }
- is_first_subdiv = false;
- }
- else if (md->type == eModifierType_Multires) {
- MultiresModifierData *mmd = (MultiresModifierData *)md;
- if (is_first_subdiv) {
- mmd->flags |= eMultiresModifierFlag_UseCrease;
- }
- else {
- mmd->flags &= ~eMultiresModifierFlag_UseCrease;
- }
- is_first_subdiv = false;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 55)) {
- 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) {
- if (sl->spacetype == SPACE_TEXT) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
-
- /* Remove multiple footers that were added by mistake. */
- do_versions_remove_regions_by_type(regionbase, RGN_TYPE_FOOTER);
-
- /* Add footer. */
- ARegion *ar = do_versions_add_region(RGN_TYPE_FOOTER, "footer for text");
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
-
- ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
- BLI_insertlinkafter(regionbase, ar_header, ar);
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 56)) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->gizmo_show_armature = V3D_GIZMO_SHOW_ARMATURE_BBONE |
- V3D_GIZMO_SHOW_ARMATURE_ROLL;
- v3d->gizmo_show_empty = V3D_GIZMO_SHOW_EMPTY_IMAGE | V3D_GIZMO_SHOW_EMPTY_FORCE_FIELD;
- v3d->gizmo_show_light = V3D_GIZMO_SHOW_LIGHT_SIZE | V3D_GIZMO_SHOW_LIGHT_LOOK_AT;
- v3d->gizmo_show_camera = V3D_GIZMO_SHOW_CAMERA_LENS | V3D_GIZMO_SHOW_CAMERA_DOF_DIST;
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 57)) {
- /* Enable Show Interpolation in dopesheet by default. */
- 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) {
- if (sl->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sl;
- if ((saction->flag & SACTION_SHOW_EXTREMES) == 0) {
- saction->flag |= SACTION_SHOW_INTERPOLATION;
- }
- }
- }
- }
- }
-
- /* init grease pencil brush gradients */
- if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "gradient_f")) {
- 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;
- }
- }
- }
-
- /* init grease pencil stroke gradients */
- if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "gradient_f")) {
- 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;
- }
- }
- }
- }
- }
-
- /* enable the axis aligned ortho grid by default */
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->gridflag |= V3D_SHOW_ORTHO_GRID;
- }
- }
- }
- }
- }
-
- /* Keep un-versioned until we're finished adding space types. */
- {
- 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) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- /* All spaces that use tools must be eventually added. */
- ARegion *ar = NULL;
- if (ELEM(sl->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ) &&
- ((ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOL_HEADER)) == NULL)) {
- /* Add tool header. */
- ar = do_versions_add_region(RGN_TYPE_TOOL_HEADER, "tool header");
- ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
-
- ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
- BLI_insertlinkbefore(regionbase, ar_header, ar);
- /* Hide by default, enable for painting workspaces (startup only). */
- ar->flag |= RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
- }
- if (ar != NULL) {
- SET_FLAG_FROM_TEST(ar->flag, ar->flag & RGN_FLAG_HIDDEN_BY_USER, RGN_FLAG_HIDDEN);
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 60)) {
- if (!DNA_struct_elem_find(fd->filesdna, "bSplineIKConstraint", "short", "yScaleMode")) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->pose) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (bConstraint *con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
- bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
- if ((data->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) == 0) {
- data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE;
- }
- }
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(
- fd->filesdna, "View3DOverlay", "float", "sculpt_mode_mask_opacity")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.sculpt_mode_mask_opacity = 0.75f;
- }
- }
- }
- }
- }
- if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "char", "render_aa")) {
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- scene->display.render_aa = SCE_DISPLAY_AA_SAMPLES_8;
- scene->display.viewport_aa = SCE_DISPLAY_AA_FXAA;
- }
- }
-
- /* Split bbone_scalein/bbone_scaleout into x and y fields. */
- if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "scale_out_y")) {
- /* Update armature data and pose channels. */
- LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
- do_version_bones_split_bbone_scale(&arm->bonebase);
- }
-
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- if (ob->pose) {
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- pchan->scale_in_y = pchan->scale_in_x;
- pchan->scale_out_y = pchan->scale_out_x;
- }
- }
- }
-
- /* Update action curves and drivers. */
- LISTBASE_FOREACH (bAction *, act, &bmain->actions) {
- LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &act->curves) {
- do_version_bbone_scale_fcurve_fix(&act->curves, fcu);
- }
- }
-
- BKE_animdata_main_cb(bmain, do_version_bbone_scale_animdata_cb, NULL);
- }
-
- for (Scene *sce = bmain->scenes.first; sce != NULL; sce = sce->id.next) {
- if (sce->ed != NULL) {
- do_versions_seq_set_cache_defaults(sce->ed);
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 61)) {
- /* Added a power option to Copy Scale. */
- if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "float", "power")) {
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- do_version_constraints_copy_scale_power(&ob->constraints);
- if (ob->pose) {
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- do_version_constraints_copy_scale_power(&pchan->constraints);
- }
- }
- }
- }
-
- 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) {
- if (ELEM(sl->spacetype, SPACE_CLIP, SPACE_GRAPH, SPACE_SEQ)) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
-
- ARegion *ar = NULL;
- if (sl->spacetype == SPACE_CLIP) {
- if (((SpaceClip *)sl)->view == SC_VIEW_GRAPH) {
- ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_PREVIEW);
- }
- }
- else {
- ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_WINDOW);
- }
-
- if (ar != NULL) {
- ar->v2d.scroll &= ~V2D_SCROLL_LEFT;
- ar->v2d.scroll |= V2D_SCROLL_RIGHT;
- }
- }
- }
- }
- }
-
- 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) {
- if (sl->spacetype != SPACE_OUTLINER) {
- continue;
- }
- SpaceOutliner *so = (SpaceOutliner *)sl;
- so->filter &= ~SO_FLAG_UNUSED_1;
- so->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
- LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
- arm->flag &= ~(ARM_FLAG_UNUSED_7 | ARM_FLAG_UNUSED_9);
- }
-
- /* Initializes sun lights with the new angular diameter property */
- if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "sun_angle")) {
- LISTBASE_FOREACH (Light *, light, &bmain->lights) {
- light->sun_angle = 2.0f * atanf(light->area_size);
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) {
- /* New image alpha modes. */
- LISTBASE_FOREACH (Image *, image, &bmain->images) {
- const int IMA_IGNORE_ALPHA = (1 << 12);
- if (image->flag & IMA_IGNORE_ALPHA) {
- image->alpha_mode = IMA_ALPHA_IGNORE;
- image->flag &= ~IMA_IGNORE_ALPHA;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 71)) {
- /* This assumes the Blender builtin config. Depending on the OCIO
- * environment variable for versioning is weak, and these deprecated view
- * transforms and look names don't seem to exist in other commonly used
- * OCIO configs so .blend files created for those would be unaffected. */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- ColorManagedViewSettings *view_settings;
- view_settings = &scene->view_settings;
-
- if (STREQ(view_settings->view_transform, "Default")) {
- STRNCPY(view_settings->view_transform, "Standard");
- }
- else if (STREQ(view_settings->view_transform, "RRT") ||
- STREQ(view_settings->view_transform, "Film")) {
- STRNCPY(view_settings->view_transform, "Filmic");
- }
- else if (STREQ(view_settings->view_transform, "Log")) {
- STRNCPY(view_settings->view_transform, "Filmic Log");
- }
-
- if (STREQ(view_settings->look, "Filmic - Base Contrast")) {
- STRNCPY(view_settings->look, "None");
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 74)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- if (scene->ed != NULL) {
- do_versions_seq_alloc_transform_and_crop(&scene->ed->seqbase);
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 75)) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- if (scene->master_collection != NULL) {
- scene->master_collection->flag &= ~(COLLECTION_RESTRICT_VIEWPORT |
- COLLECTION_RESTRICT_SELECT |
- COLLECTION_RESTRICT_RENDER);
- }
-
- UnitSettings *unit = &scene->unit;
- if (unit->system == USER_UNIT_NONE) {
- unit->length_unit = (char)USER_UNIT_ADAPTIVE;
- unit->mass_unit = (char)USER_UNIT_ADAPTIVE;
- }
-
- RenderData *render_data = &scene->r;
- switch (render_data->ffcodecdata.ffmpeg_preset) {
- case FFM_PRESET_ULTRAFAST:
- case FFM_PRESET_SUPERFAST:
- render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_REALTIME;
- break;
- case FFM_PRESET_VERYFAST:
- case FFM_PRESET_FASTER:
- case FFM_PRESET_FAST:
- case FFM_PRESET_MEDIUM:
- render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_GOOD;
- break;
- case FFM_PRESET_SLOW:
- case FFM_PRESET_SLOWER:
- case FFM_PRESET_VERYSLOW:
- render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_BEST;
- }
- }
-
- LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
- arm->flag &= ~(ARM_FLAG_UNUSED_6);
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 1)) {
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_DataTransfer) {
- /* Now datatransfer's mix factor is multiplied with weights when any,
- * instead of being ignored,
- * we need to take care of that to keep 'old' files compatible. */
- DataTransferModifierData *dtmd = (DataTransferModifierData *)md;
- if (dtmd->defgrp_name[0] != '\0') {
- dtmd->mix_factor = 1.0f;
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
- 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) {
- if (sl->spacetype == SPACE_TEXT) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- ARegion *ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_UI);
- if (ar) {
- ar->alignment = RGN_ALIGN_RIGHT;
- }
- }
- /* Mark outliners as dirty for syncing and enable synced selection */
- if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *soutliner = (SpaceOutliner *)sl;
- soutliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL;
- soutliner->flag |= SO_SYNC_SELECT;
- }
- }
- }
- }
- for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
- if (mesh->remesh_voxel_size == 0.0f) {
- mesh->remesh_voxel_size = 0.1f;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 4)) {
- ID *id;
- FOREACH_MAIN_ID_BEGIN (bmain, id) {
- bNodeTree *ntree = ntreeFromID(id);
- if (ntree) {
- ntree->id.flag |= LIB_PRIVATE_DATA;
- }
- }
- FOREACH_MAIN_ID_END;
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 5)) {
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- if (br->ob_mode & OB_MODE_SCULPT && br->normal_radius_factor == 0.0f) {
- br->normal_radius_factor = 0.5f;
- }
- }
-
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- /* Older files do not have a master collection, which is then added through
- * `BKE_collection_master_add()`, so everything is fine. */
- if (scene->master_collection != NULL) {
- scene->master_collection->id.flag |= LIB_PRIVATE_DATA;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 6)) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.flag |= V3D_SHADING_SCENE_LIGHTS_RENDER | V3D_SHADING_SCENE_WORLD_RENDER;
-
- /* files by default don't have studio lights selected unless interacted
- * with the shading popover. When no studiolight could be read, we will
- * select the default world one. */
- StudioLight *studio_light = BKE_studiolight_find(v3d->shading.lookdev_light,
- STUDIOLIGHT_TYPE_WORLD);
- if (studio_light != NULL) {
- STRNCPY(v3d->shading.lookdev_light, studio_light->name);
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 9)) {
- 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) {
- if (sl->spacetype == SPACE_FILE) {
- SpaceFile *sfile = (SpaceFile *)sl;
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- ARegion *ar_ui = do_versions_find_region(regionbase, RGN_TYPE_UI);
- ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
- ARegion *ar_toolprops = do_versions_find_region_or_null(regionbase,
- RGN_TYPE_TOOL_PROPS);
-
- /* Reinsert UI region so that it spawns entire area width */
- BLI_remlink(regionbase, ar_ui);
- BLI_insertlinkafter(regionbase, ar_header, ar_ui);
-
- ar_ui->flag |= RGN_FLAG_DYNAMIC_SIZE;
-
- if (ar_toolprops && (ar_toolprops->alignment == (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) {
- SpaceType *stype = BKE_spacetype_from_id(sl->spacetype);
-
- /* Remove empty region at old location. */
- BLI_assert(sfile->op == NULL);
- BKE_area_region_free(stype, ar_toolprops);
- BLI_freelinkN(regionbase, ar_toolprops);
- }
-
- if (sfile->params) {
- sfile->params->details_flags |= FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME;
- }
- }
- }
- }
- }
-
- /* Convert the BONE_NO_SCALE flag to inherit_scale_mode enum. */
- if (!DNA_struct_elem_find(fd->filesdna, "Bone", "char", "inherit_scale_mode")) {
- LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
- do_version_bones_inherit_scale(&arm->bonebase);
- }
- }
-
- /* Convert the Offset flag to the mix mode enum. */
- if (!DNA_struct_elem_find(fd->filesdna, "bRotateLikeConstraint", "char", "mix_mode")) {
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- do_version_constraints_copy_rotation_mix_mode(&ob->constraints);
- if (ob->pose) {
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- do_version_constraints_copy_rotation_mix_mode(&pchan->constraints);
- }
- }
- }
- }
-
- /* Added studiolight intensity */
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "studiolight_intensity")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.studiolight_intensity = 1.0f;
- }
- }
- }
- }
- }
-
- /* Elatic deform brush */
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- if (br->ob_mode & OB_MODE_SCULPT && br->elastic_deform_volume_preservation == 0.0f) {
- br->elastic_deform_volume_preservation = 0.5f;
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 281, 15)) {
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_NODE_X) {
- scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
- }
- }
-
- if (!DNA_struct_elem_find(
- fd->filesdna, "LayerCollection", "short", "local_collections_bits")) {
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
- LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
- do_versions_local_collection_bits_set(layer_collection);
- }
- }
- }
- }
-
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
-
- for (ScrArea *sa_other = screen->areabase.first; sa_other; sa_other = sa_other->next) {
- for (SpaceLink *sl_other = sa_other->spacedata.first; sl_other;
- sl_other = sl_other->next) {
- if (sl != sl_other && sl_other->spacetype == SPACE_VIEW3D) {
- View3D *v3d_other = (View3D *)sl_other;
-
- if (v3d->shading.prop == v3d_other->shading.prop) {
- v3d_other->shading.prop = NULL;
- }
- }
- }
- }
- }
- else if (sl->spacetype == SPACE_FILE) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- ARegion *ar_tools = do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOLS);
- ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
-
- if (ar_tools) {
- ARegion *ar_next = ar_tools->next;
-
- /* We temporarily had two tools regions, get rid of the second one. */
- if (ar_next && ar_next->regiontype == RGN_TYPE_TOOLS) {
- do_versions_remove_region(regionbase, ar_next);
- }
-
- BLI_remlink(regionbase, ar_tools);
- BLI_insertlinkafter(regionbase, ar_header, ar_tools);
- }
- else {
- ar_tools = do_versions_add_region(RGN_TYPE_TOOLS, "versioning file tools region");
- BLI_insertlinkafter(regionbase, ar_header, ar_tools);
- ar_tools->alignment = RGN_ALIGN_LEFT;
- }
- }
- }
- }
- }
-
- {
- /* Initialize new grease pencil uv scale parameter. */
- if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "uv_scale")) {
- 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->uv_scale = 1.0f;
- }
- }
- }
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 282, 2)) {
- do_version_curvemapping_walker(bmain, do_version_curvemapping_flag_extend_extrapolate);
-
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- sa->flag &= ~AREA_FLAG_UNUSED_6;
- }
- }
-
- /* Add custom curve profile to toolsettings for bevel tool */
- if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "CurveProfile", "custom_profile")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- ToolSettings *ts = scene->toolsettings;
- if ((ts) && (ts->custom_bevel_profile_preset == NULL)) {
- ts->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
- }
- }
- }
-
- /* Add custom curve profile to bevel modifier */
- if (!DNA_struct_elem_find(fd->filesdna, "BevelModifier", "CurveProfile", "custom_profile")) {
- for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- for (ModifierData *md = object->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Bevel) {
- BevelModifierData *bmd = (BevelModifierData *)md;
- if (!bmd->custom_profile) {
- bmd->custom_profile = BKE_curveprofile_add(PROF_PRESET_LINE);
- }
- }
- }
- }
- }
-
- /* Dash Ratio and Dash Samples */
- if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "dash_ratio")) {
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- br->dash_ratio = 1.0f;
- br->dash_samples = 20;
- }
- }
-
- /* Pose brush smooth iterations */
- if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_iterations")) {
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- br->pose_smooth_iterations = 4;
- }
- }
-
- /* Cloth pressure */
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData *)md;
-
- clmd->sim_parms->pressure_factor = 1;
- }
- }
- }
- }
-
- if (!MAIN_VERSION_ATLEAST(bmain, 282, 3)) {
- /* Remove Unified pressure/size and pressure/alpha */
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- ToolSettings *ts = scene->toolsettings;
- UnifiedPaintSettings *ups = &ts->unified_paint_settings;
- ups->flag &= ~(UNIFIED_PAINT_FLAG_UNUSED_0 | UNIFIED_PAINT_FLAG_UNUSED_1);
- }
-
- /* Set the default render pass in the viewport to Combined. */
- if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "int", "render_pass")) {
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
- scene->display.shading.render_pass = SCE_PASS_COMBINED;
- }
-
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->shading.render_pass = SCE_PASS_COMBINED;
- }
- }
- }
- }
- }
-
- /* Make markers region visible by default. */
- 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) {
- switch (sl->spacetype) {
- case SPACE_SEQ: {
- SpaceSeq *sseq = (SpaceSeq *)sl;
- sseq->flag |= SEQ_SHOW_MARKERS;
- break;
- }
- case SPACE_ACTION: {
- SpaceAction *saction = (SpaceAction *)sl;
- saction->flag |= SACTION_SHOW_MARKERS;
- break;
- }
- case SPACE_GRAPH: {
- SpaceGraph *sipo = (SpaceGraph *)sl;
- sipo->flag |= SIPO_SHOW_MARKERS;
- break;
- }
- case SPACE_NLA: {
- SpaceNla *snla = (SpaceNla *)sl;
- snla->flag |= SNLA_SHOW_MARKERS;
- break;
- }
- }
- }
- }
- }
-
- /* Init new Grease Pencil Paint tools. */
- {
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if (brush->gpencil_settings != NULL) {
- brush->gpencil_vertex_tool = brush->gpencil_settings->brush_type;
- }
- }
-
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if (brush->gpencil_settings != NULL) {
- brush->gpencil_sculpt_tool = brush->gpencil_settings->brush_type;
- }
- }
-
- for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) {
- if (brush->gpencil_settings != NULL) {
- brush->gpencil_weight_tool = brush->gpencil_settings->brush_type;
- }
- }
-
- BKE_paint_toolslots_init_from_main(bmain);
- }
-
- /* Init default Grease Pencil Vertex paint mix factor for Viewport. */
- {
- if (!DNA_struct_elem_find(
- fd->filesdna, "View3DOverlay", "float", "gpencil_vertex_paint_opacity")) {
- 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) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- v3d->overlay.gpencil_vertex_paint_opacity = 1.0f;
- }
- }
- }
- }
- }
- }
-
- /* Init default Grease Pencil Vertex paint layer mix factor. */
- {
- if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "float", "vertex_paint_opacity")) {
- for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->vertex_paint_opacity = 1.0f;
- }
- }
- }
- }
- }
-
- /**
- * Versioning code until next subversion bump goes here.
- *
- * \note Be sure to check when bumping the version:
- * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
- * - "versioning_userdef.c", #do_versions_theme
- *
- * \note Keep this message at the bottom of the function.
- */
- {
- /* Keep this block, even when empty. */
-
- /* Sequencer Tool region */
- do_versions_area_ensure_tool_region(bmain, SPACE_SEQ, RGN_FLAG_HIDDEN);
-
- /* Cloth internal springs */
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData *)md;
-
- clmd->sim_parms->internal_tension = 15.0f;
- clmd->sim_parms->max_internal_tension = 15.0f;
- clmd->sim_parms->internal_compression = 15.0f;
- clmd->sim_parms->max_internal_compression = 15.0f;
- clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
- }
- }
- }
-
- /* Add primary tile to images. */
- if (!DNA_struct_elem_find(fd->filesdna, "Image", "ListBase", "tiles")) {
- for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
- ImageTile *tile = MEM_callocN(sizeof(ImageTile), "Image Tile");
- tile->ok = 1;
- tile->tile_number = 1001;
- BLI_addtail(&ima->tiles, tile);
- }
- }
-
- /* UDIM Image Editor change. */
- if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "int", "tile_grid_shape[2]")) {
- 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) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
- sima->tile_grid_shape[0] = 1;
- sima->tile_grid_shape[1] = 1;
- }
- }
- }
- }
- }
-
- /* Brush cursor alpha */
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- br->add_col[3] = 0.9f;
- br->sub_col[3] = 0.9f;
- }
-
- /* Pose brush IK segments. */
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- if (br->pose_ik_segments == 0) {
- br->pose_ik_segments = 1;
- }
- }
- }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 34)) {
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea* area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink* slink = area->spacedata.first; slink; slink = slink->next) {
+ if (slink->spacetype == SPACE_USERPREF) {
+ ARegion* navigation_region = BKE_spacedata_find_region_type(
+ slink, area, RGN_TYPE_NAV_BAR);
+
+ if (!navigation_region) {
+ ARegion* main_region = BKE_spacedata_find_region_type(slink, area, RGN_TYPE_WINDOW);
+ ListBase* regionbase = (slink == area->spacedata.first) ? &area->regionbase :
+ &slink->regionbase;
+
+ navigation_region = MEM_callocN(sizeof(ARegion),
+ "userpref navigation-region do_versions");
+
+ /* Order matters, addhead not addtail! */
+ BLI_insertlinkbefore(regionbase, main_region, navigation_region);
+
+ navigation_region->regiontype = RGN_TYPE_NAV_BAR;
+ navigation_region->alignment = RGN_ALIGN_LEFT;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 36)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "curvature_ridge_factor")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.curvature_ridge_factor = 1.0f;
+ v3d->shading.curvature_valley_factor = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ /* Rename OpenGL to Workbench. */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (STREQ(scene->r.engine, "BLENDER_OPENGL")) {
+ STRNCPY(scene->r.engine, RE_engine_id_BLENDER_WORKBENCH);
+ }
+ }
+
+ /* 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) {
+ 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);
+ }
+ }
+ }
+
+ /* Move studio_light selection to lookdev_light. */
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "lookdev_light[256]")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ memcpy(v3d->shading.lookdev_light, v3d->shading.studio_light, sizeof(char) * 256);
+ }
+ }
+ }
+ }
+ }
+
+ /* Change Solid mode shadow orientation. */
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "float", "shadow_focus")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ float* dir = scene->display.light_direction;
+ SWAP(float, dir[2], dir[1]);
+ dir[2] = -dir[2];
+ dir[0] = -dir[0];
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 37)) {
+ for (Camera* ca = bmain->cameras.first; ca; ca = ca->id.next) {
+ ca->drawsize *= 2.0f;
+ }
+
+ /* Grease pencil primitive curve */
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "GP_Sculpt_Settings", "CurveMapping", "cur_primitive")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ GP_Sculpt_Settings* gset = &scene->toolsettings->gp_sculpt;
+ if ((gset) && (gset->cur_primitive == NULL)) {
+ gset->cur_primitive = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ BKE_curvemapping_initialize(gset->cur_primitive);
+ BKE_curvemap_reset(gset->cur_primitive->cm,
+ &gset->cur_primitive->clipr,
+ CURVE_PRESET_BELL,
+ CURVEMAP_SLOPE_POSITIVE);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 38)) {
+ if (DNA_struct_elem_find(fd->filesdna, "Object", "char", "empty_image_visibility_flag")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ ob->empty_image_visibility_flag ^= (OB_EMPTY_IMAGE_HIDE_PERSPECTIVE |
+ OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC |
+ OB_EMPTY_IMAGE_HIDE_BACK);
+ }
+ }
+
+ 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) {
+ switch (sl->spacetype) {
+ case SPACE_IMAGE: {
+ SpaceImage* sima = (SpaceImage*)sl;
+ sima->flag &= ~(SI_FLAG_UNUSED_0 | SI_FLAG_UNUSED_1 | SI_FLAG_UNUSED_3 |
+ SI_FLAG_UNUSED_6 | SI_FLAG_UNUSED_7 | SI_FLAG_UNUSED_8 |
+ SI_FLAG_UNUSED_17 | SI_FLAG_UNUSED_18 | SI_FLAG_UNUSED_23 |
+ SI_FLAG_UNUSED_24);
+ break;
+ }
+ case SPACE_VIEW3D: {
+ View3D* v3d = (View3D*)sl;
+ v3d->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_FLAG_UNUSED_1 | V3D_FLAG_UNUSED_10 |
+ V3D_FLAG_UNUSED_12);
+ v3d->flag2 &= ~(V3D_FLAG2_UNUSED_3 | V3D_FLAG2_UNUSED_6 | V3D_FLAG2_UNUSED_12 |
+ V3D_FLAG2_UNUSED_13 | V3D_FLAG2_UNUSED_14 | V3D_FLAG2_UNUSED_15);
+ break;
+ }
+ case SPACE_OUTLINER: {
+ SpaceOutliner* so = (SpaceOutliner*)sl;
+ so->filter &= ~(SO_FILTER_UNUSED_1 | SO_FILTER_UNUSED_5 | SO_FILTER_UNUSED_12);
+ so->storeflag &= ~(SO_TREESTORE_UNUSED_1);
+ break;
+ }
+ case SPACE_FILE: {
+ SpaceFile* sfile = (SpaceFile*)sl;
+ if (sfile->params) {
+ sfile->params->flag &= ~(FILE_PARAMS_FLAG_UNUSED_1 | FILE_PARAMS_FLAG_UNUSED_6 |
+ FILE_PARAMS_FLAG_UNUSED_9);
+ }
+ break;
+ }
+ case SPACE_NODE: {
+ SpaceNode* snode = (SpaceNode*)sl;
+ snode->flag &= ~(SNODE_FLAG_UNUSED_6 | SNODE_FLAG_UNUSED_10 | SNODE_FLAG_UNUSED_11);
+ break;
+ }
+ case SPACE_PROPERTIES: {
+ SpaceProperties* sbuts = (SpaceProperties*)sl;
+ sbuts->flag &= ~(SB_FLAG_UNUSED_2 | SB_FLAG_UNUSED_3);
+ break;
+ }
+ case SPACE_NLA: {
+ SpaceNla* snla = (SpaceNla*)sl;
+ snla->flag &= ~(SNLA_FLAG_UNUSED_0 | SNLA_FLAG_UNUSED_1 | SNLA_FLAG_UNUSED_3);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->r.mode &= ~(R_MODE_UNUSED_1 | R_MODE_UNUSED_2 | R_MODE_UNUSED_3 | R_MODE_UNUSED_4 |
+ R_MODE_UNUSED_5 | R_MODE_UNUSED_6 | R_MODE_UNUSED_7 | R_MODE_UNUSED_8 |
+ R_MODE_UNUSED_10 | R_MODE_UNUSED_13 | R_MODE_UNUSED_16 |
+ R_MODE_UNUSED_17 | R_MODE_UNUSED_18 | R_MODE_UNUSED_19 |
+ R_MODE_UNUSED_20 | R_MODE_UNUSED_21 | R_MODE_UNUSED_27);
+
+ scene->r.scemode &= ~(R_SCEMODE_UNUSED_8 | R_SCEMODE_UNUSED_11 | R_SCEMODE_UNUSED_13 |
+ R_SCEMODE_UNUSED_16 | R_SCEMODE_UNUSED_17 | R_SCEMODE_UNUSED_19);
+
+ if (scene->toolsettings->sculpt) {
+ scene->toolsettings->sculpt->flags &= ~(SCULPT_FLAG_UNUSED_0 | SCULPT_FLAG_UNUSED_1 |
+ SCULPT_FLAG_UNUSED_2);
+ }
+
+ if (scene->ed) {
+ Sequence* seq;
+ SEQ_BEGIN(scene->ed, seq) {
+ seq->flag &= ~(SEQ_FLAG_UNUSED_6 | SEQ_FLAG_UNUSED_18 | SEQ_FLAG_UNUSED_19 |
+ SEQ_FLAG_UNUSED_21);
+ if (seq->type == SEQ_TYPE_SPEED) {
+ SpeedControlVars* s = (SpeedControlVars*)seq->effectdata;
+ s->flags &= ~(SEQ_SPEED_UNUSED_1);
+ }
+ }
+ SEQ_END;
+ }
+ }
+
+ for (World* world = bmain->worlds.first; world; world = world->id.next) {
+ world->flag &= ~(WO_MODE_UNUSED_1 | WO_MODE_UNUSED_2 | WO_MODE_UNUSED_3 | WO_MODE_UNUSED_4 |
+ WO_MODE_UNUSED_5 | WO_MODE_UNUSED_7);
+ }
+
+ for (Image* image = bmain->images.first; image; image = image->id.next) {
+ image->flag &= ~(IMA_FLAG_UNUSED_0 | IMA_FLAG_UNUSED_1 | IMA_FLAG_UNUSED_4 |
+ IMA_FLAG_UNUSED_6 | IMA_FLAG_UNUSED_8 | IMA_FLAG_UNUSED_15 |
+ IMA_FLAG_UNUSED_16);
+ }
+
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ ob->flag &= ~(OB_FLAG_UNUSED_11 | OB_FLAG_UNUSED_12);
+ ob->transflag &= ~(OB_TRANSFLAG_UNUSED_0 | OB_TRANSFLAG_UNUSED_1);
+ ob->shapeflag &= ~OB_SHAPE_FLAG_UNUSED_1;
+ }
+
+ for (Mesh* me = bmain->meshes.first; me; me = me->id.next) {
+ me->flag &= ~(ME_FLAG_UNUSED_0 | ME_FLAG_UNUSED_1 | ME_FLAG_UNUSED_3 | ME_FLAG_UNUSED_4 |
+ ME_FLAG_UNUSED_6 | ME_FLAG_UNUSED_7 | ME_FLAG_UNUSED_8);
+ }
+
+ for (Material* mat = bmain->materials.first; mat; mat = mat->id.next) {
+ mat->blend_flag &= ~(1 << 2); /* UNUSED */
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 40)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "char", "snap_transform_mode_flag")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->toolsettings->snap_transform_mode_flag = SCE_SNAP_TRANSFORM_MODE_TRANSLATE;
+ }
+ }
+
+ 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) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D: {
+ enum { V3D_BACKFACE_CULLING = (1 << 10) };
+ View3D* v3d = (View3D*)sl;
+ if (v3d->flag2 & V3D_BACKFACE_CULLING) {
+ v3d->flag2 &= ~V3D_BACKFACE_CULLING;
+ v3d->shading.flag |= V3D_SHADING_BACKFACE_CULLING;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_find(fd->filesdna, "TransformOrientationSlot")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
+ scene->orientation_slots[i].index_custom = -1;
+ }
+ }
+ }
+
+ /* 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) {
+ GP_Sculpt_Settings* gset = &scene->toolsettings->gp_sculpt;
+ if (gset) {
+ gset->isect_threshold = 0.1f;
+ }
+ }
+ }
+
+ /* Fix anamorphic bokeh eevee rna limits.*/
+ for (Camera* ca = bmain->cameras.first; ca; ca = ca->id.next) {
+ if (ca->gpu_dof.ratio < 0.01f) {
+ ca->gpu_dof.ratio = 0.01f;
+ }
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_USERPREF) {
+ ARegion* execute_region = BKE_spacedata_find_region_type(sl, area, RGN_TYPE_EXECUTE);
+
+ if (!execute_region) {
+ ListBase* regionbase = (sl == area->spacedata.first) ? &area->regionbase :
+ &sl->regionbase;
+ ARegion* ar_navbar = BKE_spacedata_find_region_type(sl, area, RGN_TYPE_NAV_BAR);
+
+ execute_region = MEM_callocN(sizeof(ARegion), "execute region for properties");
+
+ BLI_assert(ar_navbar);
+
+ BLI_insertlinkafter(regionbase, ar_navbar, execute_region);
+
+ execute_region->regiontype = RGN_TYPE_EXECUTE;
+ execute_region->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+ execute_region->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 43)) {
+ ListBase* lb = which_libbase(bmain, ID_BR);
+ BKE_main_id_repair_duplicate_names_listbase(lb);
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 44)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Material", "float", "a")) {
+ for (Material* mat = bmain->materials.first; mat; mat = mat->id.next) {
+ mat->a = 1.0f;
+ }
+ }
+
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ enum {
+ R_ALPHAKEY = 2,
+ };
+ scene->r.seq_flag &= ~(R_SEQ_UNUSED_0 | R_SEQ_UNUSED_1 | R_SEQ_UNUSED_2);
+ scene->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT_UNUSED_1;
+ if (scene->r.alphamode == R_ALPHAKEY) {
+ scene->r.alphamode = R_ADDSKY;
+ }
+ ToolSettings* ts = scene->toolsettings;
+ ts->particle.flag &= ~PE_UNUSED_6;
+ if (ts->sculpt != NULL) {
+ ts->sculpt->flags &= ~SCULPT_FLAG_UNUSED_6;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 46)) {
+ /* Add wireframe color. */
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "wire_color_type")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.wire_color_type = V3D_SHADING_SINGLE_COLOR;
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DCursor", "short", "rotation_mode")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (is_zero_v3(scene->cursor.rotation_axis)) {
+ scene->cursor.rotation_mode = ROT_MODE_XYZ;
+ scene->cursor.rotation_quaternion[0] = 1.0f;
+ scene->cursor.rotation_axis[1] = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 47)) {
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ ParticleEditSettings* pset = &scene->toolsettings->particle;
+ if (pset->brushtype < 0) {
+ pset->brushtype = PE_BRUSH_COMB;
+ }
+ }
+
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ {
+ enum { PARCURVE = 1, PARKEY = 2, PAR_DEPRECATED = 16 };
+ if (ELEM(ob->partype, PARCURVE, PARKEY, PAR_DEPRECATED)) {
+ ob->partype = PAROBJECT;
+ }
+ }
+
+ {
+ enum { OB_WAVE = 21, OB_LIFE = 23, OB_SECTOR = 24 };
+ if (ELEM(ob->type, OB_WAVE, OB_LIFE, OB_SECTOR)) {
+ ob->type = OB_EMPTY;
+ }
+ }
+
+ ob->transflag &= ~(OB_TRANSFLAG_UNUSED_0 | OB_TRANSFLAG_UNUSED_1 | OB_TRANSFLAG_UNUSED_3 |
+ OB_TRANSFLAG_UNUSED_6 | OB_TRANSFLAG_UNUSED_12);
+
+ ob->nlaflag &= ~(OB_ADS_UNUSED_1 | OB_ADS_UNUSED_2);
+ }
+
+ LISTBASE_FOREACH(bArmature*, arm, &bmain->armatures) {
+ arm->flag &= ~(ARM_FLAG_UNUSED_1 | ARM_FLAG_UNUSED_5 | ARM_FLAG_UNUSED_6 |
+ ARM_FLAG_UNUSED_7 | ARM_FLAG_UNUSED_12);
+ }
+
+ LISTBASE_FOREACH(Text*, text, &bmain->texts) {
+ text->flags &= ~(TXT_FLAG_UNUSED_8 | TXT_FLAG_UNUSED_9);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 48)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ /* Those are not currently used, but are accessible through RNA API and were not
+ * properly initialized previously. This is mere copy of BKE_init_scene() code. */
+ if (scene->r.im_format.view_settings.look[0] == '\0') {
+ BKE_color_managed_display_settings_init(&scene->r.im_format.display_settings);
+ BKE_color_managed_view_settings_init_render(
+ &scene->r.im_format.view_settings, &scene->r.im_format.display_settings, "Filmic");
+ }
+
+ if (scene->r.bake.im_format.view_settings.look[0] == '\0') {
+ BKE_color_managed_display_settings_init(&scene->r.bake.im_format.display_settings);
+ BKE_color_managed_view_settings_init_render(&scene->r.bake.im_format.view_settings,
+ &scene->r.bake.im_format.display_settings,
+ "Filmic");
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 49)) {
+ /* All tool names changed, reset to defaults. */
+ for (WorkSpace* workspace = bmain->workspaces.first; workspace;
+ workspace = workspace->id.next) {
+ while (!BLI_listbase_is_empty(&workspace->tools)) {
+ BKE_workspace_tool_remove(workspace, workspace->tools.first);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 52)) {
+ LISTBASE_FOREACH(ParticleSettings*, part, &bmain->particles) {
+ /* Replace deprecated PART_DRAW_BB by PART_DRAW_NOT */
+ if (part->ren_as == PART_DRAW_BB) {
+ part->ren_as = PART_DRAW_NOT;
+ }
+ if (part->draw_as == PART_DRAW_BB) {
+ part->draw_as = PART_DRAW_NOT;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "TriangulateModifierData", "int", "min_vertices")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Triangulate) {
+ TriangulateModifierData* smd = (TriangulateModifierData*)md;
+ smd->min_vertices = 4;
+ }
+ }
+ }
+ }
+
+ FOREACH_NODETREE_BEGIN(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ for (bNode* node = ntree->nodes.first; node; node = node->next) {
+ /* Fix missing version patching from earlier changes. */
+ if (STREQ(node->idname, "ShaderNodeOutputLamp")) {
+ STRNCPY(node->idname, "ShaderNodeOutputLight");
+ }
+ if (node->type == SH_NODE_BSDF_PRINCIPLED && node->custom2 == 0) {
+ node->custom2 = SHD_SUBSURFACE_BURLEY;
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 53)) {
+ for (Material* mat = bmain->materials.first; mat; mat = mat->id.next) {
+ /* Eevee: Keep material appearance consistent with previous behavior. */
+ if (!mat->use_nodes || !mat->nodetree || mat->blend_method == MA_BM_SOLID) {
+ mat->blend_shadow = MA_BS_SOLID;
+ }
+ }
+
+ /* grease pencil default animation channel color */
+ {
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ if (gpd->flag & GP_DATA_ANNOTATIONS) {
+ continue;
+ }
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ /* default channel color */
+ ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 54)) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ bool is_first_subdiv = true;
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Subsurf) {
+ SubsurfModifierData* smd = (SubsurfModifierData*)md;
+ if (is_first_subdiv) {
+ smd->flags |= eSubsurfModifierFlag_UseCrease;
+ }
+ else {
+ smd->flags &= ~eSubsurfModifierFlag_UseCrease;
+ }
+ is_first_subdiv = false;
+ }
+ else if (md->type == eModifierType_Multires) {
+ MultiresModifierData* mmd = (MultiresModifierData*)md;
+ if (is_first_subdiv) {
+ mmd->flags |= eMultiresModifierFlag_UseCrease;
+ }
+ else {
+ mmd->flags &= ~eMultiresModifierFlag_UseCrease;
+ }
+ is_first_subdiv = false;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 55)) {
+ 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) {
+ if (sl->spacetype == SPACE_TEXT) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+
+ /* Remove multiple footers that were added by mistake. */
+ do_versions_remove_regions_by_type(regionbase, RGN_TYPE_FOOTER);
+
+ /* Add footer. */
+ ARegion* ar = do_versions_add_region(RGN_TYPE_FOOTER, "footer for text");
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_TOP : RGN_ALIGN_BOTTOM;
+
+ ARegion* ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
+ BLI_insertlinkafter(regionbase, ar_header, ar);
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 56)) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->gizmo_show_armature = V3D_GIZMO_SHOW_ARMATURE_BBONE |
+ V3D_GIZMO_SHOW_ARMATURE_ROLL;
+ v3d->gizmo_show_empty = V3D_GIZMO_SHOW_EMPTY_IMAGE | V3D_GIZMO_SHOW_EMPTY_FORCE_FIELD;
+ v3d->gizmo_show_light = V3D_GIZMO_SHOW_LIGHT_SIZE | V3D_GIZMO_SHOW_LIGHT_LOOK_AT;
+ v3d->gizmo_show_camera = V3D_GIZMO_SHOW_CAMERA_LENS | V3D_GIZMO_SHOW_CAMERA_DOF_DIST;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 57)) {
+ /* Enable Show Interpolation in dopesheet by default. */
+ 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) {
+ if (sl->spacetype == SPACE_ACTION) {
+ SpaceAction* saction = (SpaceAction*)sl;
+ if ((saction->flag & SACTION_SHOW_EXTREMES) == 0) {
+ saction->flag |= SACTION_SHOW_INTERPOLATION;
+ }
+ }
+ }
+ }
+ }
+
+ /* init grease pencil brush gradients */
+ if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "gradient_f")) {
+ 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;
+ }
+ }
+ }
+
+ /* init grease pencil stroke gradients */
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "gradient_f")) {
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ LISTBASE_FOREACH(bGPDframe*, gpf, &gpl->frames) {
+ LISTBASE_FOREACH(bGPDstroke*, gps, &gpf->strokes) {
+ gps->gradient_f = 1.0f;
+ gps->gradient_s[0] = 1.0f;
+ gps->gradient_s[1] = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ /* enable the axis aligned ortho grid by default */
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->gridflag |= V3D_SHOW_ORTHO_GRID;
+ }
+ }
+ }
+ }
+ }
+
+ /* Keep un-versioned until we're finished adding space types. */
+ {
+ 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) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ /* All spaces that use tools must be eventually added. */
+ ARegion* ar = NULL;
+ if (ELEM(sl->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ) &&
+ ((ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOL_HEADER)) == NULL)) {
+ /* Add tool header. */
+ ar = do_versions_add_region(RGN_TYPE_TOOL_HEADER, "tool header");
+ ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
+
+ ARegion* ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
+ BLI_insertlinkbefore(regionbase, ar_header, ar);
+ /* Hide by default, enable for painting workspaces (startup only). */
+ ar->flag |= RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
+ }
+ if (ar != NULL) {
+ SET_FLAG_FROM_TEST(ar->flag, ar->flag & RGN_FLAG_HIDDEN_BY_USER, RGN_FLAG_HIDDEN);
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 60)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "bSplineIKConstraint", "short", "yScaleMode")) {
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->pose) {
+ for (bPoseChannel* pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (bConstraint* con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
+ bSplineIKConstraint* data = (bSplineIKConstraint*)con->data;
+ if ((data->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) == 0) {
+ data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "View3DOverlay", "float", "sculpt_mode_mask_opacity")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.sculpt_mode_mask_opacity = 0.75f;
+ }
+ }
+ }
+ }
+ }
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "char", "render_aa")) {
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ scene->display.render_aa = SCE_DISPLAY_AA_SAMPLES_8;
+ scene->display.viewport_aa = SCE_DISPLAY_AA_FXAA;
+ }
+ }
+
+ /* Split bbone_scalein/bbone_scaleout into x and y fields. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "scale_out_y")) {
+ /* Update armature data and pose channels. */
+ LISTBASE_FOREACH(bArmature*, arm, &bmain->armatures) {
+ do_version_bones_split_bbone_scale(&arm->bonebase);
+ }
+
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ if (ob->pose) {
+ LISTBASE_FOREACH(bPoseChannel*, pchan, &ob->pose->chanbase) {
+ pchan->scale_in_y = pchan->scale_in_x;
+ pchan->scale_out_y = pchan->scale_out_x;
+ }
+ }
+ }
+
+ /* Update action curves and drivers. */
+ LISTBASE_FOREACH(bAction*, act, &bmain->actions) {
+ LISTBASE_FOREACH_MUTABLE(FCurve*, fcu, &act->curves) {
+ do_version_bbone_scale_fcurve_fix(&act->curves, fcu);
+ }
+ }
+
+ BKE_animdata_main_cb(bmain, do_version_bbone_scale_animdata_cb, NULL);
+ }
+
+ for (Scene* sce = bmain->scenes.first; sce != NULL; sce = sce->id.next) {
+ if (sce->ed != NULL) {
+ do_versions_seq_set_cache_defaults(sce->ed);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 61)) {
+ /* Added a power option to Copy Scale. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "float", "power")) {
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ do_version_constraints_copy_scale_power(&ob->constraints);
+ if (ob->pose) {
+ LISTBASE_FOREACH(bPoseChannel*, pchan, &ob->pose->chanbase) {
+ do_version_constraints_copy_scale_power(&pchan->constraints);
+ }
+ }
+ }
+ }
+
+ 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) {
+ if (ELEM(sl->spacetype, SPACE_CLIP, SPACE_GRAPH, SPACE_SEQ)) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+
+ ARegion* ar = NULL;
+ if (sl->spacetype == SPACE_CLIP) {
+ if (((SpaceClip*)sl)->view == SC_VIEW_GRAPH) {
+ ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_PREVIEW);
+ }
+ }
+ else {
+ ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_WINDOW);
+ }
+
+ if (ar != NULL) {
+ ar->v2d.scroll &= ~V2D_SCROLL_LEFT;
+ ar->v2d.scroll |= V2D_SCROLL_RIGHT;
+ }
+ }
+ }
+ }
+ }
+
+ 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) {
+ if (sl->spacetype != SPACE_OUTLINER) {
+ continue;
+ }
+ SpaceOutliner* so = (SpaceOutliner*)sl;
+ so->filter &= ~SO_FLAG_UNUSED_1;
+ so->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
+ LISTBASE_FOREACH(bArmature*, arm, &bmain->armatures) {
+ arm->flag &= ~(ARM_FLAG_UNUSED_7 | ARM_FLAG_UNUSED_9);
+ }
+
+ /* Initializes sun lights with the new angular diameter property */
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "sun_angle")) {
+ LISTBASE_FOREACH(Light*, light, &bmain->lights) {
+ light->sun_angle = 2.0f * atanf(light->area_size);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) {
+ /* New image alpha modes. */
+ LISTBASE_FOREACH(Image*, image, &bmain->images) {
+ const int IMA_IGNORE_ALPHA = (1 << 12);
+ if (image->flag & IMA_IGNORE_ALPHA) {
+ image->alpha_mode = IMA_ALPHA_IGNORE;
+ image->flag &= ~IMA_IGNORE_ALPHA;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 71)) {
+ /* This assumes the Blender builtin config. Depending on the OCIO
+ * environment variable for versioning is weak, and these deprecated view
+ * transforms and look names don't seem to exist in other commonly used
+ * OCIO configs so .blend files created for those would be unaffected. */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ ColorManagedViewSettings* view_settings;
+ view_settings = &scene->view_settings;
+
+ if (STREQ(view_settings->view_transform, "Default")) {
+ STRNCPY(view_settings->view_transform, "Standard");
+ }
+ else if (STREQ(view_settings->view_transform, "RRT") ||
+ STREQ(view_settings->view_transform, "Film")) {
+ STRNCPY(view_settings->view_transform, "Filmic");
+ }
+ else if (STREQ(view_settings->view_transform, "Log")) {
+ STRNCPY(view_settings->view_transform, "Filmic Log");
+ }
+
+ if (STREQ(view_settings->look, "Filmic - Base Contrast")) {
+ STRNCPY(view_settings->look, "None");
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 74)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (scene->ed != NULL) {
+ do_versions_seq_alloc_transform_and_crop(&scene->ed->seqbase);
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 75)) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (scene->master_collection != NULL) {
+ scene->master_collection->flag &= ~(COLLECTION_RESTRICT_VIEWPORT |
+ COLLECTION_RESTRICT_SELECT |
+ COLLECTION_RESTRICT_RENDER);
+ }
+
+ UnitSettings* unit = &scene->unit;
+ if (unit->system == USER_UNIT_NONE) {
+ unit->length_unit = (char)USER_UNIT_ADAPTIVE;
+ unit->mass_unit = (char)USER_UNIT_ADAPTIVE;
+ }
+
+ RenderData* render_data = &scene->r;
+ switch (render_data->ffcodecdata.ffmpeg_preset) {
+ case FFM_PRESET_ULTRAFAST:
+ case FFM_PRESET_SUPERFAST:
+ render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_REALTIME;
+ break;
+ case FFM_PRESET_VERYFAST:
+ case FFM_PRESET_FASTER:
+ case FFM_PRESET_FAST:
+ case FFM_PRESET_MEDIUM:
+ render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_GOOD;
+ break;
+ case FFM_PRESET_SLOW:
+ case FFM_PRESET_SLOWER:
+ case FFM_PRESET_VERYSLOW:
+ render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_BEST;
+ }
+ }
+
+ LISTBASE_FOREACH(bArmature*, arm, &bmain->armatures) {
+ arm->flag &= ~(ARM_FLAG_UNUSED_6);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 1)) {
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_DataTransfer) {
+ /* Now datatransfer's mix factor is multiplied with weights when any,
+ * instead of being ignored,
+ * we need to take care of that to keep 'old' files compatible. */
+ DataTransferModifierData* dtmd = (DataTransferModifierData*)md;
+ if (dtmd->defgrp_name[0] != '\0') {
+ dtmd->mix_factor = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
+ 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) {
+ if (sl->spacetype == SPACE_TEXT) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion* ar = do_versions_find_region_or_null(regionbase, RGN_TYPE_UI);
+ if (ar) {
+ ar->alignment = RGN_ALIGN_RIGHT;
+ }
+ }
+ /* Mark outliners as dirty for syncing and enable synced selection */
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner* soutliner = (SpaceOutliner*)sl;
+ soutliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL;
+ soutliner->flag |= SO_SYNC_SELECT;
+ }
+ }
+ }
+ }
+ for (Mesh* mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
+ if (mesh->remesh_voxel_size == 0.0f) {
+ mesh->remesh_voxel_size = 0.1f;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 4)) {
+ ID* id;
+ FOREACH_MAIN_ID_BEGIN(bmain, id) {
+ bNodeTree* ntree = ntreeFromID(id);
+ if (ntree) {
+ ntree->id.flag |= LIB_PRIVATE_DATA;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 5)) {
+ for (Brush* br = bmain->brushes.first; br; br = br->id.next) {
+ if (br->ob_mode & OB_MODE_SCULPT && br->normal_radius_factor == 0.0f) {
+ br->normal_radius_factor = 0.5f;
+ }
+ }
+
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ /* Older files do not have a master collection, which is then added through
+ * `BKE_collection_master_add()`, so everything is fine. */
+ if (scene->master_collection != NULL) {
+ scene->master_collection->id.flag |= LIB_PRIVATE_DATA;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 6)) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.flag |= V3D_SHADING_SCENE_LIGHTS_RENDER | V3D_SHADING_SCENE_WORLD_RENDER;
+
+ /* files by default don't have studio lights selected unless interacted
+ * with the shading popover. When no studiolight could be read, we will
+ * select the default world one. */
+ StudioLight* studio_light = BKE_studiolight_find(v3d->shading.lookdev_light,
+ STUDIOLIGHT_TYPE_WORLD);
+ if (studio_light != NULL) {
+ STRNCPY(v3d->shading.lookdev_light, studio_light->name);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 9)) {
+ 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) {
+ if (sl->spacetype == SPACE_FILE) {
+ SpaceFile* sfile = (SpaceFile*)sl;
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion* ar_ui = do_versions_find_region(regionbase, RGN_TYPE_UI);
+ ARegion* ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
+ ARegion* ar_toolprops = do_versions_find_region_or_null(regionbase,
+ RGN_TYPE_TOOL_PROPS);
+
+ /* Reinsert UI region so that it spawns entire area width */
+ BLI_remlink(regionbase, ar_ui);
+ BLI_insertlinkafter(regionbase, ar_header, ar_ui);
+
+ ar_ui->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
+ if (ar_toolprops && (ar_toolprops->alignment == (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) {
+ SpaceType* stype = BKE_spacetype_from_id(sl->spacetype);
+
+ /* Remove empty region at old location. */
+ BLI_assert(sfile->op == NULL);
+ BKE_area_region_free(stype, ar_toolprops);
+ BLI_freelinkN(regionbase, ar_toolprops);
+ }
+
+ if (sfile->params) {
+ sfile->params->details_flags |= FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME;
+ }
+ }
+ }
+ }
+ }
+
+ /* Convert the BONE_NO_SCALE flag to inherit_scale_mode enum. */
+ if (!DNA_struct_elem_find(fd->filesdna, "Bone", "char", "inherit_scale_mode")) {
+ LISTBASE_FOREACH(bArmature*, arm, &bmain->armatures) {
+ do_version_bones_inherit_scale(&arm->bonebase);
+ }
+ }
+
+ /* Convert the Offset flag to the mix mode enum. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bRotateLikeConstraint", "char", "mix_mode")) {
+ LISTBASE_FOREACH(Object*, ob, &bmain->objects) {
+ do_version_constraints_copy_rotation_mix_mode(&ob->constraints);
+ if (ob->pose) {
+ LISTBASE_FOREACH(bPoseChannel*, pchan, &ob->pose->chanbase) {
+ do_version_constraints_copy_rotation_mix_mode(&pchan->constraints);
+ }
+ }
+ }
+ }
+
+ /* Added studiolight intensity */
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "studiolight_intensity")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.studiolight_intensity = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ /* Elatic deform brush */
+ for (Brush* br = bmain->brushes.first; br; br = br->id.next) {
+ if (br->ob_mode & OB_MODE_SCULPT && br->elastic_deform_volume_preservation == 0.0f) {
+ br->elastic_deform_volume_preservation = 0.5f;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 15)) {
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_NODE_X) {
+ scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
+ }
+ }
+
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "LayerCollection", "short", "local_collections_bits")) {
+ LISTBASE_FOREACH(Scene*, scene, &bmain->scenes) {
+ LISTBASE_FOREACH(ViewLayer*, view_layer, &scene->view_layers) {
+ LISTBASE_FOREACH(LayerCollection*, layer_collection, &view_layer->layer_collections) {
+ do_versions_local_collection_bits_set(layer_collection);
+ }
+ }
+ }
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+
+ for (ScrArea* sa_other = screen->areabase.first; sa_other; sa_other = sa_other->next) {
+ for (SpaceLink* sl_other = sa_other->spacedata.first; sl_other;
+ sl_other = sl_other->next) {
+ if (sl != sl_other && sl_other->spacetype == SPACE_VIEW3D) {
+ View3D* v3d_other = (View3D*)sl_other;
+
+ if (v3d->shading.prop == v3d_other->shading.prop) {
+ v3d_other->shading.prop = NULL;
+ }
+ }
+ }
+ }
+ }
+ else if (sl->spacetype == SPACE_FILE) {
+ ListBase* regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion* ar_tools = do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOLS);
+ ARegion* ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
+
+ if (ar_tools) {
+ ARegion* ar_next = ar_tools->next;
+
+ /* We temporarily had two tools regions, get rid of the second one. */
+ if (ar_next && ar_next->regiontype == RGN_TYPE_TOOLS) {
+ do_versions_remove_region(regionbase, ar_next);
+ }
+
+ BLI_remlink(regionbase, ar_tools);
+ BLI_insertlinkafter(regionbase, ar_header, ar_tools);
+ }
+ else {
+ ar_tools = do_versions_add_region(RGN_TYPE_TOOLS, "versioning file tools region");
+ BLI_insertlinkafter(regionbase, ar_header, ar_tools);
+ ar_tools->alignment = RGN_ALIGN_LEFT;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ /* Initialize new grease pencil uv scale parameter. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "uv_scale")) {
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ LISTBASE_FOREACH(bGPDframe*, gpf, &gpl->frames) {
+ LISTBASE_FOREACH(bGPDstroke*, gps, &gpf->strokes) {
+ gps->uv_scale = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 282, 2)) {
+ do_version_curvemapping_walker(bmain, do_version_curvemapping_flag_extend_extrapolate);
+
+ for (bScreen* screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea* sa = screen->areabase.first; sa; sa = sa->next) {
+ sa->flag &= ~AREA_FLAG_UNUSED_6;
+ }
+ }
+
+ /* Add custom curve profile to toolsettings for bevel tool */
+ if (!DNA_struct_elem_find(fd->filesdna, "ToolSettings", "CurveProfile", "custom_profile")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ ToolSettings* ts = scene->toolsettings;
+ if ((ts) && (ts->custom_bevel_profile_preset == NULL)) {
+ ts->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
+ }
+ }
+ }
+
+ /* Add custom curve profile to bevel modifier */
+ if (!DNA_struct_elem_find(fd->filesdna, "BevelModifier", "CurveProfile", "custom_profile")) {
+ for (Object* object = bmain->objects.first; object != NULL; object = object->id.next) {
+ for (ModifierData* md = object->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Bevel) {
+ BevelModifierData* bmd = (BevelModifierData*)md;
+ if (!bmd->custom_profile) {
+ bmd->custom_profile = BKE_curveprofile_add(PROF_PRESET_LINE);
+ }
+ }
+ }
+ }
+ }
+
+ /* Dash Ratio and Dash Samples */
+ if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "dash_ratio")) {
+ for (Brush* br = bmain->brushes.first; br; br = br->id.next) {
+ br->dash_ratio = 1.0f;
+ br->dash_samples = 20;
+ }
+ }
+
+ /* Pose brush smooth iterations */
+ if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_iterations")) {
+ for (Brush* br = bmain->brushes.first; br; br = br->id.next) {
+ br->pose_smooth_iterations = 4;
+ }
+ }
+
+ /* Cloth pressure */
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Cloth) {
+ ClothModifierData* clmd = (ClothModifierData*)md;
+
+ clmd->sim_parms->pressure_factor = 1;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 282, 3)) {
+ /* Remove Unified pressure/size and pressure/alpha */
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ ToolSettings* ts = scene->toolsettings;
+ UnifiedPaintSettings* ups = &ts->unified_paint_settings;
+ ups->flag &= ~(UNIFIED_PAINT_FLAG_UNUSED_0 | UNIFIED_PAINT_FLAG_UNUSED_1);
+ }
+
+ /* Set the default render pass in the viewport to Combined. */
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "int", "render_pass")) {
+ for (Scene* scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ scene->display.shading.render_pass = SCE_PASS_COMBINED;
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->shading.render_pass = SCE_PASS_COMBINED;
+ }
+ }
+ }
+ }
+ }
+
+ /* Make markers region visible by default. */
+ 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) {
+ switch (sl->spacetype) {
+ case SPACE_SEQ: {
+ SpaceSeq* sseq = (SpaceSeq*)sl;
+ sseq->flag |= SEQ_SHOW_MARKERS;
+ break;
+ }
+ case SPACE_ACTION: {
+ SpaceAction* saction = (SpaceAction*)sl;
+ saction->flag |= SACTION_SHOW_MARKERS;
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph* sipo = (SpaceGraph*)sl;
+ sipo->flag |= SIPO_SHOW_MARKERS;
+ break;
+ }
+ case SPACE_NLA: {
+ SpaceNla* snla = (SpaceNla*)sl;
+ snla->flag |= SNLA_SHOW_MARKERS;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Init new Grease Pencil Paint tools. */
+ {
+ for (Brush* brush = bmain->brushes.first; brush; brush = brush->id.next) {
+ 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);
+ }
+
+ /* Init default Grease Pencil Vertex paint mix factor for Viewport. */
+ {
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "View3DOverlay", "float", "gpencil_vertex_paint_opacity")) {
+ 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) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D* v3d = (View3D*)sl;
+ v3d->overlay.gpencil_vertex_paint_opacity = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Init default Grease Pencil Vertex paint layer mix factor. */
+ {
+ if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "float", "vertex_paint_opacity")) {
+ for (bGPdata* gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ gpl->vertex_paint_opacity = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 283, 0)) {
+
+ /* Update Grease Pencil after drawing engine refactor. */
+ {
+ 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);
+ srgb_to_linearrgb_v3_v3(vfx->select_color, vfx->select_color);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /* Modifiers. */
+ LISTBASE_FOREACH(GpencilModifierData*, md, &ob->greasepencil_modifiers) {
+ const GpencilModifierTypeInfo* mti = BKE_gpencil_modifierType_getInfo(md->type);
+ switch (mti->type) {
+ case eGpencilModifierTypeType_Gpencil: {
+ TintGpencilModifierData* mmd = (TintGpencilModifierData*)md;
+ srgb_to_linearrgb_v3_v3(mmd->rgb, mmd->rgb);
+ 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);
+
+ LISTBASE_FOREACH(bGPDlayer*, gpl, &gpd->layers) {
+ gpl->flag |= GP_LAYER_USE_LIGHTS;
+ srgb_to_linearrgb_v4(gpl->tintcolor, gpl->tintcolor);
+
+ 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.
+ *
+ * \note Be sure to check when bumping the version:
+ * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+
+ /* Sequencer Tool region */
+ do_versions_area_ensure_tool_region(bmain, SPACE_SEQ, RGN_FLAG_HIDDEN);
+
+ /* Cloth internal springs */
+ for (Object* ob = bmain->objects.first; ob; ob = ob->id.next) {
+ for (ModifierData* md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Cloth) {
+ ClothModifierData* clmd = (ClothModifierData*)md;
+
+ clmd->sim_parms->internal_tension = 15.0f;
+ clmd->sim_parms->max_internal_tension = 15.0f;
+ clmd->sim_parms->internal_compression = 15.0f;
+ clmd->sim_parms->max_internal_compression = 15.0f;
+ clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
+ }
+ }
+ }
+
+ /* Add primary tile to images. */
+ if (!DNA_struct_elem_find(fd->filesdna, "Image", "ListBase", "tiles")) {
+ for (Image* ima = bmain->images.first; ima; ima = ima->id.next) {
+ ImageTile* tile = MEM_callocN(sizeof(ImageTile), "Image Tile");
+ tile->ok = 1;
+ tile->tile_number = 1001;
+ BLI_addtail(&ima->tiles, tile);
+ }
+ }
+
+ /* UDIM Image Editor change. */
+ if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "int", "tile_grid_shape[2]")) {
+ 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) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage* sima = (SpaceImage*)sl;
+ sima->tile_grid_shape[0] = 1;
+ sima->tile_grid_shape[1] = 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* Brush cursor alpha */
+ for (Brush* br = bmain->brushes.first; br; br = br->id.next) {
+ br->add_col[3] = 0.9f;
+ br->sub_col[3] = 0.9f;
+ }
+
+ /* Pose brush IK segments. */
+ for (Brush* br = bmain->brushes.first; br; br = br->id.next) {
+ if (br->pose_ik_segments == 0) {
+ br->pose_ik_segments = 1;
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 8dc71dd314e..1c0ea8d20ed 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -241,6 +241,8 @@ static void blo_update_defaults_screen(bScreen *screen,
View3D *v3d = sa->spacedata.first;
/* Set Vertex Color by default. */
v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR;
+ /* Enable Annotations. */
+ v3d->flag2 |= V3D_SHOW_ANNOTATION;
}
}
}
@@ -614,14 +616,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
if (ma == NULL) {
ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
}
- ma->gp_style->mode = GP_STYLE_MODE_DOTS;
+ ma->gp_style->mode = GP_MATERIAL_MODE_DOT;
/* Boxes Stroke. */
ma = BLI_findstring(&bmain->materials, "Boxes Stroke", offsetof(ID, name) + 2);
if (ma == NULL) {
ma = BKE_gpencil_material_add(bmain, "Boxes Stroke");
}
- ma->gp_style->mode = GP_STYLE_MODE_BOX;
+ ma->gp_style->mode = GP_MATERIAL_MODE_SQUARE;
/* Reset all grease pencil brushes. */
Scene *scene = bmain->scenes.first;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 055bc96f5d9..dd8a5a6795a 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2726,14 +2726,15 @@ 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 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);
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 98864b11c4a..6a936b560b2 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -2149,6 +2149,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:
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index b74e5715e14..5873a5cd65f 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -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_library.h"
#include "BKE_scene.h"
@@ -790,6 +791,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);
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index a74a255045a..5d11578fe19 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -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
@@ -110,12 +111,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
@@ -127,6 +129,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
@@ -273,36 +276,17 @@ 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_composite_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_layer_blend_frag.glsl SRC)
+data_to_c_simple(engines/gpencil/shaders/gpencil_layer_mask_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)
@@ -334,6 +318,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)
diff --git a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
new file mode 100644
index 00000000000..f53746b922b
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
@@ -0,0 +1,155 @@
+/*
+ * 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;
+
+ /* We need a temporary buffer to output result. */
+ BLI_assert(pd->color_layer_tx && pd->reveal_layer_tx);
+
+ 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);
+ }
+
+ const float *size = DRW_viewport_size_get();
+ float metrics[4] = {1.0f / size[0], 1.0f / size[1], size[0], size[1]};
+
+ {
+ 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. */
+ /* TODO merge it with the main composite pass. */
+ DRW_PASS_CREATE(psl->smaa_resolve_ps, DRW_STATE_WRITE_COLOR);
+
+ 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_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;
+
+ 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(fbl->layer_fb);
+ DRW_draw_pass(psl->smaa_resolve_ps);
+
+ /* Swap buffers */
+ SWAP(GPUTexture *, pd->color_tx, pd->color_layer_tx);
+ SWAP(GPUTexture *, pd->reveal_tx, pd->reveal_layer_tx);
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index f21d96a304c..ae8ac611570 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -33,324 +33,218 @@
#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)
+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;
- }
- /* 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;
- }
- }
+ 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);
+
+ /* 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 false;
+ return tgp_ob;
}
-/* 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)
+GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGPDlayer *gpl)
{
- 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;
+ 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. */
+ float fade_layer_opacity = gpl->opacity;
+ if (!pd->is_render) {
+ if ((is_obact) && (is_fade)) {
+ fade_layer_opacity = pd->fade_layer_opacity;
}
- else {
- *gp_cache_size += GP_CACHE_BLOCK_SIZE;
- p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
+ else if ((!is_obact) && (pd->fade_gp_object_opacity > -1.0f)) {
+ fade_layer_opacity = pd->fade_gp_object_opacity;
}
- 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;
- }
-
- cache_elem->scale = mat4_to_scale(ob->obmat);
-
- /* save FXs */
- cache_elem->pixfactor = cache_elem->gpd->pixfactor;
- cache_elem->shader_fx = ob->shader_fx;
-
- /* save wire mode (object mode is always primary option) */
- if (ob->dt == OB_WIRE) {
- cache_elem->shading_type[0] = (int)OB_WIRE;
- }
- else {
- if (v3d) {
- cache_elem->shading_type[0] = (int)v3d->shading.type;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
+
+ const bool is_mask = (gpl->flag & GP_LAYER_USE_MASK) != 0;
+ tgp_layer->is_mask = is_mask;
+ tgp_layer->do_masked_clear = false;
+
+ if (!is_mask) {
+ tgp_layer->is_masked = false;
+ for (bGPDlayer *gpl_m = gpl->next; gpl_m; gpl_m = gpl_m->next) {
+ if (gpl_m->flag & GP_LAYER_USE_MASK) {
+ if (gpl_m->flag & GP_LAYER_HIDE) {
+ /* We don't mask but we dont try to mask with further layers. */
+ }
+ else {
+ tgp_layer->is_masked = true;
+ }
+ break;
+ }
}
}
- /* 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);
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
+ if (GPENCIL_3D_DRAWMODE(ob, gpd) || pd->draw_depth_only) {
+ /* TODO better 3D mode. */
+ state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
}
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);
+ /* We render all strokes with uniform depth (increasing with stroke id). */
+ state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_GREATER;
}
- }
- cache_elem->zdepth = zdepth;
- /* increase slots used in cache */
- (*gp_cache_used)++;
- return cache_array;
-}
-
-/* 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;
+ if (gpl->flag & GP_LAYER_USE_MASK) {
+ state |= DRW_STATE_STENCIL_EQUAL;
}
else {
- *grp_size += GPENCIL_GROUPS_BLOCK_SIZE;
- p = MEM_recallocN(cache_array, sizeof(struct GpencilBatchGroup) * *grp_size);
+ state |= DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
}
- 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);
+ tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
+ }
+
+ if (is_mask) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_BLEND_MUL;
+ tgp_layer->blend_ps = DRW_pass_create("GPencil Mask Layer", state);
+
+ GPUShader *sh = GPENCIL_shader_layer_mask_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
+ DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
+ DRW_shgroup_uniform_float_copy(grp, "maskOpacity", fade_layer_opacity);
+ DRW_shgroup_uniform_bool_copy(grp, "maskInvert", gpl->flag & GP_LAYER_MASK_INVERT);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_masked_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_masked_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "maskBuf", &pd->reveal_layer_tx);
+ DRW_shgroup_stencil_mask(grp, 0xFF);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ /* We cannot do custom blending on MultiTarget framebuffers.
+ * Workaround by doing 2 passes. */
+ grp = DRW_shgroup_create_sub(grp);
+ 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, "isFirstPass", false);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ pd->use_mask_fb = true;
+ }
+ else if ((gpl->blend_mode != eGplBlendMode_Regular) || (fade_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;
}
- 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;
-}
+ 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;
+ }
-/* 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;
+ 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", fade_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_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);
}
- }
- /* 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);
+ pd->use_layer_fb = true;
+ }
+ else {
+ tgp_layer->blend_ps = NULL;
}
- ob->runtime.gpencil_tot_layers = 0;
- MEM_SAFE_FREE(ob->runtime.gpencil_evaluated_frames);
+ return tgp_layer;
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
deleted file mode 100644
index 30fc1896bbb..00000000000
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ /dev/null
@@ -1,1144 +0,0 @@
-/*
- * 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.
- *
- * The Original Code is Copyright (C) 2008, Blender Foundation
- * This is a new part of Blender
- */
-
-/** \file
- * \ingroup draw
- */
-
-#include "BLI_polyfill_2d.h"
-#include "BLI_math_color.h"
-
-#include "DNA_meshdata_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_view3d_types.h"
-
-#include "BKE_deform.h"
-#include "BKE_gpencil.h"
-
-#include "DRW_render.h"
-
-#include "ED_gpencil.h"
-#include "ED_view3d.h"
-
-#include "UI_resources.h"
-
-#include "gpencil_engine.h"
-
-/* Helper to add stroke point to vbo */
-static void gpencil_set_stroke_point(GPUVertBuf *vbo,
- const bGPDspoint *pt,
- int idx,
- uint pos_id,
- uint color_id,
- uint thickness_id,
- uint uvdata_id,
- short thickness,
- const bool attenuate,
- const float ink[4])
-{
- float alpha = ink[3] * pt->strength;
-
- /* If using vertex paint mask, attenuate not selected. */
- if ((attenuate) && ((pt->flag & GP_SPOINT_SELECT) == 0)) {
- alpha *= GP_VERTEX_MASK_ATTENUATE;
- }
-
- CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- float col[4];
- ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha);
-
- GPU_vertbuf_attr_set(vbo, color_id, idx, col);
-
- /* transfer both values using the same shader variable */
- float uvdata[2] = {pt->uv_fac, pt->uv_rot};
- GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
-
- /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */
- float thick = max_ff(pt->pressure * thickness, 1.0f);
- GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick);
-
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
-}
-
-/* Helper to add buffer_stroke point to vbo */
-static void gpencil_set_buffer_stroke_point(GPUVertBuf *vbo,
- const bGPDspoint *pt,
- int idx,
- uint pos_id,
- uint color_id,
- uint thickness_id,
- uint uvdata_id,
- uint prev_pos_id,
- const float ref_pt[3],
- short thickness,
- const float ink[4])
-{
-
- float alpha = ink[3] * pt->strength;
- CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- float col[4];
- ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha);
-
- GPU_vertbuf_attr_set(vbo, color_id, idx, col);
-
- /* transfer both values using the same shader variable */
- float uvdata[2] = {pt->uv_fac, pt->uv_rot};
- GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata);
-
- /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */
- float thick = max_ff(pt->pressure * thickness, 1.0f);
- GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick);
-
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
- /* reference point to follow drawing path */
- GPU_vertbuf_attr_set(vbo, prev_pos_id, idx, ref_pt);
-}
-
-/* Helper to add a new fill point and texture coordinates to vertex buffer */
-static void gpencil_set_fill_point(GPUVertBuf *vbo,
- int idx,
- bGPDspoint *pt,
- const float fcolor[4],
- const float uv[2],
- uint pos_id,
- uint color_id,
- uint text_id)
-{
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x);
- GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor);
- GPU_vertbuf_attr_set(vbo, text_id, idx, uv);
-}
-
-static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex)
-{
- if (be->vbo->vertex_alloc <= be->vbo_len + totvertex) {
- uint newsize = be->vbo->vertex_alloc +
- (((totvertex / GPENCIL_VBO_BLOCK_SIZE) + 1) * GPENCIL_VBO_BLOCK_SIZE);
- GPU_vertbuf_data_resize(be->vbo, newsize);
- }
-}
-
-static void gpencil_elem_format_ensure(GpencilBatchCacheElem *be)
-{
- if (be->format == NULL) {
- be->format = MEM_callocN(sizeof(GPUVertFormat), __func__);
- }
-}
-
-/* create batch geometry data for points stroke shader */
-void gpencil_get_point_geom(GpencilBatchCacheElem *be,
- bGPDlayer *gpl,
- bGPDstroke *gps,
- short thickness,
- const float ink[4],
- const float tintcolor[4],
- const int alignment_mode,
- const bool onion)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- ToolSettings *ts = draw_ctx->scene->toolsettings;
- Object *ob = draw_ctx->obact;
- bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
- int totvertex = gps->totpoints;
- float mix_color[4];
-
- const float vpaint_mix = gpencil_get_vertex_paint_factor(v3d);
- const bool attenuate = (GPENCIL_VERTEX_MODE(gpd) &&
- GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex));
-
- if (be->vbo == NULL) {
- gpencil_elem_format_ensure(be);
- be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- be->thickness_id = GPU_vertformat_attr_add(
- be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- be->uvdata_id = GPU_vertformat_attr_add(
- be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- be->prev_pos_id = GPU_vertformat_attr_add(
- be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- be->vbo = GPU_vertbuf_create_with_format(be->format);
- GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
- be->vbo_len = 0;
- }
- gpencil_vbo_ensure_size(be, totvertex);
-
- /* draw stroke curve */
- const bGPDspoint *pt = gps->points;
- float alpha;
- float col[4];
-
- for (int i = 0; i < gps->totpoints; i++, pt++) {
- /* set point */
- alpha = ink[3] * pt->strength;
- CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- /* Apply the mix color. */
- if (!onion) {
- float mixtint[3];
- interp_v3_v3v3(mixtint, pt->mix_color, tintcolor, tintcolor[3]);
- interp_v3_v3v3(
- mix_color, ink, mixtint, pt->mix_color[3] * vpaint_mix * gpl->vertex_paint_opacity);
- }
- /* If using vertex paint mask, attenuate not selected. */
- if ((attenuate) && ((pt->flag & GP_SPOINT_SELECT) == 0)) {
- alpha *= GP_VERTEX_MASK_ATTENUATE;
- }
-
- ARRAY_SET_ITEMS(col, mix_color[0], mix_color[1], mix_color[2], alpha);
-
- float thick = max_ff(pt->pressure * thickness, 1.0f);
-
- GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, col);
- GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &thick);
-
- /* transfer both values using the same shader variable */
- float uvdata[2] = {pt->uv_fac, pt->uv_rot};
- GPU_vertbuf_attr_set(be->vbo, be->uvdata_id, be->vbo_len, uvdata);
-
- GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x);
-
- /* use previous point to determine stroke direction */
- bGPDspoint *pt2 = NULL;
- float fpt[3];
- if (alignment_mode != GP_STYLE_FOLLOW_PATH) {
- /* add small offset to get a vector */
- copy_v3_v3(fpt, &pt->x);
- fpt[0] += 0.00001f;
- fpt[1] += 0.00001f;
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
- }
- else {
- if (i == 0) {
- if (gps->totpoints > 1) {
- /* extrapolate a point before first point */
- pt2 = &gps->points[1];
- interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f);
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
- }
- else {
- /* add small offset to get a vector */
- copy_v3_v3(fpt, &pt->x);
- fpt[0] += 0.00001f;
- fpt[1] += 0.00001f;
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
- }
- }
- else {
- pt2 = &gps->points[i - 1];
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x);
- }
- }
- be->vbo_len++;
- }
-}
-
-/* create batch geometry data for stroke shader */
-void gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be,
- bGPDlayer *gpl,
- bGPDstroke *gps,
- short thickness,
- const float ink[4],
- const float tintcolor[4],
- const bool onion)
-{
- bGPDspoint *points = gps->points;
- int totpoints = gps->totpoints;
- /* if cyclic needs more vertex */
- int cyclic_add = (gps->flag & GP_STROKE_CYCLIC) ? 1 : 0;
- int totvertex = totpoints + cyclic_add + 2;
- float mix_color[4];
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- ToolSettings *ts = draw_ctx->scene->toolsettings;
- Object *ob = draw_ctx->obact;
- bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
-
- const float vpaint_mix = gpencil_get_vertex_paint_factor(v3d);
- const bool attenuate = (GPENCIL_VERTEX_MODE(gpd) &&
- GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex));
-
- if (be->vbo == NULL) {
- gpencil_elem_format_ensure(be);
- be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- be->thickness_id = GPU_vertformat_attr_add(
- be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- be->uvdata_id = GPU_vertformat_attr_add(
- be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- be->vbo = GPU_vertbuf_create_with_format(be->format);
- GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
- be->vbo_len = 0;
- }
- gpencil_vbo_ensure_size(be, totvertex);
-
- /* draw stroke curve */
- const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints; i++, pt++) {
- /* Apply the mix color. */
- copy_v4_v4(mix_color, ink);
- if (!onion) {
- float mixtint[3];
- interp_v3_v3v3(mixtint, pt->mix_color, tintcolor, tintcolor[3]);
- interp_v3_v3v3(
- mix_color, ink, mixtint, pt->mix_color[3] * vpaint_mix * gpl->vertex_paint_opacity);
- }
-
- /* first point for adjacency (not drawn) */
- if (i == 0) {
- if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
- gpencil_set_stroke_point(be->vbo,
- &points[totpoints - 1],
- be->vbo_len,
- be->pos_id,
- be->color_id,
- be->thickness_id,
- be->uvdata_id,
- thickness,
- attenuate,
- mix_color);
- be->vbo_len++;
- }
- else {
- gpencil_set_stroke_point(be->vbo,
- &points[1],
- be->vbo_len,
- be->pos_id,
- be->color_id,
- be->thickness_id,
- be->uvdata_id,
- thickness,
- attenuate,
- mix_color);
- be->vbo_len++;
- }
- }
- /* set point */
- gpencil_set_stroke_point(be->vbo,
- pt,
- be->vbo_len,
- be->pos_id,
- be->color_id,
- be->thickness_id,
- be->uvdata_id,
- thickness,
- attenuate,
- mix_color);
- be->vbo_len++;
- }
-
- if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) {
- /* draw line to first point to complete the cycle */
- gpencil_set_stroke_point(be->vbo,
- &points[0],
- be->vbo_len,
- be->pos_id,
- be->color_id,
- be->thickness_id,
- be->uvdata_id,
- thickness,
- attenuate,
- mix_color);
- be->vbo_len++;
- /* now add adjacency point (not drawn) */
- gpencil_set_stroke_point(be->vbo,
- &points[1],
- be->vbo_len,
- be->pos_id,
- be->color_id,
- be->thickness_id,
- be->uvdata_id,
- thickness,
- attenuate,
- mix_color);
- be->vbo_len++;
- }
- /* last adjacency point (not drawn) */
- else {
- gpencil_set_stroke_point(be->vbo,
- &points[totpoints - 2],
- be->vbo_len,
- be->pos_id,
- be->color_id,
- be->thickness_id,
- be->uvdata_id,
- thickness,
- attenuate,
- mix_color);
- be->vbo_len++;
- }
-}
-
-/* create batch geometry data for stroke shader */
-void gpencil_get_fill_geom(struct GpencilBatchCacheElem *be,
- Object *ob,
- bGPDstroke *gps,
- const float color[4])
-{
- BLI_assert(gps->totpoints >= 3);
-
- /* Calculate triangles cache for filling area (must be done only after changes) */
- if ((gps->flag & GP_STROKE_RECALC_GEOMETRY) || (gps->tot_triangles == 0) ||
- (gps->triangles == NULL)) {
- BKE_gpencil_triangulate_stroke_fill((bGPdata *)ob->data, gps);
- }
-
- BLI_assert(gps->tot_triangles >= 1);
- int totvertex = gps->tot_triangles * 3;
-
- if (be->vbo == NULL) {
- gpencil_elem_format_ensure(be);
- be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- be->uvdata_id = GPU_vertformat_attr_add(
- be->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- be->vbo = GPU_vertbuf_create_with_format(be->format);
- GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
- be->vbo_len = 0;
- }
- gpencil_vbo_ensure_size(be, totvertex);
-
- /* Draw all triangles for filling the polygon (cache must be calculated before) */
- bGPDtriangle *stroke_triangle = gps->triangles;
- for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
- for (int j = 0; j < 3; j++) {
- gpencil_set_fill_point(be->vbo,
- be->vbo_len,
- &gps->points[stroke_triangle->verts[j]],
- color,
- stroke_triangle->uv[j],
- be->pos_id,
- be->color_id,
- be->uvdata_id);
- be->vbo_len++;
- }
- }
-}
-
-/* create batch geometry data for current buffer stroke shader */
-GPUBatch *gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ARegion *ar = draw_ctx->ar;
- RegionView3D *rv3d = draw_ctx->rv3d;
- ToolSettings *ts = scene->toolsettings;
- Object *ob = draw_ctx->obact;
-
- tGPspoint *points = gpd->runtime.sbuffer;
- int totpoints = gpd->runtime.sbuffer_used;
- /* if cyclic needs more vertex */
- int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0;
- int totvertex = totpoints + cyclic_add + 2;
-
- static GPUVertFormat format = {0};
- static uint pos_id, color_id, thickness_id, uvdata_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, totvertex);
-
- /* draw stroke curve */
- const tGPspoint *tpt = points;
- bGPDspoint pt, pt2, pt3;
- int idx = 0;
-
- /* get origin to reproject point */
- float origin[3];
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
-
- for (int i = 0; i < totpoints; i++, tpt++) {
- ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
- ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
-
- /* first point for adjacency (not drawn) */
- if (i == 0) {
- if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) {
- ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 1], &pt2);
- gpencil_set_stroke_point(vbo,
- &pt2,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- thickness,
- false,
- gpd->runtime.scolor);
- idx++;
- }
- else {
- ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2);
- gpencil_set_stroke_point(vbo,
- &pt2,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- thickness,
- false,
- gpd->runtime.scolor);
- idx++;
- }
- }
-
- /* set point */
- gpencil_set_stroke_point(vbo,
- &pt,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- thickness,
- false,
- gpd->runtime.scolor);
- idx++;
- }
-
- /* last adjacency point (not drawn) */
- if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) {
- /* draw line to first point to complete the cycle */
- ED_gpencil_tpoint_to_point(ar, origin, &points[0], &pt2);
- gpencil_set_stroke_point(vbo,
- &pt2,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- thickness,
- false,
- gpd->runtime.scolor);
- idx++;
- /* now add adjacency point (not drawn) */
- ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt3);
- gpencil_set_stroke_point(vbo,
- &pt3,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- thickness,
- false,
- gpd->runtime.scolor);
- idx++;
- }
- /* last adjacency point (not drawn) */
- else {
- ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2);
- gpencil_set_stroke_point(vbo,
- &pt2,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- thickness,
- false,
- gpd->runtime.scolor);
- idx++;
- }
-
- return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO);
-}
-
-/* create batch geometry data for current buffer point shader */
-GPUBatch *gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ARegion *ar = draw_ctx->ar;
- RegionView3D *rv3d = draw_ctx->rv3d;
- ToolSettings *ts = scene->toolsettings;
- Object *ob = draw_ctx->obact;
-
- tGPspoint *points = gpd->runtime.sbuffer;
- int totpoints = gpd->runtime.sbuffer_used;
-
- static GPUVertFormat format = {0};
- static uint pos_id, color_id, thickness_id, uvdata_id, prev_pos_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- prev_pos_id = GPU_vertformat_attr_add(&format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, totpoints);
-
- /* draw stroke curve */
- const tGPspoint *tpt = points;
- bGPDspoint pt;
- int idx = 0;
-
- /* get origin to reproject point */
- float origin[3];
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
-
- for (int i = 0; i < totpoints; i++, tpt++) {
- ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
- ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
-
- /* use previous point to determine stroke direction (drawing path) */
- bGPDspoint pt2;
- float ref_pt[3];
-
- if (i == 0) {
- if (totpoints > 1) {
- /* extrapolate a point before first point */
- tGPspoint *tpt2 = &points[1];
- ED_gpencil_tpoint_to_point(ar, origin, tpt2, &pt2);
- ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt2);
-
- interp_v3_v3v3(ref_pt, &pt2.x, &pt.x, 1.5f);
- }
- else {
- copy_v3_v3(ref_pt, &pt.x);
- }
- }
- else {
- tGPspoint *tpt2 = &points[i - 1];
- ED_gpencil_tpoint_to_point(ar, origin, tpt2, &pt2);
- ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt2);
-
- copy_v3_v3(ref_pt, &pt2.x);
- }
-
- /* set point */
- gpencil_set_buffer_stroke_point(vbo,
- &pt,
- idx,
- pos_id,
- color_id,
- thickness_id,
- uvdata_id,
- prev_pos_id,
- ref_pt,
- thickness,
- gpd->runtime.scolor);
- idx++;
- }
-
- return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
-}
-
-/* create batch geometry data for current buffer control point shader */
-GPUBatch *gpencil_get_buffer_ctrlpoint_geom(bGPdata *gpd)
-{
- bGPDcontrolpoint *cps = gpd->runtime.cp_points;
- int totpoints = gpd->runtime.tot_cp_points;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ToolSettings *ts = scene->toolsettings;
-
- if (ts->gp_sculpt.guide.use_guide) {
- totpoints++;
- }
-
- static GPUVertFormat format = {0};
- static uint pos_id, color_id, size_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, totpoints);
-
- int idx = 0;
- for (int i = 0; i < gpd->runtime.tot_cp_points; i++) {
- bGPDcontrolpoint *cp = &cps[i];
-
- GPU_vertbuf_attr_set(vbo, color_id, idx, cp->color);
-
- /* scale size */
- float size = cp->size * 0.8f;
- GPU_vertbuf_attr_set(vbo, size_id, idx, &size);
-
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &cp->x);
- idx++;
- }
-
- if (ts->gp_sculpt.guide.use_guide) {
- float size = 10 * 0.8f;
- float color[4];
- float position[3];
- if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_CUSTOM) {
- UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
- copy_v3_v3(position, ts->gp_sculpt.guide.location);
- }
- else if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_OBJECT &&
- ts->gp_sculpt.guide.reference_object != NULL) {
- UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
- copy_v3_v3(position, ts->gp_sculpt.guide.reference_object->loc);
- }
- else {
- UI_GetThemeColor4fv(TH_REDALERT, color);
- copy_v3_v3(position, scene->cursor.location);
- }
- GPU_vertbuf_attr_set(vbo, pos_id, idx, position);
- GPU_vertbuf_attr_set(vbo, size_id, idx, &size);
- GPU_vertbuf_attr_set(vbo, color_id, idx, color);
- }
-
- return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
-}
-
-/* create batch geometry data for current buffer fill shader */
-GPUBatch *gpencil_get_buffer_fill_geom(bGPdata *gpd)
-{
- if (gpd == NULL) {
- return NULL;
- }
-
- const tGPspoint *points = gpd->runtime.sbuffer;
- int totpoints = gpd->runtime.sbuffer_used;
- if (totpoints < 3) {
- return NULL;
- }
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ARegion *ar = draw_ctx->ar;
- ToolSettings *ts = scene->toolsettings;
- Object *ob = draw_ctx->obact;
-
- /* get origin to reproject point */
- float origin[3];
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
-
- int tot_triangles = totpoints - 2;
- /* allocate memory for temporary areas */
- uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, __func__);
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, __func__);
-
- /* Convert points to array and triangulate
- * Here a cache is not used because while drawing the information changes all the time, so the
- * cache would be recalculated constantly, so it is better to do direct calculation for each
- * function call
- */
- for (int i = 0; i < totpoints; i++) {
- const tGPspoint *pt = &points[i];
- points2d[i][0] = pt->x;
- points2d[i][1] = pt->y;
- }
- BLI_polyfill_calc(points2d, (uint)totpoints, 0, tmp_triangles);
-
- static GPUVertFormat format = {0};
- static uint pos_id, color_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
-
- /* draw triangulation data */
- if (tot_triangles > 0) {
- GPU_vertbuf_data_alloc(vbo, tot_triangles * 3);
-
- const tGPspoint *tpt;
- bGPDspoint pt;
-
- int idx = 0;
- for (int i = 0; i < tot_triangles; i++) {
- for (int j = 0; j < 3; j++) {
- tpt = &points[tmp_triangles[i][j]];
- ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
- GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt.x);
- GPU_vertbuf_attr_set(vbo, color_id, idx, gpd->runtime.sfill);
- idx++;
- }
- }
- }
-
- /* clear memory */
- if (tmp_triangles) {
- MEM_freeN(tmp_triangles);
- }
- if (points2d) {
- MEM_freeN(points2d);
- }
-
- return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
-}
-
-/* Draw selected verts for strokes being edited */
-void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
- bGPDstroke *gps,
- float alpha,
- short dflag)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Object *ob = draw_ctx->obact;
- bGPdata *gpd = ob->data;
- const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
- const bool is_vertex_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_VERTEXMODE);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- int vgindex = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, vgindex)) {
- vgindex = -1;
- }
-
- /* Get size of verts:
- * - The selected state needs to be larger than the unselected state so that
- * they stand out more.
- * - We use the theme setting for size of the unselected verts
- */
- float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
- float vsize;
- if ((int)bsize > 8) {
- vsize = 10.0f;
- bsize = 8.0f;
- }
- else {
- vsize = bsize + 2;
- }
-
- /* for now, we assume that the base color of the points is not too close to the real color */
- float selectColor[4];
- float unselectColor[4];
- if (!is_vertex_paint) {
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
- UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor);
- }
- else {
- UI_GetThemeColor3fv(TH_ACTIVE_VERT, selectColor);
- UI_GetThemeColor3fv(TH_VERTEX, unselectColor);
- /* Make smaller */
- vsize *= 0.8f;
- bsize *= 0.8f;
- }
- selectColor[3] = alpha;
- unselectColor[3] = alpha;
-
- float linecolor[4];
- copy_v4_v4(linecolor, gpd->line_color);
-
- if (be->vbo == NULL) {
- gpencil_elem_format_ensure(be);
- be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- be->thickness_id = GPU_vertformat_attr_add(
- be->format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
-
- be->vbo = GPU_vertbuf_create_with_format(be->format);
- GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
- be->vbo_len = 0;
- }
- gpencil_vbo_ensure_size(be, gps->totpoints);
-
- /* Draw start and end point differently if enabled stroke direction hint */
- bool show_direction_hint = (dflag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
-
- /* Draw all the stroke points (selected or not) */
- bGPDspoint *pt = gps->points;
- MDeformVert *dvert = gps->dvert;
-
- float fcolor[4];
- float fsize = 0;
- for (int i = 0; i < gps->totpoints; i++, pt++) {
- /* weight paint */
- if (is_weight_paint) {
- float weight = (dvert && dvert->dw && (vgindex > -1)) ? defvert_find_weight(dvert, vgindex) :
- 0.0f;
- float hue = 2.0f * (1.0f - weight) / 3.0f;
- hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]);
- selectColor[3] = 1.0f;
- copy_v4_v4(fcolor, selectColor);
- fsize = vsize;
- }
- /* weight paint */
- else if (is_vertex_paint) {
- if (pt->flag & GP_SPOINT_SELECT) {
- copy_v4_v4(fcolor, selectColor);
- fsize = vsize;
- }
- else {
- copy_v4_v4(fcolor, unselectColor);
- fsize = bsize;
- }
- }
- else {
- if (show_direction_hint && i == 0) {
- /* start point in green bigger */
- ARRAY_SET_ITEMS(fcolor, 0.0f, 1.0f, 0.0f, 1.0f);
- fsize = vsize + 4;
- }
- else if (show_direction_hint && (i == gps->totpoints - 1)) {
- /* end point in red smaller */
- ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f);
- fsize = vsize + 1;
- }
- else if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
- ARRAY_SET_ITEMS(fcolor, linecolor[0], linecolor[1], linecolor[2], selectColor[3]);
- mul_v4_fl(fcolor, 0.9f);
- copy_v4_v4(fcolor, fcolor);
- fsize = vsize * 0.8f;
- }
- else if (pt->flag & GP_SPOINT_SELECT) {
- copy_v4_v4(fcolor, selectColor);
- fsize = vsize;
- }
- else {
- copy_v4_v4(fcolor, unselectColor);
- fsize = bsize;
- }
- }
-
- GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor);
- GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &fsize);
- GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x);
- be->vbo_len++;
- if (gps->dvert != NULL) {
- dvert++;
- }
- }
-}
-
-/* Draw lines for strokes being edited */
-void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
- bGPDstroke *gps,
- float alpha,
- const bool hide_select)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Object *ob = draw_ctx->obact;
- bGPdata *gpd = ob->data;
- const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
- const int fake_point = (gps->totpoints == 1) ? 1 : 0;
-
- int vgindex = ob->actdef - 1;
- if (!BLI_findlink(&ob->defbase, vgindex)) {
- vgindex = -1;
- }
-
- float selectColor[4];
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
- selectColor[3] = alpha;
- float linecolor[4];
- copy_v4_v4(linecolor, gpd->line_color);
-
- if (be->vbo == NULL) {
- gpencil_elem_format_ensure(be);
- be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- be->vbo = GPU_vertbuf_create_with_format(be->format);
- GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
- be->vbo_len = 0;
- }
- gpencil_vbo_ensure_size(be, gps->totpoints + fake_point);
-
- /* Draw all the stroke lines (selected or not) */
- bGPDspoint *pt = gps->points;
- MDeformVert *dvert = gps->dvert;
-
- float fcolor[4];
- for (int i = 0; i < gps->totpoints; i++, pt++) {
- /* weight paint */
- if (is_weight_paint) {
- float weight = (dvert && dvert->dw && (vgindex > -1)) ? defvert_find_weight(dvert, vgindex) :
- 0.0f;
- float hue = 2.0f * (1.0f - weight) / 3.0f;
- hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]);
- selectColor[3] = 1.0f;
- copy_v4_v4(fcolor, selectColor);
- }
- else {
- if ((pt->flag & GP_SPOINT_SELECT) && (!hide_select)) {
- copy_v4_v4(fcolor, selectColor);
- }
- else {
- copy_v4_v4(fcolor, linecolor);
- }
- }
-
- GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor);
- GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x);
- be->vbo_len++;
-
- if (gps->dvert != NULL) {
- dvert++;
- }
- }
- /* If only 1 point in the stroke, add a point moved slightly. */
- if (fake_point > 0) {
- float fpt[3];
- pt = &gps->points[0];
- mul_v3_v3fl(fpt, &pt->x, 1.001f);
- GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor);
- GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, fpt);
- be->vbo_len++;
- }
-}
-
-static void set_grid_point(GPUVertBuf *vbo,
- int idx,
- const float col_grid[4],
- uint pos_id,
- uint color_id,
- float v1,
- float v2,
- const int axis)
-{
- GPU_vertbuf_attr_set(vbo, color_id, idx, col_grid);
-
- float pos[3];
- /* Set the grid in the selected axis */
- switch (axis) {
- case GP_LOCKAXIS_X: {
- ARRAY_SET_ITEMS(pos, 0.0f, v1, v2);
- break;
- }
- case GP_LOCKAXIS_Y: {
- ARRAY_SET_ITEMS(pos, v1, 0.0f, v2);
- break;
- }
- case GP_LOCKAXIS_Z:
- default: /* view aligned */
- {
- ARRAY_SET_ITEMS(pos, v1, v2, 0.0f);
- break;
- }
- }
-
- GPU_vertbuf_attr_set(vbo, pos_id, idx, pos);
-}
-
-/* Draw grid lines */
-GPUBatch *gpencil_get_grid(Object *ob)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ToolSettings *ts = scene->toolsettings;
- View3D *v3d = draw_ctx->v3d;
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool do_center = (gpd->grid.lines <= 0) ? false : true;
-
- float col_grid[4];
-
- /* verify we have something to draw and valid values */
- if (gpd->grid.scale[0] == 0.0f) {
- gpd->grid.scale[0] = 1.0f;
- }
- if (gpd->grid.scale[1] == 0.0f) {
- gpd->grid.scale[1] = 1.0f;
- }
-
- if (v3d->overlay.gpencil_grid_opacity < 0.1f) {
- v3d->overlay.gpencil_grid_opacity = 0.1f;
- }
-
- /* set color */
- copy_v3_v3(col_grid, gpd->grid.color);
- col_grid[3] = v3d->overlay.gpencil_grid_opacity;
-
- const int axis = ts->gp_sculpt.lock_axis;
-
- const char *grid_unit = NULL;
- const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines;
- const float grid_w = gpd->grid.scale[0] * ED_scene_grid_scale(scene, &grid_unit);
- const float grid_h = gpd->grid.scale[1] * ED_scene_grid_scale(scene, &grid_unit);
- const float space_w = (grid_w / gridlines);
- const float space_h = (grid_h / gridlines);
- const float offset[2] = {gpd->grid.offset[0], gpd->grid.offset[1]};
-
- const uint vertex_len = 2 * (gridlines * 4 + 2);
-
- static GPUVertFormat format = {0};
- static uint pos_id, color_id;
- if (format.attr_len == 0) {
- pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(vbo, vertex_len);
-
- int idx = 0;
-
- for (int a = 1; a <= gridlines; a++) {
- const float line_w = a * space_w;
- const float line_h = a * space_h;
-
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], -line_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], -line_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], +line_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], +line_h + offset[1], axis);
- idx++;
-
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], -grid_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], +grid_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], -grid_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], +grid_h + offset[1], axis);
- idx++;
- }
- /* center lines */
- if (do_center) {
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], 0.0f + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], 0.0f + offset[1], axis);
- idx++;
-
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], -grid_h + offset[1], axis);
- idx++;
- set_grid_point(
- vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], +grid_h + offset[1], axis);
- idx++;
- }
- return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
-}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
new file mode 100644
index 00000000000..97e5a44f0ab
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -0,0 +1,506 @@
+/*
+ * 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"
+
+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;
+}
+
+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;
+}
+
+#if 0 /* Old implementation. Reference for doing versioning code. TODO remove. */
+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];
+ float scale_v3[3] = {scale[0], scale[1], 0.0};
+ /* Scale */
+ size_to_mat4(mat, scale_v3);
+ /* Offset to center. */
+ translate_m4(mat, 0.5f + ofs[0], 0.5f + ofs[1], 0.0f);
+ /* Rotation; */
+ rotate_m4(mat, 'Z', -rotation);
+ /* Translate. */
+ translate_m4(mat, -0.5f, -0.5f, 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]);
+}
+#endif
+
+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];
+ }
+}
+
+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 */
+ // 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);
+}
+
+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_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_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;
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
deleted file mode 100644
index f2fc77dccf6..00000000000
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ /dev/null
@@ -1,2128 +0,0 @@
-/*
- * 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 2017, Blender Foundation.
- */
-
-/** \file
- * \ingroup draw
- */
-
-#include "DRW_render.h"
-
-#include "BKE_gpencil.h"
-#include "BKE_gpencil_modifier.h"
-#include "BKE_image.h"
-#include "BKE_material.h"
-#include "BKE_paint.h"
-
-#include "BLI_hash.h"
-
-#include "ED_gpencil.h"
-
-#include "DNA_gpencil_types.h"
-#include "DNA_material_types.h"
-#include "DNA_view3d_types.h"
-
-/* If builtin shaders are needed */
-#include "GPU_shader.h"
-#include "GPU_texture.h"
-
-/* For EvaluationContext... */
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-
-#include "IMB_imbuf_types.h"
-
-#include "gpencil_engine.h"
-
-#include "UI_resources.h"
-
-/* fill type to communicate to shader */
-#define SOLID 0
-#define GRADIENT 1
-#define RADIAL 2
-#define CHECKER 3
-#define TEXTURE 4
-#define PATTERN 5
-
-/* Verify if must fade object or not. */
-static bool gpencil_fade_object_check(GPENCIL_StorageList *stl, Object *ob)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- const bool is_overlay = (bool)((v3d) && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) &&
- (v3d->gp_flag & V3D_GP_SHOW_PAPER));
-
- if ((!is_overlay) || (ob == draw_ctx->obact) ||
- ((v3d->gp_flag & V3D_GP_FADE_NOACTIVE_GPENCIL) == 0) ||
- (v3d->overlay.gpencil_paper_opacity == 1.0f)) {
- return false;
- }
-
- const bool playing = stl->storage->is_playing;
- const bool is_render = (bool)stl->storage->is_render;
- const bool is_mat_preview = (bool)stl->storage->is_mat_preview;
- const bool is_select = (bool)(DRW_state_is_select() || DRW_state_is_depth());
-
- return (bool)((!is_render) && (!playing) && (!is_mat_preview) && (!is_select));
-}
-
-/* Define Fade layer uniforms. */
-static void gpencil_set_fade_layer_uniforms(
- GPENCIL_StorageList *stl, DRWShadingGroup *grp, Object *ob, bGPDlayer *gpl, const bool skip)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true;
- const bool is_fade = (v3d) && (v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS) &&
- (draw_ctx->obact) && (draw_ctx->obact == ob) &&
- ((gpl->flag & GP_LAYER_ACTIVE) == 0);
-
- const bool playing = stl->storage->is_playing;
- const bool is_render = (bool)stl->storage->is_render;
- const bool is_mat_preview = (bool)stl->storage->is_mat_preview;
- const bool is_select = (bool)(DRW_state_is_select() || DRW_state_is_depth());
-
- /* If drawing or not fading layer, skip. */
- if ((!overlay) || (skip) || (!is_fade) || (is_render) || (playing) || (is_mat_preview) ||
- (is_select)) {
- DRW_shgroup_uniform_int_copy(grp, "fade_layer", 0);
- return;
- }
-
- /* If layer is above active, use alpha (2) if below use mix with background (1). */
- if (stl->storage->is_ontop) {
- DRW_shgroup_uniform_int_copy(grp, "fade_layer", 2);
- }
- else {
- DRW_shgroup_uniform_int_copy(grp, "fade_layer", 1);
- }
- if (v3d) {
- DRW_shgroup_uniform_vec3(grp, "fade_color", v3d->shading.background_color, 1);
- DRW_shgroup_uniform_float(grp, "fade_layer_factor", &v3d->overlay.gpencil_fade_layer, 1);
- }
-}
-
-/* Define Fade object uniforms. */
-static void gpencil_set_fade_ob_uniforms(View3D *v3d, DRWShadingGroup *grp, bool status)
-{
- DRW_shgroup_uniform_bool_copy(grp, "fade_ob", status);
- if (v3d) {
- DRW_shgroup_uniform_vec3(grp, "fade_color", v3d->shading.background_color, 1);
- DRW_shgroup_uniform_float(grp, "fade_ob_factor", &v3d->overlay.gpencil_paper_opacity, 1);
- }
-}
-
-/* Get number of vertex for using in GPU VBOs */
-static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
- tGPencilObjectCache *cache_ob,
- GpencilBatchCache *cache,
- bGPdata *gpd)
-{
- if ((!cache->is_dirty) || (gpd == NULL)) {
- return;
- }
-
- Object *ob = cache_ob->ob;
- const bool main_onion = stl->storage->is_main_onion;
- const bool playing = stl->storage->is_playing;
- const bool overlay = stl->storage->is_main_overlay;
- const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
- main_onion && !playing && gpencil_onion_active(gpd);
-
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
-
- /* Onion skinning. */
- const int step = gpd->gstep;
- const int mode = gpd->onion_mode;
- const short onion_keytype = gpd->onion_keytype;
-
- cache_ob->tot_vertex = 0;
- cache_ob->tot_triangles = 0;
- int idx_eval = 0;
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *init_gpf = NULL;
- const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN));
- if (gpl->flag & GP_LAYER_HIDE) {
- idx_eval++;
- continue;
- }
-
- /* Relative onion mode needs to find the frame range before. */
- int frame_from = -9999;
- int frame_to = 9999;
- if ((is_onion) && (mode == GP_ONION_MODE_RELATIVE)) {
- /* 1) Found first Frame. */
- int idx = 0;
- if (gpl->actframe) {
- for (bGPDframe *gf = gpl->actframe->prev; gf; gf = gf->prev) {
- idx++;
- frame_from = gf->framenum;
- if (idx >= step) {
- break;
- }
- }
- /* 2) Found last Frame. */
- idx = 0;
- for (bGPDframe *gf = gpl->actframe->next; gf; gf = gf->next) {
- idx++;
- frame_to = gf->framenum;
- if (idx >= gpd->gstep_next) {
- break;
- }
- }
- }
- }
-
- /* If multiedit or onion skin need to count all frames of the layer. */
- if ((is_multiedit) || (is_onion)) {
- init_gpf = gpl->frames.first;
- }
- else {
- init_gpf = &ob->runtime.gpencil_evaluated_frames[idx_eval];
- }
-
- if (init_gpf == NULL) {
- continue;
- }
-
- for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- if (!is_onion) {
- if ((!is_multiedit) ||
- ((is_multiedit) && ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)))) {
- cache_ob->tot_vertex += gps->totpoints + 3;
- cache_ob->tot_triangles += gps->totpoints - 1;
- }
- }
- else {
- bool select = ((is_multiedit) &&
- ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)));
-
- if (!select) {
- /* Only selected frames. */
- if ((mode == GP_ONION_MODE_SELECTED) && ((gpf->flag & GP_FRAME_SELECT) == 0)) {
- continue;
- }
- /* Verify keyframe type. */
- if ((onion_keytype > -1) && (gpf->key_type != onion_keytype)) {
- continue;
- }
- /* Absolute range. */
- if (mode == GP_ONION_MODE_ABSOLUTE) {
- if ((gpl->actframe) && (abs(gpl->actframe->framenum - gpf->framenum) > step)) {
- continue;
- }
- }
- /* Relative range. */
- if (mode == GP_ONION_MODE_RELATIVE) {
- if ((gpf->framenum < frame_from) || (gpf->framenum > frame_to)) {
- continue;
- }
- }
- }
-
- cache_ob->tot_vertex += gps->totpoints + 3;
- cache_ob->tot_triangles += gps->totpoints - 1;
- }
- }
-
- /* If not multiframe nor Onion skin, don't need follow counting. */
- if ((!is_multiedit) && (!is_onion)) {
- break;
- }
- }
- idx_eval++;
- }
-
- cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3;
- cache->b_stroke.tot_vertex = cache_ob->tot_vertex;
- cache->b_point.tot_vertex = cache_ob->tot_vertex;
- cache->b_edit.tot_vertex = cache_ob->tot_vertex;
- cache->b_edlin.tot_vertex = cache_ob->tot_vertex;
-}
-
-/* Helper for doing all the checks on whether a stroke can be drawn */
-static bool gpencil_can_draw_stroke(struct MaterialGPencilStyle *gp_style,
- const bGPDstroke *gps,
- const bool onion,
- const bool is_mat_preview)
-{
- /* skip stroke if it doesn't have any valid data */
- if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) {
- return false;
- }
-
- /* if mat preview render always visible */
- if (is_mat_preview) {
- return true;
- }
-
- /* check if the color is visible */
- if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- (onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN))) {
- return false;
- }
-
- /* stroke can be drawn */
- return true;
-}
-
-/* recalc the internal geometry caches for fill and uvs */
-static void gpencil_recalc_geometry_caches(Object *ob,
- bGPDlayer *gpl,
- MaterialGPencilStyle *gp_style,
- bGPDstroke *gps)
-{
- if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
- /* Calculate triangles cache for filling area (must be done only after changes) */
- if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
- if ((gps->totpoints > 2) && (gp_style->flag & GP_STYLE_FILL_SHOW) &&
- ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0) ||
- (gpl->blend_mode != eGplBlendMode_Regular))) {
- BKE_gpencil_triangulate_stroke_fill((bGPdata *)ob->data, gps);
- }
- }
-
- /* calc uv data along the stroke */
- ED_gpencil_calc_stroke_uv(ob, gps);
-
- /* clear flag */
- gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
- }
-}
-
-static void set_wireframe_color(Object *ob,
- bGPDlayer *gpl,
- View3D *v3d,
- GPENCIL_StorageList *stl,
- MaterialGPencilStyle *gp_style,
- int id,
- const bool is_fill)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- World *world = draw_ctx->scene->world;
-
- float color[4];
- if (((gp_style->stroke_rgba[3] < GPENCIL_ALPHA_OPACITY_THRESH) ||
- (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0))) &&
- (gp_style->fill_rgba[3] >= GPENCIL_ALPHA_OPACITY_THRESH)) {
- copy_v4_v4(color, gp_style->fill_rgba);
- }
- else {
- copy_v4_v4(color, gp_style->stroke_rgba);
- }
-
- /* wire color */
- if ((v3d) && (id > -1)) {
- const char type = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ?
- v3d->shading.wire_color_type :
- v3d->shading.color_type);
- /* if fill and wire, use background color */
- if ((is_fill) && (stl->shgroups[id].shading_type[0] == OB_WIRE)) {
- if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_THEME) {
- UI_GetThemeColor4fv(TH_BACK, stl->shgroups[id].wire_color);
- stl->shgroups[id].wire_color[3] = 1.0f;
- }
- else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) {
- color[0] = world->horr;
- color[1] = world->horg;
- color[2] = world->horb;
- color[3] = 1.0f;
- linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color);
- }
- else {
- copy_v3_v3(color, v3d->shading.background_color);
- color[3] = 1.0f;
- linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color);
- }
- return;
- }
-
- /* strokes */
- switch (type) {
- case V3D_SHADING_SINGLE_COLOR: {
- if (stl->shgroups[id].shading_type[0] == OB_WIRE) {
- UI_GetThemeColor4fv(TH_WIRE, color);
- }
- else {
- copy_v3_v3(color, v3d->shading.single_color);
- }
- color[3] = 1.0f;
- linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color);
- break;
- }
- case V3D_SHADING_OBJECT_COLOR: {
- copy_v4_v4(color, ob->color);
- color[3] = 1.0f;
- linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color);
- break;
- }
- case V3D_SHADING_RANDOM_COLOR: {
- uint gpl_hash = 1;
- uint ob_hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
- if (gpl) {
- gpl_hash = BLI_ghashutil_strhash_p_murmur(gpl->info);
- }
-
- float hue = BLI_hash_int_01(ob_hash * gpl_hash);
- float hsv[3] = {hue, 0.40f, 0.8f};
- float wire_col[3];
- hsv_to_rgb_v(hsv, &wire_col[0]);
-
- copy_v3_v3(stl->shgroups[id].wire_color, wire_col);
- stl->shgroups[id].wire_color[3] = 1.0f;
- break;
- }
- default: {
- copy_v4_v4(stl->shgroups[id].wire_color, color);
- break;
- }
- }
- }
- else {
- copy_v4_v4(stl->shgroups[id].wire_color, color);
- }
-
- /* if solid, the alpha must be set to alpha */
- if (stl->shgroups[id].shading_type[0] == OB_SOLID) {
- stl->shgroups[id].wire_color[3] = 1.0f;
- }
-}
-
-/* create shading group for filling */
-static DRWShadingGroup *gpencil_shgroup_fill_create(GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- DRWPass *pass,
- GPUShader *shader,
- Object *ob,
- float (*obmat)[4],
- bGPdata *gpd,
- bGPDlayer *gpl,
- MaterialGPencilStyle *gp_style,
- int id,
- const int shading_type[2])
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
-
- /* e_data.gpencil_fill_sh */
- DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
-
- DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat);
-
- DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1);
-
- /* set style type */
- switch (gp_style->fill_style) {
- case GP_STYLE_FILL_STYLE_SOLID:
- stl->shgroups[id].fill_style = SOLID;
- break;
- case GP_STYLE_FILL_STYLE_GRADIENT:
- if (gp_style->gradient_type == GP_STYLE_GRADIENT_LINEAR) {
- stl->shgroups[id].fill_style = GRADIENT;
- }
- else {
- stl->shgroups[id].fill_style = RADIAL;
- }
- break;
- case GP_STYLE_FILL_STYLE_CHECKER:
- stl->shgroups[id].fill_style = CHECKER;
- break;
- case GP_STYLE_FILL_STYLE_TEXTURE:
- if (gp_style->flag & GP_STYLE_FILL_PATTERN) {
- stl->shgroups[id].fill_style = PATTERN;
- }
- else {
- stl->shgroups[id].fill_style = TEXTURE;
- }
- break;
- default:
- stl->shgroups[id].fill_style = GP_STYLE_FILL_STYLE_SOLID;
- break;
- }
- DRW_shgroup_uniform_int(grp, "fill_type", &stl->shgroups[id].fill_style, 1);
-
- DRW_shgroup_uniform_float(grp, "mix_factor", &gp_style->mix_factor, 1);
-
- DRW_shgroup_uniform_float(grp, "gradient_angle", &gp_style->gradient_angle, 1);
- DRW_shgroup_uniform_float(grp, "gradient_radius", &gp_style->gradient_radius, 1);
- DRW_shgroup_uniform_float(grp, "pattern_gridsize", &gp_style->pattern_gridsize, 1);
- DRW_shgroup_uniform_vec2(grp, "gradient_scale", gp_style->gradient_scale, 1);
- DRW_shgroup_uniform_vec2(grp, "gradient_shift", gp_style->gradient_shift, 1);
-
- DRW_shgroup_uniform_float(grp, "texture_angle", &gp_style->texture_angle, 1);
- DRW_shgroup_uniform_vec2(grp, "texture_scale", gp_style->texture_scale, 1);
- DRW_shgroup_uniform_vec2(grp, "texture_offset", gp_style->texture_offset, 1);
- DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1);
- DRW_shgroup_uniform_float(grp, "layer_opacity", &gpl->opacity, 1);
-
- stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_FILL_TEX_MIX ? 1 : 0;
- DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1);
-
- stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0;
- DRW_shgroup_uniform_int(grp, "texture_flip", &stl->shgroups[id].texture_flip, 1);
-
- stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE;
- DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1);
- DRW_shgroup_uniform_int(grp, "drawmode", (const int *)&gpd->draw_mode, 1);
-
- /* viewport x-ray */
- stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray;
- DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1);
-
- /* shading type */
- stl->shgroups[id].shading_type[0] = GPENCIL_USE_SOLID(stl) ? (int)OB_RENDER : shading_type[0];
- if (v3d) {
- stl->shgroups[id].shading_type[1] = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ?
- v3d->shading.wire_color_type :
- v3d->shading.color_type);
- }
-
- DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2);
-
- /* Fade layer uniforms. */
- gpencil_set_fade_layer_uniforms(stl, grp, ob, gpl, false);
-
- /* Fade object uniforms. */
- gpencil_set_fade_ob_uniforms(v3d, grp, gpencil_fade_object_check(stl, ob));
-
- /* wire color */
- set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, true);
- DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1);
-
- /* image texture */
- if ((gp_style->flag & GP_STYLE_FILL_TEX_MIX) ||
- (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE)) {
- ImBuf *ibuf;
- Image *image = gp_style->ima;
- ImageUser iuser = {NULL};
- void *lock;
-
- iuser.ok = true;
-
- ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
-
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- else {
- GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, ibuf, GL_TEXTURE_2D);
- DRW_shgroup_uniform_texture(grp, "myTexture", texture);
- DRW_shgroup_uniform_bool_copy(
- grp, "myTexturePremultiplied", (image->alpha_mode == IMA_ALPHA_PREMUL));
-
- stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0;
- DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
-
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- }
- else {
- /* if no texture defined, need a blank texture to avoid errors in draw manager */
- DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
- stl->shgroups[id].texture_clamp = 0;
- DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1);
- }
-
- return grp;
-}
-
-/* check if some onion is enabled */
-bool gpencil_onion_active(bGPdata *gpd)
-{
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
- return true;
- }
- }
- return false;
-}
-
-/* create shading group for strokes */
-DRWShadingGroup *gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- DRWPass *pass,
- GPUShader *shader,
- Object *ob,
- float (*obmat)[4],
- bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDstroke *gps,
- MaterialGPencilStyle *gp_style,
- int id,
- bool onion,
- const float scale,
- const int shading_type[2])
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const float *viewport_size = DRW_viewport_size_get();
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
-
- /* e_data.gpencil_stroke_sh */
- DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
-
- DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
-
- DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
-
- DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat);
-
- /* avoid wrong values */
- if ((gpd) && (gpd->pixfactor == 0.0f)) {
- gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
- }
-
- /* object scale and depth */
- if ((ob) && (id > -1)) {
- stl->shgroups[id].obj_scale = scale;
- DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
- stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
- DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
-
- stl->shgroups[id].stroke_style = gp_style->stroke_style;
- stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
- if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
- stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
- if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
- stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
- }
- }
- DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
- DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
-
- stl->shgroups[id].caps_mode[0] = gps->caps[0];
- stl->shgroups[id].caps_mode[1] = gps->caps[1];
- DRW_shgroup_uniform_int(grp, "caps_mode", &stl->shgroups[id].caps_mode[0], 2);
-
- stl->shgroups[id].gradient_f = gps->gradient_f;
- copy_v2_v2(stl->shgroups[id].gradient_s, gps->gradient_s);
- DRW_shgroup_uniform_float(grp, "gradient_f", &stl->shgroups[id].gradient_f, 1);
-
- /* viewport x-ray */
- stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray;
- DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1);
-
- stl->shgroups[id].shading_type[0] = (GPENCIL_USE_SOLID(stl) || onion) ? (int)OB_RENDER :
- shading_type[0];
- if (v3d) {
- stl->shgroups[id].shading_type[1] = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ?
- v3d->shading.wire_color_type :
- v3d->shading.color_type);
- }
- DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2);
-
- /* Fade layer uniforms. */
- gpencil_set_fade_layer_uniforms(stl, grp, ob, gpl, false);
-
- /* Fade object uniforms. */
- gpencil_set_fade_ob_uniforms(v3d, grp, gpencil_fade_object_check(stl, ob));
-
- /* wire color */
- set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false);
- DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1);
-
- /* mix stroke factor */
- stl->shgroups[id].mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ?
- gp_style->mix_stroke_factor :
- 0.0f;
- DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->shgroups[id].mix_stroke_factor, 1);
- }
- else {
- stl->storage->obj_scale = 1.0f;
- stl->storage->keep_size = 0;
- stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
- DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
- DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
- DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
- if (gpd) {
- DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
- }
- else {
- DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
- }
- const int zero[2] = {0, 0};
- DRW_shgroup_uniform_int(grp, "caps_mode", &zero[0], 2);
-
- DRW_shgroup_uniform_float(grp, "gradient_f", &stl->storage->gradient_f, 1);
-
- /* viewport x-ray */
- DRW_shgroup_uniform_int(grp, "viewport_xray", &stl->storage->is_xray, 1);
- DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2);
-
- /* mix stroke factor */
- stl->storage->mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ?
- gp_style->mix_stroke_factor :
- 0.0f;
- DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->storage->mix_stroke_factor, 1);
- }
-
- DRW_shgroup_uniform_vec4(grp, "colormix", gp_style->stroke_rgba, 1);
-
- if ((gpd) && (id > -1)) {
- stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE;
- DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1);
- }
- else {
- /* for drawing always on predefined z-depth */
- DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
- }
-
- /* Fade layer uniforms. */
- gpencil_set_fade_layer_uniforms(stl, grp, ob, gpl, true);
-
- /* Fade object uniforms. */
- gpencil_set_fade_ob_uniforms(v3d, grp, false);
-
- /* image texture for pattern */
- if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
- ImBuf *ibuf;
- Image *image = gp_style->sima;
- ImageUser iuser = {NULL};
- void *lock;
-
- iuser.ok = true;
-
- ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
-
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- else {
- GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, ibuf, GL_TEXTURE_2D);
- DRW_shgroup_uniform_texture(grp, "myTexture", texture);
- DRW_shgroup_uniform_bool_copy(
- grp, "myTexturePremultiplied", (image->alpha_mode == IMA_ALPHA_PREMUL));
-
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- }
- else {
- /* if no texture defined, need a blank texture to avoid errors in draw manager */
- DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
- }
-
- return grp;
-}
-
-/* create shading group for points */
-static DRWShadingGroup *gpencil_shgroup_point_create(GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- DRWPass *pass,
- GPUShader *shader,
- Object *ob,
- float (*obmat)[4],
- bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDstroke *gps,
- MaterialGPencilStyle *gp_style,
- int id,
- bool onion,
- const float scale,
- const int shading_type[2])
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const float *viewport_size = DRW_viewport_size_get();
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
-
- /* e_data.gpencil_stroke_sh */
- DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
-
- DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1);
- DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
-
- DRW_shgroup_uniform_mat4(grp, "gpModelMatrix", obmat);
-
- /* avoid wrong values */
- if ((gpd) && (gpd->pixfactor == 0.0f)) {
- gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
- }
-
- /* object scale and depth */
- if ((ob) && (id > -1)) {
- stl->shgroups[id].obj_scale = scale;
- DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1);
- stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
- DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1);
-
- stl->shgroups[id].mode = gp_style->mode;
- stl->shgroups[id].stroke_style = gp_style->stroke_style;
- stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID;
- if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
- stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE;
- if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
- stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN;
- }
- }
- DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1);
- DRW_shgroup_uniform_int(grp, "mode", &stl->shgroups[id].mode, 1);
- DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
-
- stl->shgroups[id].gradient_f = gps->gradient_f;
- copy_v2_v2(stl->shgroups[id].gradient_s, gps->gradient_s);
- DRW_shgroup_uniform_float(grp, "gradient_f", &stl->shgroups[id].gradient_f, 1);
- DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->shgroups[id].gradient_s, 1);
-
- /* viewport x-ray */
- stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray;
- DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1);
-
- stl->shgroups[id].shading_type[0] = (GPENCIL_USE_SOLID(stl) || onion) ? (int)OB_RENDER :
- shading_type[0];
- if (v3d) {
- stl->shgroups[id].shading_type[1] = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ?
- v3d->shading.wire_color_type :
- v3d->shading.color_type);
- }
- DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2);
-
- /* Fade layer uniforms. */
- gpencil_set_fade_layer_uniforms(stl, grp, ob, gpl, false);
-
- /* Fade object uniforms. */
- gpencil_set_fade_ob_uniforms(v3d, grp, gpencil_fade_object_check(stl, ob));
-
- /* wire color */
- set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false);
- DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1);
-
- /* mix stroke factor */
- stl->shgroups[id].mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ?
- gp_style->mix_stroke_factor :
- 0.0f;
- DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->shgroups[id].mix_stroke_factor, 1);
-
- /* lock rotation of dots and boxes */
- stl->shgroups[id].alignment_mode = gp_style->alignment_mode;
- DRW_shgroup_uniform_int(grp, "alignment_mode", &stl->shgroups[id].alignment_mode, 1);
- }
- else {
- stl->storage->obj_scale = 1.0f;
- stl->storage->keep_size = 0;
- stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR;
- stl->storage->mode = gp_style->mode;
- DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1);
- DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1);
- DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1);
- DRW_shgroup_uniform_int(grp, "mode", &stl->storage->mode, 1);
- if (gpd) {
- DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1);
- }
- else {
- DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1);
- }
-
- DRW_shgroup_uniform_float(grp, "gradient_f", &stl->storage->gradient_f, 1);
- DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->storage->gradient_s, 1);
-
- /* viewport x-ray */
- DRW_shgroup_uniform_int(grp, "viewport_xray", &stl->storage->is_xray, 1);
- DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2);
-
- /* mix stroke factor */
- stl->storage->mix_stroke_factor = (gp_style->flag & GP_STYLE_STROKE_TEX_MIX) ?
- gp_style->mix_stroke_factor :
- 0.0f;
- DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->storage->mix_stroke_factor, 1);
-
- /* lock rotation of dots and boxes */
- DRW_shgroup_uniform_int(grp, "alignment_mode", &stl->storage->alignment_mode, 1);
- }
-
- DRW_shgroup_uniform_vec4(grp, "colormix", gp_style->stroke_rgba, 1);
-
- if ((gpd) && (id > -1)) {
- stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE;
- DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&stl->shgroups[id].xray_mode, 1);
- }
- else {
- /* for drawing always on predefined z-depth */
- DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1);
- }
-
- /* Fade layer uniforms. */
- gpencil_set_fade_layer_uniforms(stl, grp, ob, gpl, true);
-
- /* Fade object uniforms. */
- gpencil_set_fade_ob_uniforms(v3d, grp, false);
-
- /* image texture */
- if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) {
- ImBuf *ibuf;
- Image *image = gp_style->sima;
- ImageUser iuser = {NULL};
- void *lock;
-
- iuser.ok = true;
-
- ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
-
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- else {
- GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, ibuf, GL_TEXTURE_2D);
- DRW_shgroup_uniform_texture(grp, "myTexture", texture);
- DRW_shgroup_uniform_bool_copy(
- grp, "myTexturePremultiplied", (image->alpha_mode == IMA_ALPHA_PREMUL));
-
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
- }
- else {
- /* if no texture defined, need a blank texture to avoid errors in draw manager */
- DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture);
- }
-
- return grp;
-}
-
-/* Get vertex Paint factor */
-float gpencil_get_vertex_paint_factor(View3D *v3d)
-{
- if (v3d) {
- float vpaint_mix = ((v3d->shading.type < OB_MATERIAL) &&
- (v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR)) ?
- 0.0f :
- v3d->overlay.gpencil_vertex_paint_opacity;
- return vpaint_mix;
- }
-
- return 1.0f;
-}
-
-/* add fill vertex info */
-static void gpencil_add_fill_vertexdata(GpencilBatchCache *cache,
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- bGPDstroke *gps,
- float opacity,
- const float tintcolor[4],
- const bool onion,
- const bool custonion)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- ToolSettings *ts = draw_ctx->scene->toolsettings;
- View3D *v3d = draw_ctx->v3d;
- bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
-
- const float vpaint_mix = gpencil_get_vertex_paint_factor(v3d);
- const bool attenuate = (GPENCIL_VERTEX_MODE(gpd) &&
- GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex));
-
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- if (gps->totpoints >= 3) {
- float tfill[4];
- /* set color using material, tint color and opacity */
- interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
- tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
- if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0) ||
- (gpl->blend_mode != eGplBlendMode_Regular)) {
- if (cache->is_dirty) {
- const float *color;
- if (!onion) {
- /* Apply the mix color of the fill and layer tint. */
- float mixtint[3];
- interp_v3_v3v3(mixtint, gps->mix_color_fill, tintcolor, tintcolor[3]);
- interp_v3_v3v3(tfill,
- tfill,
- mixtint,
- gps->mix_color_fill[3] * vpaint_mix * gpl->vertex_paint_opacity);
- /* If using vertex paint mask, attenuate not selected. */
- if ((attenuate) && ((gps->flag & GP_STROKE_SELECT) == 0)) {
- tfill[3] *= GP_VERTEX_MASK_ATTENUATE;
- }
- color = tfill;
- }
- else {
- if (custonion) {
- color = tintcolor;
- }
- else {
- ARRAY_SET_ITEMS(tfill, UNPACK3(gps->runtime.tmp_fill_rgba), tintcolor[3]);
- color = tfill;
- }
- }
- /* create vertex data */
- const int old_len = cache->b_fill.vbo_len;
- gpencil_get_fill_geom(&cache->b_fill, ob, gps, color);
-
- /* add to list of groups */
- if (old_len < cache->b_fill.vbo_len) {
- cache->grp_cache = gpencil_group_cache_add(cache->grp_cache,
- gpl,
- gpf,
- gps,
- eGpencilBatchGroupType_Fill,
- onion,
- cache->b_fill.vbo_len,
- &cache->grp_size,
- &cache->grp_used);
- }
- }
- }
- }
-}
-
-/* add stroke vertex info */
-static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache,
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- bGPDstroke *gps,
- const float opacity,
- const float tintcolor[4],
- const bool onion,
- const bool custonion)
-{
- float tcolor[4];
- float ink[4];
- short sthickness;
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- const int alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH;
-
- /* set color using base color, tint color and opacity */
- if (cache->is_dirty) {
- if (!onion) {
- /* if special stroke, use fill color as stroke color */
- if (gps->flag & GP_STROKE_NOFILL) {
- interp_v3_v3v3(tcolor, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
- tcolor[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
- }
- else {
- interp_v3_v3v3(tcolor, gps->runtime.tmp_stroke_rgba, tintcolor, tintcolor[3]);
- tcolor[3] = gps->runtime.tmp_stroke_rgba[3] * opacity;
- }
- copy_v4_v4(ink, tcolor);
- }
- else {
- if (custonion) {
- copy_v4_v4(ink, tintcolor);
- }
- else {
- ARRAY_SET_ITEMS(tcolor, UNPACK3(gps->runtime.tmp_stroke_rgba), opacity);
- copy_v4_v4(ink, tcolor);
- }
- }
-
- sthickness = gps->thickness + gpl->line_change;
- CLAMP_MIN(sthickness, 1);
-
- if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
- /* create vertex data */
- const int old_len = cache->b_stroke.vbo_len;
- gpencil_get_stroke_geom(&cache->b_stroke, gpl, gps, sthickness, ink, tintcolor, onion);
-
- /* add to list of groups */
- if (old_len < cache->b_stroke.vbo_len) {
- cache->grp_cache = gpencil_group_cache_add(cache->grp_cache,
- gpl,
- gpf,
- gps,
- eGpencilBatchGroupType_Stroke,
- onion,
- cache->b_stroke.vbo_len,
- &cache->grp_size,
- &cache->grp_used);
- }
- }
- else {
- /* create vertex data */
- const int old_len = cache->b_point.vbo_len;
- gpencil_get_point_geom(
- &cache->b_point, gpl, gps, sthickness, ink, tintcolor, alignment_mode, onion);
-
- /* add to list of groups */
- if (old_len < cache->b_point.vbo_len) {
- cache->grp_cache = gpencil_group_cache_add(cache->grp_cache,
- gpl,
- gpf,
- gps,
- eGpencilBatchGroupType_Point,
- onion,
- cache->b_point.vbo_len,
- &cache->grp_size,
- &cache->grp_used);
- }
- }
- }
-}
-
-/* add edit points vertex info */
-static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache,
- Object *ob,
- bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- bGPDstroke *gps)
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- ToolSettings *ts = draw_ctx->scene->toolsettings;
- const bool is_overlay = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0);
- const bool use_sculpt_mask = (GPENCIL_SCULPT_MODE(gpd) &&
- GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt));
-
- const bool show_sculpt_points = (GPENCIL_SCULPT_MODE(gpd) &&
- (ts->gpencil_selectmode_sculpt &
- (GP_SCULPT_MASK_SELECTMODE_POINT |
- GP_SCULPT_MASK_SELECTMODE_SEGMENT)));
-
- const bool use_vertex_mask = (GPENCIL_VERTEX_MODE(gpd) &&
- GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex));
-
- const bool show_vertex_points = (GPENCIL_VERTEX_MODE(gpd) &&
- (ts->gpencil_selectmode_vertex &
- (GP_VERTEX_MASK_SELECTMODE_POINT |
- GP_VERTEX_MASK_SELECTMODE_SEGMENT)));
-
- const bool hide_vertex_lines = (GPENCIL_VERTEX_MODE(gpd) && (use_vertex_mask) &&
- ((v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) == 0));
-
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
-
- /* alpha factor for edit points/line to make them more subtle */
- float edit_alpha = v3d->vertex_opacity;
-
- if (GPENCIL_ANY_EDIT_MODE(gpd) || GPENCIL_VERTEX_MODE(gpd)) {
- Object *obact = DRW_context_state_get()->obact;
- if ((!obact) || (obact->type != OB_GPENCIL)) {
- return;
- }
- const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
- const bool is_vertex_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_VERTEXMODE);
-
- /* If Sculpt/Vertex mode and the mask is disabled, the select must be hidden. */
- const bool hide_select = ((GPENCIL_SCULPT_MODE(gpd) && !use_sculpt_mask) ||
- (GPENCIL_VERTEX_MODE(gpd) && !use_vertex_mask));
-
- /* Show Edit points if:
- * Edit mode: Not in Stroke selection mode
- * Sculpt mode: Not in Stroke mask mode and any other mask mode enabled
- * Weight mode: Always
- * Vertex mode: Always
- */
- const bool show_points = (show_sculpt_points) || (show_vertex_points) || (is_weight_paint) ||
- (is_vertex_paint) ||
- (GPENCIL_EDIT_MODE(gpd) &&
- ((ts->gpencil_selectmode_edit != GP_SELECTMODE_STROKE) ||
- (gps->totpoints == 1)));
-
- if (GPENCIL_VERTEX_MODE(gpd) && (!use_vertex_mask) &&
- ((v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) == 0)) {
- return;
- }
-
- if (cache->is_dirty) {
- if ((obact == ob) && (is_overlay) && (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) &&
- (!hide_vertex_lines)) {
- /* line of the original stroke */
- gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, hide_select);
-
- /* add to list of groups */
- cache->grp_cache = gpencil_group_cache_add(cache->grp_cache,
- gpl,
- gpf,
- gps,
- eGpencilBatchGroupType_Edlin,
- false,
- cache->b_edlin.vbo_len,
- &cache->grp_size,
- &cache->grp_used);
- }
-
- /* If the points are hidden return. */
- if ((!show_points) || (hide_select) || ((is_vertex_paint) && (!is_overlay))) {
- return;
- }
-
- /* edit points */
- if (((gps->flag & GP_STROKE_SELECT) && (is_overlay)) || (is_weight_paint) ||
- (is_vertex_paint)) {
- if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) ||
- ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) {
- if (obact == ob) {
- gpencil_get_edit_geom(&cache->b_edit, gps, edit_alpha, gpd->flag);
-
- /* add to list of groups */
- cache->grp_cache = gpencil_group_cache_add(cache->grp_cache,
- gpl,
- gpf,
- gps,
- eGpencilBatchGroupType_Edit,
- false,
- cache->b_edit.vbo_len,
- &cache->grp_size,
- &cache->grp_used);
- }
- }
- }
- }
- }
-}
-
-/* main function to draw strokes */
-static void gpencil_draw_strokes(GpencilBatchCache *cache,
- GPENCIL_e_data *e_data,
- void *vedata,
- Object *ob,
- bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- const float opacity,
- const float tintcolor[4],
- const bool custonion,
- tGPencilObjectCache *cache_ob)
-{
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- View3D *v3d = draw_ctx->v3d;
- bGPDstroke *gps;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const bool playing = stl->storage->is_playing;
- const bool is_render = (bool)stl->storage->is_render;
- const bool is_mat_preview = (bool)stl->storage->is_mat_preview;
- const bool overlay_multiedit = v3d != NULL ? (!(v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES)) :
- true;
-
- /* Get evaluation context */
- /* NOTE: We must check if C is valid, otherwise we get crashes when trying to save files
- * (i.e. the thumbnail offscreen rendering fails)
- */
- Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
-
- /* get parent matrix and save as static data */
- if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) {
- copy_m4_m4(gpf->runtime.parent_obmat, cache_ob->obmat);
- }
- else {
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, gpf->runtime.parent_obmat);
- }
-
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
-
- /* check if stroke can be drawn */
- if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) {
- continue;
- }
-
- /* Copy color to temp fields. */
- if ((is_multiedit) && (gp_style)) {
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
- }
-
- /* be sure recalc all cache in source stroke to avoid recalculation when frame change
- * and improve fps */
- gpencil_recalc_geometry_caches(
- ob, gpl, gp_style, (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps);
-
- /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is
- * enabled */
- if ((stl->storage->simplify_fill) &&
- (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) {
- if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
- (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) ||
- (gpl->blend_mode != eGplBlendMode_Regular)) {
-
- continue;
- }
- }
-
- if ((gpl->actframe && (gpl->actframe->framenum == gpf->framenum)) || (!is_multiedit) ||
- (overlay_multiedit)) {
- /* hide any blend layer */
- if ((!stl->storage->simplify_blend) || (gpl->blend_mode == eGplBlendMode_Regular)) {
- /* fill */
- if ((gp_style->flag & GP_STYLE_FILL_SHOW) && (!stl->storage->simplify_fill) &&
- ((gps->flag & GP_STROKE_NOFILL) == 0)) {
- gpencil_add_fill_vertexdata(
- cache, ob, gpl, gpf, gps, opacity, tintcolor, false, custonion);
- }
- /* stroke
- * No fill strokes, must show stroke always or if the total points is lower than 3,
- * because the stroke cannot be filled and it would be invisible. */
- if (((gp_style->flag & GP_STYLE_STROKE_SHOW) || (gps->flag & GP_STROKE_NOFILL) ||
- (gps->totpoints < 3)) &&
- ((gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
- (gpl->blend_mode == eGplBlendMode_Regular))) {
- /* recalc strokes uv (geometry can be changed by modifiers) */
- if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
- ED_gpencil_calc_stroke_uv(ob, gps);
- }
-
- gpencil_add_stroke_vertexdata(
- cache, ob, gpl, gpf, gps, opacity, tintcolor, false, custonion);
- }
- }
- }
-
- /* edit points (only in edit mode or mask and not play animation not render) */
- if ((draw_ctx->obact == ob) && (!playing) && (!is_render) && (!cache_ob->is_dup_ob)) {
- if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
- if (!stl->g_data->shgrps_edit_line) {
- stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh,
- psl->edit_pass);
- DRW_shgroup_uniform_mat4(stl->g_data->shgrps_edit_line, "gpModelMatrix", ob->obmat);
- }
- if (!stl->g_data->shgrps_edit_point) {
- stl->g_data->shgrps_edit_point = DRW_shgroup_create(e_data->gpencil_edit_point_sh,
- psl->edit_pass);
- const float *viewport_size = DRW_viewport_size_get();
- DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
- DRW_shgroup_uniform_mat4(stl->g_data->shgrps_edit_point, "gpModelMatrix", ob->obmat);
- }
-
- gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, gpf, gps);
- }
- }
- }
-}
-
-/* get alpha factor for onion strokes */
-static void gpencil_get_onion_alpha(float color[4], bGPdata *gpd)
-{
-#define MIN_ALPHA_VALUE 0.01f
-
- /* if fade is disabled, opacity is equal in all frames */
- if ((gpd->onion_flag & GP_ONION_FADE) == 0) {
- color[3] = gpd->onion_factor;
- }
- else {
- /* add override opacity factor */
- color[3] += gpd->onion_factor - 0.5f;
- }
-
- CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f);
-}
-
-/* function to draw strokes for onion only */
-static void gpencil_draw_onion_strokes(GpencilBatchCache *cache,
- void *vedata,
- Object *ob,
- bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- const float opacity,
- const float tintcolor[4],
- const bool custonion)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- Depsgraph *depsgraph = DRW_context_state_get()->depsgraph;
-
- /* get parent matrix and save as static data */
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, gpf->runtime.parent_obmat);
-
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- if (gp_style == NULL) {
- continue;
- }
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
- int id = stl->storage->shgroup_id;
- /* check if stroke can be drawn */
- if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) {
- continue;
- }
- /* limit the number of shading groups */
- if (id >= GPENCIL_MAX_SHGROUPS) {
- continue;
- }
-
- /* stroke */
- gpencil_add_stroke_vertexdata(cache, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion);
-
- stl->storage->shgroup_id++;
- }
-}
-
-/* draw onion-skinning for a layer */
-static void gpencil_draw_onionskins(GpencilBatchCache *cache,
- void *vedata,
- Object *ob,
- bGPdata *gpd,
- bGPDlayer *gpl,
- bGPDframe *gpf)
-{
-
- const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)};
- const float alpha = 1.0f;
- float color[4];
- int idx;
- float fac = 1.0f;
- int step = 0;
- bool colflag = false;
- const int mode = gpd->onion_mode;
- bGPDframe *gpf_loop = ((gpd->onion_flag & GP_ONION_LOOP) && (mode != GP_ONION_MODE_SELECTED)) ?
- gpl->frames.first :
- NULL;
- int last = gpf->framenum;
-
- colflag = (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) != 0;
- const short onion_keytype = gpd->onion_keytype;
- /* -------------------------------
- * 1) Draw Previous Frames First
- * ------------------------------- */
- step = gpd->gstep;
-
- if (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) {
- copy_v3_v3(color, gpd->gcolor_prev);
- }
- else {
- copy_v3_v3(color, default_color);
- }
-
- idx = 0;
- for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
- /* only selected frames */
- if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
- continue;
- }
- /* verify keyframe type */
- if ((onion_keytype > -1) && (gf->key_type != onion_keytype)) {
- continue;
- }
- /* absolute range */
- if (mode == GP_ONION_MODE_ABSOLUTE) {
- if ((gpf->framenum - gf->framenum) > step) {
- break;
- }
- }
- /* relative range */
- if (mode == GP_ONION_MODE_RELATIVE) {
- idx++;
- if (idx > step) {
- break;
- }
- }
- /* alpha decreases with distance from curframe index */
- if (mode != GP_ONION_MODE_SELECTED) {
- if (mode == GP_ONION_MODE_ABSOLUTE) {
- fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(step + 1));
- }
- else {
- fac = 1.0f - ((float)idx / (float)(step + 1));
- }
- color[3] = alpha * fac * 0.66f;
- }
- else {
- idx++;
- fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
- color[3] = fac;
- }
-
- /* if loop option, save the frame to use later */
- if ((mode == GP_ONION_MODE_SELECTED) && (gpd->onion_flag & GP_ONION_LOOP)) {
- gpf_loop = gf;
- }
-
- gpencil_get_onion_alpha(color, gpd);
- gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
- }
- /* -------------------------------
- * 2) Now draw next frames
- * ------------------------------- */
- step = gpd->gstep_next;
-
- if (gpd->onion_flag & GP_ONION_GHOST_NEXTCOL) {
- copy_v3_v3(color, gpd->gcolor_next);
- }
- else {
- copy_v3_v3(color, default_color);
- }
-
- idx = 0;
- for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
- /* only selected frames */
- if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
- continue;
- }
- /* verify keyframe type */
- if ((onion_keytype > -1) && (gf->key_type != onion_keytype)) {
- continue;
- }
- /* absolute range */
- if (mode == GP_ONION_MODE_ABSOLUTE) {
- if ((gf->framenum - gpf->framenum) > step) {
- break;
- }
- }
- /* relative range */
- if (mode == GP_ONION_MODE_RELATIVE) {
- idx++;
- if (idx > step) {
- break;
- }
- }
- /* alpha decreases with distance from curframe index */
- if (mode != GP_ONION_MODE_SELECTED) {
- if (mode == GP_ONION_MODE_ABSOLUTE) {
- fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(step + 1));
- }
- else {
- fac = 1.0f - ((float)idx / (float)(step + 1));
- }
- color[3] = alpha * fac * 0.66f;
- }
- else {
- idx++;
- fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f);
- color[3] = fac;
- }
-
- gpencil_get_onion_alpha(color, gpd);
- gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gf, color[3], color, colflag);
- if (last < gf->framenum) {
- last = gf->framenum;
- }
- }
-
- /* Draw first frame in blue for loop mode */
- if ((gpd->onion_flag & GP_ONION_LOOP) && (gpf_loop != NULL)) {
- if ((last == gpf->framenum) || (gpf->next == NULL)) {
- gpencil_get_onion_alpha(color, gpd);
- gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gpf_loop, color[3], color, colflag);
- }
- }
-}
-
-/* Check if stencil is required */
-static bool gpencil_is_stencil_required(MaterialGPencilStyle *gp_style)
-{
- return (bool)((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_SOLID) &&
- ((gp_style->flag & GP_STYLE_DISABLE_STENCIL) == 0));
-}
-
-/* draw stroke in drawing buffer */
-void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
- void *vedata,
- ToolSettings *ts,
- Object *ob)
-{
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true;
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
- const bool is_paint_tool = (bool)((brush) && (brush->gpencil_tool == GPAINT_TOOL_DRAW));
- bGPdata *gpd_eval = ob->data;
- /* need the original to avoid cow overhead while drawing */
- bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
-
- MaterialGPencilStyle *gp_style = NULL;
- float obscale = mat4_to_scale(ob->obmat);
-
- /* use the brush material */
- Material *ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
- if (ma != NULL) {
- gp_style = ma->gp_style;
- }
- /* this is not common, but avoid any special situations when brush could be without material */
- if (gp_style == NULL) {
- gp_style = BKE_gpencil_material_settings(ob, ob->actcol);
- }
-
- static float unit_mat[4][4] = {
- {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}};
-
- /* drawing strokes */
- /* Check if may need to draw the active stroke cache, only if this layer is the active layer
- * that is being edited. (Stroke buffer is currently stored in gp-data)
- */
- if (gpd->runtime.sbuffer_used > 0) {
- if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
- /* It should also be noted that sbuffer contains temporary point types
- * i.e. tGPspoints NOT bGPDspoints
- */
- short lthick = brush->size * obscale;
-
- /* save gradient info */
- stl->storage->gradient_f = brush->gpencil_settings->gradient_f;
- copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s);
- stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH;
-
- /* if only one point, don't need to draw buffer because the user has no time to see it */
- if (gpd->runtime.sbuffer_used > 1) {
- if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) {
- stl->g_data->shgrps_drawing_stroke = gpencil_shgroup_stroke_create(
- e_data,
- vedata,
- psl->drawing_pass,
- e_data->gpencil_stroke_sh,
- NULL,
- unit_mat,
- gpd,
- NULL,
- NULL,
- gp_style,
- -1,
- false,
- 1.0f,
- (const int *)stl->storage->shade_render);
-
- if (gpencil_is_stencil_required(gp_style)) {
- DRW_shgroup_stencil_mask(stl->g_data->shgrps_drawing_stroke, 0x01);
- }
- else {
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(stl->g_data->shgrps_drawing_stroke,
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
- }
- }
- else {
- stl->g_data->shgrps_drawing_stroke = gpencil_shgroup_point_create(
- e_data,
- vedata,
- psl->drawing_pass,
- e_data->gpencil_point_sh,
- NULL,
- unit_mat,
- gpd,
- NULL,
- NULL,
- gp_style,
- -1,
- false,
- 1.0f,
- (const int *)stl->storage->shade_render);
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(stl->g_data->shgrps_drawing_stroke,
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
- }
-
- /* use unit matrix because the buffer is in screen space and does not need conversion */
- if (gpd->runtime.mode == GP_STYLE_MODE_LINE) {
- stl->g_data->batch_buffer_stroke = gpencil_get_buffer_stroke_geom(gpd, lthick);
- }
- else {
- stl->g_data->batch_buffer_stroke = gpencil_get_buffer_point_geom(gpd, lthick);
- }
-
- /* buffer strokes, must show stroke always */
- DRW_shgroup_call(
- stl->g_data->shgrps_drawing_stroke, stl->g_data->batch_buffer_stroke, NULL);
-
- if ((gpd->runtime.sbuffer_used >= 3) &&
- (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
- ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) &&
- ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) &&
- (gp_style->flag & GP_STYLE_FILL_SHOW)) {
- /* if not solid, fill is simulated with solid color */
- if (gpd->runtime.bfill_style > 0) {
- gpd->runtime.sfill[3] = 0.5f;
- }
- stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(e_data->gpencil_drawing_fill_sh,
- psl->drawing_pass);
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(stl->g_data->shgrps_drawing_fill,
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
-
- stl->g_data->batch_buffer_fill = gpencil_get_buffer_fill_geom(gpd);
- DRW_shgroup_call(stl->g_data->shgrps_drawing_fill, stl->g_data->batch_buffer_fill, NULL);
- }
- }
- }
- }
-
- /* control points for primitives and speed guide */
- const bool is_cppoint = (gpd->runtime.tot_cp_points > 0);
- const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide &&
- (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL));
- const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) &&
- ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0));
-
- if ((overlay) && (is_paint_tool) && (is_cppoint || is_speed_guide) && (is_show_gizmo) &&
- ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0)) {
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->drawing_pass);
- const float *viewport_size = DRW_viewport_size_get();
- DRW_shgroup_uniform_vec2(shgrp, "Viewport", viewport_size, 1);
- DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", unit_mat);
-
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
- stl->g_data->batch_buffer_ctrlpoint = gpencil_get_buffer_ctrlpoint_geom(gpd);
-
- DRW_shgroup_call(shgrp, stl->g_data->batch_buffer_ctrlpoint, NULL);
- }
-}
-
-/* create all missing batches */
-static void gpencil_batches_ensure(GpencilBatchCache *cache)
-{
- if ((cache->b_point.vbo) && (cache->b_point.batch == NULL)) {
- cache->b_point.batch = GPU_batch_create_ex(
- GPU_PRIM_POINTS, cache->b_point.vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
- if ((cache->b_stroke.vbo) && (cache->b_stroke.batch == NULL)) {
- cache->b_stroke.batch = GPU_batch_create_ex(
- GPU_PRIM_LINE_STRIP_ADJ, cache->b_stroke.vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
- if ((cache->b_fill.vbo) && (cache->b_fill.batch == NULL)) {
- cache->b_fill.batch = GPU_batch_create_ex(
- GPU_PRIM_TRIS, cache->b_fill.vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
- if ((cache->b_edit.vbo) && (cache->b_edit.batch == NULL)) {
- cache->b_edit.batch = GPU_batch_create_ex(
- GPU_PRIM_POINTS, cache->b_edit.vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
- if ((cache->b_edlin.vbo) && (cache->b_edlin.batch == NULL)) {
- cache->b_edlin.batch = GPU_batch_create_ex(
- GPU_PRIM_LINE_STRIP, cache->b_edlin.vbo, NULL, GPU_BATCH_OWNS_VBO);
- }
-}
-
-/* create all shading groups */
-static void gpencil_shgroups_create(GPENCIL_e_data *e_data,
- void *vedata,
- Object *ob,
- GpencilBatchCache *cache,
- tGPencilObjectCache *cache_ob)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- bGPdata *gpd = (bGPdata *)ob->data;
- DRWPass *stroke_pass = GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d;
-
- GpencilBatchGroup *elm = NULL;
- DRWShadingGroup *shgrp = NULL;
- tGPencilObjectCache_shgrp *array_elm = NULL;
-
- bGPDlayer *gpl = NULL;
- bGPDlayer *gpl_prev = NULL;
- int idx = 0;
- bool tag_first = false;
- bool strokes = false;
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const View3D *v3d = draw_ctx->v3d;
-
- const bool overlay = draw_ctx->v3d != NULL ?
- (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) :
- true;
- const bool screen_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true;
- const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && screen_onion &&
- overlay && gpencil_onion_active(gpd);
-
- int start_stroke = 0;
- int start_point = 0;
- int start_fill = 0;
- int start_edit = 0;
- int start_edlin = 0;
-
- uint stencil_id = 1;
- /* Flag to determine if the layer is above active layer. */
- stl->storage->is_ontop = false;
- for (int i = 0; i < cache->grp_used; i++) {
- elm = &cache->grp_cache[i];
- array_elm = &cache_ob->shgrp_array[idx];
-
- /* Limit stencil id */
- if (stencil_id > 255) {
- stencil_id = 1;
- }
-
- /* save last group when change */
- if (gpl_prev == NULL) {
- gpl_prev = elm->gpl;
- tag_first = true;
- }
- else {
- if (elm->gpl != gpl_prev) {
- /* first layer is always blend Normal */
- array_elm->mode = idx == 0 ? eGplBlendMode_Regular : gpl->blend_mode;
- array_elm->end_shgrp = shgrp;
- gpl_prev = elm->gpl;
- tag_first = true;
- idx++;
- }
- }
-
- gpl = elm->gpl;
- if ((!stl->storage->is_ontop) && (gpl->flag & GP_LAYER_ACTIVE)) {
- stl->storage->is_ontop = true;
- }
-
- bGPDframe *gpf = elm->gpf;
- bGPDstroke *gps = elm->gps;
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- /* if the user switch used material from data to object,
- * the material could not be available */
- if (gp_style == NULL) {
- break;
- }
-
- /* limit the number of shading groups */
- if (i >= GPENCIL_MAX_SHGROUPS) {
- break;
- }
-
- const float scale = (!cache_ob->is_dup_ob) ? mat4_to_scale(gpf->runtime.parent_obmat) :
- cache_ob->scale;
- float(*obmat)[4] = (!cache_ob->is_dup_ob) ? gpf->runtime.parent_obmat : cache_ob->obmat;
- switch (elm->type) {
- case eGpencilBatchGroupType_Stroke: {
- const int len = elm->vertex_idx - start_stroke;
- strokes = true;
-
- shgrp = gpencil_shgroup_stroke_create(e_data,
- vedata,
- stroke_pass,
- e_data->gpencil_stroke_sh,
- ob,
- obmat,
- gpd,
- gpl,
- gps,
- gp_style,
- stl->storage->shgroup_id,
- elm->onion,
- scale,
- cache_ob->shading_type);
-
- /* set stencil mask id */
- if (gpencil_is_stencil_required(gp_style)) {
- if (stencil_id == 1) {
- /* Clear previous stencils. */
- DRW_shgroup_clear_framebuffer(shgrp, GPU_STENCIL_BIT, 0, 0, 0, 0, 0.0f, 0x0);
- }
- DRW_shgroup_stencil_mask(shgrp, stencil_id);
- stencil_id++;
- }
- else {
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
- }
-
- if ((do_onion) || (elm->onion == false)) {
- DRW_shgroup_call_range(shgrp, cache->b_stroke.batch, start_stroke, len);
- }
- stl->storage->shgroup_id++;
- start_stroke = elm->vertex_idx;
- break;
- }
- case eGpencilBatchGroupType_Point: {
- const int len = elm->vertex_idx - start_point;
- strokes = true;
-
- shgrp = gpencil_shgroup_point_create(e_data,
- vedata,
- stroke_pass,
- e_data->gpencil_point_sh,
- ob,
- obmat,
- gpd,
- gpl,
- gps,
- gp_style,
- stl->storage->shgroup_id,
- elm->onion,
- scale,
- cache_ob->shading_type);
-
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
-
- if ((do_onion) || (elm->onion == false)) {
- DRW_shgroup_call_range(shgrp, cache->b_point.batch, start_point, len);
- }
- stl->storage->shgroup_id++;
- start_point = elm->vertex_idx;
- break;
- }
- case eGpencilBatchGroupType_Fill: {
- const int len = elm->vertex_idx - start_fill;
- strokes = true;
-
- shgrp = gpencil_shgroup_fill_create(e_data,
- vedata,
- stroke_pass,
- e_data->gpencil_fill_sh,
- ob,
- obmat,
- gpd,
- gpl,
- gp_style,
- stl->storage->shgroup_id,
- cache_ob->shading_type);
-
- /* Disable stencil for this type */
- DRW_shgroup_state_disable(shgrp, DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
-
- if ((do_onion) || (elm->onion == false)) {
- DRW_shgroup_call_range(shgrp, cache->b_fill.batch, start_fill, len);
- }
- stl->storage->shgroup_id++;
- start_fill = elm->vertex_idx;
- break;
- }
- case eGpencilBatchGroupType_Edit: {
- if (stl->g_data->shgrps_edit_point) {
- const int len = elm->vertex_idx - start_edit;
-
- shgrp = DRW_shgroup_create_sub(stl->g_data->shgrps_edit_point);
- DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", obmat);
- /* use always the same group */
- DRW_shgroup_call_range(
- stl->g_data->shgrps_edit_point, cache->b_edit.batch, start_edit, len);
-
- start_edit = elm->vertex_idx;
- }
- break;
- }
- case eGpencilBatchGroupType_Edlin: {
- if (stl->g_data->shgrps_edit_line) {
- const int len = elm->vertex_idx - start_edlin;
-
- shgrp = DRW_shgroup_create_sub(stl->g_data->shgrps_edit_line);
- DRW_shgroup_uniform_mat4(shgrp, "gpModelMatrix", obmat);
- /* use always the same group */
- DRW_shgroup_call_range(
- stl->g_data->shgrps_edit_line, cache->b_edlin.batch, start_edlin, len);
-
- start_edlin = elm->vertex_idx;
- }
- break;
- }
- default: {
- break;
- }
- }
- /* save first group */
- if ((shgrp != NULL) && (tag_first) && (strokes)) {
- array_elm = &cache_ob->shgrp_array[idx];
- array_elm->mode = idx == 0 ? eGplBlendMode_Regular : gpl->blend_mode;
- array_elm->mask_layer = gpl->flag & GP_LAYER_USE_MASK;
- array_elm->blend_opacity = gpl->opacity;
- array_elm->init_shgrp = shgrp;
- cache_ob->tot_layers++;
- tag_first = false;
- }
- }
-
- /* save last group */
- if (shgrp != NULL) {
- array_elm->mode = idx == 0 ? eGplBlendMode_Regular : gpl->blend_mode;
- array_elm->end_shgrp = shgrp;
- }
-}
-/* populate a datablock for multiedit (no onions, no modifiers) */
-void gpencil_populate_multiedit(GPENCIL_e_data *e_data,
- void *vedata,
- Object *ob,
- tGPencilObjectCache *cache_ob)
-{
- bGPdata *gpd = (bGPdata *)ob->data;
- bGPDframe *gpf = NULL;
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
- GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
-
- /* check if playing animation */
- const bool playing = stl->storage->is_playing;
-
- /* calc max size of VBOs */
- gpencil_calc_vertex(stl, cache_ob, cache, gpd);
-
- /* draw strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* don't draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE) {
- continue;
- }
- const float alpha = GPENCIL_SIMPLIFY_TINT(scene, playing) ? 0.0f : gpl->tintcolor[3];
- const float tintcolor[4] = {gpl->tintcolor[0], gpl->tintcolor[1], gpl->tintcolor[2], alpha};
-
- /* list of frames to draw */
- if (!playing) {
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
- gpencil_draw_strokes(
- cache, e_data, vedata, ob, gpd, gpl, gpf, gpl->opacity, tintcolor, false, cache_ob);
- }
- }
- }
- else {
- gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV);
- if (gpf) {
- gpencil_draw_strokes(
- cache, e_data, vedata, ob, gpd, gpl, gpf, gpl->opacity, tintcolor, false, cache_ob);
- }
- }
- }
-
- /* create batchs and shading groups */
- gpencil_batches_ensure(cache);
- gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
-
- cache->is_dirty = false;
-}
-
-/* helper for populate a complete grease pencil datablock */
-void gpencil_populate_datablock(GPENCIL_e_data *e_data,
- void *vedata,
- Object *ob,
- tGPencilObjectCache *cache_ob)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
- Scene *scene = draw_ctx->scene;
-
- /* TODO: Review why is needed this recalc when render cycles + GP object in background.
- * We need these lines to keep running the background render, but asap we get an alternative
- * solution, we must remove it and keep all logic inside gpencil_modifier module. (antoniov)
- */
- if (ob->runtime.gpencil_tot_layers == 0) {
- BKE_gpencil_modifiers_calc(draw_ctx->depsgraph, draw_ctx->scene, ob);
- }
-
- bGPdata *gpd = (bGPdata *)ob->data;
-
- /* If render mode, instead to use view switches, test if the datablock has
- * the onion activated for render. */
- const bool render_onion = (gpd && gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
- const bool main_onion = (stl->storage->is_render) ? render_onion : stl->storage->is_main_onion;
- const bool overlay = (stl->storage->is_render) ? render_onion : stl->storage->is_main_overlay;
- const bool playing = stl->storage->is_playing;
- const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
- main_onion && !playing && gpencil_onion_active(gpd);
-
- View3D *v3d = draw_ctx->v3d;
- int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
-
- bGPDframe *gpf_eval = NULL;
- const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
-
- float opacity;
- bGPDframe *gpf = NULL;
-
- GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval);
-
- /* if object is duplicate, only create shading groups */
- if (cache_ob->is_dup_ob) {
- gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
- return;
- }
-
- /* calc max size of VBOs */
- gpencil_calc_vertex(stl, cache_ob, cache, gpd);
-
- /* draw normal strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* don't draw layer if hidden */
- if (gpl->flag & GP_LAYER_HIDE) {
- continue;
- }
-
- const bool is_solomode = GPENCIL_PAINT_MODE(gpd) && (!playing) && (!stl->storage->is_render) &&
- (gpl->flag & GP_LAYER_SOLO_MODE);
-
- /* filter view layer to gp layers in the same view layer (for compo) */
- if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) {
- if (!STREQ(view_layer->name, gpl->viewlayername)) {
- continue;
- }
- }
-
- /* remap time */
- int remap_cfra = cfra_eval;
- if ((time_remap) && (!stl->storage->simplify_modif)) {
- remap_cfra = BKE_gpencil_time_modifier(
- draw_ctx->depsgraph, scene, ob, gpl, cfra_eval, stl->storage->is_render);
- }
-
- gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
- if (gpf == NULL) {
- continue;
- }
-
- /* if solo mode, display only frames with keyframe in the current frame */
- if ((is_solomode) && (gpf->framenum != remap_cfra)) {
- continue;
- }
-
- opacity = gpl->opacity;
- /* if pose mode, maybe the overlay to fade geometry is enabled */
- if ((draw_ctx->obact) && (draw_ctx->object_mode == OB_MODE_POSE) &&
- (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT)) {
- opacity = opacity * v3d->overlay.xray_alpha_bone;
- }
-
- /* Get evaluated frames array data */
- int idx_eval = BLI_findindex(&gpd->layers, gpl);
- gpf_eval = &ob->runtime.gpencil_evaluated_frames[idx_eval];
-
- /* draw onion skins */
- if (!ID_IS_LINKED(&gpd->id)) {
- if ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) &&
- ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) && (!cache_ob->is_dup_ob) &&
- (gpd->id.us <= 1)) {
- if ((!stl->storage->is_render) ||
- ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) {
- gpencil_draw_onionskins(cache, vedata, ob, gpd, gpl, gpf);
- }
- }
- }
- /* draw normal strokes */
- const float alpha = GPENCIL_SIMPLIFY_TINT(scene, playing) ? 0.0f : gpl->tintcolor[3];
- const float tintcolor[4] = {gpl->tintcolor[0], gpl->tintcolor[1], gpl->tintcolor[2], alpha};
- gpencil_draw_strokes(
- cache, e_data, vedata, ob, gpd, gpl, gpf_eval, opacity, tintcolor, false, cache_ob);
- }
-
- /* create batchs and shading groups */
- gpencil_batches_ensure(cache);
- gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
-
- cache->is_dirty = false;
-}
-
-void gpencil_populate_particles(GPENCIL_e_data *e_data, GHash *gh_objects, void *vedata)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
-
- /* add particles */
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
- if (cache_ob->is_dup_ob) {
- /* Reassign duplicate objects because memory for particles is not available
- * and need to use the original data-block and run-time data. */
- Object *ob = (Object *)BLI_ghash_lookup(gh_objects, cache_ob->name);
- if (ob) {
- cache_ob->ob = ob;
- cache_ob->gpd = (bGPdata *)ob->data;
- GpencilBatchCache *cache = ob->runtime.gpencil_cache;
- if (cache != NULL) {
- gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
- }
- }
- }
- }
-}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index f44551356c4..8736857c45c 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -29,11 +29,19 @@
#include "BKE_paint.h"
#include "BKE_shader_fx.h"
+#include "BKE_camera.h"
+#include "BKE_global.h" /* for G.debug */
+
+#include "BLI_link_utils.h"
+#include "BLI_memblock.h"
+
+#include "DNA_camera_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
#include "gpencil_engine.h"
@@ -44,1129 +52,947 @@
#include "UI_resources.h"
-extern char datatoc_gpencil_fill_vert_glsl[];
-extern char datatoc_gpencil_fill_frag_glsl[];
-extern char datatoc_gpencil_stroke_vert_glsl[];
-extern char datatoc_gpencil_stroke_geom_glsl[];
-extern char datatoc_gpencil_stroke_frag_glsl[];
-extern char datatoc_gpencil_zdepth_mix_frag_glsl[];
-extern char datatoc_gpencil_simple_mix_frag_glsl[];
-extern char datatoc_gpencil_point_vert_glsl[];
-extern char datatoc_gpencil_point_geom_glsl[];
-extern char datatoc_gpencil_point_frag_glsl[];
-extern char datatoc_gpencil_background_frag_glsl[];
-extern char datatoc_gpencil_paper_frag_glsl[];
-extern char datatoc_gpencil_edit_point_vert_glsl[];
-extern char datatoc_gpencil_edit_point_geom_glsl[];
-extern char datatoc_gpencil_edit_point_frag_glsl[];
-extern char datatoc_gpencil_blend_frag_glsl[];
-
-extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
-
-extern char datatoc_common_colormanagement_lib_glsl[];
-extern char datatoc_common_view_lib_glsl[];
-
-/* *********** STATIC *********** */
-static GPENCIL_e_data e_data = {NULL}; /* Engine data */
-
/* *********** FUNCTIONS *********** */
-/* create a multisample buffer if not present */
-void gpencil_multisample_ensure(GPENCIL_Data *vedata, int rect_w, int rect_h)
+void GPENCIL_engine_init(void *ved)
{
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_StorageList *stl = vedata->stl;
+ GPENCIL_TextureList *txl = vedata->txl;
GPENCIL_FramebufferList *fbl = vedata->fbl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
-
- short samples = stl->storage->multisamples;
-
- if (samples > 0) {
- if (!fbl->multisample_fb) {
- fbl->multisample_fb = GPU_framebuffer_create();
- if (fbl->multisample_fb) {
- if (txl->multisample_color == NULL) {
- txl->multisample_color = GPU_texture_create_2d_multisample(
- rect_w, rect_h, GPU_RGBA16F, NULL, samples, NULL);
- }
- if (txl->multisample_depth == NULL) {
- txl->multisample_depth = GPU_texture_create_2d_multisample(
- rect_w, rect_h, GPU_DEPTH24_STENCIL8, NULL, samples, NULL);
- }
- GPU_framebuffer_ensure_config(&fbl->multisample_fb,
- {GPU_ATTACHMENT_TEXTURE(txl->multisample_depth),
- GPU_ATTACHMENT_TEXTURE(txl->multisample_color)});
- }
- }
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ const DRWContextState *ctx = DRW_context_state_get();
+ const View3D *v3d = ctx->v3d;
+
+ if (!stl->pd) {
+ stl->pd = MEM_callocN(sizeof(GPENCIL_PrivateData), "GPENCIL_PrivateData");
+ }
+
+ if (txl->dummy_texture == NULL) {
+ float pixels[1][4] = {{1.0f, 0.0f, 1.0f, 1.0f}};
+ txl->dummy_texture = DRW_texture_create_2d(1, 1, GPU_RGBA8, DRW_TEX_WRAP, (float *)pixels);
+ }
+
+ GPENCIL_ViewLayerData *vldata = GPENCIL_view_layer_data_ensure();
+
+ /* Resize and reset memblocks. */
+ BLI_memblock_clear(vldata->gp_light_pool, gpencil_light_pool_free);
+ BLI_memblock_clear(vldata->gp_material_pool, gpencil_material_pool_free);
+ BLI_memblock_clear(vldata->gp_object_pool, NULL);
+ BLI_memblock_clear(vldata->gp_layer_pool, NULL);
+ BLI_memblock_clear(vldata->gp_vfx_pool, NULL);
+
+ stl->pd->gp_light_pool = vldata->gp_light_pool;
+ stl->pd->gp_material_pool = vldata->gp_material_pool;
+ stl->pd->gp_object_pool = vldata->gp_object_pool;
+ stl->pd->gp_layer_pool = vldata->gp_layer_pool;
+ stl->pd->gp_vfx_pool = vldata->gp_vfx_pool;
+ stl->pd->last_light_pool = NULL;
+ stl->pd->last_material_pool = NULL;
+ stl->pd->tobjects.first = NULL;
+ stl->pd->tobjects.last = NULL;
+ stl->pd->tobjects_infront.first = NULL;
+ stl->pd->tobjects_infront.last = NULL;
+ stl->pd->sbuffer_tobjects.first = NULL;
+ stl->pd->sbuffer_tobjects.last = NULL;
+ stl->pd->dummy_tx = txl->dummy_texture;
+ stl->pd->draw_depth_only = !DRW_state_is_fbo() || (v3d && v3d->shading.type == OB_WIRE);
+ stl->pd->scene_depth_tx = stl->pd->draw_depth_only ? txl->dummy_texture : dtxl->depth;
+ stl->pd->scene_fb = dfbl->default_fb;
+ stl->pd->is_render = txl->render_depth_tx || (v3d && v3d->shading.type == OB_RENDER);
+ stl->pd->global_light_pool = gpencil_light_pool_add(stl->pd);
+ stl->pd->shadeless_light_pool = gpencil_light_pool_add(stl->pd);
+ /* Small HACK: we don't want the global pool to be reused,
+ * so we set the last light pool to NULL. */
+ stl->pd->last_light_pool = NULL;
+
+ bool use_scene_lights = false;
+ bool use_scene_world = false;
+
+ if (v3d) {
+ use_scene_lights = ((v3d->shading.type == OB_MATERIAL) &&
+ (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) ||
+ ((v3d->shading.type == OB_RENDER) &&
+ (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER));
+
+ use_scene_world = ((v3d->shading.type == OB_MATERIAL) &&
+ (v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) ||
+ ((v3d->shading.type == OB_RENDER) &&
+ (v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER));
+
+ stl->pd->v3d_color_type = (v3d->shading.type == OB_SOLID) ? v3d->shading.color_type : -1;
+ copy_v3_v3(stl->pd->v3d_single_color, v3d->shading.single_color);
+
+ /* For non active frame, use only lines in multiedit mode. */
+ const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
+ stl->pd->use_multiedit_lines_only = !overlays_on ||
+ (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) != 0;
+ }
+ else if (stl->pd->is_render) {
+ use_scene_lights = true;
+ use_scene_world = true;
+ stl->pd->use_multiedit_lines_only = false;
+ }
+
+ stl->pd->use_lighting = (v3d && v3d->shading.type > OB_SOLID) || stl->pd->is_render;
+ stl->pd->use_lights = use_scene_lights;
+
+ if (txl->render_depth_tx != NULL) {
+ stl->pd->scene_depth_tx = txl->render_depth_tx;
+ stl->pd->scene_fb = fbl->render_fb;
+ }
+
+ gpencil_light_ambient_add(stl->pd->shadeless_light_pool, (float[3]){1.0f, 1.0f, 1.0f});
+
+ World *world = ctx->scene->world;
+ if (world != NULL && use_scene_world) {
+ gpencil_light_ambient_add(stl->pd->global_light_pool, &world->horr);
+ }
+ else if (v3d) {
+ float world_light[3];
+ copy_v3_fl(world_light, v3d->shading.studiolight_intensity);
+ gpencil_light_ambient_add(stl->pd->global_light_pool, world_light);
+ }
+
+ float viewmatinv[4][4];
+ DRW_view_viewmat_get(NULL, viewmatinv, true);
+ copy_v3_v3(stl->pd->camera_z_axis, viewmatinv[2]);
+ copy_v3_v3(stl->pd->camera_pos, viewmatinv[3]);
+ stl->pd->camera_z_offset = dot_v3v3(viewmatinv[3], viewmatinv[2]);
+
+ if (ctx && ctx->rv3d && v3d) {
+ stl->pd->camera = (ctx->rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
+ }
+ else {
+ stl->pd->camera = NULL;
}
}
-static void GPENCIL_create_framebuffers(void *vedata)
+void GPENCIL_cache_init(void *ved)
{
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
-
- /* Go full 32bits for rendering */
- eGPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F;
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_PassList *psl = vedata->psl;
+ GPENCIL_TextureList *txl = vedata->txl;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ DRWShadingGroup *grp;
- if (DRW_state_is_fbo()) {
- const float *viewport_size = DRW_viewport_size_get();
- const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ pd->cfra = (int)DEG_get_ctime(draw_ctx->depsgraph);
+ pd->simplify_antialias = GPENCIL_SIMPLIFY_AA(draw_ctx->scene);
+ /* Antialiasing needs the layer buffer to output to. */
+ pd->use_layer_fb = false || !pd->simplify_antialias;
+ pd->use_object_fb = false;
+ pd->use_mask_fb = false;
+ pd->use_signed_fb = false;
+
+ if (draw_ctx->v3d) {
+ const bool hide_overlay = ((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) != 0);
+ const bool show_onion = ((draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) != 0);
+ const bool playing = (draw_ctx->evil_C != NULL) ?
+ ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) !=
+ NULL :
+ false;
+ pd->do_onion = show_onion && !hide_overlay && !playing;
+ /* Save simplify flags (can change while drawing, so it's better to save). */
+ Scene *scene = draw_ctx->scene;
+ pd->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, playing);
+ pd->simplify_fx = GPENCIL_SIMPLIFY_FX(scene, playing);
+
+ /* Fade Layer. */
+ const bool is_fade_layer = ((!hide_overlay) && (!pd->is_render) &&
+ (draw_ctx->v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS));
+ pd->fade_layer_opacity = (is_fade_layer) ? draw_ctx->v3d->overlay.gpencil_fade_layer : -1.0f;
+ /* Fade GPencil Objects. */
+ const bool is_fade_object = ((!hide_overlay) && (!pd->is_render) &&
+ (draw_ctx->v3d->gp_flag & V3D_GP_FADE_OBJECTS) &&
+ (draw_ctx->v3d->gp_flag & V3D_GP_FADE_NOACTIVE_GPENCIL));
+ pd->fade_gp_object_opacity = (is_fade_object) ? draw_ctx->v3d->overlay.gpencil_paper_opacity :
+ -1.0f;
+ pd->fade_3d_object_opacity = ((!hide_overlay) && (!pd->is_render) &&
+ (draw_ctx->v3d->gp_flag & V3D_GP_FADE_OBJECTS)) ?
+ draw_ctx->v3d->overlay.gpencil_paper_opacity :
+ -1.0f;
+ }
+ else {
+ pd->do_onion = true;
+ pd->simplify_fill = false;
+ pd->simplify_fx = false;
+ pd->fade_layer_opacity = -1.0f;
+ }
- /* create multisample framebuffer for AA */
- if ((stl->storage->framebuffer_flag & GP_FRAMEBUFFER_MULTISAMPLE) &&
- (stl->storage->multisamples > 0)) {
- gpencil_multisample_ensure(vedata, size[0], size[1]);
+ {
+ pd->sbuffer_stroke = NULL;
+ pd->sbuffer_gpd = NULL;
+ pd->sbuffer_layer = NULL;
+ pd->stroke_batch = NULL;
+ pd->fill_batch = NULL;
+ pd->do_fast_drawing = false;
+
+ pd->obact = draw_ctx->obact;
+ if (pd->obact && pd->obact->type == OB_GPENCIL) {
+ /* Check if active object has a temp stroke data. */
+ bGPdata *gpd = (bGPdata *)pd->obact->data;
+ if (gpd->runtime.sbuffer_used > 0) {
+ pd->sbuffer_gpd = gpd;
+ pd->sbuffer_stroke = DRW_cache_gpencil_sbuffer_stroke_data_get(pd->obact);
+ pd->sbuffer_layer = BKE_gpencil_layer_active_get(pd->sbuffer_gpd);
+ pd->do_fast_drawing = false; /* TODO option */
+ }
}
+ }
- /* Framebufers for basic object drawing */
- if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_BASIC) {
- /* temp textures for ping-pong buffers */
- stl->g_data->temp_depth_tx_a = DRW_texture_pool_query_2d(
- size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type);
- stl->g_data->temp_color_tx_a = DRW_texture_pool_query_2d(
- size[0], size[1], fb_format, &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(&fbl->temp_fb_a,
- {
- GPU_ATTACHMENT_TEXTURE(stl->g_data->temp_depth_tx_a),
- GPU_ATTACHMENT_TEXTURE(stl->g_data->temp_color_tx_a),
- });
+ if (pd->do_fast_drawing) {
+ pd->snapshot_buffer_dirty = (txl->snapshot_color_tx == NULL);
+ const float *size = DRW_viewport_size_get();
+ DRW_texture_ensure_2d(&txl->snapshot_depth_tx, size[0], size[1], GPU_DEPTH24_STENCIL8, 0);
+ DRW_texture_ensure_2d(&txl->snapshot_color_tx, size[0], size[1], GPU_R11F_G11F_B10F, 0);
+ DRW_texture_ensure_2d(&txl->snapshot_reveal_tx, size[0], size[1], GPU_R11F_G11F_B10F, 0);
- stl->g_data->temp_depth_tx_b = DRW_texture_pool_query_2d(
- size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type);
- stl->g_data->temp_color_tx_b = DRW_texture_pool_query_2d(
- size[0], size[1], fb_format, &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(&fbl->temp_fb_b,
- {
- GPU_ATTACHMENT_TEXTURE(stl->g_data->temp_depth_tx_b),
- GPU_ATTACHMENT_TEXTURE(stl->g_data->temp_color_tx_b),
- });
+ GPU_framebuffer_ensure_config(&fbl->snapshot_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(txl->snapshot_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(txl->snapshot_color_tx),
+ GPU_ATTACHMENT_TEXTURE(txl->snapshot_reveal_tx),
+ });
+ }
+ else {
+ /* Free uneeded buffers. */
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->snapshot_fb);
+ DRW_TEXTURE_FREE_SAFE(txl->snapshot_depth_tx);
+ DRW_TEXTURE_FREE_SAFE(txl->snapshot_color_tx);
+ DRW_TEXTURE_FREE_SAFE(txl->snapshot_reveal_tx);
+ }
- /* used for FX effects and Layer blending */
- stl->g_data->temp_depth_tx_fx = DRW_texture_pool_query_2d(
- size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type);
- stl->g_data->temp_color_tx_fx = DRW_texture_pool_query_2d(
- size[0], size[1], fb_format, &draw_engine_gpencil_type);
- GPU_framebuffer_ensure_config(&fbl->temp_fb_fx,
- {
- GPU_ATTACHMENT_TEXTURE(stl->g_data->temp_depth_tx_fx),
- GPU_ATTACHMENT_TEXTURE(stl->g_data->temp_color_tx_fx),
- });
- }
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
+ DRW_PASS_CREATE(psl->composite_ps, state);
- /* background framebuffer to speed up drawing process */
- if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_DRAW) {
- if (txl->background_color_tx == NULL) {
- stl->storage->background_ready = false;
- }
- DRW_texture_ensure_2d(
- &txl->background_depth_tx, size[0], size[1], GPU_DEPTH_COMPONENT24, DRW_TEX_FILTER);
- DRW_texture_ensure_2d(
- &txl->background_color_tx, size[0], size[1], GPU_RGBA16F, DRW_TEX_FILTER);
- GPU_framebuffer_ensure_config(&fbl->background_fb,
- {
- GPU_ATTACHMENT_TEXTURE(txl->background_depth_tx),
- GPU_ATTACHMENT_TEXTURE(txl->background_color_tx),
- });
- }
- else {
- DRW_TEXTURE_FREE_SAFE(txl->background_depth_tx);
- DRW_TEXTURE_FREE_SAFE(txl->background_color_tx);
- }
+ GPUShader *sh = GPENCIL_shader_composite_get();
+ grp = DRW_shgroup_create(sh, psl->composite_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_tx);
+ DRW_shgroup_uniform_bool_copy(grp, "doSrgb", txl->render_depth_tx == NULL);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-}
+ {
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ DRW_PASS_CREATE(psl->merge_depth_ps, state);
-static void GPENCIL_create_shaders(void)
-{
- /* blank texture used if no texture defined for fill shader */
- if (!e_data.gpencil_blank_texture) {
- float rect[1][1][4] = {{{0.0f}}};
- e_data.gpencil_blank_texture = DRW_texture_create_2d(
- 1, 1, GPU_RGBA8, DRW_TEX_FILTER, (float *)rect);
- }
- /* normal fill shader */
- if (!e_data.gpencil_fill_sh) {
- e_data.gpencil_fill_sh = GPU_shader_create_from_arrays({
- .vert =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_gpencil_fill_vert_glsl, NULL},
- .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
- datatoc_gpencil_fill_frag_glsl,
- NULL},
- });
- }
-
- /* normal stroke shader using geometry to display lines (line mode) */
- if (!e_data.gpencil_stroke_sh) {
- e_data.gpencil_stroke_sh = GPU_shader_create_from_arrays({
- .vert =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_gpencil_stroke_vert_glsl, NULL},
- .geom = (const char *[]){datatoc_gpencil_stroke_geom_glsl, NULL},
- .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
- datatoc_gpencil_stroke_frag_glsl,
- NULL},
- });
- }
-
- /* dot/rectangle mode for normal strokes using geometry */
- if (!e_data.gpencil_point_sh) {
- e_data.gpencil_point_sh = GPU_shader_create_from_arrays({
- .vert =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_gpencil_point_vert_glsl, NULL},
- .geom = (const char *[]){datatoc_gpencil_point_geom_glsl, NULL},
- .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
- datatoc_gpencil_point_frag_glsl,
- NULL},
- });
- }
- /* used for edit points or strokes with one point only */
- if (!e_data.gpencil_edit_point_sh) {
- e_data.gpencil_edit_point_sh = DRW_shader_create_with_lib(datatoc_gpencil_edit_point_vert_glsl,
- datatoc_gpencil_edit_point_geom_glsl,
- datatoc_gpencil_edit_point_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
- }
-
- /* used for edit lines for edit modes */
- if (!e_data.gpencil_line_sh) {
- e_data.gpencil_line_sh = DRW_shader_create_with_lib(
- datatoc_gpencil_edit_point_vert_glsl,
- NULL,
- datatoc_gpu_shader_3D_smooth_color_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
- }
-
- /* used to filling during drawing */
- if (!e_data.gpencil_drawing_fill_sh) {
- e_data.gpencil_drawing_fill_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR);
- }
-
- /* full screen for mix zdepth*/
- if (!e_data.gpencil_fullscreen_sh) {
- e_data.gpencil_fullscreen_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_zdepth_mix_frag_glsl, NULL);
- }
- if (!e_data.gpencil_simple_fullscreen_sh) {
- e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_simple_mix_frag_glsl, NULL);
- }
-
- /* blend */
- if (!e_data.gpencil_blend_fullscreen_sh) {
- e_data.gpencil_blend_fullscreen_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_blend_frag_glsl, NULL);
- }
-
- /* shaders for use when drawing */
- if (!e_data.gpencil_background_sh) {
- e_data.gpencil_background_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_background_frag_glsl, NULL);
- }
- if (!e_data.gpencil_paper_sh) {
- e_data.gpencil_paper_sh = DRW_shader_create_fullscreen(datatoc_gpencil_paper_frag_glsl, NULL);
+ GPUShader *sh = GPENCIL_shader_depth_merge_get();
+ grp = DRW_shgroup_create(sh, psl->merge_depth_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuf", &pd->depth_tx);
+ DRW_shgroup_uniform_bool(grp, "strokeOrder3d", &pd->is_stroke_order_3d, 1);
+ DRW_shgroup_uniform_vec4(grp, "gpModelMatrix[0]", pd->object_bound_mat[0], 4);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-}
-void GPENCIL_engine_init(void *vedata)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- /* init storage */
- if (!stl->storage) {
- stl->storage = MEM_callocN(sizeof(GPENCIL_Storage), "GPENCIL_Storage");
- stl->storage->shade_render[0] = OB_RENDER;
- stl->storage->shade_render[1] = 0;
- }
+ Camera *cam = (pd->camera != NULL) ? pd->camera->data : NULL;
- stl->storage->multisamples = U.gpencil_multisamples;
+ /* Pseudo DOF setup. */
+ if (cam && (cam->dof.flag & CAM_DOF_ENABLED)) {
+ const float *vp_size = DRW_viewport_size_get();
+ float fstop = cam->dof.aperture_fstop;
+ float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+ float focus_dist = BKE_camera_object_dof_distance(pd->camera);
+ float focal_len = cam->lens;
- /* create shaders */
- GPENCIL_create_shaders();
- GPENCIL_create_fx_shaders(&e_data);
-}
+ const float scale_camera = 0.001f;
+ /* we want radius here for the aperture number */
+ float aperture = 0.5f * scale_camera * focal_len / fstop;
+ float focal_len_scaled = scale_camera * focal_len;
+ float sensor_scaled = scale_camera * sensor;
-static void GPENCIL_engine_free(void)
-{
- /* only free custom shaders, builtin shaders are freed in blender close */
- DRW_SHADER_FREE_SAFE(e_data.gpencil_fill_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_stroke_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_point_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_line_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh);
- DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh);
-
- DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture);
-
- /* effects */
- GPENCIL_delete_fx_shaders(&e_data);
+ if (draw_ctx->rv3d != NULL) {
+ sensor_scaled *= draw_ctx->rv3d->viewcamtexcofac[0];
+ }
+
+ pd->dof_params[1] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
+ pd->dof_params[1] *= vp_size[0] / sensor_scaled;
+ pd->dof_params[0] = -focus_dist * pd->dof_params[1];
+ }
+ else {
+ /* Disable DoF blur scalling. */
+ pd->camera = NULL;
+ }
}
-/* Helper: Check if the main overlay and onion switches are enabled in any screen.
- *
- * This is required to generate the onion skin and limit the times the cache is updated because the
- * cache is generated only in the first screen and if the first screen has the onion disabled the
- * cache for onion skin is not generated. The loop adds time, but always is faster than regenerate
- * the cache all the times.
- */
-static void gpencil_check_screen_switches(const DRWContextState *draw_ctx,
- GPENCIL_StorageList *stl)
+#define DRAW_NOW 2
+
+typedef struct gpIterPopulateData {
+ Object *ob;
+ GPENCIL_tObject *tgp_ob;
+ GPENCIL_PrivateData *pd;
+ GPENCIL_MaterialPool *matpool;
+ DRWShadingGroup *grp;
+ /* Last material UBO bound. Used to avoid uneeded buffer binding. */
+ GPUUniformBuffer *ubo_mat;
+ GPUUniformBuffer *ubo_lights;
+ /* Last texture bound. */
+ GPUTexture *tex_fill;
+ GPUTexture *tex_stroke;
+ /* Offset in the material pool to the first material of this object. */
+ int mat_ofs;
+ /* Is the sbuffer call need to be issued. */
+ int do_sbuffer_call;
+ /* Indices to do correct insertion of the sbuffer stroke. */
+ int stroke_index_last;
+ int stroke_index_offset;
+ /* Infos for call batching. */
+ struct GPUBatch *geom;
+ bool instancing;
+ int vfirst, vcount;
+} gpIterPopulateData;
+
+#define DISABLE_BATCHING 0
+
+static void gp_drawcall_flush(gpIterPopulateData *iter)
{
- stl->storage->is_main_overlay = false;
- stl->storage->is_main_onion = false;
- /* Check if main onion switch is enabled in any screen. */
- Main *bmain = CTX_data_main(draw_ctx->evil_C);
-
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- if (v3d == NULL) {
- continue;
- }
- if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
- stl->storage->is_main_overlay = true;
- }
- if (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) {
- stl->storage->is_main_onion = true;
- }
- }
- /* If found, don't need loop more. */
- if ((stl->storage->is_main_overlay) && (stl->storage->is_main_onion)) {
- return;
- }
+#if !DISABLE_BATCHING
+ if (iter->geom != NULL) {
+ if (iter->instancing) {
+ DRW_shgroup_call_instance_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount);
+ }
+ else {
+ DRW_shgroup_call_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount);
}
}
+#endif
+
+ iter->geom = NULL;
+ iter->vfirst = -1;
+ iter->vcount = 0;
}
-void GPENCIL_cache_init(void *vedata)
+/* Group drawcalls that are consecutive and with the same type. Reduces GPU driver overhead. */
+static void gp_drawcall_add(
+ gpIterPopulateData *iter, struct GPUBatch *geom, bool instancing, int v_first, int v_count)
{
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ToolSettings *ts = scene->toolsettings;
- View3D *v3d = draw_ctx->v3d;
- Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
- const View3DCursor *cursor = &scene->cursor;
-
- /* Special handling for when active object is GP object (e.g. for draw mode) */
- Object *obact = draw_ctx->obact;
- bGPdata *obact_gpd = NULL;
- MaterialGPencilStyle *gp_style = NULL;
-
- if (obact && (obact->type == OB_GPENCIL) && (obact->data)) {
- obact_gpd = (bGPdata *)obact->data;
- /* use the brush material */
- Material *ma = BKE_gpencil_object_material_get_from_brush(obact, brush);
- if (ma != NULL) {
- gp_style = ma->gp_style;
- }
- /* this is not common, but avoid any special situations when brush could be without material */
- if (gp_style == NULL) {
- gp_style = BKE_gpencil_material_settings(obact, obact->actcol);
- }
+#if DISABLE_BATCHING
+ if (instancing) {
+ DRW_shgroup_call_instance_range(iter->grp, iter->ob, geom, v_first, v_count);
}
+ else {
+ DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count);
+ }
+#endif
- if (!stl->g_data) {
- /* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
- stl->storage->xray = GP_XRAY_FRONT; /* used for drawing */
- stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID; /* used for drawing */
+ int last = iter->vfirst + iter->vcount;
+ /* Interupt drawcall grouping if the sequence is not consecutive. */
+ if ((geom != iter->geom) || (v_first - last > 3)) {
+ gp_drawcall_flush(iter);
+ }
+ iter->geom = geom;
+ iter->instancing = instancing;
+ if (iter->vfirst == -1) {
+ iter->vfirst = v_first;
}
- stl->storage->tonemapping = 0;
+ iter->vcount = v_first + v_count - iter->vfirst;
+}
- stl->g_data->shgrps_edit_line = NULL;
- stl->g_data->shgrps_edit_point = NULL;
+static void gp_stroke_cache_populate(bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, void *thunk);
- /* reset textures */
- stl->g_data->batch_buffer_stroke = NULL;
- stl->g_data->batch_buffer_fill = NULL;
- stl->g_data->batch_buffer_ctrlpoint = NULL;
- stl->g_data->batch_grid = NULL;
+static void gp_sbuffer_cache_populate(gpIterPopulateData *iter)
+{
+ iter->do_sbuffer_call = DRAW_NOW;
+ /* In order to draw the sbuffer stroke correctly mixed with other strokes,
+ * we need to offset the stroke index of the sbuffer stroke and the subsequent strokes.
+ * Remember, sbuffer stroke indices start from 0. So we add last index to avoid
+ * masking issues. */
+ iter->grp = DRW_shgroup_create_sub(iter->grp);
+ DRW_shgroup_uniform_block(iter->grp, "gpMaterialBlock", iter->ubo_mat);
+ DRW_shgroup_uniform_float_copy(iter->grp, "strokeIndexOffset", iter->stroke_index_last);
+
+ const DRWContextState *ctx = DRW_context_state_get();
+ ToolSettings *ts = ctx->scene->toolsettings;
+ if (ts->gpencil_v3d_align & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)) {
+ /* In this case we can't do correct projection during stroke. We just disable depth test. */
+ DRW_shgroup_uniform_texture(iter->grp, "gpSceneDepthTexture", iter->pd->dummy_tx);
+ }
+
+ gp_stroke_cache_populate(NULL, NULL, iter->pd->sbuffer_stroke, iter);
+ gp_drawcall_flush(iter);
+
+ iter->stroke_index_offset = iter->pd->sbuffer_stroke->totpoints + 1;
+ iter->do_sbuffer_call = 0;
+}
- if (!stl->shgroups) {
- /* Alloc maximum size because count strokes is very slow and can be very complex due onion
- * skinning.
- */
- stl->shgroups = MEM_mallocN(sizeof(GPENCIL_shgroup) * GPENCIL_MAX_SHGROUPS, "GPENCIL_shgroup");
+static void gp_layer_cache_populate(bGPDlayer *gpl,
+ bGPDframe *gpf,
+ bGPDstroke *UNUSED(gps),
+ void *thunk)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
+ gpIterPopulateData *iter = (gpIterPopulateData *)thunk;
+ bGPdata *gpd = (bGPdata *)iter->ob->data;
+
+ gp_drawcall_flush(iter);
+
+ if (iter->do_sbuffer_call) {
+ gp_sbuffer_cache_populate(iter);
+ }
+ else {
+ iter->do_sbuffer_call = !iter->pd->do_fast_drawing && (gpd == iter->pd->sbuffer_gpd) &&
+ (gpl == iter->pd->sbuffer_layer);
+ }
+
+ GPENCIL_tLayer *tgp_layer_prev = iter->tgp_ob->layers.last;
+ GPENCIL_tLayer *tgp_layer = gpencil_layer_cache_add(iter->pd, iter->ob, gpl);
+ BLI_LINKS_APPEND(&iter->tgp_ob->layers, tgp_layer);
+
+ if (tgp_layer->is_masked && (tgp_layer_prev == NULL || !tgp_layer_prev->is_masked)) {
+ tgp_layer->do_masked_clear = true;
+ }
+
+ gpencil_material_resources_get(iter->matpool, 0, NULL, NULL, &iter->ubo_mat);
+
+ const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D) || iter->pd->draw_depth_only;
+ const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
+
+ float object_scale = mat4_to_scale(iter->ob->obmat);
+ /* 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);
+
+ const bool use_lights = iter->pd->use_lighting && ((gpl->flag & GP_LAYER_USE_LIGHTS) != 0) &&
+ (iter->ob->dtx & OB_USE_GPENCIL_LIGHTS);
+ iter->ubo_lights = (use_lights) ? iter->pd->global_light_pool->ubo :
+ iter->pd->shadeless_light_pool->ubo;
+ const bool is_in_front = (iter->ob->dtx & OB_DRAWXRAY);
+
+ bool overide_vertcol = (iter->pd->v3d_color_type != -1);
+ bool is_vert_col_mode = (iter->pd->v3d_color_type == V3D_SHADING_VERTEX_COLOR) ||
+ GPENCIL_VERTEX_MODE(gpd) || iter->pd->is_render;
+ float vert_col_opacity = (overide_vertcol) ? (is_vert_col_mode ? 1.0f : 0.0f) :
+ gpl->vertex_paint_opacity;
+
+ /* Check if object is defined in front. */
+ GPUTexture *depth_tex = (is_in_front) ? iter->pd->dummy_tx : iter->pd->scene_depth_tx;
+
+ struct GPUShader *sh = GPENCIL_shader_geometry_get();
+ iter->grp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
+ DRW_shgroup_uniform_block_persistent(iter->grp, "gpLightBlock", iter->ubo_lights);
+ DRW_shgroup_uniform_block(iter->grp, "gpMaterialBlock", iter->ubo_mat);
+ DRW_shgroup_uniform_texture(iter->grp, "gpFillTexture", iter->tex_fill);
+ DRW_shgroup_uniform_texture(iter->grp, "gpStrokeTexture", iter->tex_stroke);
+ DRW_shgroup_uniform_texture(iter->grp, "gpSceneDepthTexture", depth_tex);
+ DRW_shgroup_uniform_int_copy(iter->grp, "gpMaterialOffset", iter->mat_ofs);
+ DRW_shgroup_uniform_bool_copy(iter->grp, "strokeOrder3d", is_stroke_order_3d);
+ DRW_shgroup_uniform_vec3_copy(iter->grp, "gpNormal", iter->tgp_ob->plane_normal);
+ DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewportInv", DRW_viewport_invert_size_get());
+ DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewport", DRW_viewport_size_get());
+ DRW_shgroup_uniform_float_copy(iter->grp, "thicknessScale", object_scale);
+ DRW_shgroup_uniform_float_copy(iter->grp, "thicknessOffset", (float)gpl->line_change);
+ DRW_shgroup_uniform_float_copy(iter->grp, "thicknessWorldScale", thickness_scale);
+ DRW_shgroup_uniform_float_copy(iter->grp, "vertexColorOpacity", vert_col_opacity);
+ DRW_shgroup_uniform_float_copy(iter->grp, "strokeIndexOffset", iter->stroke_index_offset);
+ DRW_shgroup_stencil_mask(iter->grp, 0xFF);
+
+ bool use_onion = gpf && 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;
+ float *onion_col_custom = (use_next_col) ? gpd->gcolor_next : gpd->gcolor_prev;
+ onion_col_custom = (use_onion_custom_col) ? onion_col_custom : U.gpencil_new_layer_col;
+ float onion_col[4] = {UNPACK3(onion_col_custom), 1.0f};
+ float onion_alpha = use_onion_fade ? (1.0f / abs(gpf->runtime.onion_id)) : 0.5f;
+ onion_alpha += (gpd->onion_factor * 2.0f - 1.0f);
+ onion_alpha = clamp_f(onion_alpha, 0.01f, 1.0f);
+
+ DRW_shgroup_uniform_vec4_copy(iter->grp, "layerTint", onion_col);
+ DRW_shgroup_uniform_float_copy(iter->grp, "layerOpacity", onion_alpha);
+ }
+ else {
+ float alpha = GPENCIL_SIMPLIFY_TINT(scene) ? 0.0f : gpl->tintcolor[3];
+ float tintcolor[4] = {gpl->tintcolor[0], gpl->tintcolor[1], gpl->tintcolor[2], alpha};
+ DRW_shgroup_uniform_vec4_copy(iter->grp, "layerTint", tintcolor);
+ DRW_shgroup_uniform_float_copy(iter->grp, "layerOpacity", 1.0f);
}
+}
- /* init gp objects cache */
- stl->g_data->gp_cache_used = 0;
- stl->g_data->gp_cache_size = 0;
- stl->g_data->gp_object_cache = NULL;
- stl->g_data->do_instances = false;
+static void gp_stroke_cache_populate(bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, void *thunk)
+{
+ gpIterPopulateData *iter = (gpIterPopulateData *)thunk;
- {
- /* Stroke pass 2D */
- psl->stroke_pass_2d = DRW_pass_create("GPencil Stroke Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
- stl->storage->shgroup_id = 0;
- /* Stroke pass 3D */
- psl->stroke_pass_3d = DRW_pass_create("GPencil Stroke Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
- stl->storage->shgroup_id = 0;
-
- /* edit pass */
- psl->edit_pass = DRW_pass_create("GPencil Edit Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
-
- /* detect if playing animation */
- if (draw_ctx->evil_C) {
-
- bool playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL;
- if (playing != stl->storage->is_playing) {
- stl->storage->reset_cache = true;
- }
- stl->storage->is_playing = playing;
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(iter->ob, gps->mat_nr + 1);
- /* Found if main overlay and onion switches are enabled in any screen. */
- gpencil_check_screen_switches(draw_ctx, stl);
- }
- else {
- stl->storage->is_playing = false;
- stl->storage->reset_cache = false;
- stl->storage->is_main_overlay = false;
- stl->storage->is_main_onion = false;
- }
- /* save render state */
- stl->storage->is_render = DRW_state_is_scene_render();
- stl->storage->is_mat_preview = (bool)stl->storage->is_render &&
- STREQ(scene->id.name + 2, "preview");
-
- if (obact_gpd) {
- /* for some reason, when press play there is a delay in the animation flag check
- * and this produces errors. To be sure, we set cache as dirty because the frame
- * is changing.
- */
- if (stl->storage->is_playing == true) {
- obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
- /* if render, set as dirty to update all data */
- else if (stl->storage->is_render == true) {
- obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
- }
+ bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
+ bool show_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0;
+ bool show_fill = (gps->tot_triangles > 0) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0) &&
+ (!iter->pd->simplify_fill);
- /* save simplify flags (can change while drawing, so it's better to save) */
- stl->storage->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, stl->storage->is_playing);
- stl->storage->simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
- stl->storage->simplify_fx = GPENCIL_SIMPLIFY_FX(scene, stl->storage->is_playing);
- stl->storage->simplify_blend = GPENCIL_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
+ bool only_lines = gpl && gpf && gpl->actframe != gpf && iter->pd->use_multiedit_lines_only;
- /* xray mode */
- if (v3d) {
- stl->storage->is_xray = XRAY_ACTIVE(v3d);
- }
- else {
- stl->storage->is_xray = 0;
- }
+ if (hide_material || (!show_stroke && !show_fill) || only_lines) {
+ return;
+ }
- /* Save pixsize. */
- stl->storage->pixsize = DRW_viewport_pixelsize_get();
- if ((!DRW_state_is_opengl_render()) && (stl->storage->is_render)) {
- stl->storage->pixsize = &stl->storage->render_pixsize;
- }
+ GPUUniformBuffer *ubo_mat;
+ GPUTexture *tex_stroke, *tex_fill;
+ gpencil_material_resources_get(iter->matpool, gps->mat_nr, &tex_stroke, &tex_fill, &ubo_mat);
- /* Detect if painting session. */
- if ((obact_gpd) && (obact_gpd->flag & GP_DATA_STROKE_PAINTMODE) &&
- (stl->storage->is_playing == false)) {
- /* Need the original to avoid cow overhead while drawing. */
- bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&obact_gpd->id);
- if (((gpd_orig->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) &&
- (gpd_orig->runtime.sbuffer_used > 0) && (!DRW_state_is_depth()) &&
- (stl->storage->background_ready == true)) {
- stl->g_data->session_flag |= GP_DRW_PAINT_PAINTING;
- }
- else {
- stl->g_data->session_flag = GP_DRW_PAINT_IDLE;
- }
- }
- else {
- /* if not drawing mode */
- stl->g_data->session_flag = GP_DRW_PAINT_HOLD;
- }
+ bool resource_changed = (iter->ubo_mat != ubo_mat) ||
+ (tex_fill && (iter->tex_fill != tex_fill)) ||
+ (tex_stroke && (iter->tex_stroke != tex_stroke));
- if (gp_style) {
- stl->storage->stroke_style = gp_style->stroke_style;
- stl->storage->color_type = GPENCIL_COLOR_SOLID;
- if (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) {
- stl->storage->color_type = GPENCIL_COLOR_TEXTURE;
- if (gp_style->flag & GP_STYLE_STROKE_PATTERN) {
- stl->storage->color_type = GPENCIL_COLOR_PATTERN;
- }
- }
+ if (resource_changed) {
+ gp_drawcall_flush(iter);
+
+ iter->grp = DRW_shgroup_create_sub(iter->grp);
+ if (iter->ubo_mat != ubo_mat) {
+ DRW_shgroup_uniform_block(iter->grp, "gpMaterialBlock", ubo_mat);
+ iter->ubo_mat = ubo_mat;
}
- else {
- stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID;
- stl->storage->color_type = GPENCIL_COLOR_SOLID;
+ if (tex_fill) {
+ DRW_shgroup_uniform_texture(iter->grp, "gpFillTexture", tex_fill);
+ iter->tex_fill = tex_fill;
}
-
- /* drawing buffer pass for drawing the stroke that is being drawing by the user. The data
- * is stored in sbuffer
- */
- psl->drawing_pass = DRW_pass_create("GPencil Drawing Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_NEQUAL);
-
- /* full screen pass to combine the result with default framebuffer */
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
- psl->mix_pass = DRW_pass_create("GPencil Mix Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
- DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass);
- DRW_shgroup_call(mix_shgrp, quad, NULL);
- DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeColor", &stl->g_data->input_color_tx);
- DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeDepth", &stl->g_data->input_depth_tx);
- DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1);
- DRW_shgroup_uniform_int(mix_shgrp, "do_select", &stl->storage->do_select_outline, 1);
- DRW_shgroup_uniform_vec4(mix_shgrp, "select_color", stl->storage->select_color, 1);
-
- /* Mix pass no blend used to copy between passes. A separated pass is required
- * because if mix_pass is used, the accumulation of blend degrade the colors.
- *
- * This pass is used too to take the snapshot used for background_pass. This image
- * will be used as the background while the user is drawing.
- */
- psl->mix_pass_noblend = DRW_pass_create("GPencil Mix Pass no blend",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS);
- DRWShadingGroup *mix_shgrp_noblend = DRW_shgroup_create(e_data.gpencil_fullscreen_sh,
- psl->mix_pass_noblend);
- DRW_shgroup_call(mix_shgrp_noblend, quad, NULL);
- DRW_shgroup_uniform_texture_ref(
- mix_shgrp_noblend, "strokeColor", &stl->g_data->input_color_tx);
- DRW_shgroup_uniform_texture_ref(
- mix_shgrp_noblend, "strokeDepth", &stl->g_data->input_depth_tx);
- DRW_shgroup_uniform_int(mix_shgrp_noblend, "tonemapping", &stl->storage->tonemapping, 1);
- DRW_shgroup_uniform_int(mix_shgrp_noblend, "do_select", &stl->storage->do_select_outline, 1);
- DRW_shgroup_uniform_vec4(mix_shgrp_noblend, "select_color", stl->storage->select_color, 1);
-
- /* Painting session pass (used only to speedup while the user is drawing )
- * This pass is used to show the snapshot of the current grease pencil strokes captured
- * when the user starts to draw (see comments above).
- * In this way, the previous strokes don't need to be redraw and the drawing process
- * is far to agile.
- */
- psl->background_pass = DRW_pass_create("GPencil Background Painting Session Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
- DRWShadingGroup *background_shgrp = DRW_shgroup_create(e_data.gpencil_background_sh,
- psl->background_pass);
- DRW_shgroup_call(background_shgrp, quad, NULL);
- DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeColor", &txl->background_color_tx);
- DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeDepth", &txl->background_depth_tx);
-
- /* pass for drawing paper (only if viewport)
- * In render, the v3d is null so the paper is disabled
- * The paper is way to isolate the drawing in complex scene and to have a cleaner
- * drawing area.
- */
- if (v3d) {
- psl->paper_pass = DRW_pass_create("GPencil Paper Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
- DRWShadingGroup *paper_shgrp = DRW_shgroup_create(e_data.gpencil_paper_sh, psl->paper_pass);
- DRW_shgroup_call(paper_shgrp, quad, NULL);
- DRW_shgroup_uniform_vec3(paper_shgrp, "color", v3d->shading.background_color, 1);
- DRW_shgroup_uniform_float(paper_shgrp, "opacity", &v3d->overlay.gpencil_paper_opacity, 1);
+ if (tex_stroke) {
+ DRW_shgroup_uniform_texture(iter->grp, "gpStrokeTexture", tex_stroke);
+ iter->tex_stroke = tex_stroke;
}
+ }
- /* grid pass */
- if ((v3d) && (obact) && (obact->type == OB_GPENCIL)) {
- psl->grid_pass = DRW_pass_create("GPencil Grid Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
- stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass);
-
- /* define grid orientation */
- switch (ts->gp_sculpt.lock_axis) {
- case GP_LOCKAXIS_VIEW: {
- /* align always to view */
- invert_m4_m4(stl->storage->grid_matrix, draw_ctx->rv3d->viewmat);
- /* copy ob location */
- copy_v3_v3(stl->storage->grid_matrix[3], obact->obmat[3]);
- break;
- }
- case GP_LOCKAXIS_CURSOR: {
- float scale[3] = {1.0f, 1.0f, 1.0f};
- loc_eul_size_to_mat4(
- stl->storage->grid_matrix, cursor->location, cursor->rotation_euler, scale);
- break;
- }
- default: {
- copy_m4_m4(stl->storage->grid_matrix, obact->obmat);
- break;
- }
- }
+ bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW);
- /* Move the origin to Object or Cursor */
- if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
- copy_v3_v3(stl->storage->grid_matrix[3], cursor->location);
- }
- else {
- copy_v3_v3(stl->storage->grid_matrix[3], obact->obmat[3]);
- }
- DRW_shgroup_uniform_mat4(
- stl->g_data->shgrps_grid, "gpModelMatrix", stl->storage->grid_matrix);
- }
+ if (show_fill) {
+ GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_fill_get(iter->ob) :
+ DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra);
+ int vfirst = gps->runtime.fill_start * 3;
+ int vcount = gps->tot_triangles * 3;
+ gp_drawcall_add(iter, geom, false, vfirst, vcount);
+ }
- /* blend layers pass */
- psl->blend_pass = DRW_pass_create("GPencil Blend Layers Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
- DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh,
- psl->blend_pass);
- DRW_shgroup_call(blend_shgrp, quad, NULL);
- DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &stl->g_data->temp_depth_tx_fx);
- DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1);
- DRW_shgroup_uniform_int(blend_shgrp, "mask_layer", &stl->storage->mask_layer, 1);
- DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1);
-
- /* create effects passes */
- if (!stl->storage->simplify_fx) {
- GPENCIL_create_fx_passes(psl);
- }
+ if (show_stroke) {
+ GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_stroke_get(iter->ob) :
+ DRW_cache_gpencil_strokes_get(iter->ob, iter->pd->cfra);
+ /* Start one vert before to have gl_InstanceID > 0 (see shader). */
+ int vfirst = gps->runtime.stroke_start - 1;
+ /* Include "potential" cyclic vertex and start adj vertex (see shader). */
+ int vcount = gps->totpoints + 1 + 1;
+ gp_drawcall_add(iter, geom, true, vfirst, vcount);
}
+
+ iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1;
}
-static void gpencil_add_draw_data(void *vedata, Object *ob)
+static void gp_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter)
{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const View3D *v3d = draw_ctx->v3d;
+ bGPdata *gpd = (bGPdata *)iter->ob->data;
+ if (gpd != iter->pd->sbuffer_gpd) {
+ return;
+ }
- int i = stl->g_data->gp_cache_used - 1;
- tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
+ GPENCIL_TextureList *txl = vedata->txl;
+ GPUTexture *depth_texture = iter->pd->scene_depth_tx;
+ GPENCIL_tObject *last_tgp_ob = iter->pd->tobjects.last;
+ /* Create another temp object that only contain the stroke. */
+ iter->tgp_ob = gpencil_object_cache_add(iter->pd, iter->ob);
+ /* Remove from the main list. */
+ iter->pd->tobjects.last = last_tgp_ob;
+ last_tgp_ob->next = NULL;
+ /* Add to sbuffer tgpobject list. */
+ BLI_LINKS_APPEND(&iter->pd->sbuffer_tobjects, iter->tgp_ob);
+ /* Remove depth test with scene (avoid self occlusion). */
+ iter->pd->scene_depth_tx = txl->dummy_texture;
- if (!cache_ob->is_dup_ob) {
- /* fill shading groups */
- if ((!is_multiedit) || (stl->storage->is_render)) {
- gpencil_populate_datablock(&e_data, vedata, ob, cache_ob);
- }
- else {
- gpencil_populate_multiedit(&e_data, vedata, ob, cache_ob);
- }
- }
+ gp_layer_cache_populate(iter->pd->sbuffer_layer, iter->pd->sbuffer_layer->actframe, NULL, iter);
- /* FX passses */
- cache_ob->has_fx = false;
- if ((!stl->storage->simplify_fx) &&
- ((!ELEM(cache_ob->shading_type[0], OB_WIRE, OB_SOLID)) ||
- ((v3d->spacetype != SPACE_VIEW3D))) &&
- (BKE_shaderfx_has_gpencil(ob))) {
- cache_ob->has_fx = true;
- if ((!stl->storage->simplify_fx) && (!is_multiedit)) {
- gpencil_fx_prepare(&e_data, vedata, cache_ob);
- }
+ const DRWContextState *ctx = DRW_context_state_get();
+ ToolSettings *ts = ctx->scene->toolsettings;
+ if (ts->gpencil_v3d_align & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)) {
+ /* In this case we can't do correct projection during stroke. We just disable depth test. */
+ DRW_shgroup_uniform_texture(iter->grp, "gpSceneDepthTexture", iter->pd->dummy_tx);
}
+
+ iter->do_sbuffer_call = DRAW_NOW;
+ gp_stroke_cache_populate(NULL, NULL, iter->pd->sbuffer_stroke, iter);
+ gp_drawcall_flush(iter);
+
+ gpencil_vfx_cache_populate(vedata, iter->ob, iter->tgp_ob);
+
+ /* Restore state. */
+ iter->do_sbuffer_call = 0;
+ iter->pd->scene_depth_tx = depth_texture;
}
-void GPENCIL_cache_populate(void *vedata, Object *ob)
+void GPENCIL_cache_populate(void *ved, Object *ob)
{
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ GPENCIL_TextureList *txl = vedata->txl;
+
/* object must be visible */
if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
return;
}
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- ToolSettings *ts = scene->toolsettings;
- View3D *v3d = draw_ctx->v3d;
+ if (ob->data && (ob->type == OB_GPENCIL) && (ob->dt >= OB_SOLID)) {
+ gpIterPopulateData iter = {0};
+ iter.ob = ob;
+ iter.pd = pd;
+ iter.tgp_ob = gpencil_object_cache_add(pd, ob);
+ iter.matpool = gpencil_material_pool_create(pd, ob, &iter.mat_ofs);
+ iter.tex_fill = txl->dummy_texture;
+ iter.tex_stroke = txl->dummy_texture;
- if (ob->type == OB_GPENCIL && ob->data) {
+ /* Specil case for rendering onion skin. */
bGPdata *gpd = (bGPdata *)ob->data;
+ bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
- /* enable multisample and basic framebuffer creation */
- stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_MULTISAMPLE;
- stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_BASIC;
+ BKE_gpencil_visible_stroke_iter(
+ ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, do_onion, pd->cfra);
- /* when start/stop animation the cache must be set as dirty to reset all data */
- if (stl->storage->reset_cache) {
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- stl->storage->reset_cache = false;
- }
-
- if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) {
- /* bound box object are not visible, only external box*/
- if (ob->dt != OB_BOUNDBOX) {
- /* save gp objects for drawing later */
- stl->g_data->gp_object_cache = gpencil_object_cache_add(stl->g_data->gp_object_cache,
- ob,
- &stl->g_data->gp_cache_size,
- &stl->g_data->gp_cache_used);
-
- /* enable instance loop */
- if (!stl->g_data->do_instances) {
- tGPencilObjectCache *cache_ob =
- &stl->g_data->gp_object_cache[stl->g_data->gp_cache_used - 1];
- stl->g_data->do_instances = cache_ob->is_dup_ob;
- }
-
- /* load drawing data */
- gpencil_add_draw_data(vedata, ob);
- }
- }
+ gp_drawcall_flush(&iter);
- /* draw current painting strokes
- * (only if region is equal to originated paint region)
- *
- * Need to use original data because to use the copy of data, the paint
- * operator must update depsgraph and this makes that first events of the
- * mouse are missed if the datablock is very big due the time required to
- * copy the datablock. The search of the original data is faster than a
- * full datablock copy.
- * Using the original data doesn't require a copy and the feel when drawing
- * is far better.
- */
-
- bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
- if ((draw_ctx->obact == ob) &&
- ((gpd_orig->runtime.ar == NULL) || (gpd_orig->runtime.ar == draw_ctx->ar))) {
- gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob);
+ if (iter.do_sbuffer_call) {
+ gp_sbuffer_cache_populate(&iter);
}
- /* grid */
- if ((v3d) && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_GRID) &&
- (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact) &&
- ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0) &&
- ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) == 0)) {
+ gpencil_vfx_cache_populate(vedata, ob, iter.tgp_ob);
- stl->g_data->batch_grid = gpencil_get_grid(ob);
- DRW_shgroup_call(stl->g_data->shgrps_grid, stl->g_data->batch_grid, NULL);
+ if (pd->do_fast_drawing) {
+ gp_sbuffer_cache_populate_fast(vedata, &iter);
}
}
+
+ if (ob->type == OB_LAMP && pd->use_lights) {
+ gpencil_light_pool_populate(pd->global_light_pool, ob);
+ }
}
-void GPENCIL_cache_finish(void *vedata)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- tGPencilObjectCache *cache_ob = NULL;
- Object *ob = NULL;
-
- /* create data for instances */
- if (stl->g_data->do_instances) {
- GHash *gh_objects = BLI_ghash_str_new(__func__);
- /* create hash of real object (non duplicated) */
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- cache_ob = &stl->g_data->gp_object_cache[i];
- if (!cache_ob->is_dup_ob) {
- ob = cache_ob->ob;
- char *name = BKE_id_to_unique_string_key(&ob->id);
- BLI_ghash_insert(gh_objects, name, cache_ob->ob);
- }
- }
+#define SORT_IMPL_LINKTYPE GPENCIL_tObject
- /* draw particles */
- gpencil_populate_particles(&e_data, gh_objects, vedata);
+#define SORT_IMPL_FUNC gpencil_tobject_sort_fn_r
+#include "../../blenlib/intern/list_sort_impl.h"
+#undef SORT_IMPL_FUNC
- /* free hash */
- BLI_ghash_free(gh_objects, MEM_freeN, NULL);
- }
+#undef SORT_IMPL_LINKTYPE
- if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) {
- stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_DRAW;
+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;
}
-
- /* create framebuffers (only for normal drawing) */
- if (!DRW_state_is_select() || !DRW_state_is_depth()) {
- GPENCIL_create_framebuffers(vedata);
+ else if (ob_a->camera_z < ob_b->camera_z) {
+ return -1;
+ }
+ else {
+ return 0;
}
}
-/* helper function to sort inverse gpencil objects using qsort */
-static int gpencil_object_cache_compare_zdepth(const void *a1, const void *a2)
+void GPENCIL_cache_finish(void *ved)
{
- const tGPencilObjectCache *ps1 = a1, *ps2 = a2;
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
- if (ps1->zdepth < ps2->zdepth) {
- return 1;
- }
- else if (ps1->zdepth > ps2->zdepth) {
- return -1;
+ /* Upload UBO data. */
+ BLI_memblock_iter iter;
+ BLI_memblock_iternew(pd->gp_material_pool, &iter);
+ GPENCIL_MaterialPool *pool;
+ while ((pool = (GPENCIL_MaterialPool *)BLI_memblock_iterstep(&iter))) {
+ GPU_uniformbuffer_update(pool->ubo, pool->mat_data);
}
- return 0;
-}
+ BLI_memblock_iternew(pd->gp_light_pool, &iter);
+ GPENCIL_LightPool *lpool;
+ while ((lpool = (GPENCIL_LightPool *)BLI_memblock_iterstep(&iter))) {
+ GPU_uniformbuffer_update(lpool->ubo, lpool->light_data);
+ }
-/* prepare a texture with full viewport screenshot for fast drawing */
-static void gpencil_prepare_fast_drawing(GPENCIL_StorageList *stl,
- DefaultFramebufferList *dfbl,
- GPENCIL_FramebufferList *fbl,
- DRWPass *pass,
- const float clearcol[4])
-{
- if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) {
- GPU_framebuffer_bind(fbl->background_fb);
- /* clean only in first loop cycle */
- if (stl->g_data->session_flag & GP_DRW_PAINT_IDLE) {
- GPU_framebuffer_clear_color_depth_stencil(fbl->background_fb, clearcol, 1.0f, 0x0);
- stl->g_data->session_flag = GP_DRW_PAINT_FILLING;
+ /* 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 != NULL)) {
+ pd->tobjects.last = pd->tobjects.last->next;
}
- /* repeat pass to fill temp texture */
- DRW_draw_pass(pass);
- /* set default framebuffer again */
- GPU_framebuffer_bind(dfbl->default_fb);
+ }
+ 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 != NULL)) {
+ pd->tobjects_infront.last = pd->tobjects_infront.last->next;
+ }
+ }
- stl->storage->background_ready = true;
+ /* 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;
+ }
}
-}
-void DRW_gpencil_free_runtime_data(void *ved)
-{
- GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ /* Create framebuffers only if needed. */
+ if (pd->tobjects.first) {
+ eGPUTextureFormat format = pd->use_signed_fb ? GPU_RGBA16F : GPU_R11F_G11F_B10F;
+
+ const float *size = DRW_viewport_size_get();
+ pd->depth_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_gpencil_type);
+ pd->color_tx = DRW_texture_pool_query_2d(size[0], size[1], format, &draw_engine_gpencil_type);
+ pd->reveal_tx = DRW_texture_pool_query_2d(size[0], size[1], format, &draw_engine_gpencil_type);
- /* free gpu data */
- GPU_BATCH_DISCARD_SAFE(stl->g_data->batch_buffer_stroke);
- MEM_SAFE_FREE(stl->g_data->batch_buffer_stroke);
+ GPU_framebuffer_ensure_config(&fbl->gpencil_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->color_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->reveal_tx),
+ });
- GPU_BATCH_DISCARD_SAFE(stl->g_data->batch_buffer_fill);
- MEM_SAFE_FREE(stl->g_data->batch_buffer_fill);
+ if (pd->use_layer_fb) {
+ pd->color_layer_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], format, &draw_engine_gpencil_type);
+ pd->reveal_layer_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], format, &draw_engine_gpencil_type);
- GPU_BATCH_DISCARD_SAFE(stl->g_data->batch_buffer_ctrlpoint);
- MEM_SAFE_FREE(stl->g_data->batch_buffer_ctrlpoint);
+ GPU_framebuffer_ensure_config(&fbl->layer_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->color_layer_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->reveal_layer_tx),
+ });
+ };
- GPU_BATCH_DISCARD_SAFE(stl->g_data->batch_grid);
- MEM_SAFE_FREE(stl->g_data->batch_grid);
+ if (pd->use_object_fb) {
+ pd->color_object_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], format, &draw_engine_gpencil_type);
+ pd->reveal_object_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], format, &draw_engine_gpencil_type);
- if (stl->g_data->gp_object_cache == NULL) {
- return;
- }
+ GPU_framebuffer_ensure_config(&fbl->object_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->color_object_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->reveal_object_tx),
+ });
+ }
+
+ if (pd->use_mask_fb) {
+ /* We need to separate all the masked layer together in order to correctly mix them. */
+ pd->color_masked_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], format, &draw_engine_gpencil_type);
+ pd->reveal_masked_tx = DRW_texture_pool_query_2d(
+ size[0], size[1], format, &draw_engine_gpencil_type);
- /* reset all cache flags */
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
- if (cache_ob) {
- bGPdata *gpd = cache_ob->gpd;
- gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
+ GPU_framebuffer_ensure_config(&fbl->masked_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(pd->depth_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->color_masked_tx),
+ GPU_ATTACHMENT_TEXTURE(pd->reveal_masked_tx),
+ });
+ }
- /* free shgrp array */
- cache_ob->tot_layers = 0;
- MEM_SAFE_FREE(cache_ob->name);
- MEM_SAFE_FREE(cache_ob->shgrp_array);
+ if (!pd->simplify_antialias) {
+ GPENCIL_antialiasing_init(vedata);
}
}
-
- /* free the cache itself */
- MEM_SAFE_FREE(stl->g_data->gp_object_cache);
}
-static void gpencil_draw_pass_range(GPENCIL_FramebufferList *fbl,
- GPENCIL_StorageList *stl,
- GPENCIL_PassList *psl,
- GPENCIL_TextureList *txl,
- GPUFrameBuffer *fb,
- Object *ob,
- bGPdata *gpd,
- DRWShadingGroup *init_shgrp,
- DRWShadingGroup *end_shgrp,
- bool multi)
+static void GPENCIL_draw_scene_depth_only(void *ved)
{
- if (init_shgrp == NULL) {
- return;
- }
-
- const bool do_antialiasing = ((!stl->storage->is_mat_preview) && (multi));
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- if (do_antialiasing) {
- MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(dfbl->depth_only_fb);
}
- DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d,
- init_shgrp,
- end_shgrp);
+ for (GPENCIL_tObject *ob = pd->tobjects.first; ob; ob = ob->next) {
+ for (GPENCIL_tLayer *layer = ob->layers.first; layer; layer = layer->next) {
+ DRW_draw_pass(layer->geom_ps);
+ }
+ }
- if (do_antialiasing) {
- MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl);
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(dfbl->default_fb);
}
-}
-/* draw strokes to use for selection */
-static void drw_gpencil_select_render(GPENCIL_StorageList *stl, GPENCIL_PassList *psl)
-{
- tGPencilObjectCache *cache_ob;
- tGPencilObjectCache_shgrp *array_elm = NULL;
- DRWShadingGroup *init_shgrp = NULL;
- DRWShadingGroup *end_shgrp = NULL;
-
- /* Draw all pending objects */
- if ((stl->g_data->gp_cache_used > 0) && (stl->g_data->gp_object_cache)) {
- /* sort by zdepth */
- qsort(stl->g_data->gp_object_cache,
- stl->g_data->gp_cache_used,
- sizeof(tGPencilObjectCache),
- gpencil_object_cache_compare_zdepth);
-
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- cache_ob = &stl->g_data->gp_object_cache[i];
- if (cache_ob) {
- Object *ob = cache_ob->ob;
- bGPdata *gpd = cache_ob->gpd;
- init_shgrp = NULL;
- if (cache_ob->tot_layers > 0) {
- for (int e = 0; e < cache_ob->tot_layers; e++) {
- array_elm = &cache_ob->shgrp_array[e];
- if (init_shgrp == NULL) {
- init_shgrp = array_elm->init_shgrp;
- }
- end_shgrp = array_elm->end_shgrp;
- }
- /* draw group */
- DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d :
- psl->stroke_pass_2d,
- init_shgrp,
- end_shgrp);
- }
- /* the cache must be dirty for next loop */
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
- }
+ pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = NULL;
+
+ /* Free temp stroke buffers. */
+ if (pd->sbuffer_gpd) {
+ DRW_cache_gpencil_sbuffer_clear(pd->obact);
}
}
-/* draw scene */
-void GPENCIL_draw_scene(void *ved)
+static void GPENCIL_draw_object(GPENCIL_Data *vedata, GPENCIL_tObject *ob)
{
- GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+ GPENCIL_PassList *psl = vedata->psl;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ float clear_cols[2][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}};
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
+ DRW_stats_group_start("GPencil Object");
- tGPencilObjectCache *cache_ob;
- tGPencilObjectCache_shgrp *array_elm = NULL;
- DRWShadingGroup *init_shgrp = NULL;
- DRWShadingGroup *end_shgrp = NULL;
+ GPUFrameBuffer *fb_object = (ob->vfx.first) ? fbl->object_fb : fbl->gpencil_fb;
- const float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_framebuffer_bind(fb_object);
+ GPU_framebuffer_clear_depth_stencil(fb_object, ob->is_drawmode3d ? 1.0f : 0.0f, 0x00);
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- Object *obact = draw_ctx->obact;
- const bool playing = stl->storage->is_playing;
- const bool is_render = stl->storage->is_render;
- bGPdata *gpd_act = (obact) && (obact->type == OB_GPENCIL) ? (bGPdata *)obact->data : NULL;
- const bool is_edit = (GPENCIL_ANY_EDIT_MODE(gpd_act) || GPENCIL_VERTEX_MODE(gpd_act));
- const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true;
-
- /* if the draw is for select, do a basic drawing and return */
- if (DRW_state_is_select() || DRW_state_is_depth()) {
- drw_gpencil_select_render(stl, psl);
- return;
+ if (ob->vfx.first) {
+ GPU_framebuffer_multi_clear(fb_object, clear_cols);
}
- /* paper pass to display a comfortable area to draw over complex scenes with geometry */
- if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
- if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_PAPER)) {
- DRW_draw_pass(psl->paper_pass);
+ for (GPENCIL_tLayer *layer = ob->layers.first; layer; layer = layer->next) {
+ if (layer->blend_ps) {
+ GPU_framebuffer_bind(fbl->layer_fb);
+ GPU_framebuffer_multi_clear(fbl->layer_fb, clear_cols);
+ }
+ else if (layer->is_masked) {
+ GPU_framebuffer_bind(fbl->masked_fb);
+ if (layer->do_masked_clear) {
+ GPU_framebuffer_multi_clear(fbl->masked_fb, clear_cols);
+ }
+ }
+ else {
+ GPU_framebuffer_bind(fb_object);
}
- }
- /* if we have a painting session, we use fast viewport drawing method */
- if ((!is_render) && (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING)) {
- GPU_framebuffer_bind(dfbl->default_fb);
+ DRW_draw_pass(layer->geom_ps);
- if (obact->dt != OB_BOUNDBOX) {
- DRW_draw_pass(psl->background_pass);
+ if (layer->blend_ps) {
+ if (layer->is_masked) {
+ GPU_framebuffer_bind(fbl->masked_fb);
+ if (layer->do_masked_clear) {
+ GPU_framebuffer_multi_clear(fbl->masked_fb, clear_cols);
+ }
+ }
+ else {
+ GPU_framebuffer_bind(fb_object);
+ }
+ DRW_draw_pass(layer->blend_ps);
}
+ }
- MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
+ for (GPENCIL_tVfx *vfx = ob->vfx.first; vfx; vfx = vfx->next) {
+ GPU_framebuffer_bind(*(vfx->target_fb));
+ DRW_draw_pass(vfx->vfx_ps);
+ }
- DRW_draw_pass(psl->drawing_pass);
+ copy_m4_m4(pd->object_bound_mat, ob->plane_mat);
+ pd->is_stroke_order_3d = ob->is_drawmode3d;
- MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, dfbl->default_fb, txl);
+ if (pd->scene_fb) {
+ GPU_framebuffer_bind(pd->scene_fb);
+ DRW_draw_pass(psl->merge_depth_ps);
+ }
- /* grid pass */
- if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
- if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_GRID)) {
- DRW_draw_pass(psl->grid_pass);
- }
- }
+ DRW_stats_group_end();
+}
- /* free memory */
- DRW_gpencil_free_runtime_data(ved);
+static void GPENCIL_fast_draw_start(GPENCIL_Data *vedata)
+{
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- return;
+ if (!pd->snapshot_buffer_dirty) {
+ /* Copy back cached render. */
+ GPU_framebuffer_blit(fbl->snapshot_fb, 0, dfbl->default_fb, 0, GPU_DEPTH_BIT);
+ GPU_framebuffer_blit(fbl->snapshot_fb, 0, fbl->gpencil_fb, 0, GPU_COLOR_BIT);
+ GPU_framebuffer_blit(fbl->snapshot_fb, 1, fbl->gpencil_fb, 1, GPU_COLOR_BIT);
+ /* Bypass drawing. */
+ pd->tobjects.first = pd->tobjects.last = NULL;
}
+}
- if (DRW_state_is_fbo()) {
+static void GPENCIL_fast_draw_end(GPENCIL_Data *vedata)
+{
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- /* Draw all pending objects */
- if (stl->g_data->gp_cache_used > 0) {
- /* sort by zdepth */
- qsort(stl->g_data->gp_object_cache,
- stl->g_data->gp_cache_used,
- sizeof(tGPencilObjectCache),
- gpencil_object_cache_compare_zdepth);
-
- for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
- cache_ob = &stl->g_data->gp_object_cache[i];
- Object *ob = cache_ob->ob;
- bGPdata *gpd = cache_ob->gpd;
- init_shgrp = NULL;
- /* Render stroke in separated framebuffer */
- GPU_framebuffer_bind(fbl->temp_fb_a);
- GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_a, clearcol, 1.0f, 0x0);
- /* Stroke Pass:
- * draw only a subset that usually starts with a fill and ends with stroke
- */
- bool use_blend = false;
- if (cache_ob->tot_layers > 0) {
- for (int e = 0; e < cache_ob->tot_layers; e++) {
- bool is_last = (e == cache_ob->tot_layers - 1) ? true : false;
- array_elm = &cache_ob->shgrp_array[e];
-
- if (((array_elm->mode == eGplBlendMode_Regular) && (!use_blend) &&
- (!array_elm->mask_layer)) ||
- (e == 0)) {
- if (init_shgrp == NULL) {
- init_shgrp = array_elm->init_shgrp;
- }
- end_shgrp = array_elm->end_shgrp;
- }
- else {
- use_blend = true;
- /* draw pending groups */
- gpencil_draw_pass_range(
- fbl, stl, psl, txl, fbl->temp_fb_a, ob, gpd, init_shgrp, end_shgrp, is_last);
-
- /* Draw current group in separated texture to blend later */
- init_shgrp = array_elm->init_shgrp;
- end_shgrp = array_elm->end_shgrp;
-
- GPU_framebuffer_bind(fbl->temp_fb_fx);
- GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_fx, clearcol, 1.0f, 0x0);
- gpencil_draw_pass_range(
- fbl, stl, psl, txl, fbl->temp_fb_fx, ob, gpd, init_shgrp, end_shgrp, is_last);
-
- /* Blend A texture and FX texture */
- GPU_framebuffer_bind(fbl->temp_fb_b);
- GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_b, clearcol, 1.0f, 0x0);
- stl->storage->blend_mode = array_elm->mode;
- stl->storage->mask_layer = (int)array_elm->mask_layer;
- stl->storage->tonemapping = DRW_state_do_color_management() ? 0 : 1;
- DRW_draw_pass(psl->blend_pass);
- stl->storage->tonemapping = 0;
-
- /* Copy B texture to A texture to follow loop */
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_b;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b;
-
- GPU_framebuffer_bind(fbl->temp_fb_a);
- GPU_framebuffer_clear_color_depth_stencil(fbl->temp_fb_a, clearcol, 1.0f, 0x0);
- DRW_draw_pass(psl->mix_pass_noblend);
-
- /* prepare next group */
- init_shgrp = NULL;
- }
- }
- /* last group */
- gpencil_draw_pass_range(
- fbl, stl, psl, txl, fbl->temp_fb_a, ob, gpd, init_shgrp, end_shgrp, true);
- }
+ if (pd->snapshot_buffer_dirty) {
+ /* Save to snapshot buffer. */
+ GPU_framebuffer_blit(dfbl->default_fb, 0, fbl->snapshot_fb, 0, GPU_DEPTH_BIT);
+ GPU_framebuffer_blit(fbl->gpencil_fb, 0, fbl->snapshot_fb, 0, GPU_COLOR_BIT);
+ GPU_framebuffer_blit(fbl->gpencil_fb, 1, fbl->snapshot_fb, 1, GPU_COLOR_BIT);
+ pd->snapshot_buffer_dirty = false;
+ }
+ /* Draw the sbuffer stroke(s). */
+ for (GPENCIL_tObject *ob = pd->sbuffer_tobjects.first; ob; ob = ob->next) {
+ GPENCIL_draw_object(vedata, ob);
+ }
+}
- /* Current buffer drawing */
- if ((!is_render) && (cache_ob->is_dup_ob == false)) {
- DRW_draw_pass(psl->drawing_pass);
- }
- /* fx passes */
- if (cache_ob->has_fx == true) {
- stl->storage->tonemapping = 0;
- gpencil_fx_draw(&e_data, vedata, cache_ob);
- }
+void GPENCIL_draw_scene(void *ved)
+{
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_PassList *psl = vedata->psl;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ float clear_cols[2][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}};
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_a;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_a;
+ /* Fade 3D objects. */
+ if ((!pd->is_render) && (pd->fade_3d_object_opacity > -1.0f)) {
+ mul_v4_fl(clear_cols[1], pd->fade_3d_object_opacity);
+ }
- /* Combine with scene buffer */
- if ((!is_render) || (fbl->main == NULL)) {
- GPU_framebuffer_bind(dfbl->default_fb);
- }
- else {
- GPU_framebuffer_bind(fbl->main);
- }
- /* tonemapping */
- stl->storage->tonemapping = DRW_state_do_color_management() ? 0 : 1;
+ if (pd->draw_depth_only) {
+ GPENCIL_draw_scene_depth_only(vedata);
+ return;
+ }
- /* active select flag and selection color */
- if (!is_render) {
- UI_GetThemeColorShadeAlpha4fv(
- (ob == draw_ctx->obact) ? TH_ACTIVE : TH_SELECT, 0, -40, stl->storage->select_color);
- }
- stl->storage->do_select_outline = ((overlay) && (ob->base_flag & BASE_SELECTED) &&
- (ob->mode == OB_MODE_OBJECT) && (!is_render) &&
- (!playing) && (v3d->flag & V3D_SELECT_OUTLINE));
-
- /* if active object is not object mode, disable for all objects */
- if ((stl->storage->do_select_outline) && (draw_ctx->obact) &&
- (draw_ctx->obact->mode != OB_MODE_OBJECT)) {
- stl->storage->do_select_outline = 0;
- }
+ if (pd->tobjects.first == NULL) {
+ return;
+ }
- /* draw mix pass */
- DRW_draw_pass(psl->mix_pass);
+ if (pd->do_fast_drawing) {
+ GPENCIL_fast_draw_start(vedata);
+ }
- /* disable select flag */
- stl->storage->do_select_outline = 0;
+ if (pd->tobjects.first) {
+ GPU_framebuffer_bind(fbl->gpencil_fb);
+ GPU_framebuffer_multi_clear(fbl->gpencil_fb, clear_cols);
+ }
- /* prepare for fast drawing */
- if (!is_render) {
- if (!playing) {
- gpencil_prepare_fast_drawing(stl, dfbl, fbl, psl->mix_pass_noblend, clearcol);
- }
- }
- else {
- /* if render, the cache must be dirty for next loop */
- gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
- }
- }
- /* edit points */
- if ((!is_render) && (!playing) && (is_edit)) {
- DRW_draw_pass(psl->edit_pass);
- }
- }
- /* grid pass */
- if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) {
- if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_GRID)) {
- DRW_draw_pass(psl->grid_pass);
- }
- }
+ for (GPENCIL_tObject *ob = pd->tobjects.first; ob; ob = ob->next) {
+ GPENCIL_draw_object(vedata, ob);
}
- /* free memory */
- DRW_gpencil_free_runtime_data(ved);
- /* reset */
- if (DRW_state_is_fbo()) {
- /* attach again default framebuffer */
- if (!is_render) {
- GPU_framebuffer_bind(dfbl->default_fb);
- }
+ if (pd->do_fast_drawing) {
+ GPENCIL_fast_draw_end(vedata);
+ }
- /* the temp texture is ready. Now we can use fast screen drawing */
- if (stl->g_data->session_flag & GP_DRW_PAINT_FILLING) {
- stl->g_data->session_flag = GP_DRW_PAINT_READY;
- }
+ if (!pd->simplify_antialias) {
+ GPENCIL_antialiasing_draw(vedata);
+ }
+
+ if (pd->scene_fb) {
+ GPU_framebuffer_bind(pd->scene_fb);
+ DRW_draw_pass(psl->composite_ps);
+ }
+
+ pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = NULL;
+
+ /* Free temp stroke buffers. */
+ if (pd->sbuffer_gpd) {
+ DRW_cache_gpencil_sbuffer_clear(pd->obact);
}
}
+static void GPENCIL_engine_free(void)
+{
+ GPENCIL_shader_free();
+}
+
static const DrawEngineDataSize GPENCIL_data_size = DRW_VIEWPORT_DATA_SIZE(GPENCIL_Data);
DrawEngineType draw_engine_gpencil_type = {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index aaafa689202..3ebefe83ce6 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -23,6 +23,8 @@
#ifndef __GPENCIL_ENGINE_H__
#define __GPENCIL_ENGINE_H__
+#include "DNA_gpencil_types.h"
+
#include "GPU_batch.h"
extern DrawEngineType draw_engine_gpencil_type;
@@ -35,207 +37,191 @@ struct RenderEngine;
struct RenderLayer;
struct bGPDstroke;
struct View3D;
-
+struct GpencilBatchCache;
struct GPUBatch;
struct GPUVertBuf;
struct GPUVertFormat;
-#define GPENCIL_CACHE_BLOCK_SIZE 8
-#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_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
-/* *********** 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;
-
-/* 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;
-
- /* 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;
-
- 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;
-
- /* shading type */
- int shading_type[2];
-
- /* GPU data size */
- int tot_vertex;
- int tot_triangles;
-
- /* Save shader groups by layer */
- int tot_layers;
- tGPencilObjectCache_shgrp *shgrp_array;
-
-} tGPencilObjectCache;
+/* 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;
+
+/* 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)
+
+#define GPENCIL_LIGHT_BUFFER_LEN 128
+
+/* 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;
+
+/* 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
+
+BLI_STATIC_ASSERT_ALIGN(gpMaterial, 16)
+BLI_STATIC_ASSERT_ALIGN(gpLight, 16)
+
+/* *********** 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;
+
+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;
+} 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;
+ /** Used to identify which layers are masks and which are masked. */
+ bool is_mask;
+ bool is_masked;
+ bool do_masked_clear;
+} 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;
+ /* 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;
+ /* 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 *masked_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 {
@@ -244,255 +230,156 @@ 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;
-
- int gp_cache_used; /* total objects in cache */
- int gp_cache_size; /* size of the cache */
- struct tGPencilObjectCache *gp_object_cache;
-
- /* 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 bGPDlayer *gpl,
- struct bGPDstroke *gps,
- short thickness,
- const float ink[4],
- const float tintcolor[4],
- const int follow_mode,
- const bool onion);
-void gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be,
- struct bGPDlayer *gpl,
- struct bGPDstroke *gps,
- short thickness,
- const float ink[4],
- const float tintcolor[4],
- const bool onion);
-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);
-float gpencil_get_vertex_paint_factor(struct View3D *v3d);
-
-/* 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);
+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;
+ /* 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;
+ GPUTexture *color_masked_tx;
+ /* Revealage is 1 - alpha */
+ GPUTexture *reveal_tx;
+ GPUTexture *reveal_layer_tx;
+ GPUTexture *reveal_object_tx;
+ GPUTexture *reveal_masked_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;
+ /* True in selection and auto_depth drawing */
+ bool draw_depth_only;
+ /* 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;
+
+ /* 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;
+
+ /* 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;
+} 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);
+GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
+ Object *ob,
+ struct bGPDlayer *layer);
+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);
+/* Meh, TODO fix naming...*/
+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);
-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);
+/* 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_layer_mask_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);
@@ -504,44 +391,19 @@ 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);
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_multisamples_resolve(txl->multisample_depth, txl->multisample_color, true); \
- DRW_stats_query_end(); \
- } \
- } \
- ((void)0)
+/* Draw Data. */
+void gpencil_light_pool_free(void *storage);
+void gpencil_material_pool_free(void *storage);
+GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void);
#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)))
-
#endif /* __GPENCIL_ENGINE_H__ */
diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c
index 8c126310ea2..ebb87880ce7 100644
--- a/source/blender/draw/engines/gpencil/gpencil_render.c
+++ b/source/blender/draw/engines/gpencil/gpencil_render.c
@@ -33,66 +33,21 @@
#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)
{
- 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 +60,70 @@ 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) {
+ /* TODO: put this message in a better place */
+ printf("Warning: To render grease pencil, enable Combined and Z passes.\n");
+ }
+
+ 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);
+ }
+ }
+ }
+
+ /* 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, pix_z);
+ txl->render_color_tx = DRW_texture_create_2d(size[0], size[1], GPU_RGBA16F, 0, pix_col);
+
+ GPU_framebuffer_ensure_config(&fbl->render_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(txl->render_depth_tx),
+ GPU_ATTACHMENT_TEXTURE(txl->render_color_tx),
+ });
+
+ 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 +131,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 +185,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 +196,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);
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);
- }
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader.c b/source/blender/draw/engines/gpencil/gpencil_shader.c
new file mode 100644
index 00000000000..3e436d27922
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/gpencil_shader.c
@@ -0,0 +1,305 @@
+/*
+ * 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_composite_frag_glsl[];
+extern char datatoc_gpencil_layer_blend_frag_glsl[];
+extern char datatoc_gpencil_layer_mask_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;
+ /* To blend masked layer with other layers. */
+ GPUShader *layer_mask_sh;
+ /* Merge the final object depth to the depth buffer. */
+ GPUShader *depth_merge_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_composite_get(void)
+{
+ if (!g_shaders.composite_sh) {
+ g_shaders.composite_sh = DRW_shader_create_fullscreen(datatoc_gpencil_composite_frag_glsl,
+ NULL);
+ }
+ return g_shaders.composite_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_layer_mask_get(void)
+{
+ if (!g_shaders.layer_mask_sh) {
+ g_shaders.layer_mask_sh = DRW_shader_create_fullscreen(datatoc_gpencil_layer_mask_frag_glsl,
+ NULL);
+ }
+ return g_shaders.layer_mask_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 = DRW_shader_create_fullscreen(datatoc_gpencil_vfx_frag_glsl,
+ "#define GLOW\n");
+ }
+ 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;
+}
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index f6a62e0d472..6e1eb4bfc47 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -26,26 +26,15 @@
#include "BKE_gpencil.h"
+#include "BLI_link_utils.h"
+#include "BLI_memblock.h"
+
#include "DRW_render.h"
#include "BKE_camera.h"
#include "gpencil_engine.h"
-extern char datatoc_gpencil_fx_blur_frag_glsl[];
-extern char datatoc_gpencil_fx_colorize_frag_glsl[];
-extern char datatoc_gpencil_fx_flip_frag_glsl[];
-extern char datatoc_gpencil_fx_light_frag_glsl[];
-extern char datatoc_gpencil_fx_pixel_frag_glsl[];
-extern char datatoc_gpencil_fx_rim_prepare_frag_glsl[];
-extern char datatoc_gpencil_fx_rim_resolve_frag_glsl[];
-extern char datatoc_gpencil_fx_shadow_prepare_frag_glsl[];
-extern char datatoc_gpencil_fx_shadow_resolve_frag_glsl[];
-extern char datatoc_gpencil_fx_glow_prepare_frag_glsl[];
-extern char datatoc_gpencil_fx_glow_resolve_frag_glsl[];
-extern char datatoc_gpencil_fx_swirl_frag_glsl[];
-extern char datatoc_gpencil_fx_wave_frag_glsl[];
-
/* verify if this fx is active */
static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_render)
{
@@ -70,995 +59,563 @@ static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_render)
return false;
}
-/**
- * Get normal of draw using one stroke of visible layer
- * \param gpd: GP datablock
- * \param r_point: Point on plane
- * \param r_normal: Normal vector
- */
-static bool get_normal_vector(bGPdata *gpd, float r_point[3], float r_normal[3])
+typedef struct gpIterVfxData {
+ GPENCIL_PrivateData *pd;
+ GPENCIL_tObject *tgp_ob;
+ GPUFrameBuffer **target_fb;
+ GPUFrameBuffer **source_fb;
+ GPUTexture **target_color_tx;
+ GPUTexture **source_color_tx;
+ GPUTexture **target_reveal_tx;
+ GPUTexture **source_reveal_tx;
+} gpIterVfxData;
+
+static DRWShadingGroup *gpencil_vfx_pass_create(const char *name,
+ DRWState state,
+ gpIterVfxData *iter,
+ GPUShader *sh)
{
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->flag & GP_LAYER_HIDE) {
- continue;
- }
+ DRWPass *pass = DRW_pass_create(name, state);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuf", iter->source_color_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "revealBuf", iter->source_reveal_tx);
- /* get frame */
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- if (gps->totpoints >= 3) {
- bGPDspoint *pt = &gps->points[0];
- BKE_gpencil_stroke_normal(gps, r_normal);
- /* in some weird situations, the normal cannot be calculated, so try next stroke */
- if ((r_normal[0] != 0.0f) || (r_normal[1] != 0.0f) || (r_normal[2] != 0.0f)) {
- copy_v3_v3(r_point, &pt->x);
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-/* helper to get near and far depth of field values */
-static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2])
-{
- if (camera == NULL) {
- return;
- }
- Camera *cam = camera->data;
+ GPENCIL_tVfx *tgp_vfx = BLI_memblock_alloc(iter->pd->gp_vfx_pool);
+ tgp_vfx->target_fb = iter->target_fb;
+ tgp_vfx->vfx_ps = pass;
- float fstop = cam->dof.aperture_fstop;
- float focus_dist = BKE_camera_object_dof_distance(camera);
- float focal_len = cam->lens;
+ SWAP(GPUFrameBuffer **, iter->target_fb, iter->source_fb);
+ SWAP(GPUTexture **, iter->target_color_tx, iter->source_color_tx);
+ SWAP(GPUTexture **, iter->target_reveal_tx, iter->source_reveal_tx);
- const float scale_camera = 0.001f;
- /* we want radius here for the aperture number */
- float aperture_scaled = 0.5f * scale_camera * focal_len / fstop;
- float focal_len_scaled = scale_camera * focal_len;
+ BLI_LINKS_APPEND(&iter->tgp_ob->vfx, tgp_vfx);
- float hyperfocal = (focal_len_scaled * focal_len_scaled) / (aperture_scaled * coc);
- nearfar[0] = (hyperfocal * focus_dist) / (hyperfocal + focal_len);
- nearfar[1] = (hyperfocal * focus_dist) / (hyperfocal - focal_len);
+ return grp;
}
-/* **************** Shader Effects ***************************** */
-
-/* Gaussian Blur FX
- * The effect is done using two shading groups because is faster to apply horizontal
- * and vertical in different operations.
- */
-static void gpencil_fx_blur(ShaderFxData *fx,
- int ob_idx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
+static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
- }
-
- BlurShaderFxData *fxd = (BlurShaderFxData *)fx;
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
- RegionView3D *rv3d = draw_ctx->rv3d;
- DRWShadingGroup *fx_shgrp;
- bGPdata *gpd = cache->gpd;
- copy_v3_v3(fxd->runtime.loc, cache->loc);
-
- fxd->blur[0] = fxd->radius[0];
- fxd->blur[1] = fxd->radius[1];
-
- /* init weight */
- if (fxd->flag & FX_BLUR_DOF_MODE) {
- /* viewport and opengl render */
- Object *camera = NULL;
- if (rv3d) {
- if (rv3d->persp == RV3D_CAMOB) {
- camera = v3d->camera;
- }
- }
- else {
- camera = stl->storage->camera;
- }
-
- if (camera) {
- float nearfar[2];
- GPENCIL_dof_nearfar(camera, fxd->coc, nearfar);
- float zdepth = stl->g_data->gp_object_cache[ob_idx].zdepth;
- /* the object is on focus area */
- if ((zdepth >= nearfar[0]) && (zdepth <= nearfar[1])) {
- fxd->blur[0] = 0;
- fxd->blur[1] = 0;
- }
- else {
- float f;
- if (zdepth < nearfar[0]) {
- f = nearfar[0] - zdepth;
- }
- else {
- f = zdepth - nearfar[1];
- }
- fxd->blur[0] = f;
- fxd->blur[1] = f;
- CLAMP2(&fxd->blur[0], 0, fxd->radius[0]);
- }
- }
- else {
- /* if not camera view, the blur is disabled */
- fxd->blur[0] = 0;
- fxd->blur[1] = 0;
- }
- }
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ DRWShadingGroup *grp;
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
+ float winmat[4][4], persmat[4][4];
+ float blur_size[2] = {fx->radius[0], fx->radius[1]};
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
-}
-
-/* Colorize FX */
-static void gpencil_fx_colorize(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata)
-{
- if (fx == NULL) {
- return;
+ if ((fx->flag & FX_BLUR_DOF_MODE) && iter->pd->camera != NULL) {
+ /* Compute circle of confusion size. */
+ float coc = (iter->pd->dof_params[0] / -w) - iter->pd->dof_params[1];
+ copy_v2_fl(blur_size, fabsf(coc));
}
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_vec4(fx_shgrp, "low_color", &fxd->low_color[0], 1);
- DRW_shgroup_uniform_vec4(fx_shgrp, "high_color", &fxd->high_color[0], 1);
- DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "factor", &fxd->factor, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
+ else {
+ /* Modify by distance to camera and object scale. */
+ DRW_view_winmat_get(NULL, winmat, false);
+ const float *vp_size = DRW_viewport_size_get();
+ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
+ float scale = mat4_to_scale(ob->obmat);
+ float distance_factor = world_pixel_scale * scale * winmat[1][1] * vp_size[1] / w;
+ mul_v2_fl(blur_size, distance_factor);
+ }
+
+ GPUShader *sh = GPENCIL_shader_fx_blur_get();
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Blur H", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){blur_size[0], 0.0f});
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ grp = gpencil_vfx_pass_create("Fx Blur V", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){0.0f, blur_size[1]});
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-/* Flip FX */
-static void gpencil_fx_flip(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata)
+static void gpencil_vfx_colorize(ColorizeShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
- }
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- FlipShaderFxData *fxd = (FlipShaderFxData *)fx;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
-
- fxd->flipmode = 100;
- /* the number works as bit flag */
- if (fxd->flag & FX_FLIP_HORIZONTAL) {
- fxd->flipmode += 10;
- }
- if (fxd->flag & FX_FLIP_VERTICAL) {
- fxd->flipmode += 1;
- }
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_int(fx_shgrp, "flipmode", &fxd->flipmode, 1);
+ DRWShadingGroup *grp;
- DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1);
+ GPUShader *sh = GPENCIL_shader_fx_colorize_get();
- fxd->runtime.fx_sh = fx_shgrp;
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Colorize", state, iter, sh);
+ DRW_shgroup_uniform_vec3_copy(grp, "lowColor", fx->low_color);
+ DRW_shgroup_uniform_vec3_copy(grp, "highColor", fx->high_color);
+ DRW_shgroup_uniform_float_copy(grp, "factor", fx->factor);
+ DRW_shgroup_uniform_int_copy(grp, "mode", fx->mode);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-/* Light FX */
-static void gpencil_fx_light(ShaderFxData *fx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
+static void gpencil_vfx_flip(FlipShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
- }
- LightShaderFxData *fxd = (LightShaderFxData *)fx;
-
- if (fxd->object == NULL) {
- return;
- }
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
-
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
-
- /* location of the light using obj location as origin */
- copy_v3_v3(fxd->loc, fxd->object->obmat[3]);
-
- /* Calc distance to strokes plane
- * The w component of location is used to transfer the distance to drawing plane
- */
- float r_point[3], r_normal[3];
- float r_plane[4];
- bGPdata *gpd = cache->gpd;
- if (!get_normal_vector(gpd, r_point, r_normal)) {
- return;
- }
- mul_mat3_m4_v3(cache->obmat, r_normal); /* only rotation component */
- plane_from_point_normal_v3(r_plane, r_point, r_normal);
- float dt = dist_to_plane_v3(fxd->object->obmat[3], r_plane);
- fxd->loc[3] = dt; /* use last element to save it */
+ DRWShadingGroup *grp;
- DRW_shgroup_uniform_vec4(fx_shgrp, "loc", &fxd->loc[0], 1);
+ float axis_flip[2];
+ axis_flip[0] = (fx->flag & FX_FLIP_HORIZONTAL) ? -1.0f : 1.0f;
+ axis_flip[1] = (fx->flag & FX_FLIP_VERTICAL) ? -1.0f : 1.0f;
- DRW_shgroup_uniform_float(fx_shgrp, "energy", &fxd->energy, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "ambient", &fxd->ambient, 1);
+ GPUShader *sh = GPENCIL_shader_fx_transform_get();
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", axis_flip);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", (float[2]){0.0f, 0.0f});
+ DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-/* Pixelate FX */
-static void gpencil_fx_pixel(ShaderFxData *fx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
+static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
+ DRWShadingGroup *grp;
+
+ float winmat[4][4], persmat[4][4];
+ float offset[2] = {fx->offset[0], fx->offset[1]};
+ float blur_size[2] = {fx->blur[0], fx->blur[1]};
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float *vp_size = DRW_viewport_size_get();
+ const float *vp_size_inv = DRW_viewport_invert_size_get();
+
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+
+ /* Modify by distance to camera and object scale. */
+ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
+ float scale = mat4_to_scale(ob->obmat);
+ float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
+ mul_v2_fl(offset, distance_factor);
+ mul_v2_v2(offset, vp_size_inv);
+ mul_v2_fl(blur_size, distance_factor);
+
+ GPUShader *sh = GPENCIL_shader_fx_rim_get();
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Rim H", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){blur_size[0] * vp_size_inv[0], 0.0f});
+ DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
+ DRW_shgroup_uniform_vec3_copy(grp, "maskColor", fx->mask_rgb);
+ DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ switch (fx->mode) {
+ case eShaderFxRimMode_Normal:
+ state |= DRW_STATE_BLEND_ALPHA_PREMUL;
+ break;
+ case eShaderFxRimMode_Add:
+ state |= DRW_STATE_BLEND_ADD_FULL;
+ break;
+ case eShaderFxRimMode_Subtract:
+ state |= DRW_STATE_BLEND_SUB;
+ break;
+ case eShaderFxRimMode_Multiply:
+ case eShaderFxRimMode_Divide:
+ case eShaderFxRimMode_Overlay:
+ state |= DRW_STATE_BLEND_MUL;
+ break;
+ }
+
+ zero_v2(offset);
+
+ grp = gpencil_vfx_pass_create("Fx Rim V", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "blurDir", (float[2]){0.0f, blur_size[1] * vp_size_inv[1]});
+ DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", offset);
+ DRW_shgroup_uniform_vec3_copy(grp, "rimColor", fx->rim_rgb);
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
+ DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->mode);
+ DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ if (fx->mode == eShaderFxRimMode_Overlay) {
+ /* We cannot do custom blending on MultiTarget framebuffers.
+ * Workaround by doing 2 passes. */
+ grp = DRW_shgroup_create_sub(grp);
+ 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);
}
- PixelShaderFxData *fxd = (PixelShaderFxData *)fx;
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
- bGPdata *gpd = cache->gpd;
- copy_v3_v3(fxd->runtime.loc, cache->loc);
-
- fxd->size[2] = (int)fxd->flag & FX_PIXEL_USE_LINES;
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3);
- DRW_shgroup_uniform_vec4(fx_shgrp, "color", &fxd->rgba[0], 1);
-
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
}
-/* Rim FX */
-static void gpencil_fx_rim(ShaderFxData *fx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
+static void gpencil_vfx_pixelize(PixelShaderFxData *fx, Object *ob, gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
+ DRWShadingGroup *grp;
+
+ float persmat[4][4], winmat[4][4], ob_center[3], pixsize_uniform[2];
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float *vp_size = DRW_viewport_size_get();
+ const float *vp_size_inv = DRW_viewport_invert_size_get();
+ float pixel_size[2] = {fx->size[0], fx->size[1]};
+ mul_v2_v2(pixel_size, vp_size_inv);
+
+ /* Fixed pixelisation center from object center. */
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+ mul_v3_m4v3(ob_center, persmat, ob->obmat[3]);
+ mul_v3_fl(ob_center, 1.0f / w);
+
+ /* Convert to uvs. */
+ mul_v2_fl(ob_center, 0.5f);
+ add_v2_fl(ob_center, 0.5f);
+
+ /* Modify by distance to camera and object scale. */
+ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
+ float scale = mat4_to_scale(ob->obmat);
+ mul_v2_fl(pixel_size, (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w);
+
+ /* Center to texel */
+ madd_v2_v2fl(ob_center, pixel_size, -0.5f);
+
+ GPUShader *sh = GPENCIL_shader_fx_pixelize_get();
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+
+ /* Only if pixelated effect is bigger than 1px. */
+ if (pixel_size[0] > vp_size_inv[0]) {
+ copy_v2_fl2(pixsize_uniform, pixel_size[0], vp_size_inv[1]);
+ grp = gpencil_vfx_pass_create("Fx Pixelize X", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
+ DRW_shgroup_uniform_vec2_copy(grp, "targetPixelOffset", ob_center);
+ DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){pixel_size[0], 0.0f});
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", (pixel_size[0] / vp_size_inv[0] > 3.0) ? 2 : 1);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
+
+ if (pixel_size[1] > vp_size_inv[1]) {
+ copy_v2_fl2(pixsize_uniform, vp_size_inv[0], pixel_size[1]);
+ grp = gpencil_vfx_pass_create("Fx Pixelize Y", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "targetPixelSize", pixsize_uniform);
+ DRW_shgroup_uniform_vec2_copy(grp, "accumOffset", (float[2]){0.0f, pixel_size[1]});
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", (pixel_size[1] / vp_size_inv[1] > 3.0) ? 2 : 1);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
- RimShaderFxData *fxd = (RimShaderFxData *)fx;
- bGPdata *gpd = cache->gpd;
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- copy_v3_v3(fxd->runtime.loc, cache->loc);
-
- /* prepare pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_prepare_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
-
- DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2);
- DRW_shgroup_uniform_vec3(fx_shgrp, "rim_color", &fxd->rim_rgb[0], 1);
- DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1);
-
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
-
- /* blur pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_fx);
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
-
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh_b = fx_shgrp;
-
- /* resolve pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_resolve_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1);
- DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1);
-
- fxd->runtime.fx_sh_c = fx_shgrp;
}
-/* Shadow FX */
-static void gpencil_fx_shadow(ShaderFxData *fx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
+static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
- }
- ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
- if ((!fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) {
- fxd->runtime.fx_sh = NULL;
- fxd->runtime.fx_sh_b = NULL;
- fxd->runtime.fx_sh_c = NULL;
- return;
- }
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
- bGPdata *gpd = cache->gpd;
- copy_v3_v3(fxd->runtime.loc, cache->loc);
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- /* prepare pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_prepare_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
-
- DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2);
- DRW_shgroup_uniform_float(fx_shgrp, "scale", &fxd->scale[0], 2);
- DRW_shgroup_uniform_float(fx_shgrp, "rotation", &fxd->rotation, 1);
- DRW_shgroup_uniform_vec4(fx_shgrp, "shadow_color", &fxd->shadow_rgba[0], 1);
-
- if ((fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) {
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->object->obmat[3], 1);
- }
- else {
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- }
-
- if (fxd->flag & FX_SHADOW_USE_WAVE) {
- DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1);
+ DRWShadingGroup *grp;
+
+ const bool use_obj_pivot = (fx->flag & FX_SHADOW_USE_OBJECT) != 0;
+ const bool use_wave = (fx->flag & FX_SHADOW_USE_WAVE) != 0;
+
+ float uv_mat[4][4], winmat[4][4], persmat[4][4], rot_center[3];
+ float wave_ofs[3], wave_dir[3], wave_phase, blur_dir[2], tmp[2];
+ float offset[2] = {fx->offset[0], fx->offset[1]};
+ float blur_size[2] = {fx->blur[0], fx->blur[1]};
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float *vp_size = DRW_viewport_size_get();
+ const float *vp_size_inv = DRW_viewport_invert_size_get();
+ const float ratio = vp_size_inv[1] / vp_size_inv[0];
+
+ copy_v3_v3(rot_center, (use_obj_pivot && fx->object) ? fx->object->obmat[3] : ob->obmat[3]);
+
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, rot_center));
+ mul_v3_m4v3(rot_center, persmat, rot_center);
+ mul_v3_fl(rot_center, 1.0f / w);
+
+ /* Modify by distance to camera and object scale. */
+ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
+ float scale = mat4_to_scale(ob->obmat);
+ float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
+ mul_v2_fl(offset, distance_factor);
+ mul_v2_v2(offset, vp_size_inv);
+ mul_v2_fl(blur_size, distance_factor);
+
+ rot_center[0] = rot_center[0] * 0.5f + 0.5f;
+ rot_center[1] = rot_center[1] * 0.5f + 0.5f;
+
+ /* UV transform matrix. (loc, rot, scale) Sent to shader as 2x3 matrix. */
+ unit_m4(uv_mat);
+ translate_m4(uv_mat, rot_center[0], rot_center[1], 0.0f);
+ rescale_m4(uv_mat, (float[3]){1.0f / fx->scale[0], 1.0f / fx->scale[1], 1.0f});
+ translate_m4(uv_mat, -offset[0], -offset[1], 0.0f);
+ rescale_m4(uv_mat, (float[3]){1.0f / ratio, 1.0f, 1.0f});
+ rotate_m4(uv_mat, 'Z', fx->rotation);
+ rescale_m4(uv_mat, (float[3]){ratio, 1.0f, 1.0f});
+ translate_m4(uv_mat, -rot_center[0], -rot_center[1], 0.0f);
+
+ if (use_wave) {
+ float dir[2];
+ if (fx->orientation == 0) {
+ /* Horizontal */
+ copy_v2_fl2(dir, 1.0f, 0.0f);
+ }
+ else {
+ /* Vertical */
+ copy_v2_fl2(dir, 0.0f, 1.0f);
+ }
+ /* This is applied after rotation. Counter the rotation to keep aligned with global axis. */
+ rotate_v2_v2fl(wave_dir, dir, fx->rotation);
+ /* Rotate 90°. */
+ copy_v2_v2(wave_ofs, wave_dir);
+ SWAP(float, wave_ofs[0], wave_ofs[1]);
+ wave_ofs[1] *= -1.0f;
+ /* Keep world space scalling and aspect ratio. */
+ mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
+ mul_v2_v2(wave_dir, vp_size);
+ mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
+ mul_v2_v2(wave_ofs, vp_size_inv);
+ /* Phase start at shadow center. */
+ wave_phase = fx->phase - dot_v2v2(rot_center, wave_dir);
}
else {
- DRW_shgroup_uniform_int_copy(fx_shgrp, "orientation", -1);
- }
- DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1);
-
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
-
- /* blur pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_fx);
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
-
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh_b = fx_shgrp;
-
- /* resolve pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_resolve_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowColor", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowDepth", &stl->g_data->temp_depth_tx_fx);
-
- fxd->runtime.fx_sh_c = fx_shgrp;
+ zero_v2(wave_dir);
+ zero_v2(wave_ofs);
+ wave_phase = 0.0f;
+ }
+
+ GPUShader *sh = GPENCIL_shader_fx_shadow_get();
+
+ copy_v2_fl2(blur_dir, blur_size[0] * vp_size_inv[0], 0.0f);
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Shadow H", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
+ DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[0])));
+ DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", true);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ unit_m4(uv_mat);
+ zero_v2(wave_ofs);
+
+ /* We reseted the uv_mat so we need to accound for the rotation in the */
+ copy_v2_fl2(tmp, 0.0f, blur_size[1]);
+ rotate_v2_v2fl(blur_dir, tmp, -fx->rotation);
+ mul_v2_v2(blur_dir, vp_size_inv);
+
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
+ grp = gpencil_vfx_pass_create("Fx Shadow V", state, iter, sh);
+ DRW_shgroup_uniform_vec4_copy(grp, "shadowColor", fx->shadow_rgba);
+ DRW_shgroup_uniform_vec2_copy(grp, "blurDir", blur_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotX", uv_mat[0]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvRotY", uv_mat[1]);
+ DRW_shgroup_uniform_vec2_copy(grp, "uvOffset", uv_mat[3]);
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, blur_size[1])));
+ DRW_shgroup_uniform_bool_copy(grp, "isFirstPass", false);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-/* Glow FX */
-static void gpencil_fx_glow(ShaderFxData *fx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
+static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
{
- if (fx == NULL) {
- return;
- }
- GlowShaderFxData *fxd = (GlowShaderFxData *)fx;
- bGPdata *gpd = cache->gpd;
- copy_v3_v3(fxd->runtime.loc, cache->loc);
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
-
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- /* prepare pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_prepare_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
-
- DRW_shgroup_uniform_vec3(fx_shgrp, "glow_color", &fxd->glow_color[0], 1);
- DRW_shgroup_uniform_vec3(fx_shgrp, "select_color", &fxd->select_color[0], 1);
- DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "threshold", &fxd->threshold, 1);
-
- fxd->runtime.fx_sh = fx_shgrp;
-
- /* blur pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_fx);
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2);
-
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
-
- fxd->runtime.fx_sh_b = fx_shgrp;
-
- /* resolve pass */
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_resolve_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowColor", &stl->g_data->temp_color_tx_fx);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowDepth", &stl->g_data->temp_depth_tx_fx);
-
- /* reuse field */
- DRW_shgroup_uniform_int(fx_shgrp, "alpha_mode", &fxd->blur[1], 1);
-
- fxd->runtime.fx_sh_c = fx_shgrp;
-}
+ DRWShadingGroup *grp;
-/* Swirl FX */
-static void gpencil_fx_swirl(ShaderFxData *fx,
- GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache)
-{
- if (fx == NULL) {
- return;
- }
- SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
- if (fxd->object == NULL) {
- return;
- }
+ GPUShader *sh = GPENCIL_shader_fx_glow_get();
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- DRWShadingGroup *fx_shgrp;
- bGPdata *gpd = cache->gpd;
+ float ref_col[3];
- fxd->transparent = (int)fxd->flag & FX_SWIRL_MAKE_TRANSPARENT;
+ if (fx->mode == eShaderFxGlowMode_Luminance) {
+ ref_col[0] = fx->threshold;
+ ref_col[1] = -1.0f;
+ ref_col[2] = -1.0f;
+ }
+ else {
+ copy_v3_v3(ref_col, fx->select_color);
+ }
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Glow H", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){fx->blur[0], 0.0f});
+ DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0])));
+ DRW_shgroup_uniform_vec3_copy(grp, "threshold", ref_col);
+ DRW_shgroup_uniform_vec3_copy(grp, "glowColor", fx->glow_color);
+ DRW_shgroup_uniform_bool_copy(grp, "useAlphaMode", false);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ ref_col[0] = -1.0f;
+
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL;
+ grp = gpencil_vfx_pass_create("Fx Glow V", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){0.0f, fx->blur[0]});
+ DRW_shgroup_uniform_vec3_copy(grp, "threshold", ref_col);
+ DRW_shgroup_uniform_vec3_copy(grp, "glowColor", (float[3]){1.0f, 1.0f, 1.0f});
+ DRW_shgroup_uniform_bool_copy(grp, "useAlphaMode", (fx->flag & FX_GLOW_USE_ALPHA) != 0);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+}
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
- fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
+static void gpencil_vfx_wave(WaveShaderFxData *fx, Object *ob, gpIterVfxData *iter)
+{
+ DRWShadingGroup *grp;
- DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
+ float winmat[4][4], persmat[4][4], wave_center[3];
+ float wave_ofs[3], wave_dir[3], wave_phase;
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float *vp_size = DRW_viewport_size_get();
+ const float *vp_size_inv = DRW_viewport_invert_size_get();
- DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->object->obmat[3], 1);
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, ob->obmat[3]));
+ mul_v3_m4v3(wave_center, persmat, ob->obmat[3]);
+ mul_v3_fl(wave_center, 1.0f / w);
- DRW_shgroup_uniform_int(fx_shgrp, "radius", &fxd->radius, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "angle", &fxd->angle, 1);
- DRW_shgroup_uniform_int(fx_shgrp, "transparent", &fxd->transparent, 1);
+ /* Modify by distance to camera and object scale. */
+ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
+ float scale = mat4_to_scale(ob->obmat);
+ float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
- DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1);
+ wave_center[0] = wave_center[0] * 0.5f + 0.5f;
+ wave_center[1] = wave_center[1] * 0.5f + 0.5f;
- fxd->runtime.fx_sh = fx_shgrp;
+ if (fx->orientation == 0) {
+ /* Horizontal */
+ copy_v2_fl2(wave_dir, 1.0f, 0.0f);
+ }
+ else {
+ /* Vertical */
+ copy_v2_fl2(wave_dir, 0.0f, 1.0f);
+ }
+ /* Rotate 90°. */
+ copy_v2_v2(wave_ofs, wave_dir);
+ SWAP(float, wave_ofs[0], wave_ofs[1]);
+ wave_ofs[1] *= -1.0f;
+ /* Keep world space scalling and aspect ratio. */
+ mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor));
+ mul_v2_v2(wave_dir, vp_size);
+ mul_v2_fl(wave_ofs, fx->amplitude * distance_factor);
+ mul_v2_v2(wave_ofs, vp_size_inv);
+ /* Phase start at shadow center. */
+ wave_phase = fx->phase - dot_v2v2(wave_center, wave_dir);
+
+ GPUShader *sh = GPENCIL_shader_fx_transform_get();
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Wave", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", (float[2]){1.0f, 1.0f});
+ DRW_shgroup_uniform_vec2_copy(grp, "waveDir", wave_dir);
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", wave_ofs);
+ DRW_shgroup_uniform_float_copy(grp, "wavePhase", wave_phase);
+ DRW_shgroup_uniform_float_copy(grp, "swirlRadius", 0.0f);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-/* Wave Distortion FX */
-static void gpencil_fx_wave(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata)
+static void gpencil_vfx_swirl(SwirlShaderFxData *fx, Object *UNUSED(ob), gpIterVfxData *iter)
{
- if (fx == NULL) {
+ DRWShadingGroup *grp;
+
+ if (fx->object == NULL) {
return;
}
- WaveShaderFxData *fxd = (WaveShaderFxData *)fx;
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
+ float winmat[4][4], persmat[4][4], swirl_center[3];
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_persmat_get(NULL, persmat, false);
+ const float *vp_size = DRW_viewport_size_get();
- DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass);
- DRW_shgroup_call(fx_shgrp, fxquad, NULL);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &stl->g_data->temp_color_tx_a);
- DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &stl->g_data->temp_depth_tx_a);
- DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1);
- DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1);
- DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1);
- DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1);
+ copy_v3_v3(swirl_center, fx->object->obmat[3]);
- fxd->runtime.fx_sh = fx_shgrp;
-}
-
-/* ************************************************************** */
-
-/* create all FX shaders */
-void GPENCIL_create_fx_shaders(GPENCIL_e_data *e_data)
-{
- /* fx shaders (all in screen space) */
- if (!e_data->gpencil_fx_blur_sh) {
- e_data->gpencil_fx_blur_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_blur_frag_glsl,
- NULL);
- }
- if (!e_data->gpencil_fx_colorize_sh) {
- e_data->gpencil_fx_colorize_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_colorize_frag_glsl, NULL);
- }
- if (!e_data->gpencil_fx_flip_sh) {
- e_data->gpencil_fx_flip_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_flip_frag_glsl,
- NULL);
- }
- if (!e_data->gpencil_fx_light_sh) {
- e_data->gpencil_fx_light_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_light_frag_glsl,
- NULL);
- }
- if (!e_data->gpencil_fx_pixel_sh) {
- e_data->gpencil_fx_pixel_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_pixel_frag_glsl,
- NULL);
- }
- if (!e_data->gpencil_fx_rim_prepare_sh) {
- e_data->gpencil_fx_rim_prepare_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_rim_prepare_frag_glsl, NULL);
+ const float w = fabsf(mul_project_m4_v3_zfac(persmat, swirl_center));
+ mul_v3_m4v3(swirl_center, persmat, swirl_center);
+ mul_v3_fl(swirl_center, 1.0f / w);
- e_data->gpencil_fx_rim_resolve_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_rim_resolve_frag_glsl, NULL);
- }
- if (!e_data->gpencil_fx_shadow_prepare_sh) {
- e_data->gpencil_fx_shadow_prepare_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_shadow_prepare_frag_glsl, NULL);
+ /* Modify by distance to camera and object scale. */
+ float world_pixel_scale = 1.0f / GPENCIL_PIXEL_FACTOR;
+ float scale = mat4_to_scale(fx->object->obmat);
+ float distance_factor = (world_pixel_scale * scale * winmat[1][1] * vp_size[1]) / w;
- e_data->gpencil_fx_shadow_resolve_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_shadow_resolve_frag_glsl, NULL);
- }
- if (!e_data->gpencil_fx_glow_prepare_sh) {
- e_data->gpencil_fx_glow_prepare_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_glow_prepare_frag_glsl, NULL);
+ mul_v2_fl(swirl_center, 0.5f);
+ add_v2_fl(swirl_center, 0.5f);
+ mul_v2_v2(swirl_center, vp_size);
- e_data->gpencil_fx_glow_resolve_sh = DRW_shader_create_fullscreen(
- datatoc_gpencil_fx_glow_resolve_frag_glsl, NULL);
- }
- if (!e_data->gpencil_fx_swirl_sh) {
- e_data->gpencil_fx_swirl_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_swirl_frag_glsl,
- NULL);
- }
- if (!e_data->gpencil_fx_wave_sh) {
- e_data->gpencil_fx_wave_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_wave_frag_glsl,
- NULL);
+ float radius = fx->radius * distance_factor;
+ if (radius < 1.0f) {
+ return;
}
-}
-/* free FX shaders */
-void GPENCIL_delete_fx_shaders(GPENCIL_e_data *e_data)
-{
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_blur_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_colorize_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_flip_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_light_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_pixel_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_prepare_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_resolve_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_prepare_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_resolve_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_prepare_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_resolve_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh);
- DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh);
-}
+ GPUShader *sh = GPENCIL_shader_fx_transform_get();
-/* create all passes used by FX */
-void GPENCIL_create_fx_passes(GPENCIL_PassList *psl)
-{
- psl->fx_shader_pass = DRW_pass_create("GPencil Shader FX Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS);
- psl->fx_shader_pass_blend = DRW_pass_create("GPencil Shader FX Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
- DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ grp = gpencil_vfx_pass_create("Fx Flip", state, iter, sh);
+ DRW_shgroup_uniform_vec2_copy(grp, "axisFlip", (float[2]){1.0f, 1.0f});
+ DRW_shgroup_uniform_vec2_copy(grp, "waveOffset", (float[2]){0.0f, 0.0f});
+ DRW_shgroup_uniform_vec2_copy(grp, "swirlCenter", swirl_center);
+ DRW_shgroup_uniform_float_copy(grp, "swirlAngle", fx->angle);
+ DRW_shgroup_uniform_float_copy(grp, "swirlRadius", radius);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-/* prepare fx shading groups */
-void gpencil_fx_prepare(GPENCIL_e_data *e_data,
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache_ob)
+void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObject *tgp_ob)
{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- const bool wiremode = (bool)(cache_ob->shading_type[0] == OB_WIRE);
-
- int ob_idx = cache_ob->idx;
-
- if ((wiremode) || (cache_ob->shader_fx.first == NULL)) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ GPENCIL_FramebufferList *fbl = vedata->fbl;
+ GPENCIL_PrivateData *pd = vedata->stl->pd;
+ /* If simplify enabled, nothing more to do. */
+ if (pd->simplify_fx) {
return;
}
- /* loop FX */
- for (ShaderFxData *fx = cache_ob->shader_fx.first; fx; fx = fx->next) {
- if (effect_is_active(cache_ob->gpd, fx, stl->storage->is_render)) {
+
+ /* These may not be allocated yet, use adress of future pointer. */
+ gpIterVfxData iter = {
+ .pd = pd,
+ .tgp_ob = tgp_ob,
+ .target_fb = &fbl->layer_fb,
+ .source_fb = &fbl->object_fb,
+ .target_color_tx = &pd->color_layer_tx,
+ .source_color_tx = &pd->color_object_tx,
+ .target_reveal_tx = &pd->reveal_layer_tx,
+ .source_reveal_tx = &pd->reveal_object_tx,
+ };
+
+ LISTBASE_FOREACH (ShaderFxData *, fx, &ob->shader_fx) {
+ if (effect_is_active(gpd, fx, pd->is_render)) {
switch (fx->type) {
case eShaderFxType_Blur:
- gpencil_fx_blur(fx, ob_idx, e_data, vedata, cache_ob);
+ gpencil_vfx_blur((BlurShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Colorize:
- gpencil_fx_colorize(fx, e_data, vedata);
+ gpencil_vfx_colorize((ColorizeShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Flip:
- gpencil_fx_flip(fx, e_data, vedata);
- break;
- case eShaderFxType_Light:
- gpencil_fx_light(fx, e_data, vedata, cache_ob);
+ gpencil_vfx_flip((FlipShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Pixel:
- gpencil_fx_pixel(fx, e_data, vedata, cache_ob);
+ gpencil_vfx_pixelize((PixelShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Rim:
- gpencil_fx_rim(fx, e_data, vedata, cache_ob);
+ gpencil_vfx_rim((RimShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Shadow:
- gpencil_fx_shadow(fx, e_data, vedata, cache_ob);
+ gpencil_vfx_shadow((ShadowShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Glow:
- gpencil_fx_glow(fx, e_data, vedata, cache_ob);
+ gpencil_vfx_glow((GlowShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Swirl:
- gpencil_fx_swirl(fx, e_data, vedata, cache_ob);
+ gpencil_vfx_swirl((SwirlShaderFxData *)fx, ob, &iter);
break;
case eShaderFxType_Wave:
- gpencil_fx_wave(fx, e_data, vedata);
+ gpencil_vfx_wave((WaveShaderFxData *)fx, ob, &iter);
break;
default:
break;
}
}
}
-}
-
-/* helper to draw one FX pass and do ping-pong copy */
-static void gpencil_draw_fx_pass(GPENCIL_Data *vedata, DRWShadingGroup *shgrp, bool blend)
-{
- if (shgrp == NULL) {
- return;
- }
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
-
- const float clearcol[4] = {0.0f};
- GPU_framebuffer_bind(fbl->temp_fb_b);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
-
- /* draw effect pass in temp texture (B) using as source the previous image
- * existing in the other temp texture (A) */
- if (!blend) {
- DRW_draw_pass_subset(psl->fx_shader_pass, shgrp, shgrp);
- }
- else {
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, shgrp, shgrp);
- }
-
- /* copy pass from b to a for ping-pong frame buffers */
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_b;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b;
-
- GPU_framebuffer_bind(fbl->temp_fb_a);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
- DRW_draw_pass(psl->mix_pass_noblend);
-}
-
-/* helper to manage gaussian blur passes */
-static void draw_gpencil_blur_passes(GPENCIL_Data *vedata, BlurShaderFxData *fxd)
-{
- if (fxd->runtime.fx_sh == NULL) {
- return;
- }
-
- DRWShadingGroup *shgrp = fxd->runtime.fx_sh;
- int samples = fxd->samples;
-
- float bx = fxd->blur[0];
- float by = fxd->blur[1];
-
- /* the blur is done in two steps (Hor/Ver) because is faster and
- * gets better result
- *
- * samples could be 0 and disable de blur effects because sometimes
- * is easier animate the number of samples only, instead to animate the
- * hide/unhide and the number of samples to make some effects.
- */
- for (int b = 0; b < samples; b++) {
- /* horizontal */
- if (bx > 0) {
- fxd->blur[0] = bx;
- fxd->blur[1] = 0;
- gpencil_draw_fx_pass(vedata, shgrp, true);
- }
- /* vertical */
- if (by > 0) {
- fxd->blur[0] = 0;
- fxd->blur[1] = by;
- gpencil_draw_fx_pass(vedata, shgrp, true);
- }
- }
-}
-
-/* blur intermediate pass */
-static void draw_gpencil_midpass_blur(GPENCIL_Data *vedata, ShaderFxData_Runtime *runtime)
-{
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
- const float clearcol[4] = {0.0f};
-
- GPU_framebuffer_bind(fbl->temp_fb_b);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, runtime->fx_sh_b, runtime->fx_sh_b);
-
- /* copy pass from b for ping-pong frame buffers */
- GPU_framebuffer_bind(fbl->temp_fb_fx);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
- DRW_draw_pass(psl->mix_pass_noblend);
-}
-
-/* do blur of mid passes */
-static void draw_gpencil_do_blur(
- GPENCIL_Data *vedata, ShaderFxData_Runtime *runtime, int samples, int bx, int by, int blur[2])
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
-
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_b;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b;
-
- if ((samples > 0) && ((bx > 0) || (by > 0))) {
- for (int x = 0; x < samples; x++) {
-
- /* horizontal */
- blur[0] = bx;
- blur[1] = 0;
- draw_gpencil_midpass_blur(vedata, runtime);
-
- /* Vertical */
- blur[0] = 0;
- blur[1] = by;
- draw_gpencil_midpass_blur(vedata, runtime);
-
- blur[0] = bx;
- blur[1] = by;
- }
- }
-}
-
-/* helper to draw RIM passes */
-static void draw_gpencil_rim_passes(GPENCIL_Data *vedata, RimShaderFxData *fxd)
-{
- if (fxd->runtime.fx_sh_b == NULL) {
- return;
- }
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
-
- const float clearcol[4] = {0.0f};
-
- /* prepare mask */
- GPU_framebuffer_bind(fbl->temp_fb_fx);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh);
-
- /* blur rim */
- draw_gpencil_do_blur(
- vedata, &fxd->runtime, fxd->samples, fxd->blur[0], fxd->blur[1], &fxd->blur[0]);
-
- /* resolve */
- GPU_framebuffer_bind(fbl->temp_fb_b);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c);
-
- /* copy pass from b to a for ping-pong frame buffers */
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_b;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b;
-
- GPU_framebuffer_bind(fbl->temp_fb_a);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
- DRW_draw_pass(psl->mix_pass_noblend);
-}
-
-/* helper to draw SHADOW passes */
-static void draw_gpencil_shadow_passes(GPENCIL_Data *vedata, ShadowShaderFxData *fxd)
-{
- if (fxd->runtime.fx_sh_b == NULL) {
- return;
- }
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
- const float clearcol[4] = {0.0f};
-
- /* prepare shadow */
- GPU_framebuffer_bind(fbl->temp_fb_fx);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh);
-
- /* blur shadow */
- draw_gpencil_do_blur(
- vedata, &fxd->runtime, fxd->samples, fxd->blur[0], fxd->blur[1], &fxd->blur[0]);
-
- /* resolve */
- GPU_framebuffer_bind(fbl->temp_fb_b);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c);
-
- /* copy pass from b to a for ping-pong frame buffers */
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_b;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b;
-
- GPU_framebuffer_bind(fbl->temp_fb_a);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
- DRW_draw_pass(psl->mix_pass_noblend);
-}
-
-/* helper to draw GLOW passes */
-static void draw_gpencil_glow_passes(GPENCIL_Data *vedata, GlowShaderFxData *fxd)
-{
- if (fxd->runtime.fx_sh_b == NULL) {
- return;
- }
-
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
- GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
- GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl;
-
- const float clearcol[4] = {0.0f};
- /* prepare glow */
- GPU_framebuffer_bind(fbl->temp_fb_fx);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh);
+ if (tgp_ob->vfx.first != NULL) {
+ /* We need an extra pass to combine result to main buffer. */
+ iter.target_fb = &fbl->gpencil_fb;
- /* blur glow */
- draw_gpencil_do_blur(
- vedata, &fxd->runtime, fxd->samples, fxd->blur[0], fxd->blur[0], &fxd->blur[0]);
+ GPUShader *sh = GPENCIL_shader_fx_composite_get();
- /* resolve */
- GPU_framebuffer_bind(fbl->temp_fb_b);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL;
+ DRWShadingGroup *grp = gpencil_vfx_pass_create("GPencil Object Compose", state, &iter, sh);
+ DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
- /* reuses blur field to keep alpha mode */
- fxd->blur[1] = (fxd->flag & FX_GLOW_USE_ALPHA) ? 1 : 0;
+ /* We cannot do custom blending on MultiTarget framebuffers.
+ * Workaround by doing 2 passes. */
+ grp = DRW_shgroup_create_sub(grp);
+ 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, "isFirstPass", false);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
- DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c);
-
- /* copy pass from b to a for ping-pong frame buffers */
- stl->g_data->input_depth_tx = stl->g_data->temp_depth_tx_b;
- stl->g_data->input_color_tx = stl->g_data->temp_color_tx_b;
-
- GPU_framebuffer_bind(fbl->temp_fb_a);
- GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
- DRW_draw_pass(psl->mix_pass_noblend);
-}
-
-/* apply all object fx effects */
-void gpencil_fx_draw(GPENCIL_e_data *UNUSED(e_data),
- GPENCIL_Data *vedata,
- tGPencilObjectCache *cache_ob)
-{
- GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
-
- /* loop FX modifiers */
- for (ShaderFxData *fx = cache_ob->shader_fx.first; fx; fx = fx->next) {
- if (effect_is_active(cache_ob->gpd, fx, stl->storage->is_render)) {
- switch (fx->type) {
-
- case eShaderFxType_Blur: {
- BlurShaderFxData *fxd = (BlurShaderFxData *)fx;
- draw_gpencil_blur_passes(vedata, fxd);
- break;
- }
- case eShaderFxType_Colorize: {
- ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx;
- gpencil_draw_fx_pass(vedata, fxd->runtime.fx_sh, false);
- break;
- }
- case eShaderFxType_Flip: {
- FlipShaderFxData *fxd = (FlipShaderFxData *)fx;
- gpencil_draw_fx_pass(vedata, fxd->runtime.fx_sh, false);
- break;
- }
- case eShaderFxType_Light: {
- LightShaderFxData *fxd = (LightShaderFxData *)fx;
- gpencil_draw_fx_pass(vedata, fxd->runtime.fx_sh, false);
- break;
- }
- case eShaderFxType_Pixel: {
- PixelShaderFxData *fxd = (PixelShaderFxData *)fx;
- gpencil_draw_fx_pass(vedata, fxd->runtime.fx_sh, false);
- break;
- }
- case eShaderFxType_Rim: {
- RimShaderFxData *fxd = (RimShaderFxData *)fx;
- draw_gpencil_rim_passes(vedata, fxd);
- break;
- }
- case eShaderFxType_Shadow: {
- ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx;
- draw_gpencil_shadow_passes(vedata, fxd);
- break;
- }
- case eShaderFxType_Glow: {
- GlowShaderFxData *fxd = (GlowShaderFxData *)fx;
- draw_gpencil_glow_passes(vedata, fxd);
- break;
- }
- case eShaderFxType_Swirl: {
- SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx;
- gpencil_draw_fx_pass(vedata, fxd->runtime.fx_sh, false);
- break;
- }
- case eShaderFxType_Wave: {
- WaveShaderFxData *fxd = (WaveShaderFxData *)fx;
- gpencil_draw_fx_pass(vedata, fxd->runtime.fx_sh, false);
- break;
- }
- default:
- break;
- }
- }
+ pd->use_object_fb = true;
}
}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl
deleted file mode 100644
index 0f64f54c67b..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl
+++ /dev/null
@@ -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;
- }
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl
deleted file mode 100644
index 52f42d30d06..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl
deleted file mode 100644
index 2cd77007b36..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl
deleted file mode 100644
index 676b9b05db9..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl
+++ /dev/null
@@ -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);
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl
deleted file mode 100644
index e2aceb9eefe..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl
deleted file mode 100644
index a5c321c20c1..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl
+++ /dev/null
@@ -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);
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl
deleted file mode 100644
index 46b3c4286b4..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl
deleted file mode 100644
index 2a17e573978..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl
deleted file mode 100644
index fa010baa32f..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl
deleted file mode 100644
index d2e20feae18..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl
deleted file mode 100644
index 3ef11008adf..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl
deleted file mode 100644
index 01d4fe40195..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl
deleted file mode 100644
index 0a5df9f6d77..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl
+++ /dev/null
@@ -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;
- }
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_frag.glsl
new file mode 100644
index 00000000000..cdcd978015c
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_frag.glsl
@@ -0,0 +1,43 @@
+
+uniform sampler2D edgesTex;
+uniform sampler2D areaTex;
+uniform sampler2D searchTex;
+uniform sampler2D blendTex;
+uniform sampler2D colorTex;
+uniform sampler2D revealTex;
+
+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
+layout(location = 0) out vec4 outColor;
+layout(location = 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. */
+ outColor = SMAANeighborhoodBlendingPS(uvs, offset[0], colorTex, blendTex);
+ outReveal = SMAANeighborhoodBlendingPS(uvs, offset[0], revealTex, blendTex);
+
+#endif
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl
new file mode 100644
index 00000000000..07734d19972
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_antialiasing_vert.glsl
@@ -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
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl
deleted file mode 100644
index 18803bfa3fa..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl
+++ /dev/null
@@ -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);
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
deleted file mode 100644
index 85dee4390a5..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl
+++ /dev/null
@@ -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);
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
new file mode 100644
index 00000000000..83fa9d5d0f6
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -0,0 +1,549 @@
+
+/* 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 / (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;
+flat IN_OUT vec2 strokePt1;
+flat IN_OUT vec2 strokePt2;
+flat IN_OUT int matFlag;
+flat IN_OUT float depth;
+
+#ifdef GPU_FRAGMENT_SHADER
+
+float stroke_round_cap_mask(vec2 p1, vec2 p2, float thickness)
+{
+ /* 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;
+
+ return (dot(uv_end, uv_end) > 0.25) ? 0.0 : 1.0;
+}
+
+#endif
+
+/* TODO UBO */
+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;
+
+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;
+
+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;
+
+ /* TODO case where ndc1 & ndc2 is behind camera */
+ 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;
+
+ 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);
+
+ gl_Position.xy += (x * x_axis + y * y_axis) * sizeViewportInv.xy * thickness;
+
+ strokePt1 = ss1;
+ strokePt2 = ss1 + vec2(0.5, 0.0);
+ strokeThickness = (is_squares) ? 1e18 : (thickness / gl_Position.w);
+ }
+ else {
+ /* 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);
+ 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;
+
+ /* Reminder: we packed the cap flag into the sign of stength and thickness sign. */
+ bool is_stroke_start = (ma.x == -1.0 && x == -1.0 && strength1 > 0.0) || miter_break;
+ bool is_stroke_end = (ma3.x == -1.0 && x == 1.0 && thickness1 > 0.0) || miter_break;
+
+ vec2 screen_ofs = miter * y;
+
+ if (is_stroke_start || is_stroke_end) {
+ 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 + 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;
+ 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
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_composite_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_composite_frag.glsl
new file mode 100644
index 00000000000..bc283952322
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_composite_frag.glsl
@@ -0,0 +1,41 @@
+
+uniform sampler2D colorBuf;
+uniform sampler2D revealBuf;
+uniform bool doSrgb;
+
+in vec4 uvcoordsvar;
+
+/* Reminder: Blending func is fragRevealage * DST + fragColor .*/
+layout(location = 0, index = 0) out vec4 fragColor;
+layout(location = 0, index = 1) out vec4 fragRevealage;
+
+/* TODO Remove. */
+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;
+ }
+}
+
+void main()
+{
+ /* Revealage, how much light passes through. */
+ fragRevealage.rgb = textureLod(revealBuf, uvcoordsvar.xy, 0.0).rgb;
+ /* Average for alpha channel. */
+ fragRevealage.a = clamp(dot(fragRevealage.rgb, vec3(0.333334)), 0.0, 1.0);
+ /* Color buf is already premultiplied. Just add it to the color. */
+ fragColor.rgb = textureLod(colorBuf, uvcoordsvar.xy, 0.0).rgb;
+ /* Add the alpha. */
+ fragColor.a = 1.0 - fragRevealage.a;
+
+ if (doSrgb) {
+ /* Temporary srgb conversion.
+ * TODO do color management / tonemapping here. */
+ fragColor.r = linearrgb_to_srgb(fragColor.r);
+ fragColor.g = linearrgb_to_srgb(fragColor.g);
+ fragColor.b = linearrgb_to_srgb(fragColor.b);
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_frag.glsl
new file mode 100644
index 00000000000..71597197bd8
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_frag.glsl
@@ -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;
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl
new file mode 100644
index 00000000000..1e5a900f486
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_depth_merge_vert.glsl
@@ -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);
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl
deleted file mode 100644
index 6a2a4f68dc9..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
deleted file mode 100644
index e0634a7d1a7..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
+++ /dev/null
@@ -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();
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
deleted file mode 100644
index f75322f90e2..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
+++ /dev/null
@@ -1,16 +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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
deleted file mode 100644
index 8285541e0b4..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
+++ /dev/null
@@ -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);
- }
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
deleted file mode 100644
index 263dc570423..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
new file mode 100644
index 00000000000..bca922ec018
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
@@ -0,0 +1,117 @@
+
+uniform sampler2D gpFillTexture;
+uniform sampler2D gpStrokeTexture;
+uniform sampler2D gpSceneDepthTexture;
+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, strokeThickness);
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
new file mode 100644
index 00000000000..a43f69bee6a
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_layer_blend_frag.glsl
@@ -0,0 +1,27 @@
+
+uniform sampler2D colorBuf;
+uniform sampler2D revealBuf;
+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;
+
+ 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, blendOpacity, fragColor, fragRevealage);
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_layer_mask_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_layer_mask_frag.glsl
new file mode 100644
index 00000000000..64899b147dc
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_layer_mask_frag.glsl
@@ -0,0 +1,37 @@
+
+uniform sampler2D colorBuf;
+uniform sampler2D revealBuf;
+uniform sampler2D maskBuf;
+uniform float maskOpacity;
+uniform bool maskInvert;
+uniform bool isFirstPass;
+
+in vec4 uvcoordsvar;
+
+layout(location = 0) out vec4 fragColor;
+layout(location = 1) out vec4 fragRevealage;
+
+void main()
+{
+ vec3 masked_color = texture(colorBuf, uvcoordsvar.xy).rgb;
+ vec3 masked_reveal = texture(revealBuf, uvcoordsvar.xy).rgb;
+ float mask = texture(maskBuf, uvcoordsvar.xy).r;
+
+ if (maskInvert) {
+ mask = 1.0 - mask;
+ }
+
+ mask = 1.0 - mask * maskOpacity;
+
+ if (isFirstPass) {
+ /* Blend mode is multiply. */
+ fragColor.rgb = fragRevealage.rgb = mix(vec3(1.0), masked_reveal, mask);
+ fragColor.a = fragRevealage.a = 1.0;
+ }
+ else {
+ /* Blend mode is additive. */
+ fragRevealage = vec4(0.0);
+ fragColor.rgb = mix(vec3(0.0), masked_color, mask);
+ fragColor.a = 0.0;
+ }
+}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
deleted file mode 100644
index 1d1cd6349dc..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-uniform vec3 color;
-uniform float opacity;
-
-out vec4 FragColor;
-
-void main()
-{
- FragColor = vec4(color, 1.0 - opacity);
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
deleted file mode 100644
index d79b8fb4d8a..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
+++ /dev/null
@@ -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);
- }
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
deleted file mode 100644
index a2f4c1f9b15..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
+++ /dev/null
@@ -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();
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
deleted file mode 100644
index 33d7d714231..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl
deleted file mode 100644
index 2f4429a858f..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
deleted file mode 100644
index 5e3cc105081..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
+++ /dev/null
@@ -1,107 +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 */
- if (gradient_f < 1.0) {
- float dist = abs(mTexCoord.y - 0.5) * 2.0;
- float decay = dist * (1.0 - gradient_f) * fragColor.a;
- fragColor.a = clamp(fragColor.a - decay, 0.0, 1.0);
- }
-
- 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);
- }
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
deleted file mode 100644
index 3300514dd13..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
+++ /dev/null
@@ -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();
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
deleted file mode 100644
index 8df08f0bf68..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
+++ /dev/null
@@ -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;
-}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
new file mode 100644
index 00000000000..c6cfee5ef2d
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -0,0 +1,5 @@
+
+void main()
+{
+ gpencil_vertex();
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
new file mode 100644
index 00000000000..860dae08dde
--- /dev/null
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl
@@ -0,0 +1,339 @@
+
+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 vec3 glowColor;
+uniform vec2 offset;
+uniform int sampCount;
+uniform vec3 threshold;
+uniform bool useAlphaMode;
+
+void main()
+{
+ vec2 pixel_size = 1.0 / vec2(textureSize(revealBuf, 0).xy);
+ vec2 ofs = offset * pixel_size;
+
+ fragColor = vec4(0.0);
+
+ /* In first pass we copy the reveal buffer. This let us do the alpha under if needed. */
+ fragRevealage = texture(revealBuf, uvcoordsvar.xy);
+
+ 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;
+ 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;
+ }
+
+ fragColor *= glowColor.rgbb / weight_accum;
+
+ if (useAlphaMode) {
+ /* Equivalent to alpha under. */
+ fragColor *= fragRevealage;
+ }
+
+ if (threshold.x == -1.0) {
+ /* Blend Mode is additive in 2nd pass. Don't modify revealage. */
+ fragRevealage = vec4(0.0);
+ }
+}
+
+#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 \ No newline at end of file
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl
deleted file mode 100644
index be645548402..00000000000
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl
+++ /dev/null
@@ -1,74 +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;
- }
- }
- }
-}
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index fb3efd710ba..9f84978deb6 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -25,6 +25,8 @@
#include "DRW_engine.h"
#include "DRW_render.h"
+#include "DEG_depsgraph_query.h"
+
#include "ED_view3d.h"
#include "BKE_object.h"
@@ -78,6 +80,7 @@ static void OVERLAY_engine_init(void *vedata)
pd->xray_enabled = XRAY_ACTIVE(v3d);
pd->xray_enabled_and_not_wire = pd->xray_enabled && v3d->shading.type > OB_WIRE;
pd->clear_in_front = (v3d->shading.type != OB_SOLID);
+ pd->cfra = DEG_get_ctime(draw_ctx->depsgraph);
OVERLAY_antialiasing_init(vedata);
@@ -132,12 +135,14 @@ static void OVERLAY_cache_init(void *vedata)
case CTX_MODE_SCULPT:
OVERLAY_sculpt_cache_init(vedata);
break;
- case CTX_MODE_OBJECT:
- case CTX_MODE_PAINT_GPENCIL:
case CTX_MODE_EDIT_GPENCIL:
+ case CTX_MODE_PAINT_GPENCIL:
case CTX_MODE_SCULPT_GPENCIL:
- case CTX_MODE_WEIGHT_GPENCIL:
case CTX_MODE_VERTEX_GPENCIL:
+ case CTX_MODE_WEIGHT_GPENCIL:
+ OVERLAY_edit_gpencil_cache_init(vedata);
+ break;
+ case CTX_MODE_OBJECT:
break;
default:
BLI_assert(!"Draw mode invalid");
@@ -147,6 +152,7 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_armature_cache_init(vedata);
OVERLAY_extra_cache_init(vedata);
OVERLAY_facing_cache_init(vedata);
+ OVERLAY_gpencil_cache_init(vedata);
OVERLAY_grid_cache_init(vedata);
OVERLAY_image_cache_init(vedata);
OVERLAY_metaball_cache_init(vedata);
@@ -215,8 +221,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL);
- const bool has_surface = ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT);
- const bool draw_surface = !((ob->dt < OB_WIRE) || (!renderable && (ob->dt != OB_WIRE)));
+ const bool has_surface = ELEM(
+ ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT, OB_GPENCIL);
+ const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE));
const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION);
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
const bool draw_wires = draw_surface && has_surface &&
@@ -413,6 +420,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_armature_draw(vedata);
OVERLAY_particle_draw(vedata);
OVERLAY_metaball_draw(vedata);
+ OVERLAY_gpencil_draw(vedata);
OVERLAY_extra_draw(vedata);
if (DRW_state_is_fbo()) {
@@ -474,6 +482,13 @@ static void OVERLAY_draw_scene(void *vedata)
case CTX_MODE_SCULPT:
OVERLAY_sculpt_draw(vedata);
break;
+ case CTX_MODE_EDIT_GPENCIL:
+ case CTX_MODE_PAINT_GPENCIL:
+ case CTX_MODE_SCULPT_GPENCIL:
+ case CTX_MODE_VERTEX_GPENCIL:
+ case CTX_MODE_WEIGHT_GPENCIL:
+ OVERLAY_edit_gpencil_draw(vedata);
+ break;
default:
break;
}
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 688ecaf3946..489667a6c8f 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -38,7 +38,7 @@
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
-#include "DNA_gpencil_types.h"
+#include "DNA_curve_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
@@ -1328,87 +1328,6 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name GPencil.
- * \{ */
-
-static void OVERLAY_gpencil_color_names(Object *ob)
-{
- if (ob->mode != OB_MODE_EDIT_GPENCIL) {
- return;
- }
-
- bGPdata *gpd = (bGPdata *)ob->data;
- if (gpd == NULL) {
- return;
- }
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- ViewLayer *view_layer = draw_ctx->view_layer;
- int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
- uchar color[4];
- UI_GetThemeColor4ubv(theme_id, color);
- struct DRWTextStore *dt = DRW_text_cache_ensure();
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->flag & GP_LAYER_HIDE) {
- continue;
- }
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
- if (ma == NULL) {
- continue;
- }
-
- MaterialGPencilStyle *gp_style = ma->gp_style;
- /* skip stroke if it doesn't have any valid data */
- if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) {
- continue;
- }
- /* check if the color is visible */
- if (gp_style->flag & GP_STYLE_COLOR_HIDE) {
- continue;
- }
-
- /* only if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- float fpt[3];
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if (pt->flag & GP_SPOINT_SELECT) {
- mul_v3_m4v3(fpt, ob->obmat, &pt->x);
- DRW_text_cache_add(dt,
- fpt,
- ma->id.name + 2,
- strlen(ma->id.name + 2),
- 10,
- 0,
- DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR,
- color);
- break;
- }
- }
- }
- }
- }
-}
-
-void OVERLAY_gpencil_cache_populate(OVERLAY_Data *UNUSED(vedata), Object *ob)
-{
- /* don't show object extras in set's */
- if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
- if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) {
- OVERLAY_gpencil_color_names(ob);
- }
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Volumetric / Smoke sim
* \{ */
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
new file mode 100644
index 00000000000..c96c448c63b
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -0,0 +1,391 @@
+/*
+ * 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 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_gpencil.h"
+
+#include "UI_resources.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "ED_view3d.h"
+
+#include "overlay_private.h"
+
+#include "draw_common.h"
+#include "draw_manager_text.h"
+
+void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
+ /* Default: Display nothing. */
+ pd->edit_gpencil_points_grp = NULL;
+ pd->edit_gpencil_wires_grp = NULL;
+ psl->edit_gpencil_ps = NULL;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Object *ob = draw_ctx->obact;
+ bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *ts = scene->toolsettings;
+
+ if (gpd == NULL || ob->type != OB_GPENCIL) {
+ return;
+ }
+
+ /* For sculpt show only if mask mode, and only points if not stroke mode. */
+ const bool use_sculpt_mask = (GPENCIL_SCULPT_MODE(gpd) &&
+ GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt));
+ const bool show_sculpt_points = (GPENCIL_SCULPT_MODE(gpd) &&
+ (ts->gpencil_selectmode_sculpt &
+ (GP_SCULPT_MASK_SELECTMODE_POINT |
+ GP_SCULPT_MASK_SELECTMODE_SEGMENT)));
+
+ /* For vertex paint show only if mask mode, and only points if not stroke mode. */
+ bool use_vertex_mask = (GPENCIL_VERTEX_MODE(gpd) &&
+ GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex));
+ const bool show_vertex_points = (GPENCIL_VERTEX_MODE(gpd) &&
+ (ts->gpencil_selectmode_vertex &
+ (GP_VERTEX_MASK_SELECTMODE_POINT |
+ GP_VERTEX_MASK_SELECTMODE_SEGMENT)));
+
+ /* If Sculpt or Vertex mode and the mask is disabled, the select must be hidden. */
+ const bool hide_select = ((GPENCIL_SCULPT_MODE(gpd) && !use_sculpt_mask) ||
+ (GPENCIL_VERTEX_MODE(gpd) && !use_vertex_mask));
+
+ const bool do_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool show_multi_edit_lines = (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) != 0;
+
+ const bool show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) || show_multi_edit_lines;
+
+ const bool hide_lines = !GPENCIL_EDIT_MODE(gpd) && !GPENCIL_WEIGHT_MODE(gpd) &&
+ !use_sculpt_mask && !use_vertex_mask && !show_lines;
+
+ /* Special case when vertex paint and multiedit lines. */
+ if (do_multiedit && show_multi_edit_lines && GPENCIL_VERTEX_MODE(gpd)) {
+ use_vertex_mask = true;
+ }
+
+ const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+
+ /* Show Edit points if:
+ * Edit mode: Not in Stroke selection mode
+ * Sculpt mode: If use Mask and not Stroke mode
+ * Weight mode: Always
+ * Vertex mode: If use Mask and not Stroke mode
+ */
+ const bool show_points = show_sculpt_points || is_weight_paint || show_vertex_points ||
+ (GPENCIL_EDIT_MODE(gpd) &&
+ (ts->gpencil_selectmode_edit != GP_SELECTMODE_STROKE));
+
+ if ((!GPENCIL_VERTEX_MODE(gpd) && !GPENCIL_PAINT_MODE(gpd)) || use_vertex_mask) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->edit_gpencil_ps, state | pd->clipping_state);
+
+ if (show_lines && !hide_lines) {
+ sh = OVERLAY_shader_edit_gpencil_wire();
+ pd->edit_gpencil_wires_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "doMultiframe", show_multi_edit_lines);
+ DRW_shgroup_uniform_bool_copy(grp, "doWeightColor", is_weight_paint);
+ DRW_shgroup_uniform_bool_copy(grp, "hideSelect", hide_select);
+ DRW_shgroup_uniform_float_copy(grp, "gpEditOpacity", v3d->vertex_opacity);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
+ }
+
+ if (show_points && !hide_select) {
+ sh = OVERLAY_shader_edit_gpencil_point();
+ pd->edit_gpencil_points_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "doMultiframe", do_multiedit);
+ DRW_shgroup_uniform_bool_copy(grp, "doWeightColor", is_weight_paint);
+ DRW_shgroup_uniform_float_copy(grp, "gpEditOpacity", v3d->vertex_opacity);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
+ }
+ }
+
+ /* control points for primitives and speed guide */
+ const bool is_cppoint = (gpd->runtime.tot_cp_points > 0);
+ const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide &&
+ (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL));
+ const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) &&
+ ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0));
+
+ if ((is_cppoint || is_speed_guide) && (is_show_gizmo)) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->edit_gpencil_gizmos_ps, state);
+
+ sh = OVERLAY_shader_edit_gpencil_guide_point();
+ grp = DRW_shgroup_create(sh, psl->edit_gpencil_gizmos_ps);
+
+ if (gpd->runtime.cp_points != NULL) {
+ for (int i = 0; i < gpd->runtime.tot_cp_points; i++) {
+ bGPDcontrolpoint *cp = &gpd->runtime.cp_points[i];
+ grp = DRW_shgroup_create_sub(grp);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", &cp->x);
+ DRW_shgroup_uniform_float_copy(grp, "pSize", cp->size * 0.8f * G_draw.block.sizePixel);
+ DRW_shgroup_uniform_vec4_copy(grp, "pColor", cp->color);
+ DRW_shgroup_call_procedural_points(grp, NULL, 1);
+ }
+ }
+
+ if (ts->gp_sculpt.guide.use_guide) {
+ float color[4];
+ if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_CUSTOM) {
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", ts->gp_sculpt.guide.location);
+ }
+ else if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_OBJECT &&
+ ts->gp_sculpt.guide.reference_object != NULL) {
+ UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", ts->gp_sculpt.guide.reference_object->loc);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", scene->cursor.location);
+ }
+ DRW_shgroup_uniform_vec4_copy(grp, "pColor", color);
+ DRW_shgroup_uniform_float_copy(grp, "pSize", 8.0f * G_draw.block.sizePixel);
+ DRW_shgroup_call_procedural_points(grp, NULL, 1);
+ }
+ }
+}
+
+void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
+ /* Default: Display nothing. */
+ psl->gpencil_canvas_ps = NULL;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Object *ob = draw_ctx->obact;
+ bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *ts = scene->toolsettings;
+ const View3DCursor *cursor = &scene->cursor;
+
+ if (gpd == NULL || ob->type != OB_GPENCIL) {
+ return;
+ }
+
+ const bool show_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
+ const bool show_grid = (v3d->gp_flag & V3D_GP_SHOW_GRID) != 0;
+
+ if (show_grid && show_overlays) {
+ const char *grid_unit = NULL;
+ float mat[4][4];
+ float col_grid[4];
+ float size[2];
+
+ /* set color */
+ copy_v3_v3(col_grid, gpd->grid.color);
+ col_grid[3] = max_ff(v3d->overlay.gpencil_grid_opacity, 0.01f);
+
+ copy_m4_m4(mat, ob->obmat);
+
+ float viewinv[4][4];
+ /* Set the grid in the selected axis */
+ switch (ts->gp_sculpt.lock_axis) {
+ case GP_LOCKAXIS_X:
+ swap_v4_v4(mat[0], mat[2]);
+ break;
+ case GP_LOCKAXIS_Y:
+ swap_v4_v4(mat[1], mat[2]);
+ break;
+ case GP_LOCKAXIS_Z:
+ /* Default. */
+ break;
+ case GP_LOCKAXIS_CURSOR:
+ loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, (float[3]){1, 1, 1});
+ break;
+ case GP_LOCKAXIS_VIEW:
+ /* view aligned */
+ DRW_view_viewmat_get(NULL, viewinv, true);
+ copy_v3_v3(mat[0], viewinv[0]);
+ copy_v3_v3(mat[1], viewinv[1]);
+ break;
+ }
+
+ translate_m4(mat, gpd->grid.offset[0], gpd->grid.offset[1], 0.0f);
+ mul_v2_v2fl(size, gpd->grid.scale, 2.0f * ED_scene_grid_scale(scene, &grid_unit));
+ rescale_m4(mat, (float[3]){size[0], size[1], 0.0f});
+
+ const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines;
+ int line_ct = gridlines * 4 + 2;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->gpencil_canvas_ps, state);
+
+ sh = OVERLAY_shader_gpencil_canvas();
+ grp = DRW_shgroup_create(sh, psl->gpencil_canvas_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", col_grid);
+ DRW_shgroup_uniform_vec3_copy(grp, "xAxis", mat[0]);
+ DRW_shgroup_uniform_vec3_copy(grp, "yAxis", mat[1]);
+ DRW_shgroup_uniform_vec3_copy(grp, "origin", mat[3]);
+ DRW_shgroup_uniform_int_copy(grp, "halfLineCount", line_ct / 2);
+ DRW_shgroup_call_procedural_lines(grp, NULL, line_ct);
+ }
+}
+
+static void OVERLAY_edit_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+
+ if (pd->edit_gpencil_wires_grp) {
+ DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->edit_gpencil_wires_grp);
+ DRW_shgroup_uniform_vec4_copy(grp, "gpEditColor", gpd->line_color);
+
+ struct GPUBatch *geom = DRW_cache_gpencil_edit_lines_get(ob, pd->cfra);
+ DRW_shgroup_call_no_cull(pd->edit_gpencil_wires_grp, geom, ob);
+ }
+
+ if (pd->edit_gpencil_points_grp) {
+ const bool show_direction = (v3d->gp_flag & V3D_GP_SHOW_STROKE_DIRECTION) != 0;
+
+ DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->edit_gpencil_points_grp);
+ DRW_shgroup_uniform_float_copy(grp, "doStrokeEndpoints", show_direction);
+
+ struct GPUBatch *geom = DRW_cache_gpencil_edit_points_get(ob, pd->cfra);
+ DRW_shgroup_call_no_cull(grp, geom, ob);
+ }
+}
+
+static void overlay_gpencil_draw_stroke_color_name(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ Object *ob = (Object *)thunk;
+ Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
+ if (ma == NULL) {
+ return;
+ }
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) {
+ return;
+ }
+ /* check if the color is visible */
+ if (gp_style->flag & GP_MATERIAL_HIDE) {
+ return;
+ }
+ /* only if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ /* Draw name at the first selected point. */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ uchar color[4];
+ UI_GetThemeColor4ubv(theme_id, color);
+
+ float fpt[3];
+ mul_v3_m4v3(fpt, ob->obmat, &pt->x);
+
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ DRW_text_cache_add(dt,
+ fpt,
+ ma->id.name + 2,
+ strlen(ma->id.name + 2),
+ 10,
+ 0,
+ DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR,
+ color);
+ break;
+ }
+ }
+ }
+}
+
+static void OVERLAY_gpencil_color_names(Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ int cfra = DEG_get_ctime(draw_ctx->depsgraph);
+
+ BKE_gpencil_visible_stroke_iter(
+ ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
+}
+
+void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd == NULL) {
+ return;
+ }
+
+ if (GPENCIL_ANY_MODE(gpd)) {
+ OVERLAY_edit_gpencil_cache_populate(vedata, ob);
+ }
+
+ /* don't show object extras in set's */
+ if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
+ if ((v3d->gp_flag & V3D_GP_SHOW_MATERIAL_NAME) && (ob->mode == OB_MODE_EDIT_GPENCIL) &&
+ DRW_state_show_text()) {
+ OVERLAY_gpencil_color_names(ob);
+ }
+ }
+}
+
+void OVERLAY_gpencil_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ if (psl->gpencil_canvas_ps) {
+ DRW_draw_pass(psl->gpencil_canvas_ps);
+ }
+}
+
+void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ if (psl->edit_gpencil_gizmos_ps) {
+ DRW_draw_pass(psl->edit_gpencil_gizmos_ps);
+ }
+
+ if (psl->edit_gpencil_ps) {
+ DRW_draw_pass(psl->edit_gpencil_ps);
+ }
+}
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c
index a532618d472..f9c7df75e9a 100644
--- a/source/blender/draw/engines/overlay/overlay_motion_path.c
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.c
@@ -155,7 +155,7 @@ static void motion_path_cache(OVERLAY_Data *vedata,
DRW_shgroup_uniform_bool_copy(grp, "selected", selected);
DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
/* Only draw the required range. */
- DRW_shgroup_call_range(grp, mpath_batch_line_get(mpath), start_index, len);
+ DRW_shgroup_call_range(grp, NULL, mpath_batch_line_get(mpath), start_index, len);
}
/* Draw points. */
@@ -167,7 +167,7 @@ static void motion_path_cache(OVERLAY_Data *vedata,
DRW_shgroup_uniform_bool_copy(grp, "showKeyFrames", show_keyframes);
DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
/* Only draw the required range. */
- DRW_shgroup_call_range(grp, mpath_batch_points_get(mpath), start_index, len);
+ DRW_shgroup_call_range(grp, NULL, mpath_batch_points_get(mpath), start_index, len);
}
/* Draw frame numbers at each frame-step value. */
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index 63738b3c214..e77a0a143a9 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -23,13 +23,67 @@
#include "DRW_render.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
-#include "DNA_lightprobe_types.h"
+#include "BKE_object.h"
+
+#include "DNA_gpencil_types.h"
#include "UI_resources.h"
#include "overlay_private.h"
+/* Returns the normal plane in ndc space. */
+static void gpencil_depth_plane(Object *ob, float r_plane[4])
+{
+ /* TODO put that into private data. */
+ float viewinv[4][4];
+ DRW_view_viewmat_get(NULL, viewinv, true);
+ float *camera_z_axis = viewinv[2];
+ float *camera_pos = viewinv[3];
+
+ /* 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);
+ /* BBox center in world space. */
+ copy_v3_v3(center, mat[3]);
+ /* View Vector. */
+ if (DRW_view_is_persp_get(NULL)) {
+ /* BBox center to camera vector. */
+ sub_v3_v3v3(r_plane, camera_pos, mat[3]);
+ }
+ else {
+ copy_v3_v3(r_plane, camera_z_axis);
+ }
+ /* World to BBox space. */
+ invert_m4(mat);
+ /* Normalize the vector in BBox space. */
+ mul_mat3_m4_v3(mat, r_plane);
+ normalize_v3(r_plane);
+
+ transpose_m4(mat);
+ /* mat is now a "normal" matrix which will transform
+ * BBox space normal to world space. */
+ mul_mat3_m4_v3(mat, r_plane);
+ normalize_v3(r_plane);
+
+ plane_from_point_normal_v3(r_plane, center, r_plane);
+}
+
void OVERLAY_outline_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
@@ -79,6 +133,11 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
pd->outlines_grp = grp = DRW_shgroup_create(sh_geom, psl->outlines_prepass_ps);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
+
+ GPUShader *sh_gpencil = OVERLAY_shader_outline_prepass_gpencil();
+
+ pd->outlines_gpencil_grp = grp = DRW_shgroup_create(sh_gpencil, psl->outlines_prepass_ps);
+ DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
}
/* outlines_prepass_ps is still needed for selection of probes. */
@@ -107,6 +166,98 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
}
}
+typedef struct iterData {
+ Object *ob;
+ DRWShadingGroup *stroke_grp;
+ DRWShadingGroup *fill_grp;
+ int cfra;
+ float plane[4];
+} iterData;
+
+static void gp_layer_cache_populate(bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *UNUSED(gps),
+ void *thunk)
+{
+ iterData *iter = (iterData *)thunk;
+ bGPdata *gpd = (bGPdata *)iter->ob->data;
+
+ const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
+ const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D);
+
+ float object_scale = mat4_to_scale(iter->ob->obmat);
+ /* 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 / 2000.0f);
+
+ DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp);
+ DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", is_stroke_order_3d);
+ 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, "thicknessScale", object_scale);
+ DRW_shgroup_uniform_float_copy(grp, "thicknessOffset", (float)gpl->line_change);
+ DRW_shgroup_uniform_float_copy(grp, "thicknessWorldScale", thickness_scale);
+ DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane);
+}
+
+static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ iterData *iter = (iterData *)thunk;
+
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(iter->ob, gps->mat_nr + 1);
+
+ bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
+ bool show_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0;
+ // TODO: What about simplify Fill?
+ bool show_fill = (gps->tot_triangles > 0) && (gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0;
+
+ if (hide_material) {
+ return;
+ }
+
+ if (show_fill) {
+ struct GPUBatch *geom = DRW_cache_gpencil_fills_get(iter->ob, iter->cfra);
+ int vfirst = gps->runtime.fill_start * 3;
+ int vcount = gps->tot_triangles * 3;
+ DRW_shgroup_call_range(iter->fill_grp, iter->ob, geom, vfirst, vcount);
+ }
+
+ if (show_stroke) {
+ struct GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter->ob, iter->cfra);
+ /* Start one vert before to have gl_InstanceID > 0 (see shader). */
+ int vfirst = gps->runtime.stroke_start - 1;
+ /* Include "potential" cyclic vertex and start adj vertex (see shader). */
+ int vcount = gps->totpoints + 1 + 1;
+ DRW_shgroup_call_instance_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
+ }
+}
+
+static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
+{
+ /* No outlines in edit mode. */
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd && GPENCIL_ANY_MODE(gpd)) {
+ return;
+ }
+
+ iterData iter = {
+ .ob = ob,
+ .stroke_grp = pd->outlines_gpencil_grp,
+ .fill_grp = DRW_shgroup_create_sub(pd->outlines_gpencil_grp),
+ .cfra = pd->cfra,
+ };
+
+ if (gpd->draw_mode == GP_DRAWMODE_2D) {
+ gpencil_depth_plane(ob, iter.plane);
+ }
+
+ BKE_gpencil_visible_stroke_iter(
+ ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
+}
+
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
@@ -123,6 +274,11 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
return;
}
+ if (ob->type == OB_GPENCIL) {
+ OVERLAY_outline_gpencil(pd, ob);
+ return;
+ }
+
if (dupli && !init_dupli) {
geom = dupli->outline_geom;
shgroup = dupli->outline_shgrp;
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index f8eeeed42ef..55b59e24a5b 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -57,6 +57,8 @@ typedef struct OVERLAY_PassList {
DRWPass *armature_transp_ps;
DRWPass *edit_curve_wire_ps[2];
DRWPass *edit_curve_handle_ps;
+ DRWPass *edit_gpencil_ps;
+ DRWPass *edit_gpencil_gizmos_ps;
DRWPass *edit_lattice_ps;
DRWPass *edit_mesh_depth_ps[2];
DRWPass *edit_mesh_verts_ps[2];
@@ -73,6 +75,7 @@ typedef struct OVERLAY_PassList {
DRWPass *extra_blend_ps;
DRWPass *extra_centers_ps;
DRWPass *extra_grid_ps;
+ DRWPass *gpencil_canvas_ps;
DRWPass *facing_ps;
DRWPass *grid_ps;
DRWPass *image_background_under_ps;
@@ -216,6 +219,8 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *edit_curve_points_grp;
DRWShadingGroup *edit_lattice_points_grp;
DRWShadingGroup *edit_lattice_wires_grp;
+ DRWShadingGroup *edit_gpencil_points_grp;
+ DRWShadingGroup *edit_gpencil_wires_grp;
DRWShadingGroup *edit_mesh_depth_grp[2];
DRWShadingGroup *edit_mesh_faces_grp[2];
DRWShadingGroup *edit_mesh_faces_cage_grp[2];
@@ -235,6 +240,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *motion_path_lines_grp;
DRWShadingGroup *motion_path_points_grp;
DRWShadingGroup *outlines_grp;
+ DRWShadingGroup *outlines_gpencil_grp;
DRWShadingGroup *paint_surf_grp;
DRWShadingGroup *paint_wire_grp;
DRWShadingGroup *paint_wire_selected_grp;
@@ -273,6 +279,7 @@ typedef struct OVERLAY_PrivateData {
bool xray_enabled_and_not_wire;
short v3d_flag; /* TODO move to View3DOverlay */
short v3d_gridflag; /* TODO move to View3DOverlay */
+ int cfra;
DRWState clipping_state;
OVERLAY_ShadingData shdata;
@@ -411,6 +418,12 @@ void OVERLAY_edit_curve_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_surf_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata);
+void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
+void OVERLAY_gpencil_draw(OVERLAY_Data *vedata);
+void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata);
+
void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob);
@@ -438,7 +451,6 @@ void OVERLAY_extra_centers_draw(OVERLAY_Data *vedata);
void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_empty_cache_populate(OVERLAY_Data *vedata, Object *ob);
-void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_speaker_cache_populate(OVERLAY_Data *vedata, Object *ob);
@@ -536,6 +548,9 @@ GPUShader *OVERLAY_shader_depth_only(void);
GPUShader *OVERLAY_shader_edit_curve_handle(void);
GPUShader *OVERLAY_shader_edit_curve_point(void);
GPUShader *OVERLAY_shader_edit_curve_wire(void);
+GPUShader *OVERLAY_shader_edit_gpencil_guide_point(void);
+GPUShader *OVERLAY_shader_edit_gpencil_point(void);
+GPUShader *OVERLAY_shader_edit_gpencil_wire(void);
GPUShader *OVERLAY_shader_edit_lattice_point(void);
GPUShader *OVERLAY_shader_edit_lattice_wire(void);
GPUShader *OVERLAY_shader_edit_mesh_analysis(void);
@@ -553,12 +568,14 @@ GPUShader *OVERLAY_shader_extra_wire(bool use_object);
GPUShader *OVERLAY_shader_extra_loose_point(void);
GPUShader *OVERLAY_shader_extra_point(void);
GPUShader *OVERLAY_shader_facing(void);
+GPUShader *OVERLAY_shader_gpencil_canvas(void);
GPUShader *OVERLAY_shader_grid(void);
GPUShader *OVERLAY_shader_image(void);
GPUShader *OVERLAY_shader_motion_path_line(void);
GPUShader *OVERLAY_shader_motion_path_vert(void);
GPUShader *OVERLAY_shader_uniform_color(void);
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire);
+GPUShader *OVERLAY_shader_outline_prepass_gpencil(void);
GPUShader *OVERLAY_shader_extra_grid(void);
GPUShader *OVERLAY_shader_outline_detect(void);
GPUShader *OVERLAY_shader_paint_face(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 7bd3cf4a067..450fbc5d8bb 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -52,6 +52,9 @@ extern char datatoc_edit_curve_handle_geom_glsl[];
extern char datatoc_edit_curve_handle_vert_glsl[];
extern char datatoc_edit_curve_point_vert_glsl[];
extern char datatoc_edit_curve_wire_vert_glsl[];
+extern char datatoc_edit_gpencil_canvas_vert_glsl[];
+extern char datatoc_edit_gpencil_guide_vert_glsl[];
+extern char datatoc_edit_gpencil_vert_glsl[];
extern char datatoc_edit_lattice_point_vert_glsl[];
extern char datatoc_edit_lattice_wire_vert_glsl[];
extern char datatoc_edit_mesh_common_lib_glsl[];
@@ -110,6 +113,8 @@ extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
+extern char datatoc_gpencil_common_lib_glsl[];
+
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
@@ -133,6 +138,9 @@ typedef struct OVERLAY_Shaders {
GPUShader *edit_curve_handle;
GPUShader *edit_curve_point;
GPUShader *edit_curve_wire;
+ GPUShader *edit_gpencil_guide_point;
+ GPUShader *edit_gpencil_point;
+ GPUShader *edit_gpencil_wire;
GPUShader *edit_lattice_point;
GPUShader *edit_lattice_wire;
GPUShader *edit_mesh_vert;
@@ -154,11 +162,13 @@ typedef struct OVERLAY_Shaders {
GPUShader *extra_lightprobe_grid;
GPUShader *extra_loose_point;
GPUShader *facing;
+ GPUShader *gpencil_canvas;
GPUShader *grid;
GPUShader *image;
GPUShader *motion_path_line;
GPUShader *motion_path_vert;
GPUShader *outline_prepass;
+ GPUShader *outline_prepass_gpencil;
GPUShader *outline_prepass_wire;
GPUShader *outline_detect;
GPUShader *paint_face;
@@ -526,6 +536,58 @@ GPUShader *OVERLAY_shader_edit_curve_wire(void)
return sh_data->edit_curve_wire;
}
+GPUShader *OVERLAY_shader_edit_gpencil_guide_point(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_gpencil_guide_point) {
+ sh_data->edit_gpencil_guide_point = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_guide_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
+ });
+ }
+ return sh_data->edit_gpencil_guide_point;
+}
+
+GPUShader *OVERLAY_shader_edit_gpencil_point(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->edit_gpencil_point) {
+ sh_data->edit_gpencil_point = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define USE_POINTS\n", NULL},
+ });
+ }
+ return sh_data->edit_gpencil_point;
+}
+
+GPUShader *OVERLAY_shader_edit_gpencil_wire(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->edit_gpencil_wire) {
+ sh_data->edit_gpencil_wire = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
+ }
+ return sh_data->edit_gpencil_wire;
+}
+
GPUShader *OVERLAY_shader_edit_lattice_point(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -852,6 +914,21 @@ GPUShader *OVERLAY_shader_facing(void)
return sh_data->facing;
}
+GPUShader *OVERLAY_shader_gpencil_canvas(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->gpencil_canvas) {
+ sh_data->gpencil_canvas = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_canvas_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_extra_frag_glsl, NULL},
+ });
+ }
+ return sh_data->gpencil_canvas;
+}
+
GPUShader *OVERLAY_shader_grid(void)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
@@ -967,6 +1044,32 @@ GPUShader *OVERLAY_shader_outline_prepass(bool use_wire)
return use_wire ? sh_data->outline_prepass_wire : sh_data->outline_prepass;
}
+GPUShader *OVERLAY_shader_outline_prepass_gpencil(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->outline_prepass_gpencil) {
+ sh_data->outline_prepass_gpencil = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_gpencil_common_lib_glsl,
+ datatoc_gpu_shader_common_obinfos_lib_glsl,
+ datatoc_outline_prepass_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_gpencil_common_lib_glsl,
+ datatoc_outline_prepass_frag_glsl,
+ NULL},
+ .defs = (const char *[]){sh_cfg->def,
+ "#define USE_GPENCIL\n",
+ "#define UNIFORM_RESOURCE_ID\n",
+ NULL},
+ });
+ }
+ return sh_data->outline_prepass_gpencil;
+}
+
GPUShader *OVERLAY_shader_outline_detect(void)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index e39f51aa606..6ae9f19dab6 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -186,7 +186,11 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
shgrp = pd->wires_grp[is_xray][use_coloring];
}
- if (use_sculpt_pbvh) {
+ if (ob->type == OB_GPENCIL) {
+ /* TODO (fclem) Make GPencil objects have correct boundbox. */
+ DRW_shgroup_call_no_cull(shgrp, geom, ob);
+ }
+ else if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(shgrp, ob, true, false, false);
}
else {
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
new file mode 100644
index 00000000000..5aa7fe78e4e
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
@@ -0,0 +1,35 @@
+
+uniform vec4 color;
+uniform vec3 xAxis;
+uniform vec3 yAxis;
+uniform vec3 origin;
+uniform int halfLineCount;
+
+flat out vec4 finalColor;
+flat out vec2 edgeStart;
+noperspective out vec2 edgePos;
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec2 pos;
+ pos.x = float(gl_VertexID % 2);
+ pos.y = float(gl_VertexID / 2) / float(halfLineCount - 1);
+
+ if (pos.y > 1.0) {
+ pos.xy = pos.yx;
+ pos.x -= 1.0 + 1.0 / float(halfLineCount - 1);
+ }
+
+ pos -= 0.5;
+
+ vec3 world_pos = xAxis * pos.x + yAxis * pos.y + origin;
+
+ gl_Position = point_world_to_ndc(world_pos);
+
+ finalColor = color;
+
+ /* Convert to screen position [0..sizeVp]. */
+ edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl
new file mode 100644
index 00000000000..ef68b0f4e6f
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl
@@ -0,0 +1,14 @@
+uniform vec4 pColor;
+uniform float pSize;
+uniform vec3 pPosition;
+
+out vec4 finalColor;
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ gl_Position = point_world_to_ndc(pPosition);
+ finalColor = pColor;
+ gl_PointSize = pSize;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl
new file mode 100644
index 00000000000..cb03ad44615
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl
@@ -0,0 +1,103 @@
+
+uniform float normalSize;
+uniform bool doMultiframe;
+uniform bool doStrokeEndpoints;
+uniform bool hideSelect;
+uniform bool doWeightColor;
+uniform float gpEditOpacity;
+uniform vec4 gpEditColor;
+uniform sampler1D weightTex;
+
+in vec3 pos;
+in float ma;
+in uint vflag;
+in float weight;
+
+out vec4 finalColor;
+
+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);
+}
+
+#define GP_EDIT_POINT_SELECTED (1u << 0u)
+#define GP_EDIT_STROKE_SELECTED (1u << 1u)
+#define GP_EDIT_MULTIFRAME (1u << 2u)
+#define GP_EDIT_STROKE_START (1u << 3u)
+#define GP_EDIT_STROKE_END (1u << 4u)
+
+#ifdef USE_POINTS
+# define colorUnselect colorGpencilVertex
+# define colorSelect colorGpencilVertexSelect
+#else
+# define colorUnselect gpEditColor
+# define colorSelect (hideSelect ? colorUnselect : colorGpencilVertexSelect)
+#endif
+
+vec3 weight_to_rgb(float t)
+{
+ if (t < 0.0) {
+ /* No weight */
+ return colorUnselect.rgb;
+ }
+ else if (t > 1.0) {
+ /* Error color */
+ return vec3(1.0, 0.0, 1.0);
+ }
+ else {
+ return texture(weightTex, t).rgb;
+ }
+}
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
+
+ bool is_multiframe = (vflag & GP_EDIT_MULTIFRAME) != 0u;
+ bool is_stroke_sel = (vflag & GP_EDIT_STROKE_SELECTED) != 0u;
+ bool is_point_sel = (vflag & GP_EDIT_POINT_SELECTED) != 0u;
+
+ if (doWeightColor) {
+ finalColor.rgb = weight_to_rgb(weight);
+ finalColor.a = gpEditOpacity;
+ }
+ else {
+ finalColor = (is_point_sel) ? colorSelect : colorUnselect;
+ finalColor.a *= gpEditOpacity;
+ }
+
+#ifdef USE_POINTS
+ gl_PointSize = sizeVertex * 2.0;
+
+ if (doStrokeEndpoints && !doWeightColor) {
+ bool is_stroke_start = (vflag & GP_EDIT_STROKE_START) != 0u;
+ bool is_stroke_end = (vflag & GP_EDIT_STROKE_END) != 0u;
+
+ if (is_stroke_start) {
+ gl_PointSize *= 2.0;
+ finalColor.rgb = vec3(0.0, 1.0, 0.0);
+ }
+ else if (is_stroke_end) {
+ gl_PointSize *= 1.5;
+ finalColor.rgb = vec3(1.0, 0.0, 0.0);
+ }
+ }
+
+ if ((!is_stroke_sel && !doWeightColor) || (!doMultiframe && is_multiframe)) {
+ discard_vert();
+ }
+#endif
+
+ /* Discard unwanted padding vertices. */
+ if (ma == -1.0 || (is_multiframe && !doMultiframe)) {
+ discard_vert();
+ }
+
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
+#endif
+}
diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
index f6e3724eb51..fdbce27b38d 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
@@ -1,10 +1,45 @@
+uniform vec4 gpDepthPlane;
+
flat in uint objectId;
/* using uint because 16bit uint can contain more ids than int. */
out uint outId;
+vec3 ray_plane_intersection(vec3 ray_ori, vec3 ray_dir, vec4 plane)
+{
+ float d = dot(plane.xyz, ray_dir);
+ vec3 plane_co = plane.xyz * (-plane.w / dot(plane.xyz, plane.xyz));
+ vec3 h = ray_ori - plane_co;
+ float lambda = -dot(plane.xyz, h) / ((abs(d) < 1e-8) ? 1e-8 : d);
+ return ray_ori + ray_dir * lambda;
+}
+
void main()
{
- outId = objectId;
+#ifdef USE_GPENCIL
+ if (stroke_round_cap_mask(strokePt1, strokePt2, strokeThickness) < 0.001) {
+ discard;
+ }
+
+ if (depth != -1.0) {
+ /* Stroke order 2D. */
+ bool is_persp = ProjectionMatrix[3][3] == 0.0;
+ vec2 uvs = vec2(gl_FragCoord.xy) * sizeViewportInv;
+ vec3 pos_ndc = vec3(uvs, gl_FragCoord.z) * 2.0 - 1.0;
+ vec4 pos_world = ViewProjectionMatrixInverse * vec4(pos_ndc, 1.0);
+ vec3 pos = pos_world.xyz / pos_world.w;
+
+ vec3 ray_ori = pos;
+ vec3 ray_dir = (is_persp) ? (ViewMatrixInverse[3].xyz - pos) : ViewMatrixInverse[2].xyz;
+ vec3 isect = ray_plane_intersection(ray_ori, ray_dir, gpDepthPlane);
+ vec4 ndc = point_world_to_ndc(isect);
+ gl_FragDepth = (ndc.z / ndc.w) * 0.5 + 0.5;
+ }
+ else {
+ gl_FragDepth = gl_FragCoord.z;
+ }
+#endif
+
+ outId = uint(objectId);
}
diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl
index 984e55b0c46..a2021759196 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl
@@ -1,7 +1,9 @@
uniform bool isTransform;
+#ifndef USE_GPENCIL
in vec3 pos;
+#endif
#ifdef USE_GEOM
out vec3 vPos;
@@ -47,11 +49,19 @@ uint outline_colorid_get(void)
void main()
{
+#ifdef USE_GPENCIL
+ gpencil_vertex();
+# ifdef USE_WORLD_CLIP_PLANES
+ vec3 world_pos = point_object_to_world(pos1.xyz);
+# endif
+
+#else
vec3 world_pos = point_object_to_world(pos);
-#ifdef USE_GEOM
+ gl_Position = point_world_to_ndc(world_pos);
+# ifdef USE_GEOM
vPos = point_world_to_view(world_pos);
+# endif
#endif
- gl_Position = point_world_to_ndc(world_pos);
/* Small bias to always be on top of the geom. */
gl_Position.z -= 1e-3;
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
index 4d705a4ee2b..3acaa1fbcbc 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
@@ -101,8 +101,10 @@ void wire_object_color_get(out vec3 rim_col, out vec3 wire_col)
void main()
{
+ bool no_attrib = all(equal(nor, vec3(0)));
+ vec3 wnor = no_attrib ? ViewMatrixInverse[2].xyz : normalize(normal_object_to_world(nor));
+
vec3 wpos = point_object_to_world(pos);
- vec3 wnor = normalize(normal_object_to_world(nor));
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
vec3 V = (is_persp) ? normalize(ViewMatrixInverse[3].xyz - wpos) : ViewMatrixInverse[2].xyz;
@@ -144,7 +146,7 @@ void main()
#endif
/* Cull flat edges below threshold. */
- if (get_edge_sharpness(wd) < 0.0) {
+ if (!no_attrib && (get_edge_sharpness(wd) < 0.0)) {
edgeStart = vec2(-1.0);
}
diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c
index 899fbdc9b71..26f37b764be 100644
--- a/source/blender/draw/engines/workbench/workbench_render.c
+++ b/source/blender/draw/engines/workbench/workbench_render.c
@@ -117,6 +117,60 @@ static bool workbench_render_framebuffers_init(void)
return ok;
}
+static void workbench_render_result_z(struct RenderLayer *rl,
+ const char *viewname,
+ const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ if ((view_layer->passflag & SCE_PASS_Z) != 0) {
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
+
+ GPU_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_read_depth(dfbl->default_fb,
+ rect->xmin,
+ rect->ymin,
+ BLI_rcti_size_x(rect),
+ BLI_rcti_size_y(rect),
+ rp->rect);
+
+ 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] */
+ 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] = -rp->rect[i] * range + near;
+ }
+ }
+ }
+ }
+}
+
static void workbench_render_framebuffers_finish(void)
{
}
@@ -197,8 +251,8 @@ void workbench_render(WORKBENCH_Data *data,
const char *viewname = RE_GetActiveRenderView(engine->re);
RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
- GPU_framebuffer_bind(dfbl->color_only_fb);
- GPU_framebuffer_read_color(dfbl->color_only_fb,
+ GPU_framebuffer_bind(dfbl->default_fb);
+ GPU_framebuffer_read_color(dfbl->default_fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
@@ -207,6 +261,8 @@ void workbench_render(WORKBENCH_Data *data,
0,
rp->rect);
+ workbench_render_result_z(render_layer, viewname, rect);
+
workbench_render_framebuffers_finish();
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index ddaf851324d..8e9a32c003b 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -305,8 +305,9 @@ typedef enum {
DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (1 << 20),
DRW_STATE_BLEND_OIT = (1 << 21),
DRW_STATE_BLEND_MUL = (1 << 22),
+ DRW_STATE_BLEND_SUB = (1 << 23),
/** Use dual source blending. WARNING: Only one color buffer allowed. */
- DRW_STATE_BLEND_CUSTOM = (1 << 23),
+ DRW_STATE_BLEND_CUSTOM = (1 << 24),
DRW_STATE_IN_FRONT_SELECT = (1 << 25),
DRW_STATE_LOGIC_INVERT = (1 << 26),
@@ -387,10 +388,10 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
#define DRW_shgroup_call_no_cull(shgrp, geom, ob) \
DRW_shgroup_call_ex(shgrp, ob, NULL, geom, true, NULL)
-void DRW_shgroup_call_range(DRWShadingGroup *shgroup,
- struct GPUBatch *geom,
- uint v_sta,
- uint v_ct);
+void DRW_shgroup_call_range(
+ DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint v_sta, uint v_ct);
+void DRW_shgroup_call_instance_range(
+ DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint v_sta, uint v_ct);
void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_ct);
void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_ct);
@@ -427,6 +428,17 @@ void DRW_buffer_add_entry_array(DRWCallBuffer *buffer, const void *attr[], uint
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state);
+
+/* Reminders:
+ * - (compare_mask & reference) is what is tested against (compare_mask & stencil_value)
+ * stencil_value being the value stored in the stencil buffer.
+ * - (writemask & reference) is what gets written if the test condition is fullfiled.
+ **/
+void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
+ uint write_mask,
+ uint reference,
+ uint comp_mask);
+/* TODO remove this function. Obsolete version. mask is actually reference value. */
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask);
/* Issue a clear command. */
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 22fd22e4818..f21651dcfeb 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -136,6 +136,7 @@ static struct DRWShapeCache {
GPUBatch *drw_particle_cross;
GPUBatch *drw_particle_circle;
GPUBatch *drw_particle_axis;
+ GPUBatch *drw_gpencil_dummy_quad;
} SHC = {NULL};
void DRW_shape_cache_free(void)
@@ -737,6 +738,29 @@ GPUBatch *DRW_cache_normal_arrow_get(void)
}
/* -------------------------------------------------------------------- */
+/** \name Dummy vbos
+ *
+ * We need a dummy vbo containing the vertex count to draw instances ranges.
+ *
+ * \{ */
+
+GPUBatch *DRW_gpencil_dummy_buffer_get(void)
+{
+ if (SHC.drw_gpencil_dummy_quad == NULL) {
+ GPUVertFormat format = {0};
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 4);
+
+ SHC.drw_gpencil_dummy_quad = GPU_batch_create_ex(
+ GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_gpencil_dummy_quad;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Common Object API
* \{ */
@@ -783,6 +807,9 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
return DRW_cache_text_face_wireframe_get(ob);
case OB_MBALL:
return DRW_cache_mball_face_wireframe_get(ob);
+ case OB_GPENCIL: {
+ return DRW_cache_gpencil_face_wireframe_get(ob);
+ }
default:
return NULL;
}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 508a6f2c46d..5ad8d840fbf 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -29,6 +29,7 @@ struct ModifierData;
struct Object;
struct PTCacheEdit;
struct ParticleSystem;
+struct bGPDstroke;
void DRW_shape_cache_free(void);
void DRW_shape_cache_reset(void);
@@ -47,6 +48,9 @@ struct GPUBatch *DRW_cache_sphere_get(void);
struct GPUBatch *DRW_cache_screenspace_circle_get(void);
struct GPUBatch *DRW_cache_normal_arrow_get(void);
+/* Dummy VBOs */
+struct GPUBatch *DRW_gpencil_dummy_buffer_get(void);
+
/* Common Object */
struct GPUBatch *DRW_cache_object_all_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold);
@@ -197,4 +201,17 @@ struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob,
struct GPUBatch *DRW_cache_mball_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_mball_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+/* GPencil */
+struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob);
+struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob);
+
+struct GPUBatch *DRW_cache_gpencil_face_wireframe_get(struct Object *ob);
+
+struct bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(struct Object *ob);
+void DRW_cache_gpencil_sbuffer_clear(struct Object *ob);
+
#endif /* __DRAW_CACHE_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
new file mode 100644
index 00000000000..e77026e850a
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -0,0 +1,747 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "GPU_batch.h"
+#include "ED_gpencil.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "BLI_polyfill_2d.h"
+#include "BLI_hash.h"
+
+#include "draw_cache.h"
+#include "draw_cache_impl.h"
+
+/* ---------------------------------------------------------------------- */
+typedef struct GpencilBatchCache {
+ /** Instancing Data */
+ GPUVertBuf *vbo;
+ GPUVertBuf *vbo_col;
+ /** Fill Topology */
+ GPUIndexBuf *ibo;
+ /** Instancing Batches */
+ GPUBatch *stroke_batch;
+ GPUBatch *fill_batch;
+ GPUBatch *lines_batch;
+
+ /** Edit Mode */
+ GPUVertBuf *edit_vbo;
+ GPUBatch *edit_lines_batch;
+ GPUBatch *edit_points_batch;
+
+ /** Cache is dirty */
+ bool is_dirty;
+ /** Edit mode flag */
+ bool is_editmode;
+ /** Last cache frame */
+ int cache_frame;
+} GpencilBatchCache;
+
+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_dirty) {
+ /* TODO, maybe get rid of the other dirty flags. */
+ valid = false;
+ }
+
+ return valid;
+}
+
+static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ GpencilBatchCache *cache = gpd->runtime.gpencil_cache;
+
+ if (!cache) {
+ cache = gpd->runtime.gpencil_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);
+ cache->is_dirty = true;
+ cache->cache_frame = cfra;
+ return cache;
+}
+
+static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
+{
+ if (!cache) {
+ return;
+ }
+
+ GPU_BATCH_DISCARD_SAFE(cache->lines_batch);
+ GPU_BATCH_DISCARD_SAFE(cache->fill_batch);
+ GPU_BATCH_DISCARD_SAFE(cache->stroke_batch);
+ GPU_VERTBUF_DISCARD_SAFE(cache->vbo);
+ GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo);
+
+ GPU_BATCH_DISCARD_SAFE(cache->edit_lines_batch);
+ GPU_BATCH_DISCARD_SAFE(cache->edit_points_batch);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_vbo);
+
+ cache->is_dirty = true;
+}
+
+static GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ GpencilBatchCache *cache = gpd->runtime.gpencil_cache;
+ if (!gpencil_batch_cache_valid(cache, gpd, cfra)) {
+ gpencil_batch_cache_clear(cache);
+ return gpencil_batch_cache_init(ob, cfra);
+ }
+ else {
+ return cache;
+ }
+}
+
+void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
+{
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+}
+
+void DRW_gpencil_batch_cache_free(bGPdata *gpd)
+{
+ gpencil_batch_cache_clear(gpd->runtime.gpencil_cache);
+ MEM_SAFE_FREE(gpd->runtime.gpencil_cache);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ return;
+}
+
+void DRW_gpencil_freecache(struct Object *ob)
+{
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd) {
+ DRW_gpencil_batch_cache_free(gpd);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Vertex Formats.
+ * \{ */
+
+/* MUST match the format below. */
+typedef struct gpStrokeVert {
+ /** Mat is float because we need to pack other float attribs with it. */
+ float mat, strength, stroke_id, point_id;
+ /** Position and thickness packed in the same attribute. */
+ float pos[3], thickness;
+ float uv_fill[2], u_stroke, v_rot;
+} gpStrokeVert;
+
+static GPUVertFormat *gpencil_stroke_format(void)
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "ma", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ /* IMPORTANT: This means having only 4 attributes to fit into GPU module limit of 16 attrib. */
+ GPU_vertformat_multiload_enable(&format, 4);
+ }
+ return &format;
+}
+
+/* MUST match the format below. */
+typedef struct gpEditVert {
+ uint vflag;
+ float weight;
+} gpEditVert;
+
+static GPUVertFormat *gpencil_edit_stroke_format(void)
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "vflag", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+ return &format;
+}
+
+/* MUST match the format below. */
+typedef struct gpColorVert {
+ float vcol[4]; /* Vertex color */
+ float fcol[4]; /* Fill color */
+} gpColorVert;
+
+static GPUVertFormat *gpencil_color_format(void)
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "fcol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ /* IMPORTANT: This means having only 4 attributes to fit into GPU module limit of 16 attrib. */
+ GPU_vertformat_multiload_enable(&format, 4);
+ }
+ return &format;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Vertex Buffers.
+ * \{ */
+
+typedef struct gpIterData {
+ bGPdata *gpd;
+ gpStrokeVert *verts;
+ gpColorVert *cols;
+ GPUIndexBufBuilder ibo;
+ int vert_len;
+ int tri_len;
+} gpIterData;
+
+static GPUVertBuf *gpencil_dummy_buffer_get(void)
+{
+ GPUBatch *batch = DRW_gpencil_dummy_buffer_get();
+ return batch->verts[0];
+}
+
+static int gpencil_stroke_is_cyclic(const bGPDstroke *gps)
+{
+ return ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2);
+}
+
+static void gpencil_buffer_add_point(gpStrokeVert *verts,
+ gpColorVert *cols,
+ const bGPDstroke *gps,
+ const bGPDspoint *pt,
+ int v,
+ bool is_endpoint)
+{
+ /* Note: we use the sign of stength and thickness to pass cap flag. */
+ const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND);
+ const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND);
+ gpStrokeVert *vert = &verts[v];
+ gpColorVert *col = &cols[v];
+ copy_v3_v3(vert->pos, &pt->x);
+ copy_v2_v2(vert->uv_fill, pt->uv_fill);
+ copy_v4_v4(col->vcol, pt->vert_color);
+ copy_v4_v4(col->fcol, gps->vert_color_fill);
+
+ /* Encode fill opacity defined by opacity modifier in vertex color alpha. If
+ * no opacity modifier, the value will be always 1.0f. The opacity factor can be any
+ * value between 0.0f and 2.0f */
+ col->fcol[3] = (((int)(col->fcol[3] * 10000.0f)) * 10.0f) + gps->fill_opacity_fac;
+
+ vert->strength = (round_cap0) ? pt->strength : -pt->strength;
+ vert->u_stroke = pt->uv_fac;
+ vert->stroke_id = gps->runtime.stroke_start;
+ vert->point_id = v;
+ /* Rotation are in [-90°..90°] range, so we can encode the sign of the angle + the cosine
+ * because the cosine will always be positive. */
+ vert->v_rot = cosf(pt->uv_rot) * signf(pt->uv_rot);
+ vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0 : -1.0);
+ /* Tag endpoint material to -1 so they get discarded by vertex shader. */
+ vert->mat = (is_endpoint) ? -1 : (gps->mat_nr % GP_MATERIAL_BUFFER_LEN);
+}
+
+static void gpencil_buffer_add_stroke(gpStrokeVert *verts,
+ gpColorVert *cols,
+ const bGPDstroke *gps)
+{
+ const bGPDspoint *pts = gps->points;
+ int pts_len = gps->totpoints;
+ bool is_cyclic = gpencil_stroke_is_cyclic(gps);
+ int v = gps->runtime.stroke_start;
+
+ /* First point for adjacency (not drawn). */
+ int adj_idx = (is_cyclic) ? (pts_len - 1) : min_ii(pts_len - 1, 1);
+ gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true);
+
+ for (int i = 0; i < pts_len; i++) {
+ gpencil_buffer_add_point(verts, cols, gps, &pts[i], v++, false);
+ }
+ /* Draw line to first point to complete the loop for cyclic strokes. */
+ if (is_cyclic) {
+ gpencil_buffer_add_point(verts, cols, gps, &pts[0], v++, false);
+ }
+ /* Last adjacency point (not drawn). */
+ adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2);
+ gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true);
+}
+
+static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps)
+{
+ int tri_len = gps->tot_triangles;
+ int v = gps->runtime.stroke_start;
+ for (int i = 0; i < tri_len; i++) {
+ uint *tri = gps->triangles[i].verts;
+ GPU_indexbuf_add_tri_verts(ibo, v + tri[0], v + tri[1], v + tri[2]);
+ }
+}
+
+static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ gpIterData *iter = (gpIterData *)thunk;
+ gpencil_buffer_add_stroke(iter->verts, iter->cols, gps);
+ if (gps->tot_triangles > 0) {
+ gpencil_buffer_add_fill(&iter->ibo, gps);
+ }
+}
+
+static void gp_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ gpIterData *iter = (gpIterData *)thunk;
+
+ /* Store first index offset */
+ gps->runtime.stroke_start = iter->vert_len;
+ gps->runtime.fill_start = iter->tri_len;
+ iter->vert_len += gps->totpoints + 2 + gpencil_stroke_is_cyclic(gps);
+ iter->tri_len += gps->tot_triangles;
+}
+
+static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ if (cache->vbo == NULL) {
+ /* Should be discarded together. */
+ BLI_assert(cache->vbo == NULL && cache->ibo == NULL);
+ BLI_assert(cache->stroke_batch == NULL && cache->stroke_batch == NULL);
+ /* TODO/PERF: Could be changed to only do it if needed.
+ * For now it's simpler to assume we always need it
+ * since multiple viewport could or could not need it.
+ * Ideally we should have a dedicated onion skin geom batch. */
+ /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
+ bool do_onion = true;
+
+ /* First count how many vertices and triangles are needed for the whole object. */
+ gpIterData iter = {
+ .gpd = gpd,
+ .verts = NULL,
+ .ibo = {0},
+ .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
+ .tri_len = 0,
+ };
+ BKE_gpencil_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
+
+ /* Create VBOs. */
+ GPUVertFormat *format = gpencil_stroke_format();
+ GPUVertFormat *format_col = gpencil_color_format();
+ cache->vbo = GPU_vertbuf_create_with_format(format);
+ cache->vbo_col = GPU_vertbuf_create_with_format(format_col);
+ /* Add extra space at the end of the buffer because of quad load. */
+ GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2);
+ GPU_vertbuf_data_alloc(cache->vbo_col, iter.vert_len + 2);
+ iter.verts = (gpStrokeVert *)cache->vbo->data;
+ iter.cols = (gpColorVert *)cache->vbo_col->data;
+ /* Create IBO. */
+ GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
+
+ /* Fill buffers with data. */
+ BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
+
+ /* Mark last 2 verts as invalid. */
+ for (int i = 0; i < 2; i++) {
+ iter.verts[iter.vert_len + i].mat = -1;
+ }
+
+ /* Finish the IBO. */
+ cache->ibo = GPU_indexbuf_build(&iter.ibo);
+
+ /* Create the batches */
+ cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
+ GPU_batch_vertbuf_add(cache->fill_batch, cache->vbo_col);
+ cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
+ GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0);
+ GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo_col, 0);
+
+ gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
+ cache->is_dirty = false;
+ }
+}
+
+GPUBatch *DRW_cache_gpencil_strokes_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+
+ return cache->stroke_batch;
+}
+
+GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+
+ return cache->fill_batch;
+}
+
+static void gp_lines_indices_cb(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ gpIterData *iter = (gpIterData *)thunk;
+ int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps);
+
+ int start = gps->runtime.stroke_start + 1;
+ int end = start + pts_len;
+ for (int i = start; i < end; i++) {
+ GPU_indexbuf_add_generic_vert(&iter->ibo, i);
+ }
+ GPU_indexbuf_add_primitive_restart(&iter->ibo);
+}
+
+GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ int cfra = DEG_get_ctime(draw_ctx->depsgraph);
+
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+
+ if (cache->lines_batch == NULL) {
+ GPUVertBuf *vbo = cache->vbo;
+
+ gpIterData iter = {
+ .gpd = ob->data,
+ .ibo = {0},
+ };
+
+ GPU_indexbuf_init_ex(&iter.ibo, GPU_PRIM_LINE_STRIP, vbo->vertex_len, vbo->vertex_len);
+
+ /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
+ bool do_onion = true;
+ BKE_gpencil_visible_stroke_iter(ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
+
+ GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo);
+
+ cache->lines_batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, vbo, ibo, GPU_BATCH_OWNS_INDEX);
+ }
+ return cache->lines_batch;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Sbuffer stroke batches.
+ * \{ */
+
+bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ /* Convert the sbuffer to a bGPDstroke. */
+ if (gpd->runtime.sbuffer_gps == NULL) {
+ bGPDstroke *gps = MEM_callocN(sizeof(*gps), "bGPDstroke sbuffer");
+ gps->totpoints = gpd->runtime.sbuffer_used;
+ gps->mat_nr = max_ii(0, gpd->runtime.matid - 1);
+ gps->flag = gpd->runtime.sbuffer_sflag;
+ gps->thickness = gpd->runtime.brush_size;
+ /* Reduce slightly the opacity of fill to make easy fill areas while drawing. */
+ gps->fill_opacity_fac = 0.8f;
+
+ gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2);
+ gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND;
+ gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */
+ copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill);
+ gpd->runtime.sbuffer_gps = gps;
+ }
+ return gpd->runtime.sbuffer_gps;
+}
+
+/* gpd is original ID. */
+static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_fill)
+{
+ tGPspoint *tpoints = gpd->runtime.sbuffer;
+ bGPDstroke *gps = gpd->runtime.sbuffer_gps;
+ int vert_len = gpd->runtime.sbuffer_used;
+
+ /* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */
+ BLI_assert(gps != NULL);
+
+ if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) {
+ gps->points = MEM_mallocN(vert_len * sizeof(*gps->points), __func__);
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ ARegion *ar = draw_ctx->ar;
+ Object *ob = draw_ctx->obact;
+
+ BLI_assert(ob && (ob->type == OB_GPENCIL));
+
+ /* Get origin to reproject points. */
+ float origin[3];
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+ ToolSettings *ts = scene->toolsettings;
+ ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, origin);
+
+ for (int i = 0; i < vert_len; i++) {
+ ED_gpencil_tpoint_to_point(ar, origin, &tpoints[i], &gps->points[i]);
+ mul_m4_v3(ob->imat, &gps->points[i].x);
+ bGPDspoint *pt = &gps->points[i];
+ copy_v4_v4(pt->vert_color, gpd->runtime.vert_color);
+ }
+ /* Calc uv data along the stroke. */
+ BKE_gpencil_stroke_uv_update(gps);
+
+ /* Create VBO. */
+ GPUVertFormat *format = gpencil_stroke_format();
+ GPUVertFormat *format_color = gpencil_color_format();
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format);
+ GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(format_color);
+ /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */
+ GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2);
+ GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2);
+ gpStrokeVert *verts = (gpStrokeVert *)vbo->data;
+ gpColorVert *cols = (gpColorVert *)vbo_col->data;
+
+ /* Fill buffers with data. */
+ gpencil_buffer_add_stroke(verts, cols, gps);
+
+ GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
+ GPU_batch_instbuf_add_ex(batch, vbo, true);
+ GPU_batch_instbuf_add_ex(batch, vbo_col, true);
+
+ gpd->runtime.sbuffer_stroke_batch = batch;
+
+ MEM_freeN(gps->points);
+ }
+
+ if (do_fill && (gpd->runtime.sbuffer_fill_batch == NULL)) {
+ /* Create IBO. */
+ GPUIndexBufBuilder ibo_builder;
+ GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len);
+
+ if (gps->tot_triangles > 0) {
+ float(*tpoints2d)[2] = MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__);
+ /* Triangulate in 2D. */
+ for (int i = 0; i < vert_len; i++) {
+ copy_v2_v2(tpoints2d[i], &tpoints[i].x);
+ }
+ /* Compute directly inside the IBO data buffer. */
+ /* OPTI: This is a bottleneck if the stroke is very long. */
+ BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data);
+ /* Add stroke start offset. */
+ for (int i = 0; i < gps->tot_triangles * 3; i++) {
+ ibo_builder.data[i] += gps->runtime.stroke_start;
+ }
+ /* HACK since we didn't use the builder API to avoid another malloc and copy,
+ * we need to set the number of indices manually. */
+ ibo_builder.index_len = gps->tot_triangles * 3;
+
+ MEM_freeN(tpoints2d);
+ }
+
+ GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder);
+ GPUVertBuf *vbo = gpd->runtime.sbuffer_stroke_batch->inst[0];
+ GPUVertBuf *vbo_col = gpd->runtime.sbuffer_stroke_batch->inst[1];
+
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, ibo, GPU_BATCH_OWNS_INDEX);
+ GPU_batch_vertbuf_add(batch, vbo_col);
+
+ gpd->runtime.sbuffer_fill_batch = batch;
+ }
+}
+
+GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ gpencil_sbuffer_stroke_ensure(gpd, true, false);
+
+ return gpd->runtime.sbuffer_stroke_batch;
+}
+
+GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ /* Fill batch also need stroke batch to be created (vbo is shared). */
+ gpencil_sbuffer_stroke_ensure(gpd, true, true);
+
+ return gpd->runtime.sbuffer_fill_batch;
+}
+
+/* Sbuffer batches are temporary. We need to clear it after drawing */
+void DRW_cache_gpencil_sbuffer_clear(Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ MEM_SAFE_FREE(gpd->runtime.sbuffer_gps);
+ GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_fill_batch);
+ GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_stroke_batch);
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/* Edit GPencil Batches */
+
+#define GP_EDIT_POINT_SELECTED (1 << 0)
+#define GP_EDIT_STROKE_SELECTED (1 << 1)
+#define GP_EDIT_MULTIFRAME (1 << 2)
+#define GP_EDIT_STROKE_START (1 << 3)
+#define GP_EDIT_STROKE_END (1 << 4)
+
+typedef struct gpEditIterData {
+ gpEditVert *verts;
+ int vgindex;
+} gpEditIterData;
+
+static uint32_t gpencil_point_edit_flag(const bGPDspoint *pt, int v, int v_len)
+{
+ uint32_t sflag = 0;
+ SET_FLAG_FROM_TEST(sflag, pt->flag & GP_SPOINT_SELECT, GP_EDIT_POINT_SELECTED);
+ SET_FLAG_FROM_TEST(sflag, v == 0, GP_EDIT_STROKE_START);
+ SET_FLAG_FROM_TEST(sflag, v == (v_len - 1), GP_EDIT_STROKE_END);
+ return sflag;
+}
+
+static float gpencil_point_edit_weight(const MDeformVert *dvert, int v, int vgindex)
+{
+ return (dvert && dvert[v].dw) ? defvert_find_weight(&dvert[v], vgindex) : -1.0f;
+}
+
+static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl,
+ bGPDframe *gpf,
+ bGPDstroke *gps,
+ void *thunk)
+{
+ /* Cancel if layer is locked. */
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ return;
+ }
+
+ gpEditIterData *iter = (gpEditIterData *)thunk;
+ const int v_len = gps->totpoints;
+ const int v = gps->runtime.stroke_start + 1;
+ MDeformVert *dvert = ((iter->vgindex > -1) && gps->dvert) ? gps->dvert : NULL;
+ gpEditVert *vert_ptr = iter->verts + v;
+
+ uint32_t sflag = 0;
+ SET_FLAG_FROM_TEST(sflag, gps->flag & GP_STROKE_SELECT, GP_EDIT_STROKE_SELECTED);
+ SET_FLAG_FROM_TEST(sflag, gpf->runtime.onion_id != 0.0f, GP_EDIT_MULTIFRAME);
+
+ for (int i = 0; i < v_len; i++) {
+ vert_ptr->vflag = sflag | gpencil_point_edit_flag(&gps->points[i], i, v_len);
+ vert_ptr->weight = gpencil_point_edit_weight(dvert, i, iter->vgindex);
+ vert_ptr++;
+ }
+ /* Draw line to first point to complete the loop for cyclic strokes. */
+ vert_ptr->vflag = sflag | gpencil_point_edit_flag(&gps->points[0], 0, v_len);
+ vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex);
+}
+
+static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ if (cache->edit_vbo == NULL) {
+ /* TODO/PERF: Could be changed to only do it if needed.
+ * For now it's simpler to assume we always need it
+ * since multiple viewport could or could not need it.
+ * Ideally we should have a dedicated onion skin geom batch. */
+ /* IMPORTANT: Keep in sync with gpencil_batches_ensure() */
+ bool do_onion = true;
+
+ /* Vertex counting has already been done for cache->vbo. */
+ BLI_assert(cache->vbo);
+ int vert_len = cache->vbo->vertex_len;
+
+ gpEditIterData iter;
+ iter.vgindex = ob->actdef - 1;
+ if (!BLI_findlink(&ob->defbase, iter.vgindex)) {
+ iter.vgindex = -1;
+ }
+
+ /* Create VBO. */
+ GPUVertFormat *format = gpencil_edit_stroke_format();
+ cache->edit_vbo = GPU_vertbuf_create_with_format(format);
+ /* Add extra space at the end of the buffer because of quad load. */
+ GPU_vertbuf_data_alloc(cache->edit_vbo, vert_len);
+ iter.verts = (gpEditVert *)cache->edit_vbo->data;
+
+ /* Fill buffers with data. */
+ BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
+
+ /* Create the batches */
+ cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL);
+ GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo);
+
+ cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL);
+ GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo);
+
+ gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
+ cache->is_dirty = false;
+ }
+}
+
+GPUBatch *DRW_cache_gpencil_edit_lines_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+ gpencil_edit_batches_ensure(ob, cache, cfra);
+
+ return cache->edit_lines_batch;
+}
+
+GPUBatch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+ gpencil_edit_batches_ensure(ob, cache, cfra);
+
+ return cache->edit_points_batch;
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 65365ef7119..561edfae513 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -72,6 +72,8 @@ void DRW_globals_update(void)
UI_COLOR_RGBA_FROM_U8(0xB0, 0x00, 0xB0, 0xFF, gb->colorVertexMissingData);
UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, gb->colorEditMeshActive);
UI_GetThemeColor4fv(TH_EDGE_SELECT, gb->colorEdgeSelect);
+ UI_GetThemeColor4fv(TH_GP_VERTEX, gb->colorGpencilVertex);
+ UI_GetThemeColor4fv(TH_GP_VERTEX_SELECT, gb->colorGpencilVertexSelect);
UI_GetThemeColor4fv(TH_EDGE_SEAM, gb->colorEdgeSeam);
UI_GetThemeColor4fv(TH_EDGE_SHARP, gb->colorEdgeSharp);
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 97afb5e6aa4..6507dd28903 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -68,6 +68,8 @@ typedef struct GlobalsUboStorage {
float colorFace[4];
float colorFaceSelect[4];
float colorFaceFreestyle[4];
+ float colorGpencilVertex[4];
+ float colorGpencilVertexSelect[4];
float colorNormal[4];
float colorVNormal[4];
float colorLNormal[4];
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 3dc775f92c4..deec62a2a8b 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1390,7 +1390,7 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer),
const bool use_xray = XRAY_ENABLED(v3d);
drw_engines_enable_from_engine(engine_type, drawtype, use_xray);
- if (gpencil_engine_needed) {
+ if (gpencil_engine_needed && ((drawtype >= OB_SOLID) || !use_xray)) {
use_drw_engine(&draw_engine_gpencil_type);
}
drw_engines_enable_overlays();
@@ -2370,13 +2370,6 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
}
- /* TODO: GPXX Workaround for grease pencil selection while draw manager support a callback from
- * scene finish */
- void *data = GPU_viewport_engine_data_get(DST.viewport, &draw_engine_gpencil_type);
- if (data != NULL) {
- DRW_gpencil_free_runtime_data(data);
- }
-
DRW_state_lock(0);
DRW_draw_callbacks_post_scene();
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f040afc794c..7e919b9e2df 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -181,7 +181,8 @@ typedef enum {
DRW_CMD_DRAW = 0, /* Only sortable type. Must be 0. */
DRW_CMD_DRAW_RANGE = 1,
DRW_CMD_DRAW_INSTANCE = 2,
- DRW_CMD_DRAW_PROCEDURAL = 3,
+ DRW_CMD_DRAW_INSTANCE_RANGE = 3,
+ DRW_CMD_DRAW_PROCEDURAL = 4,
/* Other Commands */
DRW_CMD_CLEAR = 12,
DRW_CMD_DRWSTATE = 13,
@@ -200,6 +201,7 @@ typedef struct DRWCommandDraw {
/* Assume DRWResourceHandle to be 0. */
typedef struct DRWCommandDrawRange {
GPUBatch *batch;
+ DRWResourceHandle handle;
uint vert_first;
uint vert_count;
} DRWCommandDrawRange;
@@ -211,6 +213,13 @@ typedef struct DRWCommandDrawInstance {
uint use_attribs; /* bool */
} DRWCommandDrawInstance;
+typedef struct DRWCommandDrawInstanceRange {
+ GPUBatch *batch;
+ DRWResourceHandle handle;
+ uint inst_first;
+ uint inst_count;
+} DRWCommandDrawInstanceRange;
+
typedef struct DRWCommandDrawProcedural {
GPUBatch *batch;
DRWResourceHandle handle;
@@ -224,7 +233,9 @@ typedef struct DRWCommandSetMutableState {
} DRWCommandSetMutableState;
typedef struct DRWCommandSetStencil {
- uint mask;
+ uint write_mask;
+ uint comp_mask;
+ uint ref;
} DRWCommandSetStencil;
typedef struct DRWCommandSetSelectID {
@@ -243,6 +254,7 @@ typedef union DRWCommand {
DRWCommandDraw draw;
DRWCommandDrawRange range;
DRWCommandDrawInstance instance;
+ DRWCommandDrawInstanceRange instance_range;
DRWCommandDrawProcedural procedural;
DRWCommandSetMutableState state;
DRWCommandSetStencil stencil;
@@ -273,6 +285,7 @@ typedef enum {
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
DRW_UNIFORM_RESOURCE_CHUNK,
+ DRW_UNIFORM_RESOURCE_ID,
/** Legacy / Fallback */
DRW_UNIFORM_BASE_INSTANCE,
DRW_UNIFORM_MODEL_MATRIX,
@@ -467,7 +480,6 @@ typedef struct DRWManager {
/* Managed by `DRW_state_set`, `DRW_state_reset` */
DRWState state;
DRWState state_lock;
- uint stencil_mask;
/* Per viewport */
GPUViewport *viewport;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index f9a6b663900..2612d02691d 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -636,13 +636,12 @@ static void drw_command_draw(DRWShadingGroup *shgroup, GPUBatch *batch, DRWResou
cmd->handle = handle;
}
-static void drw_command_draw_range(DRWShadingGroup *shgroup,
- GPUBatch *batch,
- uint start,
- uint count)
+static void drw_command_draw_range(
+ DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle, uint start, uint count)
{
DRWCommandDrawRange *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_RANGE);
cmd->batch = batch;
+ cmd->handle = handle;
cmd->vert_first = start;
cmd->vert_count = count;
}
@@ -660,6 +659,16 @@ static void drw_command_draw_instance(DRWShadingGroup *shgroup,
cmd->use_attribs = use_attrib;
}
+static void drw_command_draw_intance_range(
+ DRWShadingGroup *shgroup, GPUBatch *batch, DRWResourceHandle handle, uint start, uint count)
+{
+ DRWCommandDrawInstanceRange *cmd = drw_command_create(shgroup, DRW_CMD_DRAW_INSTANCE_RANGE);
+ cmd->batch = batch;
+ cmd->handle = handle;
+ cmd->inst_first = start;
+ cmd->inst_count = count;
+}
+
static void drw_command_draw_procedural(DRWShadingGroup *shgroup,
GPUBatch *batch,
DRWResourceHandle handle,
@@ -680,11 +689,18 @@ static void drw_command_set_select_id(DRWShadingGroup *shgroup, GPUVertBuf *buf,
cmd->select_id = select_id;
}
-static void drw_command_set_stencil_mask(DRWShadingGroup *shgroup, uint mask)
+static void drw_command_set_stencil_mask(DRWShadingGroup *shgroup,
+ uint write_mask,
+ uint reference,
+ uint comp_mask)
{
- BLI_assert(mask <= 0xFF);
+ BLI_assert(write_mask <= 0xFF);
+ BLI_assert(reference <= 0xFF);
+ BLI_assert(comp_mask <= 0xFF);
DRWCommandSetStencil *cmd = drw_command_create(shgroup, DRW_CMD_STENCIL);
- cmd->mask = mask;
+ cmd->write_mask = write_mask;
+ cmd->comp_mask = comp_mask;
+ cmd->ref = reference;
}
static void drw_command_clear(DRWShadingGroup *shgroup,
@@ -745,13 +761,27 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
}
}
-void DRW_shgroup_call_range(DRWShadingGroup *shgroup, struct GPUBatch *geom, uint v_sta, uint v_ct)
+void DRW_shgroup_call_range(
+ DRWShadingGroup *shgroup, struct Object *ob, GPUBatch *geom, uint v_sta, uint v_ct)
+{
+ BLI_assert(geom != NULL);
+ if (G.f & G_FLAG_PICKSEL) {
+ drw_command_set_select_id(shgroup, NULL, DST.select_id);
+ }
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
+ drw_command_draw_range(shgroup, geom, handle, v_sta, v_ct);
+}
+
+void DRW_shgroup_call_instance_range(
+ DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint i_sta, uint i_ct)
{
+ BLI_assert(i_ct > 0);
BLI_assert(geom != NULL);
if (G.f & G_FLAG_PICKSEL) {
drw_command_set_select_id(shgroup, NULL, DST.select_id);
}
- drw_command_draw_range(shgroup, geom, v_sta, v_ct);
+ DRWResourceHandle handle = drw_resource_handle(shgroup, ob ? ob->obmat : NULL, ob);
+ drw_command_draw_intance_range(shgroup, geom, handle, i_sta, i_ct);
}
static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
@@ -1104,12 +1134,18 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
int info_ubo_location = GPU_shader_get_uniform_block(shader, "infoBlock");
int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE);
int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK);
+ int resourceid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_ID);
if (chunkid_location != -1) {
drw_shgroup_uniform_create_ex(
shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 1);
}
+ if (resourceid_location != -1) {
+ drw_shgroup_uniform_create_ex(
+ shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 1);
+ }
+
if (baseinst_location != -1) {
drw_shgroup_uniform_create_ex(
shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 1);
@@ -1308,9 +1344,18 @@ void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
drw_command_set_mutable_state(shgroup, 0x0, state);
}
+void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
+ uint write_mask,
+ uint reference,
+ uint comp_mask)
+{
+ drw_command_set_stencil_mask(shgroup, write_mask, reference, comp_mask);
+}
+
+/* TODO remove this function. */
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
{
- drw_command_set_stencil_mask(shgroup, mask);
+ drw_command_set_stencil_mask(shgroup, 0xFF, mask, 0xFF);
}
void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup,
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 75d5a5c73b9..7bcb0b0f86d 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -50,6 +50,7 @@ void DRW_select_load_id(uint id)
typedef struct DRWCommandsState {
GPUBatch *batch;
int resource_chunk;
+ int resource_id;
int base_inst;
int inst_count;
int v_first;
@@ -60,6 +61,7 @@ typedef struct DRWCommandsState {
int obinfos_loc;
int baseinst_loc;
int chunkid_loc;
+ int resourceid_loc;
/* Legacy matrix support. */
int obmat_loc;
int obinv_loc;
@@ -221,7 +223,6 @@ void drw_state_set(DRWState state)
{
int test;
if (CHANGED_ANY_STORE_VAR(DRW_STATE_STENCIL_TEST_ENABLED, test)) {
- DST.stencil_mask = STENCIL_UNDEFINED;
if (test) {
glEnable(GL_STENCIL_TEST);
}
@@ -234,11 +235,11 @@ void drw_state_set(DRWState state)
/* Blending (all buffer) */
{
int test;
- if (CHANGED_ANY_STORE_VAR(DRW_STATE_BLEND_ALPHA | DRW_STATE_BLEND_ALPHA_PREMUL |
- DRW_STATE_BLEND_ADD | DRW_STATE_BLEND_MUL |
- DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_OIT |
- DRW_STATE_BLEND_ALPHA_UNDER_PREMUL | DRW_STATE_BLEND_CUSTOM,
- test)) {
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_BLEND_ALPHA | DRW_STATE_BLEND_ALPHA_PREMUL | DRW_STATE_BLEND_ADD |
+ DRW_STATE_BLEND_MUL | DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_OIT |
+ DRW_STATE_BLEND_ALPHA_UNDER_PREMUL | DRW_STATE_BLEND_CUSTOM | DRW_STATE_BLEND_SUB,
+ test)) {
if (test) {
glEnable(GL_BLEND);
@@ -274,6 +275,9 @@ void drw_state_set(DRWState state)
/* Let alpha accumulate. */
glBlendFunc(GL_ONE, GL_ONE);
}
+ else if ((state & DRW_STATE_BLEND_SUB) != 0) {
+ glBlendFunc(GL_ONE, GL_ONE);
+ }
else if ((state & DRW_STATE_BLEND_CUSTOM) != 0) {
/* Custom blend parameters using dual source blending.
* Can only be used with one Draw Buffer. */
@@ -282,6 +286,13 @@ void drw_state_set(DRWState state)
else {
BLI_assert(0);
}
+
+ if ((state & DRW_STATE_BLEND_SUB) != 0) {
+ glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+ }
+ else {
+ glBlendEquation(GL_FUNC_ADD);
+ }
}
else {
glDisable(GL_BLEND);
@@ -389,19 +400,23 @@ void drw_state_set(DRWState state)
DST.state = state;
}
-static void drw_stencil_set(uint mask)
+static void drw_stencil_state_set(uint write_mask, uint reference, uint compare_mask)
{
- if (DST.stencil_mask != mask) {
- DST.stencil_mask = mask;
- if ((DST.state & DRW_STATE_STENCIL_ALWAYS) != 0) {
- glStencilFunc(GL_ALWAYS, mask, 0xFF);
- }
- else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
- glStencilFunc(GL_EQUAL, mask, 0xFF);
- }
- else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) {
- glStencilFunc(GL_NOTEQUAL, mask, 0xFF);
- }
+ /* Reminders:
+ * - (compare_mask & reference) is what is tested against (compare_mask & stencil_value)
+ * stencil_value being the value stored in the stencil buffer.
+ * - (writemask & reference) is what gets written if the test condition is fullfiled.
+ **/
+ glStencilMask(write_mask);
+
+ if ((DST.state & DRW_STATE_STENCIL_ALWAYS) != 0) {
+ glStencilFunc(GL_ALWAYS, reference, compare_mask);
+ }
+ else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
+ glStencilFunc(GL_EQUAL, reference, compare_mask);
+ }
+ else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) {
+ glStencilFunc(GL_NOTEQUAL, reference, compare_mask);
}
}
@@ -982,6 +997,9 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
state->chunkid_loc = uni->location;
GPU_shader_uniform_int(shgroup->shader, uni->location, 0);
break;
+ case DRW_UNIFORM_RESOURCE_ID:
+ state->resourceid_loc = uni->location;
+ break;
case DRW_UNIFORM_TFEEDBACK_TARGET:
BLI_assert(data && (*use_tfeedback == false));
*use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
@@ -1095,6 +1113,14 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa
}
state->resource_chunk = chunk;
}
+
+ if (state->resourceid_loc != -1) {
+ int id = DRW_handle_id_get(handle);
+ if (state->resource_id != id) {
+ GPU_shader_uniform_int(NULL, state->resourceid_loc, id);
+ state->resource_id = id;
+ }
+ }
}
static void draw_call_batching_flush(DRWShadingGroup *shgroup, DRWCommandsState *state)
@@ -1113,6 +1139,7 @@ static void draw_call_single_do(DRWShadingGroup *shgroup,
DRWResourceHandle handle,
int vert_first,
int vert_count,
+ int inst_first,
int inst_count,
bool do_base_instance)
{
@@ -1141,7 +1168,7 @@ static void draw_call_single_do(DRWShadingGroup *shgroup,
batch,
vert_first,
vert_count,
- do_base_instance ? DRW_handle_id_get(&handle) : 0,
+ do_base_instance ? DRW_handle_id_get(&handle) : inst_first,
inst_count,
state->baseinst_loc);
}
@@ -1150,6 +1177,7 @@ static void draw_call_batching_start(DRWCommandsState *state)
{
state->neg_scale = false;
state->resource_chunk = 0;
+ state->resource_id = -1;
state->base_inst = 0;
state->inst_count = 0;
state->v_first = 0;
@@ -1226,6 +1254,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
.obinfos_loc = -1,
.baseinst_loc = -1,
.chunkid_loc = -1,
+ .resourceid_loc = -1,
.obmat_loc = -1,
.obinv_loc = -1,
.mvp_loc = -1,
@@ -1306,7 +1335,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
drw_state_set((pass_state & ~state.drw_state_disabled) | state.drw_state_enabled);
break;
case DRW_CMD_STENCIL:
- drw_stencil_set(cmd->stencil.mask);
+ drw_stencil_state_set(cmd->stencil.write_mask, cmd->stencil.ref, cmd->stencil.comp_mask);
break;
case DRW_CMD_SELECTID:
state.select_id = cmd->select_id.select_id;
@@ -1314,8 +1343,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
break;
case DRW_CMD_DRAW:
if (!USE_BATCHING || state.obmats_loc == -1 || (G.f & G_FLAG_PICKSEL) ||
- cmd->draw.batch->inst[0]) {
- draw_call_single_do(shgroup, &state, cmd->draw.batch, cmd->draw.handle, 0, 0, 0, true);
+ cmd->draw.batch->inst) {
+ draw_call_single_do(
+ shgroup, &state, cmd->draw.batch, cmd->draw.handle, 0, 0, 0, 0, true);
}
else {
draw_call_batching_do(shgroup, &state, &cmd->draw);
@@ -1328,6 +1358,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
cmd->procedural.handle,
0,
cmd->procedural.vert_count,
+ 0,
1,
true);
break;
@@ -1338,6 +1369,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
cmd->instance.handle,
0,
0,
+ 0,
cmd->instance.inst_count,
cmd->instance.use_attribs == 0);
break;
@@ -1345,12 +1377,24 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
draw_call_single_do(shgroup,
&state,
cmd->range.batch,
- (DRWResourceHandle)0,
+ cmd->range.handle,
cmd->range.vert_first,
cmd->range.vert_count,
+ 0,
1,
true);
break;
+ case DRW_CMD_DRAW_INSTANCE_RANGE:
+ draw_call_single_do(shgroup,
+ &state,
+ cmd->instance_range.batch,
+ cmd->instance_range.handle,
+ 0,
+ 0,
+ cmd->instance_range.inst_first,
+ cmd->instance_range.inst_count,
+ false);
+ break;
}
}
diff --git a/source/blender/draw/intern/shaders/common_globals_lib.glsl b/source/blender/draw/intern/shaders/common_globals_lib.glsl
index 676492f227d..6ee0fe05721 100644
--- a/source/blender/draw/intern/shaders/common_globals_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_globals_lib.glsl
@@ -32,6 +32,8 @@ layout(std140) uniform globalsBlock
vec4 colorFace;
vec4 colorFaceSelect;
vec4 colorFaceFreestyle;
+ vec4 colorGpencilVertex;
+ vec4 colorGpencilVertexSelect;
vec4 colorNormal;
vec4 colorVNormal;
vec4 colorLNormal;
diff --git a/source/blender/draw/intern/shaders/common_smaa_lib.glsl b/source/blender/draw/intern/shaders/common_smaa_lib.glsl
index 09b573d4bb5..45d9f54d943 100644
--- a/source/blender/draw/intern/shaders/common_smaa_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_smaa_lib.glsl
@@ -692,6 +692,10 @@ void SMAANeighborhoodBlendingVS(float2 texcoord, out float4 offset)
//-----------------------------------------------------------------------------
// Edge Detection Pixel Shaders (First Pass)
+# ifndef SMAA_LUMA_WEIGHT
+# define SMAA_LUMA_WEIGHT float4(0.2126, 0.7152, 0.0722, 0.0)
+# endif
+
/**
* Luma Edge Detection
*
@@ -716,7 +720,8 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
# endif
// Calculate lumas:
- float4 weights = float4(0.2126 * 0.5, 0.7152 * 0.5, 0.0722 * 0.5, 0.5);
+ // float4 weights = float4(0.2126, 0.7152, 0.0722, 0.0);
+ float4 weights = SMAA_LUMA_WEIGHT;
float L = dot(SMAASamplePoint(colorTex, texcoord).rgba, weights);
float Lleft = dot(SMAASamplePoint(colorTex, offset[0].xy).rgba, weights);
@@ -727,9 +732,11 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
delta.xy = abs(L - float2(Lleft, Ltop));
float2 edges = step(threshold, delta.xy);
+# ifndef SMAA_NO_DISCARD
// Then discard if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0)
discard;
+# endif
// Calculate right and bottom deltas:
float Lright = dot(SMAASamplePoint(colorTex, offset[1].xy).rgba, weights);
@@ -793,9 +800,11 @@ float2 SMAAColorEdgeDetectionPS(float2 texcoord,
// We do the usual threshold:
float2 edges = step(threshold, delta.xy);
+# ifndef SMAA_NO_DISCARD
// Then discard if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0)
discard;
+# endif
// Calculate right and bottom deltas:
float3 Cright = SMAASamplePoint(colorTex, offset[1].xy).rgb;
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl
index 6605e1165d4..3faefd485bf 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -60,11 +60,11 @@ vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos)
vec2 perp = vec2(-edge.y, edge.x);
float dist = dot(perp, frag_co - edge_start);
/* Add 0.1 to diffenrentiate with cleared pixels. */
- return vec4(perp * 0.5 + 0.5, dist * 0.25 + 0.5 + 0.1, 0.0);
+ return vec4(perp * 0.5 + 0.5, dist * 0.25 + 0.5 + 0.1, 1.0);
}
else {
/* Default line if the origin is perfectly aligned with a pixel. */
- return vec4(1.0, 0.0, 0.5 + 0.1, 0.0);
+ return vec4(1.0, 0.0, 0.5 + 0.1, 1.0);
}
}
@@ -89,7 +89,14 @@ uniform int baseInstance;
# define instanceId gl_InstanceID
# endif
-# define resource_id (baseInstance + instanceId)
+# ifdef UNIFORM_RESOURCE_ID
+/* This is in the case we want to do a special instance drawcall but still want to have the
+ * right resourceId and all the correct ubo datas. */
+uniform int resourceId;
+# define resource_id resourceId
+# else
+# define resource_id (baseInstance + instanceId)
+# endif
/* Use this to declare and pass the value if
* the fragment shader uses the resource_id. */
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 2ec1634fa38..f5c0548eaa1 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -5089,24 +5089,32 @@ void ANIM_channel_draw_widgets(const bContext *C,
}
MEM_freeN(gp_rna_path);
- /* Mask Layer. */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- prop = RNA_struct_find_property(&ptr, "mask_layer");
- gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
- if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
- icon = (gpl->flag & GP_LAYER_USE_MASK) ? ICON_MOD_MASK : ICON_LAYER_ACTIVE;
- uiDefAutoButR(block,
- &ptr,
- prop,
- array_index,
- "",
- icon,
- offset + (width * 3),
- ymid,
- width,
- channel_height);
+ /* Mask Layer. */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ prop = RNA_struct_find_property(&ptr, "mask_layer");
+ gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
+ if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
+ icon = ICON_LAYER_ACTIVE;
+ if (gpl->flag & GP_LAYER_USE_MASK) {
+ if (gpl->flag & GP_LAYER_MASK_INVERT) {
+ icon = ICON_HOLDOUT_ON;
+ }
+ else {
+ icon = ICON_MOD_MASK;
+ }
}
- MEM_freeN(gp_rna_path);
+ uiDefAutoButR(block,
+ &ptr,
+ prop,
+ array_index,
+ "",
+ icon,
+ offset + (width * 3),
+ ymid,
+ width,
+ channel_height);
+ }
+ MEM_freeN(gp_rna_path);
/* Layer onion skinning switch. */
prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index e90289de963..ede32b5d08e 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -3135,7 +3135,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
if (gpl->flag & GP_LAYER_SELECT) {
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
/* update other layer status */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
BKE_gpencil_layer_autolock_set(gpd, false);
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
}
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 4162e92cfea..c9e3335d142 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -299,7 +299,7 @@ void ED_armature_bone_rename(Main *bmain,
if (ob->type == OB_GPENCIL) {
bGPdata *gpd = (bGPdata *)ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->parent != NULL) && (gpl->parent->data == arm)) {
if (STREQ(gpl->parsubstr, oldname)) {
BLI_strncpy(gpl->parsubstr, newname, MAXBONENAME);
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
index 6e91be862a9..4368a6256bb 100644
--- a/source/blender/editors/gpencil/annotate_draw.c
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -33,6 +33,7 @@
#include "BLI_sys_types.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLF_api.h"
@@ -562,7 +563,7 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd),
{
GPU_program_point_size(true);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if stroke can be drawn */
if (annotation_can_draw_stroke(gps, dflag) == false) {
continue;
@@ -625,7 +626,7 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd),
}
/* Draw selected verts for strokes being edited */
-static void annotation_draw_strokes_edit(bGPdata *gpd,
+static void annotation_draw_strokes_edit(bGPdata *UNUSED(gpd),
bGPDlayer *gpl,
const bGPDframe *gpf,
int offsx,
@@ -660,7 +661,7 @@ static void annotation_draw_strokes_edit(bGPdata *gpd,
GPU_program_point_size(true);
/* draw stroke verts */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if stroke can be drawn */
if (annotation_can_draw_stroke(gps, dflag) == false) {
continue;
@@ -689,6 +690,9 @@ static void annotation_draw_strokes_edit(bGPdata *gpd,
vsize = bsize + 2;
}
+ /* Why? */
+ UNUSED_VARS(vsize);
+
float selectColor[4];
UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
selectColor[3] = alpha;
@@ -709,31 +713,12 @@ static void annotation_draw_strokes_edit(bGPdata *gpd,
immBegin(GPU_PRIM_POINTS, gps->totpoints);
- /* Draw start and end point differently if enabled stroke direction hint */
- bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
-
/* Draw all the stroke points (selected or not) */
bGPDspoint *pt = gps->points;
for (int i = 0; i < gps->totpoints; i++, pt++) {
/* size and color first */
- if (show_direction_hint && i == 0) {
- /* start point in green bigger */
- immAttr3f(color, 0.0f, 1.0f, 0.0f);
- immAttr1f(size, vsize + 4);
- }
- else if (show_direction_hint && (i == gps->totpoints - 1)) {
- /* end point in red smaller */
- immAttr3f(color, 1.0f, 0.0f, 0.0f);
- immAttr1f(size, vsize + 1);
- }
- else if (pt->flag & GP_SPOINT_SELECT) {
- immAttr3fv(color, selectColor);
- immAttr1f(size, vsize);
- }
- else {
- immAttr3fv(color, gpl->color);
- immAttr1f(size, bsize);
- }
+ immAttr3fv(color, gpl->color);
+ immAttr1f(size, bsize);
/* then position */
if (gps->flag & GP_STROKE_3DSPACE) {
@@ -857,7 +842,7 @@ static void annotation_draw_data_layers(
{
float ink[4];
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* verify never thickness is less than 1 */
CLAMP_MIN(gpl->thickness, 1.0f);
short lthick = gpl->thickness;
@@ -872,7 +857,7 @@ static void annotation_draw_data_layers(
}
/* get frame to draw */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 875bdfddcc8..1d654703064 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -534,9 +534,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
pts->pressure = pt->pressure;
pts->strength = pt->strength;
pts->time = pt->time;
-
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
}
/* increment counters */
@@ -601,15 +599,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* copy appropriate settings for stroke */
gps->totpoints = totelem;
gps->thickness = gpl->thickness;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_f = 1.0f;
gps->gradient_s[0] = 1.0f;
gps->gradient_s[1] = 1.0f;
gps->uv_scale = 1.0f;
gps->flag = gpd->runtime.sbuffer_sflag;
gps->inittime = p->inittime;
-
- /* enable recalculation flag by default (only used if hq fill) */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
/* allocate enough memory for a continuous array for storage points */
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
@@ -1205,7 +1202,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
ToolSettings *ts = scene->toolsettings;
/* get active layer (or add a new one if non-existent) */
- p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ p->gpl = BKE_gpencil_layer_active_get(p->gpd);
if (p->gpl == NULL) {
/* tag for annotations */
p->gpd->flag |= GP_DATA_ANNOTATIONS;
@@ -1233,7 +1230,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
*/
bool has_layer_to_erase = false;
- if (gpencil_layer_is_editable(p->gpl)) {
+ if (BKE_gpencil_layer_is_editable(p->gpl)) {
/* Ensure that there's stuff to erase here (not including selection mask below)... */
if (p->gpl->actframe && p->gpl->actframe->strokes.first) {
has_layer_to_erase = true;
@@ -1261,7 +1258,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_frame_get(p->gpl, CFRA, add_frame_mode);
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index fe89ea7321f..888d78e4434 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -283,78 +283,8 @@ static void gp_calc_stroke_text_coordinates(const float (*points2d)[2],
}
}
-/* Triangulate stroke for high quality fill
- * (this is done only if cache is null or stroke was modified). */
-static void gp_triangulate_stroke_fill(bGPDstroke *gps)
-{
- BLI_assert(gps->totpoints >= 3);
-
- /* allocate memory for temporary areas */
- gps->tot_triangles = gps->totpoints - 2;
- uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles,
- "GP Stroke temp triangulation");
- float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
- "GP Stroke temp 2d points");
- float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
-
- int direction = 0;
-
- /* convert to 2d and triangulate */
- BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
- BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
-
- /* calc texture coordinates automatically */
- float minv[2];
- float maxv[2];
- /* first needs bounding box data */
- gp_calc_2d_bounding_box((const float(*)[2])points2d, gps->totpoints, minv, maxv, false);
- /* calc uv data */
- gp_calc_stroke_text_coordinates((const float(*)[2])points2d, gps->totpoints, minv, maxv, uv);
-
- /* Number of triangles */
- gps->tot_triangles = gps->totpoints - 2;
- /* save triangulation data in stroke cache */
- if (gps->tot_triangles > 0) {
- if (gps->triangles == NULL) {
- gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
- "GP Stroke triangulation");
- }
- else {
- gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
- }
-
- for (int i = 0; i < gps->tot_triangles; i++) {
- bGPDtriangle *stroke_triangle = &gps->triangles[i];
- memcpy(stroke_triangle->verts, tmp_triangles[i], sizeof(uint[3]));
- /* copy texture coordinates */
- copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
- copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
- copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
- }
- }
- else {
- /* No triangles needed - Free anything allocated previously */
- if (gps->triangles) {
- MEM_freeN(gps->triangles);
- }
-
- gps->triangles = NULL;
- }
-
- /* disable recalculation flag */
- if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
- gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
- }
-
- /* clear memory */
- MEM_SAFE_FREE(tmp_triangles);
- MEM_SAFE_FREE(points2d);
- MEM_SAFE_FREE(uv);
-}
-
/* add a new fill point and texture coordinates to vertex buffer */
static void gp_add_filldata_tobuffer(const bGPDspoint *pt,
- const float uv[2],
uint pos,
uint texcoord,
short flag,
@@ -375,8 +305,8 @@ static void gp_add_filldata_tobuffer(const bGPDspoint *pt,
fpt[2] = 0.0f; /* 2d always is z=0.0f */
}
- immAttr2f(texcoord, uv[0], uv[1]); /* texture coordinates */
- immVertex3fv(pos, fpt); /* position */
+ immAttr2f(texcoord, pt->uv_fill[0], pt->uv_fill[1]); /* texture coordinates */
+ immVertex3fv(pos, fpt); /* position */
}
/* draw fills for shapes */
@@ -390,18 +320,12 @@ static void gp_draw_stroke_fill(bGPdata *gpd,
const float color[4])
{
BLI_assert(gps->totpoints >= 3);
+ BLI_assert(gps->tot_triangles >= 1);
const bool use_mat = (gpd->mat != NULL);
Material *ma = (use_mat) ? gpd->mat[gps->mat_nr] : BKE_material_default_gpencil();
MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL;
- /* Calculate triangles cache for filling area (must be done only after changes) */
- if ((gps->flag & GP_STROKE_RECALC_GEOMETRY) || (gps->tot_triangles == 0) ||
- (gps->triangles == NULL)) {
- gp_triangulate_stroke_fill(gps);
- }
- BLI_assert(gps->tot_triangles >= 1);
-
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -414,7 +338,6 @@ static void gp_draw_stroke_fill(bGPdata *gpd,
immUniform1f("gradient_angle", gp_style->gradient_angle);
immUniform1f("gradient_radius", gp_style->gradient_radius);
- immUniform1f("pattern_gridsize", gp_style->pattern_gridsize);
immUniform2fv("gradient_scale", gp_style->gradient_scale);
immUniform2fv("gradient_shift", gp_style->gradient_shift);
@@ -422,8 +345,8 @@ static void gp_draw_stroke_fill(bGPdata *gpd,
immUniform2fv("texture_scale", gp_style->texture_scale);
immUniform2fv("texture_offset", gp_style->texture_offset);
immUniform1f("texture_opacity", gp_style->texture_opacity);
- immUniform1i("t_mix", (gp_style->flag & GP_STYLE_FILL_TEX_MIX) != 0);
- immUniform1i("t_flip", (gp_style->flag & GP_STYLE_COLOR_FLIP_FILL) != 0);
+ immUniform1i("t_mix", (gp_style->flag & GP_MATERIAL_FILL_TEX_MIX) != 0);
+ immUniform1i("t_flip", (gp_style->flag & GP_MATERIAL_FLIP_FILL) != 0);
/* Draw all triangles for filling the polygon (cache must be calculated before) */
immBegin(GPU_PRIM_TRIS, gps->tot_triangles * 3);
@@ -433,7 +356,6 @@ static void gp_draw_stroke_fill(bGPdata *gpd,
for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
for (int j = 0; j < 3; j++) {
gp_add_filldata_tobuffer(&gps->points[stroke_triangle->verts[j]],
- stroke_triangle->uv[j],
pos,
texcoord,
gps->flag,
@@ -843,15 +765,15 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
Material *ma = (use_mat) ? tgpw->gpd->mat[gps->mat_nr] : BKE_material_default_gpencil();
MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL;
- if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE) ||
/* if onion and ghost flag do not draw*/
- (tgpw->onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN))) {
+ (tgpw->onion && (gp_style->flag & GP_MATERIAL_ONIONSKIN))) {
continue;
}
/* if disable fill, the colors with fill must be omitted too except fill boundary strokes */
if ((tgpw->disable_fill == 1) && (gp_style->fill_rgba[3] > 0.0f) &&
- ((gps->flag & GP_STROKE_NOFILL) == 0) && (gp_style->flag & GP_STYLE_FILL_SHOW)) {
+ ((gps->flag & GP_STROKE_NOFILL) == 0) && (gp_style->flag & GP_MATERIAL_FILL_SHOW)) {
continue;
}
@@ -936,7 +858,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
}
}
- if (gp_style->mode == GP_STYLE_MODE_DOTS) {
+ if (gp_style->mode == GP_MATERIAL_MODE_DOT) {
/* volumetric stroke drawing */
if (tgpw->disable_fill != 1) {
gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
@@ -1017,7 +939,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
copy_v4_v4(ink, tcolor);
}
}
- if (gp_style->mode == GP_STYLE_MODE_DOTS) {
+ if (gp_style->mode == GP_MATERIAL_MODE_DOT) {
/* blob/disk-based "volumetric" drawing */
gp_draw_stroke_volumetric_2d(gps->points,
gps->totpoints,
@@ -1072,113 +994,8 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
/* ----- General Drawing ------ */
-/* draw interpolate strokes (used only while operator is running) */
-void ED_gp_draw_interpolation(const bContext *C, tGPDinterpolate *tgpi, const int type)
-{
- tGPDdraw tgpw;
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- tGPDinterpolate_layer *tgpil;
- Object *obact = CTX_data_active_object(C);
- /* Drawing code is expected to run with fully evaluated depsgraph. */
- Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
-
- float color[4];
-
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color);
- color[3] = 0.6f;
- int dflag = 0;
- /* if 3d stuff, enable flags */
- if (type == REGION_DRAW_POST_VIEW) {
- dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
- }
-
- tgpw.rv3d = rv3d;
- tgpw.depsgraph = depsgraph;
- tgpw.ob = obact;
- tgpw.gpd = tgpi->gpd;
- tgpw.offsx = 0;
- tgpw.offsy = 0;
- tgpw.winx = tgpi->ar->winx;
- tgpw.winy = tgpi->ar->winy;
- tgpw.dflag = dflag;
-
- /* turn on alpha-blending */
- GPU_blend(true);
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- /* calculate parent position */
- ED_gpencil_parent_location(depsgraph, obact, tgpi->gpd, tgpil->gpl, tgpw.diff_mat);
- if (tgpil->interFrame) {
- tgpw.gpl = tgpil->gpl;
- tgpw.gpf = tgpil->interFrame;
- tgpw.t_gpf = tgpil->interFrame;
- tgpw.gps = NULL;
-
- tgpw.lthick = tgpil->gpl->line_change;
- tgpw.opacity = 1.0;
- copy_v4_v4(tgpw.tintcolor, color);
- tgpw.onion = true;
- tgpw.custonion = true;
- if (obact->totcol == 0) {
- tgpw.gpd->mat = NULL;
- }
-
- gp_draw_strokes(&tgpw);
- }
- }
- GPU_blend(false);
-}
-
/* wrapper to draw strokes for filling operator */
void ED_gp_draw_fill(tGPDdraw *tgpw)
{
gp_draw_strokes(tgpw);
}
-
-/* draw a short status message in the top-right corner */
-static void UNUSED_FUNCTION(gp_draw_status_text)(const bGPdata *gpd, ARegion *ar)
-{
-
- /* Cannot draw any status text when drawing OpenGL Renders */
- if (G.f & G_FLAG_RENDER_VIEWPORT) {
- return;
- }
-
- /* Get bounds of region - Necessary to avoid problems with region overlap. */
- const rcti *rect = ED_region_visible_rect(ar);
-
- /* for now, this should only be used to indicate when we are in stroke editmode */
- if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
- const char *printable = IFACE_("GPencil Stroke Editing");
- float printable_size[2];
-
- int font_id = BLF_default();
-
- BLF_width_and_height(
- font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
-
- int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0];
- int yco = (rect->ymax - U.widget_unit);
-
- /* text label */
- UI_FontThemeColor(font_id, TH_TEXT_HI);
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
-#else
- BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
-#endif
-
- /* grease pencil icon... */
- // XXX: is this too intrusive?
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
-
- xco -= U.widget_unit;
- yco -= (int)printable_size[1] / 2;
-
- UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
-
- GPU_blend(false);
- }
-}
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index f4636e81966..83165fd4930 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -58,15 +58,13 @@
/* Loops over the gp-frames for a gp-layer, and applies the given callback */
bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *))
{
- bGPDframe *gpf;
-
/* error checker */
if (gpl == NULL) {
return false;
}
/* do loop */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* execute callback */
if (gpf_cb(gpf, scene)) {
return true;
@@ -83,7 +81,6 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPD
/* make a listing all the gp-frames in a layer as cfraelems */
void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
{
- bGPDframe *gpf;
CfraElem *ce;
/* error checking */
@@ -92,7 +89,7 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
}
/* loop through gp-frames, adding */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
@@ -110,15 +107,13 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel)
/* check if one of the frames in this layer is selected */
bool ED_gplayer_frame_select_check(bGPDlayer *gpl)
{
- bGPDframe *gpf;
-
/* error checking */
if (gpl == NULL) {
return false;
}
/* stop at the first one found */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
return true;
}
@@ -151,15 +146,13 @@ static void gpframe_select(bGPDframe *gpf, short select_mode)
/* set all/none/invert select (like above, but with SELECT_* modes) */
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode)
{
- bGPDframe *gpf;
-
/* error checking */
if (gpl == NULL) {
return;
}
/* handle according to mode */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
gpframe_select(gpf, select_mode);
}
}
@@ -185,7 +178,7 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
return;
}
- gpf = BKE_gpencil_layer_find_frame(gpl, selx);
+ gpf = BKE_gpencil_layer_frame_find(gpl, selx);
if (gpf) {
gpframe_select(gpf, select_mode);
@@ -195,14 +188,12 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode)
/* select the frames in this layer that occur within the bounds specified */
void ED_gplayer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode)
{
- bGPDframe *gpf;
-
if (gpl == NULL) {
return;
}
/* only select those frames which are in bounds */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (IN_RANGE(gpf->framenum, min, max)) {
gpframe_select(gpf, select_mode);
}
@@ -215,14 +206,12 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked,
short tool,
short select_mode)
{
- bGPDframe *gpf;
-
if (gpl == NULL) {
return;
}
/* only select frames which are within the region */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* construct a dummy point coordinate to do this testing with */
float pt[2] = {0};
@@ -264,7 +253,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl)
gpfn = gpf->next;
if (gpf->flag & GP_FRAME_SELECT) {
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
changed = true;
}
}
@@ -304,13 +293,11 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl)
*/
void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
{
- bGPDframe *gpf;
-
if (gpl == NULL) {
return;
}
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
gpf->key_type = type;
}
@@ -370,10 +357,9 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
for (ale = anim_data.first; ale; ale = ale->next) {
ListBase copied_frames = {NULL, NULL};
bGPDlayer *gpl = (bGPDlayer *)ale->data;
- bGPDframe *gpf;
/* loop over frames, and copy only selected frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* if frame is selected, make duplicate it and its strokes */
if (gpf->flag & GP_FRAME_SELECT) {
/* make a copy of this frame */
@@ -489,7 +475,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
gpfs->framenum += offset;
/* get frame to copy data into (if no frame returned, then just ignore) */
- gpf = BKE_gpencil_layer_getframe(gpld, gpfs->framenum, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpld, gpfs->framenum, GP_GETFRAME_ADD_NEW);
if (gpf) {
bGPDstroke *gps, *gpsn;
@@ -502,21 +488,15 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
*/
for (gps = gpfs->strokes.first; gps; gps = gps->next) {
/* make a copy of stroke, then of its points array */
- gpsn = MEM_dupallocN(gps);
- gpsn->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- gpsn->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, gpsn);
- }
- /* duplicate triangle information */
- gpsn->triangles = MEM_dupallocN(gps->triangles);
+ gpsn = BKE_gpencil_stroke_duplicate(gps, true);
+
/* append stroke to frame */
BLI_addtail(&gpf->strokes, gpsn);
}
/* if no strokes (i.e. new frame) added, free gpf */
if (BLI_listbase_is_empty(&gpf->strokes)) {
- BKE_gpencil_layer_delframe(gpld, gpf);
+ BKE_gpencil_layer_frame_delete(gpld, gpf);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index 7dc3aa1273f..2d481bed971 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -66,17 +66,20 @@ static int gpencil_monkey_color(
ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
+
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+ srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (!stroke) {
- ma->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
if (!fill) {
- ma->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
}
else {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return idx;
@@ -855,89 +858,117 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, CFRA);
/* generate strokes */
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin, 270, 75);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false);
BKE_gpencil_stroke_add_points(gps, data0, 270, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data1, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 60, false);
BKE_gpencil_stroke_add_points(gps, data2, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data3, 64, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data4, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 64, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data5, 64, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data6, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Light, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Light, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data7, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
BKE_gpencil_stroke_add_points(gps, data8, 49, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data9, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Eyes, 49, 60);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Eyes, 49, 60, false);
BKE_gpencil_stroke_add_points(gps, data10, 49, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data11, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameFills, color_Skin_Shadow, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameFills, color_Skin_Shadow, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data12, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data13, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data14, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 65, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 65, 60, false);
BKE_gpencil_stroke_add_points(gps, data15, 65, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 60, false);
BKE_gpencil_stroke_add_points(gps, data16, 34, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data17, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 40, false);
BKE_gpencil_stroke_add_points(gps, data18, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 34, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 34, 40, false);
BKE_gpencil_stroke_add_points(gps, data19, 34, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data20, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 64, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 64, 60, false);
BKE_gpencil_stroke_add_points(gps, data21, 64, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
BKE_gpencil_stroke_add_points(gps, data22, 26, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Pupils, 26, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Pupils, 26, 60, false);
BKE_gpencil_stroke_add_points(gps, data23, 26, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data24, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data25, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 18, 40);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 18, 40, false);
BKE_gpencil_stroke_add_points(gps, data26, 18, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
- gps = BKE_gpencil_add_stroke(frameLines, color_Black, 33, 60);
+ gps = BKE_gpencil_stroke_add(frameLines, color_Black, 33, 60, false);
BKE_gpencil_stroke_add_points(gps, data27, 33, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index 539f80846fd..f1678e11eb0 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -65,10 +65,13 @@ static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct,
ma = BKE_gpencil_object_material_new(bmain, ob, pct->name, &idx);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
+
copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+ srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
if (fill) {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
return idx;
@@ -240,8 +243,9 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
UNUSED_VARS(frame_color);
/* generate stroke */
- gps = BKE_gpencil_add_stroke(frame_lines, color_black, 175, 75);
+ gps = BKE_gpencil_stroke_add(frame_lines, color_black, 175, 75, false);
BKE_gpencil_stroke_add_points(gps, data0, 175, mat);
+ BKE_gpencil_stroke_geometry_update(gps);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c
index 9e70be323eb..bbc9f486f80 100644
--- a/source/blender/editors/gpencil/gpencil_armature.c
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -357,7 +357,7 @@ static void gpencil_add_verts_to_dgroups(
}
/* loop all strokes */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
bGPDspoint *pt = NULL;
@@ -368,7 +368,7 @@ static void gpencil_add_verts_to_dgroups(
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index d26d5a8a7d8..54f8b749199 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -174,7 +174,7 @@ static void gp_strokepoint_convertcoords(bContext *C,
/* apply parent transform */
float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
mul_v3_m4v3(fpt, diff_mat, &source_pt->x);
copy_v3_v3(&pt->x, fpt);
@@ -1270,7 +1270,7 @@ static void gp_layer_to_curve(bContext *C,
Collection *collection = CTX_data_collection(C);
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
Curve *cu;
@@ -1410,7 +1410,7 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe
int i;
bool valid = true;
- if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV)) ||
+ if (!gpl || !(gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV)) ||
!(gps = gpf->strokes.first)) {
return false;
}
@@ -1476,8 +1476,8 @@ static bool gp_convert_poll(bContext *C)
/* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
* and if we are not in edit mode!
*/
- return ((sa && sa->spacetype == SPACE_VIEW3D) && (gpl = BKE_gpencil_layer_getactive(gpd)) &&
- (gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV)) &&
+ return ((sa && sa->spacetype == SPACE_VIEW3D) && (gpl = BKE_gpencil_layer_active_get(gpd)) &&
+ (gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV)) &&
(gpf->strokes.first) && (!GPENCIL_ANY_EDIT_MODE(gpd)));
}
@@ -1487,7 +1487,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
const int mode = RNA_enum_get(op->ptr, "type");
const bool norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights");
@@ -1785,7 +1785,7 @@ static int image_to_gpencil_exec(bContext *C, wmOperator *op)
/* Create material slot. */
Material *ma = BKE_gpencil_object_material_new(bmain, ob, "Image Material", NULL);
MaterialGPencilStyle *gp_style = ma->gp_style;
- gp_style->mode = GP_STYLE_MODE_BOX;
+ gp_style->mode = GP_MATERIAL_MODE_SQUARE;
/* Add layer and frame. */
bGPdata *gpd = (bGPdata *)ob->data;
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index a8e7c40c031..b708039018f 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -292,7 +292,7 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl)) {
@@ -309,10 +309,10 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
* - if this is the only layer, this naturally becomes NULL
*/
if (gpl->prev) {
- BKE_gpencil_layer_setactive(gpd, gpl->prev);
+ BKE_gpencil_layer_active_set(gpd, gpl->prev);
}
else {
- BKE_gpencil_layer_setactive(gpd, gpl->next);
+ BKE_gpencil_layer_active_set(gpd, gpl->next);
}
/* delete the layer now... */
@@ -342,7 +342,7 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot)
static bool gp_active_layer_annotation_poll(bContext *C)
{
bGPdata *gpd = ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != NULL);
}
@@ -373,7 +373,7 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
const int direction = RNA_enum_get(op->ptr, "type") * -1;
@@ -441,7 +441,7 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot)
static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
bGPDlayer *new_layer;
/* sanity checks */
@@ -460,7 +460,7 @@ static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
'.',
offsetof(bGPDlayer, info),
sizeof(new_layer->info));
- BKE_gpencil_layer_setactive(gpd, new_layer);
+ BKE_gpencil_layer_active_set(gpd, new_layer);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -499,7 +499,7 @@ static bool gp_layer_duplicate_object_poll(bContext *C)
}
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl == NULL) {
return false;
@@ -532,7 +532,7 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
Object *ob_src = CTX_data_active_object(C);
bGPdata *gpd_src = (bGPdata *)ob_src->data;
- bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
+ bGPDlayer *gpl_src = BKE_gpencil_layer_active_get(gpd_src);
/* Sanity checks. */
if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
@@ -568,7 +568,7 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* Make copy of source stroke. */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
/* Check if material is in destination object,
* otherwise add the slot with the material. */
@@ -630,7 +630,7 @@ enum {
static int gp_frame_duplicate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
int mode = RNA_enum_get(op->ptr, "mode");
@@ -644,7 +644,7 @@ static int gp_frame_duplicate_exec(bContext *C, wmOperator *op)
BKE_gpencil_frame_addcopy(gpl, CFRA);
}
else {
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
BKE_gpencil_frame_addcopy(gpl, CFRA);
}
@@ -861,7 +861,7 @@ void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot)
static int gp_hide_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd);
bool unselected = RNA_boolean_get(op->ptr, "unselected");
/* sanity checks */
@@ -870,10 +870,8 @@ static int gp_hide_exec(bContext *C, wmOperator *op)
}
if (unselected) {
- bGPDlayer *gpl;
-
/* hide unselected */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl != layer) {
gpl->flag |= GP_LAYER_HIDE;
}
@@ -946,7 +944,6 @@ static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
static int gp_reveal_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
const bool select = RNA_boolean_get(op->ptr, "select");
/* sanity checks */
@@ -954,8 +951,7 @@ static int gp_reveal_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
gpl->flag &= ~GP_LAYER_HIDE;
@@ -1008,7 +1004,6 @@ void GPENCIL_OT_reveal(wmOperatorType *ot)
static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
/* sanity checks */
if (gpd == NULL) {
@@ -1016,7 +1011,7 @@ static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make all layers non-editable */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag |= GP_LAYER_LOCKED;
}
@@ -1048,7 +1043,6 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot)
static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
/* sanity checks */
if (gpd == NULL) {
@@ -1056,7 +1050,7 @@ static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make all layers editable again */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_LOCKED;
}
@@ -1087,8 +1081,7 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot)
static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
- bGPDlayer *gpl;
+ bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd);
int flags = GP_LAYER_LOCKED;
bool isolate = false;
@@ -1102,7 +1095,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
/* Test whether to isolate or clear all flags */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Skip if this is the active layer */
if (gpl == layer) {
continue;
@@ -1121,7 +1114,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
/* TODO: Include onion-skinning on this list? */
if (isolate) {
/* Set flags on all "other" layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl == layer) {
continue;
}
@@ -1132,7 +1125,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
else {
/* Clear flags - Restore everything else */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~flags;
}
}
@@ -1172,7 +1165,7 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
static int gp_merge_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_next = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_next = BKE_gpencil_layer_active_get(gpd);
bGPDlayer *gpl_current = gpl_next->prev;
if (ELEM(NULL, gpd, gpl_current, gpl_next)) {
@@ -1191,7 +1184,7 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op)
/* try to find frame in current layer */
bGPDframe *frame = BLI_ghash_lookup(gh_frames_cur, POINTER_FROM_INT(gpf->framenum));
if (!frame) {
- bGPDframe *actframe = BKE_gpencil_layer_getframe(
+ bGPDframe *actframe = BKE_gpencil_layer_frame_get(
gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
/* duplicate strokes of current active frame */
@@ -1268,7 +1261,7 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op)
}
/* Set active layer */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
/* updates */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -1312,7 +1305,7 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_act = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_act = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl_act, gpl_act->actframe)) {
@@ -1469,7 +1462,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
}
}
/* try to find slot */
- int idx = BKE_gpencil_object_material_get_index(ob, ma);
+ int idx = BKE_gpencil_object_material_index_get(ob, ma);
if (idx < 0) {
return OPERATOR_CANCELLED;
}
@@ -1494,7 +1487,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* only if selected */
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
@@ -1562,15 +1555,15 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
Material *tmp_ma = BKE_object_material_get(ob, i + 1);
if (tmp_ma) {
- tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ tmp_ma->gp_style->flag |= GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* loop all selected strokes and unlock any color */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
/* only if selected */
if (gps->flag & GP_STROKE_SELECT) {
@@ -1581,7 +1574,7 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
/* unlock color */
Material *tmp_ma = BKE_object_material_get(ob, gps->mat_nr + 1);
if (tmp_ma) {
- tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ tmp_ma->gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -1631,25 +1624,33 @@ static int gp_brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
case CTX_MODE_PAINT_GPENCIL: {
Paint *paint = &ts->gp_paint->paint;
brush = paint->brush;
- BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
break;
}
case CTX_MODE_SCULPT_GPENCIL: {
Paint *paint = &ts->gp_sculptpaint->paint;
brush = paint->brush;
- BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
break;
}
case CTX_MODE_WEIGHT_GPENCIL: {
Paint *paint = &ts->gp_weightpaint->paint;
brush = paint->brush;
- BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
break;
}
case CTX_MODE_VERTEX_GPENCIL: {
Paint *paint = &ts->gp_vertexpaint->paint;
brush = paint->brush;
- BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
break;
}
default:
@@ -1677,7 +1678,7 @@ void GPENCIL_OT_brush_reset(wmOperatorType *ot)
}
static Brush *gp_brush_get_first_by_mode(Main *bmain,
- Paint *paint,
+ Paint *UNUSED(paint),
const enum eContextObjectMode mode,
char tool)
{
@@ -1802,9 +1803,9 @@ static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op))
break;
}
+ char tool = '0';
if (paint) {
Brush *brush_active = paint->brush;
- char tool = '0';
if (brush_active) {
switch (mode) {
case CTX_MODE_PAINT_GPENCIL: {
@@ -1831,7 +1832,29 @@ static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op))
}
gp_brush_delete_mode_brushes(bmain, paint, mode);
- BKE_brush_gpencil_paint_presets(bmain, ts);
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ BKE_brush_gpencil_paint_presets(bmain, ts);
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ BKE_brush_gpencil_sculpt_presets(bmain, ts);
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ BKE_brush_gpencil_weight_presets(bmain, ts);
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ BKE_brush_gpencil_vertex_presets(bmain, ts);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
BKE_paint_toolslots_brush_validate(bmain, paint);
/* Set Again the first brush of the mode. */
@@ -2538,9 +2561,9 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
defgroup_unique_name(vgroup, ob_active);
BLI_addtail(&ob_active->defbase, vgroup);
/* update vertex groups in strokes in original data */
- for (bGPDlayer *gpl_src = gpd->layers.first; gpl_src; gpl_src = gpl_src->next) {
- for (bGPDframe *gpf = gpl_src->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
MDeformVert *dvert;
int i;
for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
@@ -2587,12 +2610,12 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
float inverse_diff_mat[4][4];
/* recalculate all stroke points */
- ED_gpencil_parent_location(depsgraph, ob_iter, gpd_src, gpl_src, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
Material *ma_src = NULL;
for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Reassign material. Look old material and try to find in destination. */
ma_src = BKE_gpencil_material(ob_src, gps->mat_nr + 1);
@@ -2707,16 +2730,16 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- gp_style->flag |= GP_STYLE_COLOR_HIDE;
+ gp_style->flag |= GP_MATERIAL_LOCKED;
+ gp_style->flag |= GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* loop all selected strokes and unlock any color used in active layer */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
(gpl->flag & GP_LAYER_ACTIVE)) {
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
/* skip strokes that are invalid for current view */
@@ -2730,8 +2753,8 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
gp_style = ma->gp_style;
/* unlock/unhide color if not unlocked before */
if (gp_style != NULL) {
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ gp_style->flag &= ~GP_MATERIAL_LOCKED;
+ gp_style->flag &= ~GP_MATERIAL_HIDE;
}
}
}
@@ -2771,11 +2794,11 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
MaterialGPencilStyle *active_color = BKE_gpencil_material_settings(ob, ob->actcol);
MaterialGPencilStyle *gp_style;
- int flags = GP_STYLE_COLOR_LOCKED;
+ int flags = GP_MATERIAL_LOCKED;
bool isolate = false;
if (RNA_boolean_get(op->ptr, "affect_visibility")) {
- flags |= GP_STYLE_COLOR_HIDE;
+ flags |= GP_MATERIAL_HIDE;
}
if (ELEM(NULL, gpd, active_color)) {
@@ -2893,7 +2916,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
if (ma) {
color = ma->gp_style;
if (active_color != color) {
- color->flag |= GP_STYLE_COLOR_HIDE;
+ color->flag |= GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2901,7 +2924,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
}
else {
/* hide selected/active */
- active_color->flag |= GP_STYLE_COLOR_HIDE;
+ active_color->flag |= GP_MATERIAL_HIDE;
}
/* updates */
@@ -2955,7 +2978,7 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ gp_style->flag &= ~GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -3008,7 +3031,7 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_MATERIAL_LOCKED;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -3061,7 +3084,7 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -3116,7 +3139,7 @@ static int gpencil_color_select_exec(bContext *C, wmOperator *op)
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
/* verify something to do */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 2b22d807f2a..781e431841c 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -775,23 +775,17 @@ static void gp_duplicate_points(const bGPDstroke *gps,
else if (i == gps->totpoints - 1) {
len = i - start_idx + 1;
}
- // printf("copying from %d to %d = %d\n", start_idx, i, len);
/* make copies of the relevant data */
if (len) {
bGPDstroke *gpsd;
/* make a stupid copy first of the entire stroke (to get the flags too) */
- gpsd = MEM_dupallocN(gps);
+ gpsd = BKE_gpencil_stroke_duplicate((bGPDstroke *)gps, false);
/* saves original layer name */
BLI_strncpy(gpsd->runtime.tmp_layerinfo, layername, sizeof(gpsd->runtime.tmp_layerinfo));
- /* initialize triangle memory - will be calculated on next redraw */
- gpsd->triangles = NULL;
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->tot_triangles = 0;
-
/* now, make a new points array, and copy of the relevant parts */
gpsd->points = MEM_callocN(sizeof(bGPDspoint) * len, "gps stroke points copy");
memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len);
@@ -811,8 +805,11 @@ static void gp_duplicate_points(const bGPDstroke *gps,
}
}
+ BKE_gpencil_stroke_geometry_update(gpsd);
+
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
+
BLI_addtail(new_strokes, gpsd);
/* cleanup + reset for next */
@@ -862,17 +859,12 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
bGPDstroke *gpsd;
/* make direct copies of the stroke and its points */
- gpsd = MEM_dupallocN(gps);
+ gpsd = BKE_gpencil_stroke_duplicate(gps, true);
+
BLI_strncpy(gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
- gpsd->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- gpsd->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
- }
- /* triangle information - will be calculated on next redraw */
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->triangles = NULL;
+ /* Initialize triangle information. */
+ BKE_gpencil_stroke_geometry_update(gpsd);
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
@@ -943,7 +935,7 @@ static void copy_move_point(bGPDstroke *gps,
pt_final->flag = pt->flag;
pt_final->uv_fac = pt->uv_fac;
pt_final->uv_rot = pt->uv_rot;
- copy_v4_v4(pt_final->mix_color, pt->mix_color);
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &temp_dverts[from_idx];
@@ -981,7 +973,7 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
pt = &gps->points[i];
if (pt->flag == GP_SPOINT_SELECT) {
/* duplicate original stroke data */
- bGPDstroke *gps_new = MEM_dupallocN(gps);
+ bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, false);
gps_new->prev = gps_new->next = NULL;
/* add new points array */
@@ -993,14 +985,15 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
gps_new->dvert = MEM_callocN(sizeof(MDeformVert), __func__);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps_new->triangles = NULL;
- gps_new->tot_triangles = 0;
BLI_insertlinkafter(&gpf->strokes, gps, gps_new);
/* copy selected point data to new stroke */
copy_move_point(gps_new, gps->points, gps->dvert, i, 0, true);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ BKE_gpencil_stroke_geometry_update(gps_new);
+
/* deselect orinal point */
pt->flag &= ~GP_SPOINT_SELECT;
}
@@ -1043,7 +1036,6 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
copy_move_point(gps, temp_points, temp_dverts, i, i2, false);
i2++;
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* If first point, add new point at the beginning. */
if (do_first) {
@@ -1068,6 +1060,9 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
pt->flag |= GP_SPOINT_SELECT;
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
MEM_SAFE_FREE(temp_points);
MEM_SAFE_FREE(temp_dverts);
}
@@ -1307,7 +1302,8 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
bGPDstroke *gpsd;
/* make direct copies of the stroke and its points */
- gpsd = MEM_dupallocN(gps);
+ gpsd = BKE_gpencil_stroke_duplicate(gps, false);
+
/* saves original layer name */
BLI_strncpy(gpsd->runtime.tmp_layerinfo, gpl->info, sizeof(gpsd->runtime.tmp_layerinfo));
gpsd->points = MEM_dupallocN(gps->points);
@@ -1316,10 +1312,8 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
BKE_gpencil_stroke_weights_duplicate(gps, gpsd);
}
- /* triangles cache - will be recalculated on next redraw */
- gpsd->flag |= GP_STROKE_RECALC_GEOMETRY;
- gpsd->tot_triangles = 0;
- gpsd->triangles = NULL;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpsd);
/* add to temp buffer */
gpsd->next = gpsd->prev = NULL;
@@ -1429,7 +1423,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
/* no active layer - let's just create one */
gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
}
- else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
+ else if ((BKE_gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
BKE_report(
op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
return OPERATOR_CANCELLED;
@@ -1495,10 +1489,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
* we are obliged to add a new frame if one
* doesn't exist already
*/
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
if (gpf) {
/* Create new stroke */
- bGPDstroke *new_stroke = MEM_dupallocN(gps);
+ bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false);
new_stroke->runtime.tmp_layerinfo[0] = '\0';
new_stroke->points = MEM_dupallocN(gps->points);
@@ -1506,15 +1500,15 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
new_stroke->dvert = MEM_dupallocN(gps->dvert);
BKE_gpencil_stroke_weights_duplicate(gps, new_stroke);
}
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
- new_stroke->triangles = NULL;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
/* Remap material */
Material *ma = BLI_ghash_lookup(new_colors, POINTER_FROM_INT(new_stroke->mat_nr));
- new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
+ new_stroke->mat_nr = BKE_gpencil_object_material_index_get(ob, ma);
CLAMP_MIN(new_stroke->mat_nr, 0);
}
}
@@ -1625,7 +1619,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
/* Paste them all in one go */
if (strokes.first) {
- bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, GP_GETFRAME_ADD_NEW);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(target_layer, CFRA, GP_GETFRAME_ADD_NEW);
BLI_movelisttolist(&gpf->strokes, &strokes);
BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
@@ -1665,32 +1659,13 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
/* ********************* Add Blank Frame *************************** */
-/* Basically the same as the drawing op */
-static bool UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C)
-{
- if (ED_operator_regionactive(C)) {
- /* check if current context can support GPencil data */
- if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
- return 1;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
- }
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Active region not set");
- }
-
- return 0;
-}
-
static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
int cfra = CFRA;
- bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *active_gpl = BKE_gpencil_layer_active_get(gpd);
const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
@@ -1710,7 +1685,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
}
/* 1) Check for an existing frame on the current frame */
- bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_find(gpl, cfra);
if (gpf) {
/* Shunt all frames after (and including) the existing one later by 1-frame */
for (; gpf; gpf = gpf->next) {
@@ -1719,7 +1694,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
}
/* 2) Now add a new frame, with nothing in it */
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_ADD_NEW);
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_ADD_NEW);
}
CTX_DATA_END;
@@ -1761,7 +1736,7 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
static bool gp_actframe_delete_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* only if there's an active layer with an active frame */
return (gpl && gpl->actframe);
@@ -1770,7 +1745,7 @@ static bool gp_actframe_delete_poll(bContext *C)
static bool gp_annotation_actframe_delete_poll(bContext *C)
{
bGPdata *gpd = ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* only if there's an active layer with an active frame */
return (gpl && gpl->actframe);
@@ -1784,11 +1759,11 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
@@ -1801,7 +1776,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
}
/* delete it... */
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -1858,14 +1833,14 @@ static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
/* try to get the "active" frame - but only if it actually occurs on this frame */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
/* delete it... */
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
/* we successfully modified something */
success = true;
@@ -2171,9 +2146,8 @@ static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
gps->dvert = new_dvert;
gps->totpoints = tot;
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
/* deselect the stroke, since none of its selected points will still be selected */
gps->flag &= ~GP_STROKE_SELECT;
@@ -2215,7 +2189,7 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
const int totpoints = gps_first->totpoints + gps_last->totpoints;
/* create new stroke */
- bGPDstroke *join_stroke = MEM_dupallocN(gps_first);
+ bGPDstroke *join_stroke = BKE_gpencil_stroke_duplicate(gps_first, false);
join_stroke->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, __func__);
join_stroke->totpoints = totpoints;
@@ -2243,7 +2217,7 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
pt_final->strength = pt->strength;
pt_final->time = delta;
pt_final->flag = pt->flag;
- copy_v4_v4(pt_final->mix_color, pt->mix_color);
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
/* retiming with fixed time interval (we cannot determine real time) */
delta += 0.01f;
@@ -2282,6 +2256,8 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst
/* add new stroke at head */
BLI_addhead(&gpf->strokes, join_stroke);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(join_stroke);
/* remove first stroke */
BLI_remlink(&gpf->strokes, gps_first);
@@ -2358,18 +2334,14 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf,
/* Create each new stroke... */
for (idx = 0; idx < num_islands; idx++) {
tGPDeleteIsland *island = &islands[idx];
- new_stroke = MEM_dupallocN(gps);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps, false);
/* if cyclic and first stroke, save to join later */
if ((is_cyclic) && (gps_first == NULL)) {
gps_first = new_stroke;
}
- /* initialize triangle memory - to be calculated on next redraw */
- new_stroke->triangles = NULL;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
new_stroke->flag &= ~GP_STROKE_CYCLIC;
- new_stroke->tot_triangles = 0;
/* Compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */
new_stroke->totpoints = island->end_idx - island->start_idx + 1;
@@ -2432,6 +2404,9 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf,
BKE_gpencil_free_stroke(new_stroke);
}
else {
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
+
if (next_stroke) {
BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke);
}
@@ -2644,16 +2619,16 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op))
Object *obact = CTX_data_active_object(C);
const float gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
/* calculate difference matrix object */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -2721,16 +2696,16 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op)
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
const float *cursor_global = scene->cursor.location;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -2819,16 +2794,16 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
INIT_MINMAX(min, max);
/* calculate midpoints from selected points */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
float diff_mat[4][4];
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -2895,7 +2870,7 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl, gpl->frames.first)) {
@@ -2903,8 +2878,8 @@ static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op))
}
/* loop all 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) {
/* Apply thickness */
if ((gps->thickness == 0) && (gpl->line_change == 0)) {
gps->thickness = gpl->thickness;
@@ -2978,8 +2953,8 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
continue;
}
/* skip hidden or locked colors */
- if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
+ (gp_style->flag & GP_MATERIAL_LOCKED)) {
continue;
}
@@ -3003,7 +2978,7 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
/* Create new geometry. */
if ((gps->flag & GP_STROKE_CYCLIC) && (geometry)) {
- BKE_gpencil_close_stroke(gps);
+ BKE_gpencil_stroke_close(gps);
}
}
@@ -3092,8 +3067,8 @@ static int gp_stroke_caps_set_exec(bContext *C, wmOperator *op)
continue;
}
/* skip hidden or locked colors */
- if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
+ (gp_style->flag & GP_MATERIAL_LOCKED)) {
continue;
}
@@ -3173,7 +3148,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
pt.pressure = point->pressure;
pt.strength = point->strength;
pt.time = point->time;
- copy_v4_v4(pt.mix_color, point->mix_color);
+ copy_v4_v4(pt.vert_color, point->vert_color);
/* replace first point with last point */
point2 = &gps->points[end];
@@ -3184,7 +3159,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
point->pressure = point2->pressure;
point->strength = point2->strength;
point->time = point2->time;
- copy_v4_v4(point->mix_color, point2->mix_color);
+ copy_v4_v4(point->vert_color, point2->vert_color);
/* replace last point with first saved before */
point = &gps->points[end];
@@ -3195,7 +3170,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps)
point->pressure = pt.pressure;
point->strength = pt.strength;
point->time = pt.time;
- copy_v4_v4(point->mix_color, pt.mix_color);
+ copy_v4_v4(point->vert_color, pt.vert_color);
end--;
}
@@ -3226,7 +3201,7 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps,
newpoint->pressure = pressure;
newpoint->strength = strength;
newpoint->time = point->time + deltatime;
- copy_v4_v4(newpoint->mix_color, point->mix_color);
+ copy_v4_v4(newpoint->vert_color, point->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[idx];
@@ -3300,7 +3275,7 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
static int gp_stroke_join_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *activegpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd);
bGPDstroke *gps, *gpsn;
Object *ob = CTX_data_active_object(C);
@@ -3357,15 +3332,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
/* create a new stroke if was not created before (only created if something to join) */
if (new_stroke == NULL) {
- new_stroke = MEM_dupallocN(stroke_a);
- new_stroke->points = MEM_dupallocN(stroke_a->points);
- if (stroke_a->dvert != NULL) {
- new_stroke->dvert = MEM_dupallocN(stroke_a->dvert);
- BKE_gpencil_stroke_weights_duplicate(stroke_a, new_stroke);
- }
- new_stroke->triangles = NULL;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
+ new_stroke = BKE_gpencil_stroke_duplicate(stroke_a, true);
/* if new, set current color */
if (type == GP_STROKE_JOINCOPY) {
@@ -3379,6 +3346,9 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
/* if join only, delete old strokes */
if (type == GP_STROKE_JOIN) {
if (stroke_a) {
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
+
BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke);
BLI_remlink(&gpf->strokes, stroke_a);
BKE_gpencil_free_stroke(stroke_a);
@@ -3403,6 +3373,8 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op)
if (activegpl->actframe == NULL) {
activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
BLI_addtail(&activegpl->actframe->strokes, new_stroke);
}
@@ -3463,7 +3435,7 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
@@ -3577,7 +3549,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
GP_REPROJECT_TOP,
GP_REPROJECT_CURSOR)) {
if (mode != GP_REPROJECT_CURSOR) {
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, origin);
}
else {
copy_v3_v3(origin, scene->cursor.location);
@@ -3745,19 +3717,19 @@ static void gp_smooth_stroke(bContext *C, wmOperator *op)
/* perform smoothing */
if (smooth_position) {
- BKE_gpencil_smooth_stroke(gps, i, factor);
+ BKE_gpencil_stroke_smooth(gps, i, factor);
}
if (smooth_strength) {
- BKE_gpencil_smooth_stroke_strength(gps, i, factor);
+ BKE_gpencil_stroke_smooth_strength(gps, i, factor);
}
if (smooth_thickness) {
/* thickness need to repeat process several times */
for (int r2 = 0; r2 < r * 20; r2++) {
- BKE_gpencil_smooth_stroke_thickness(gps, i, factor);
+ BKE_gpencil_stroke_smooth_thickness(gps, i, factor);
}
}
if (smooth_uv) {
- BKE_gpencil_smooth_stroke_uv(gps, i, factor);
+ BKE_gpencil_stroke_smooth_uv(gps, i, factor);
}
}
}
@@ -3826,7 +3798,6 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* loop and interpolate */
i2 = 0;
@@ -3840,7 +3811,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
pt_final->strength = pt->strength;
pt_final->time = pt->time;
pt_final->flag = pt->flag;
- copy_v4_v4(pt_final->mix_color, pt->mix_color);
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@@ -3864,7 +3835,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- interp_v4_v4v4(pt_final->mix_color, pt->mix_color, next->mix_color, 0.5f);
+ interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->flag |= GP_SPOINT_SELECT;
@@ -3898,9 +3869,8 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(temp_dverts);
}
- /* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -3968,7 +3938,7 @@ static int gp_stroke_simplify_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
/* simplify stroke using Ramer-Douglas-Peucker algorithm */
- BKE_gpencil_simplify_stroke(gps, factor);
+ BKE_gpencil_stroke_simplify(gps, factor);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -4017,7 +3987,7 @@ static int gp_stroke_simplify_fixed_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
for (int i = 0; i < steps; i++) {
- BKE_gpencil_simplify_fixed(gps);
+ BKE_gpencil_stroke_simplify_fixed(gps);
}
}
}
@@ -4067,7 +4037,7 @@ static int gp_stroke_sample_exec(bContext *C, wmOperator *op)
/* Go through each editable + selected stroke */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_sample_stroke(gps, length, true);
+ BKE_gpencil_stroke_sample(gps, length, true);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -4134,7 +4104,7 @@ static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op))
}
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_trim_stroke(gps);
+ BKE_gpencil_stroke_trim(gps);
}
}
/* if not multiedit, exit loop*/
@@ -4254,7 +4224,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
/* add frame if not created before */
if (gpf_dst == NULL) {
- gpf_dst = BKE_gpencil_layer_getframe(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
+ gpf_dst = BKE_gpencil_layer_frame_get(gpl_dst, gpf->framenum, GP_GETFRAME_ADD_NEW);
}
/* add duplicate materials */
@@ -4267,7 +4237,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
/* selected points mode */
if (mode == GP_SEPARATE_POINT) {
/* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true);
/* Reassign material. */
gps_dst->mat_nr = idx;
@@ -4315,10 +4285,10 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
if (gpl) {
/* try to set a new active layer in source datablock */
if (gpl->prev) {
- BKE_gpencil_layer_setactive(gpd_src, gpl->prev);
+ BKE_gpencil_layer_active_set(gpd_src, gpl->prev);
}
else if (gpl->next) {
- BKE_gpencil_layer_setactive(gpd_src, gpl->next);
+ BKE_gpencil_layer_active_set(gpd_src, gpl->next);
}
/* unlink from source datablock */
BLI_remlink(&gpd_src->layers, gpl);
@@ -4327,8 +4297,8 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
BLI_addtail(&gpd_dst->layers, gpl);
/* add duplicate materials */
- 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) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -4416,7 +4386,7 @@ static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op))
/* split selected strokes */
if (gps->flag & GP_STROKE_SELECT) {
/* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true);
/* link to same frame */
BLI_addtail(&gpf->strokes, gps_dst);
@@ -4675,7 +4645,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
/* dissolve selected points */
bGPDstroke *gpsn;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_LOCKED) {
continue;
}
@@ -4795,7 +4765,7 @@ static bool gp_merge_by_distance_poll(bContext *C)
return false;
}
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL));
}
@@ -4815,7 +4785,7 @@ static int gp_merge_by_distance_exec(bContext *C, wmOperator *op)
/* Go through each editable selected stroke */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- BKE_gpencil_merge_distance_stroke(gpf_, gps, threshold, unselected);
+ BKE_gpencil_stroke_merge_distance(gpf_, gps, threshold, unselected);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index fcbbef8cd52..8c8a9c5238f 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -247,9 +247,9 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
GPU_blend(true);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* calculate parent position */
- ED_gpencil_parent_location(tgpw.depsgraph, ob, gpd, gpl, tgpw.diff_mat);
+ BKE_gpencil_parent_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat);
/* do not draw layer if hidden */
if (gpl->flag & GP_LAYER_HIDE) {
@@ -259,24 +259,24 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
/* if active layer and no keyframe, create a new one */
if (gpl == tgpf->gpl) {
if ((gpl->actframe == NULL) || (gpl->actframe->framenum != tgpf->active_cfra)) {
- BKE_gpencil_layer_getframe(gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
+ BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
}
}
/* get frame to draw */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if stroke can be drawn */
if ((gps->points == NULL) || (gps->totpoints < 2)) {
continue;
}
/* check if the color is visible */
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE)) {
+ if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) {
continue;
}
@@ -293,7 +293,7 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
tgpw.onion = true;
tgpw.custonion = true;
- bool textured_stroke = (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE);
+ bool textured_stroke = (gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE);
/* normal strokes */
if (((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) ||
@@ -1081,7 +1081,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
}
/* Get frame or create a new one. */
- tgpf->gpf = BKE_gpencil_layer_getframe(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
+ tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW);
/* Set frame as selected. */
tgpf->gpf->flag |= GP_FRAME_SELECT;
@@ -1089,15 +1089,13 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
/* create new stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
gps->thickness = brush->size;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_f = brush->gpencil_settings->gradient_f;
copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
gps->inittime = 0.0f;
- /* Apply the mix color to fill. */
- if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
- copy_v3_v3(gps->mix_color_fill, brush->rgb);
- gps->mix_color_fill[3] = brush->gpencil_settings->vertex_factor;
- }
+ /* Apply the vertex color to fill. */
+ ED_gpencil_fill_vertex_color_set(ts, brush, gps);
/* the polygon must be closed, so enabled cyclic */
gps->flag |= GP_STROKE_CYCLIC;
@@ -1117,11 +1115,6 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
gps->totpoints = tgpf->sbuffer_used;
gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_used, "gp_stroke_points");
- /* initialize triangle memory to dummy data */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
/* add stroke to frame */
if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) || (tgpf->on_back == true)) {
BLI_addhead(&tgpf->gpf->strokes, gps);
@@ -1156,11 +1149,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
pt->strength = 1.0f;
pt->time = 0.0f;
- /* Point mix color. */
- copy_v3_v3(pt->mix_color, brush->rgb);
- pt->mix_color[3] = GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) ?
- brush->gpencil_settings->vertex_factor :
- 0.0f;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt);
if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
@@ -1184,7 +1174,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
float smoothfac = 1.0f;
for (int r = 0; r < 1; r++) {
for (int i = 0; i < gps->totpoints; i++) {
- BKE_gpencil_smooth_stroke(gps, i, smoothfac - reduce);
+ BKE_gpencil_stroke_smooth(gps, i, smoothfac - reduce);
}
reduce += 0.25f; // reduce the factor
}
@@ -1193,7 +1183,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
if ((tgpf->lock_axis > GP_LOCKAXIS_VIEW) &&
((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0)) {
float origin[3];
- ED_gp_get_drawing_reference(tgpf->scene, tgpf->ob, tgpf->gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(
+ tgpf->scene, tgpf->ob, tgpf->gpl, ts->gpencil_v3d_align, origin);
ED_gp_project_stroke_to_plane(
tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1);
}
@@ -1211,8 +1202,11 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
/* simplify stroke */
for (int b = 0; b < tgpf->fill_simplylvl; b++) {
- BKE_gpencil_simplify_fixed(gps);
+ BKE_gpencil_stroke_simplify_fixed(gps);
}
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* ----------------------- */
@@ -1297,7 +1291,7 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
/* set GP datablock */
tgpf->gpd = gpd;
- tgpf->gpl = BKE_gpencil_layer_getactive(gpd);
+ tgpf->gpl = BKE_gpencil_layer_active_get(gpd);
if (tgpf->gpl == NULL) {
tgpf->gpl = BKE_gpencil_layer_addnew(tgpf->gpd, DATA_("GP_Layer"), true);
}
@@ -1406,7 +1400,7 @@ static int gpencil_fill_init(bContext *C, wmOperator *op)
tGPDfill *tgpf;
/* cannot paint in locked layer */
bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if ((gpl) && (gpl->flag & GP_LAYER_LOCKED)) {
return 0;
}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 5c2885aa38f..4f6aedf8495 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -111,6 +111,8 @@ typedef struct tGPDinterpolate_layer {
} tGPDinterpolate_layer;
typedef struct tGPDinterpolate {
+ /** Current depsgraph from context */
+ struct Depsgraph *depsgraph;
/** current scene from context */
struct Scene *scene;
/** area where painting originated */
@@ -138,10 +140,6 @@ typedef struct tGPDinterpolate {
int flag;
NumInput num; /* numeric input */
- /** handle for drawing strokes while operator is running 3d stuff */
- void *draw_handle_3d;
- /** handle for drawing strokes while operator is running screen stuff */
- void *draw_handle_screen;
} tGPDinterpolate;
/* Temporary primitive operation data */
@@ -233,10 +231,6 @@ typedef struct tGPDprimitive {
} tGPDprimitive;
/* Modal Operator Drawing Callbacks ------------------------ */
-
-void ED_gp_draw_interpolation(const struct bContext *C,
- struct tGPDinterpolate *tgpi,
- const int type);
void ED_gp_draw_fill(struct tGPDdraw *tgpw);
/* ***************************************************** */
@@ -636,7 +630,7 @@ struct GP_EditableStrokes_Iter {
bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \
for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
- ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \
+ BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
/* loop over strokes */ \
bGPDstroke *gpsn_; \
@@ -677,26 +671,21 @@ struct GP_EditableStrokes_Iter {
struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
- Object *obeval_ = DEG_get_evaluated_object(depsgraph_, obact_); \
- bGPdata *gpd_ = CTX_data_gpencil_data(C); \
- const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
- int idx_eval = 0; \
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { \
- if (gpencil_layer_is_editable(gpl)) { \
+ Object *ob_eval_ = (Object *)DEG_get_evaluated_id(depsgraph_, &obact_->id); \
+ bGPdata *gpd = (bGPdata *)ob_eval_->data; \
+ const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); \
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { \
+ if (BKE_gpencil_layer_is_editable(gpl)) { \
bGPDframe *init_gpf_ = gpl->actframe; \
if (is_multiedit_) { \
init_gpf_ = gpl->frames.first; \
} \
for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
- ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \
+ BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \
invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
- /* get evaluated frame with modifiers applied */ \
- bGPDframe *gpf_eval_ = (!is_multiedit_) ? \
- &obeval_->runtime.gpencil_evaluated_frames[idx_eval] : \
- gpf_; \
/* loop over strokes */ \
- for (bGPDstroke *gps = gpf_eval_->strokes.first; gps; gps = gps->next) { \
+ for (bGPDstroke *gps = gpf_->strokes.first; gps; gps = gps->next) { \
/* skip strokes that are invalid for current view */ \
if (ED_gpencil_stroke_can_use(C, gps) == false) \
continue; \
@@ -713,7 +702,6 @@ struct GP_EditableStrokes_Iter {
} \
} \
} \
- idx_eval++; \
} \
} \
(void)0
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 40c95e66cb2..05d5b8d6eee 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -119,20 +119,36 @@ static void gp_interpolate_update_points(const bGPDstroke *gps_from,
}
/* ****************** Interpolate Interactive *********************** */
+/* Helper: free all temp strokes for display. */
+static void gp_interpolate_free_temp_strokes(bGPDframe *gpf)
+{
+ if (gpf == NULL) {
+ return;
+ }
+ bGPDstroke *gps_next;
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) {
+ gps_next = gps->next;
+ if (gps->flag & GP_STROKE_TAG) {
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
+ }
+ }
+}
/* Helper: Update all strokes interpolated */
static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
{
bGPdata *gpd = tgpi->gpd;
- tGPDinterpolate_layer *tgpil;
const float shift = tgpi->shift;
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- bGPDstroke *new_stroke;
+ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
const float factor = tgpil->factor + shift;
- for (new_stroke = tgpil->interFrame->strokes.first; new_stroke;
- new_stroke = new_stroke->next) {
+ bGPDframe *gpf = tgpil->gpl->actframe;
+ /* Free temp strokes. */
+ gp_interpolate_free_temp_strokes(gpf);
+
+ LISTBASE_FOREACH (bGPDstroke *, new_stroke, &tgpil->interFrame->strokes) {
bGPDstroke *gps_from, *gps_to;
int stroke_idx;
@@ -149,6 +165,13 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
/* update points position */
if ((gps_from) && (gps_to)) {
gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+
+ /* Add temp strokes. */
+ if (gpf) {
+ bGPDstroke *gps_eval = BKE_gpencil_stroke_duplicate(new_stroke, true);
+ gps_eval->flag |= GP_STROKE_TAG;
+ BLI_addtail(&gpf->strokes, gps_eval);
+ }
}
}
}
@@ -165,19 +188,18 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
/* get layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* all layers or only active */
if (!(flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && !(gpl->flag & GP_LAYER_ACTIVE)) {
continue;
}
/* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
continue;
}
/* read strokes */
- for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from;
- gps_from = gps_from->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_from, &gpl->actframe->strokes) {
bGPDstroke *gps_to;
int fFrame;
@@ -225,7 +247,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
tgpi->high_limit = 2.0f - tgpi->init_factor;
/* set layers */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
tGPDinterpolate_layer *tgpil;
/* all layers or only active */
@@ -233,7 +255,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
continue;
}
/* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
continue;
}
@@ -255,8 +277,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
(tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1);
/* create new strokes data with interpolated points reading original stroke */
- for (bGPDstroke *gps_from = tgpil->prevFrame->strokes.first; gps_from;
- gps_from = gps_from->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_from, &tgpil->prevFrame->strokes) {
bGPDstroke *gps_to;
int fFrame;
@@ -286,7 +307,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true);
if (valid) {
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
@@ -298,8 +319,6 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
sizeof(*new_stroke->dvert) * gps_to->totpoints);
}
new_stroke->totpoints = gps_to->totpoints;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
}
/* update points position */
gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
@@ -311,12 +330,10 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
if (new_stroke->dvert != NULL) {
new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert));
}
- new_stroke->tot_triangles = 0;
- new_stroke->triangles = MEM_recallocN(new_stroke->triangles,
- sizeof(*new_stroke->triangles));
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
/* add to strokes */
BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
}
@@ -324,25 +341,6 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
}
/* ----------------------- */
-/* Drawing Callbacks */
-
-/* Drawing callback for modal operator in screen mode */
-static void gpencil_interpolate_draw_screen(const struct bContext *C,
- ARegion *UNUSED(ar),
- void *arg)
-{
- tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
- ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_PIXEL);
-}
-
-/* Drawing callback for modal operator in 3d mode */
-static void gpencil_interpolate_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
-{
- tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
- ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_VIEW);
-}
-
-/* ----------------------- */
/* Helper: calculate shift based on position of mouse (we only use x-axis for now.
* since this is more convenient for users to do), and store new shift value
@@ -408,25 +406,23 @@ static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpol
static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
{
tGPDinterpolate *tgpi = op->customdata;
- tGPDinterpolate_layer *tgpil;
bGPdata *gpd = tgpi->gpd;
/* don't assume that operator data exists at all */
if (tgpi) {
- /* remove drawing handler */
- if (tgpi->draw_handle_screen) {
- ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen);
- }
- if (tgpi->draw_handle_3d) {
- ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
- }
-
/* clear status message area */
ED_area_status_text(tgpi->sa, NULL);
ED_workspace_status_text(C, NULL);
+ /* Clear any temp stroke. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ gp_interpolate_free_temp_strokes(gpf);
+ }
+ }
+
/* finally, free memory used by temp data */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
BKE_gpencil_free_strokes(tgpil->interFrame);
MEM_freeN(tgpil->interFrame);
}
@@ -448,6 +444,7 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte
bGPdata *gpd = CTX_data_gpencil_data(C);
/* set current scene and window */
+ tgpi->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
tgpi->scene = CTX_data_scene(C);
tgpi->sa = CTX_wm_area(C);
tgpi->ar = CTX_wm_region(C);
@@ -543,15 +540,6 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
tgpi = op->customdata;
}
- /* Enable custom drawing handlers
- * It needs 2 handlers because strokes can in 3d space and screen space
- * and each handler use different coord system
- */
- tgpi->draw_handle_screen = ED_region_draw_cb_activate(
- tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL);
- tgpi->draw_handle_3d = ED_region_draw_cb_activate(
- tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW);
-
/* set cursor to indicate modal */
WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL);
@@ -572,8 +560,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
tGPDinterpolate *tgpi = op->customdata;
wmWindow *win = CTX_wm_window(C);
bGPDframe *gpf_dst;
- bGPDstroke *gps_src, *gps_dst;
- tGPDinterpolate_layer *tgpil;
+ bGPDstroke *gps_dst;
const bool has_numinput = hasNumInput(&tgpi->num);
switch (event->type) {
@@ -586,26 +573,22 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
WM_cursor_modal_restore(win);
/* insert keyframes as required... */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- gpf_dst = BKE_gpencil_layer_getframe(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
+ LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
+ gpf_dst = BKE_gpencil_layer_frame_get(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
gpf_dst->key_type = BEZT_KEYTYPE_BREAKDOWN;
/* copy strokes */
BLI_listbase_clear(&gpf_dst->strokes);
- for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_src, &tgpil->interFrame->strokes) {
if (gps_src->totpoints == 0) {
continue;
}
/* make copy of source stroke, then adjust pointer to points too */
- gps_dst = MEM_dupallocN(gps_src);
- gps_dst->points = MEM_dupallocN(gps_src->points);
- if (gps_src->dvert != NULL) {
- gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
- }
- gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
- gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps_dst);
+
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
}
@@ -966,7 +949,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
}
/* loop all layer to check if need interpolation */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *prevFrame, *nextFrame;
bGPDstroke *gps_from, *gps_to;
int cframe, fFrame;
@@ -976,7 +959,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
continue;
}
/* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ if (!BKE_gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
continue;
}
@@ -1035,12 +1018,12 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
/* create a new frame if needed */
if (interFrame == NULL) {
- interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
+ interFrame = BKE_gpencil_layer_frame_get(gpl, cframe, GP_GETFRAME_ADD_NEW);
interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
}
/* create new stroke */
- new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true);
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
if (gps_from->totpoints > gps_to->totpoints) {
@@ -1057,14 +1040,14 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
new_stroke->dvert = MEM_recallocN(new_stroke->dvert,
sizeof(*new_stroke->dvert) * gps_to->totpoints);
}
- new_stroke->totpoints = gps_to->totpoints;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
}
/* update points position */
gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_stroke);
+
/* add to strokes */
BLI_addtail(&interFrame->strokes, new_stroke);
}
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index d085d791477..30496fe6bb1 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -61,7 +61,7 @@ typedef struct tGPencilPointCache {
float x, y, z;
float pressure;
float strength;
- float mix_color[4];
+ float vert_color[4];
} tGPencilPointCache;
/* helper function to sort points */
@@ -95,7 +95,7 @@ static void gpencil_insert_points_to_stroke(bGPDstroke *gps,
pt_dst->uv_fac = 1.0f;
pt_dst->uv_rot = 0;
pt_dst->flag |= GP_SPOINT_SELECT;
- copy_v4_v4(pt_dst->mix_color, point_elem->mix_color);
+ copy_v4_v4(pt_dst->vert_color, point_elem->vert_color);
}
}
@@ -128,7 +128,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
else {
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
/* stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
@@ -143,10 +143,6 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
/* allocate memory for points */
gps->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, "gp_stroke_points");
- /* initialize triangle memory to dummy data */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
if (cyclic) {
gps->flag |= GP_STROKE_CYCLIC;
@@ -227,7 +223,7 @@ static void gpencil_calc_points_factor(bContext *C,
if (gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (clear_stroke) {
@@ -242,7 +238,7 @@ static void gpencil_calc_points_factor(bContext *C,
copy_v3_v3(&pt2->x, &pt->x);
pt2->pressure = pt->pressure;
pt2->strength = pt->strength;
- copy_v4_v4(pt2->mix_color, pt->mix_color);
+ copy_v4_v4(pt2->vert_color, pt->vert_color);
pt->flag &= ~GP_SPOINT_SELECT;
if (clear_point) {
pt->flag |= GP_SPOINT_TAG;
@@ -292,7 +288,7 @@ static void gpencil_calc_points_factor(bContext *C,
copy_v3_v3(&sort_pt->x, &pt2->x);
sort_pt->pressure = pt2->pressure;
sort_pt->strength = pt2->strength;
- copy_v4_v4(sort_pt->mix_color, pt2->mix_color);
+ copy_v4_v4(sort_pt->vert_color, pt2->vert_color);
sort_pt->gps = gps_array[i];
@@ -341,7 +337,7 @@ static int gpencil_insert_to_array(tGPencilPointCache *src_array,
dst_elem->pressure = src_elem->pressure;
dst_elem->strength = src_elem->strength;
dst_elem->factor = src_elem->factor;
- copy_v4_v4(dst_elem->mix_color, src_elem->mix_color);
+ copy_v4_v4(dst_elem->vert_color, src_elem->vert_color);
}
return last;
@@ -464,7 +460,7 @@ static bool gp_strokes_merge_poll(bContext *C)
/* check hidden or locked materials */
MaterialGPencilStyle *gp_style = ma->gp_style;
- if ((gp_style->flag & GP_STYLE_COLOR_HIDE) || (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if ((gp_style->flag & GP_MATERIAL_HIDE) || (gp_style->flag & GP_MATERIAL_LOCKED)) {
return false;
}
@@ -612,8 +608,8 @@ static int gp_stroke_merge_material_exec(bContext *C, wmOperator *op)
/* Update stroke material index. */
if (changed) {
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- 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 (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c
index 3d56cb0fcb1..e5b9d902210 100644
--- a/source/blender/editors/gpencil/gpencil_ops_versioning.c
+++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c
@@ -130,7 +130,6 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
copy_v4_v4(gp_style->fill_rgba, palcolor->fill);
/* set basic settings */
- 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);
@@ -138,13 +137,13 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
gp_style->texture_opacity = 1.0f;
gp_style->texture_pixsize = 100.0f;
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
- gp_style->flag |= GP_STYLE_FILL_SHOW;
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
/* fix strokes */
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if ((gps->colorname[0] != '\0') && (STREQ(gps->colorname, palcolor->info))) {
gps->mat_nr = ob->totcol - 1;
gps->colorname[0] = '\0';
@@ -174,7 +173,7 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
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;
@@ -182,8 +181,8 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op)
gpl->opacity = 1.0f;
/* 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);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 2270159d597..e31800f20e5 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -270,11 +270,6 @@ static void gp_update_cache(bGPdata *gpd)
}
}
-static bool gp_stroke_added_check(tGPsdata *p)
-{
- return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
-}
-
static void gp_stroke_added_enable(tGPsdata *p)
{
BLI_assert(p->gpf->strokes.last != NULL);
@@ -353,7 +348,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3])
if (p->ownerPtr.type == &RNA_Object) {
ob = (Object *)p->ownerPtr.data;
}
- ED_gp_get_drawing_reference(p->scene, ob, p->gpl, *p->align_flag, vec);
+ ED_gpencil_drawing_reference_get(p->scene, ob, p->gpl, *p->align_flag, vec);
}
/* Stroke Editing ---------------------------- */
@@ -482,48 +477,26 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
}
}
-/* apply jitter to stroke */
-static void gp_brush_jitter(bGPdata *gpd,
- Brush *brush,
- tGPspoint *pt,
- const float mval[2],
- const float pressure,
- float r_mval[2],
- RNG *rng)
+/* Apply jitter to stroke point. */
+static void gp_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude)
{
- float tmp_pressure = pressure;
- if (brush->gpencil_settings->draw_jitter > 0.0f) {
- tmp_pressure = BKE_curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, pressure);
- }
- /* exponential value */
- const float exfactor = (brush->gpencil_settings->draw_jitter + 2.0f) *
- (brush->gpencil_settings->draw_jitter + 2.0f);
- const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure;
- /* Jitter is applied perpendicular to the mouse movement vector (2D space) */
- float mvec[2], svec[2];
- /* mouse movement in ints -> floats */
+ /* Jitter is applied perpendicular to the mouse movement vector (2D space). */
+ float mvec[2];
+ /* Mouse movement in ints -> floats. */
if (gpd->runtime.sbuffer_used > 1) {
- mvec[0] = (mval[0] - (pt - 1)->x);
- mvec[1] = (mval[1] - (pt - 1)->y);
+ tGPspoint *pt_prev = pt - 1;
+ sub_v2_v2v2(mvec, &pt->x, &pt_prev->x);
normalize_v2(mvec);
}
else {
mvec[0] = 0.0f;
mvec[1] = 0.0f;
}
- /* rotate mvec by 90 degrees... */
- svec[0] = -mvec[1];
- svec[1] = mvec[0];
- /* scale the displacement by the random, and apply */
- if (BLI_rng_get_float(rng) > 0.5f) {
- mul_v2_fl(svec, -fac);
- }
- else {
- mul_v2_fl(svec, fac);
- }
-
- r_mval[0] = mval[0] + svec[0];
- r_mval[1] = mval[1] + svec[1];
+ /* Rotate mvec by 90 degrees... */
+ SWAP(float, mvec[0], mvec[1]);
+ mvec[0] -= mvec[0];
+ /* Scale by displacement amount, and apply. */
+ madd_v2_v2fl(&pt->x, mvec, amplitude);
}
/* apply pressure change depending of the angle of the stroke to simulate a pen with shape */
@@ -712,10 +685,10 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
{
bGPdata *gpd = p->gpd;
Brush *brush = p->brush;
+ BrushGpencilSettings *brush_settings = p->brush->gpencil_settings;
tGPspoint *pt;
Object *obact = (Object *)p->ownerPtr.data;
RegionView3D *rv3d = p->ar->regiondata;
- MaterialGPencilStyle *gp_style = p->material->gp_style;
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
@@ -764,100 +737,72 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
return GP_STROKEADD_INVALID;
}
+ /* Set vertex colors for buffer. */
+ ED_gpencil_sbuffer_vertex_color_set(p->scene->toolsettings, p->brush, gpd);
+
/* get pointer to destination point */
pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used);
/* store settings */
+ pt->strength = brush_settings->draw_strength;
+ pt->pressure = 1.0f;
+ pt->uv_rot = 0.0f;
+ copy_v2_v2(&pt->x, mval);
+
/* pressure */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE) {
- pt->pressure = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_sensitivity, 0, pressure);
- }
- else {
- pt->pressure = 1.0f;
+ if (brush_settings->flag & GP_BRUSH_USE_PRESSURE) {
+ pt->pressure *= BKE_curvemapping_evaluateF(brush_settings->curve_sensitivity, 0, pressure);
}
- /* Apply jitter to position */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_jitter > 0.0f)) {
- float r_mval[2];
- const float jitpress = (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) ?
- pressure :
- 1.0f;
- gp_brush_jitter(gpd, brush, pt, mval, jitpress, r_mval, p->rng);
- copy_v2_v2(&pt->x, r_mval);
- }
- else {
- copy_v2_v2(&pt->x, mval);
+ /* color strength */
+ if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
+ pt->strength *= BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, pressure);
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
- /* apply randomness to pressure */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_press > 0.0f)) {
- float tmp_pressure = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_sensitivity, 0, pressure);
- if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->pressure -= tmp_pressure * (brush->gpencil_settings->draw_random_press * 2.0f) *
- BLI_rng_get_float(p->rng);
+
+ if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) {
+ /* Apply jitter to position */
+ if (brush_settings->draw_jitter > 0.0f) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ float jitpress = 1.0f;
+ if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) {
+ jitpress = BKE_curvemapping_evaluateF(brush_settings->curve_jitter, 0, pressure);
+ }
+ /* FIXME the +2 means minimum jitter is 4 which is a bit strange for UX. */
+ const float exp_factor = brush_settings->draw_jitter + 2.0f;
+ const float fac = rand * SQUARE(exp_factor) * jitpress;
+ gp_brush_jitter(gpd, pt, fac);
}
- else {
- pt->pressure += tmp_pressure * (brush->gpencil_settings->draw_random_press * 2.0f) *
- BLI_rng_get_float(p->rng);
+ /* apply randomness to pressure */
+ if (brush_settings->draw_random_press > 0.0f) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ pt->pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press;
+ CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f);
}
- CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f);
- }
-
- /* apply randomness to uv texture rotation */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->uv_random > 0.0f)) {
- if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->uv_rot = (BLI_rng_get_float(p->rng) * M_PI * -1) * brush->gpencil_settings->uv_random;
+ /* apply randomness to uv texture rotation */
+ if (brush_settings->uv_random > 0.0f) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ pt->uv_rot += rand * M_PI * brush_settings->uv_random;
+ CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
}
- else {
- pt->uv_rot = (BLI_rng_get_float(p->rng) * M_PI) * brush->gpencil_settings->uv_random;
+ /* apply randomness to color strength */
+ if (brush_settings->draw_random_strength) {
+ float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f;
+ pt->strength *= 1.0 + rand * brush_settings->draw_random_strength;
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
- CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
- }
- else {
- pt->uv_rot = 0.0f;
}
/* apply angle of stroke to brush size */
- if (brush->gpencil_settings->draw_angle_factor != 0.0f) {
+ if (brush_settings->draw_angle_factor != 0.0f) {
gp_brush_angle(gpd, brush, pt, mval);
}
- /* color strength */
- if (brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) {
- float tmp_pressure = BKE_curvemapping_evaluateF(
- brush->gpencil_settings->curve_strength, 0, pressure);
-
- pt->strength = tmp_pressure * brush->gpencil_settings->draw_strength;
- }
- else {
- pt->strength = brush->gpencil_settings->draw_strength;
- }
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
-
- /* apply randomness to color strength */
- if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) &&
- (brush->gpencil_settings->draw_random_strength > 0.0f)) {
- if (BLI_rng_get_float(p->rng) > 0.5f) {
- pt->strength -= pt->strength * brush->gpencil_settings->draw_random_strength *
- BLI_rng_get_float(p->rng);
- }
- else {
- pt->strength += pt->strength * brush->gpencil_settings->draw_random_strength *
- BLI_rng_get_float(p->rng);
- }
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- }
-
/* point time */
pt->time = (float)(curtime - p->inittime);
/* point uv (only 3d view) */
if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_used > 0)) {
- float pixsize = gp_style->texture_pixsize / 1000000.0f;
tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
bGPDspoint spt, spt2;
@@ -871,11 +816,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
/* reproject previous */
ED_gpencil_tpoint_to_point(p->ar, origin, ptb, &spt2);
ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2);
- p->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
+ p->totpixlen += len_v3v3(&spt.x, &spt2.x);
pt->uv_fac = p->totpixlen;
- if ((gp_style) && (gp_style->sima)) {
- pt->uv_fac /= gp_style->sima->gen_x;
- }
}
else {
p->totpixlen = 0.0f;
@@ -894,6 +836,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure
}
}
+ /* Update evaluated data. */
+ ED_gpencil_sbuffer_update_eval(p->depsgraph, p->ob);
+
return GP_STROKEADD_NORMAL;
}
/* return invalid state for now... */
@@ -967,25 +912,19 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* copy appropriate settings for stroke */
gps->totpoints = totelem;
gps->thickness = brush->size;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_f = brush->gpencil_settings->gradient_f;
copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
gps->flag = gpd->runtime.sbuffer_sflag;
gps->inittime = p->inittime;
gps->uv_scale = 1.0f;
- /* enable recalculation flag by default */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
/* allocate enough memory for a continuous array for storage points */
const int subdivide = brush->gpencil_settings->draw_subdivide;
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
gps->dvert = NULL;
- /* initialize triangle memory to dummy data */
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
/* drawing batch cache is dirty now */
gp_update_cache(p->gpd);
/* set pointer to first non-initialized point */
@@ -994,11 +933,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
dvert = gps->dvert + (gps->totpoints - totelem);
}
- /* Apply the mix color to fill for stroke. */
- if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
- copy_v3_v3(gps->mix_color_fill, brush->rgb);
- gps->mix_color_fill[3] = brush->gpencil_settings->vertex_factor;
- }
+ /* Apply the vertex color to fill. */
+ ED_gpencil_fill_vertex_color_set(ts, brush, gps);
/* copy points from the buffer to the stroke */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
@@ -1014,11 +950,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
- /* Point mix color. */
- copy_v3_v3(pt->mix_color, brush->rgb);
- pt->mix_color[3] = GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) ?
- brush->gpencil_settings->vertex_factor :
- 0.0f;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt);
pt++;
@@ -1050,11 +983,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->strength = ptc->strength;
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt->time = ptc->time;
- /* Point mix color. */
- copy_v3_v3(pt->mix_color, brush->rgb);
- pt->mix_color[3] = GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) ?
- brush->gpencil_settings->vertex_factor :
- 0.0f;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt);
if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) {
BKE_gpencil_dvert_ensure(gps);
@@ -1176,11 +1106,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
pt->time = ptc->time;
pt->uv_fac = ptc->uv_fac;
pt->uv_rot = ptc->uv_rot;
- /* Point mix color. */
- copy_v3_v3(pt->mix_color, brush->rgb);
- pt->mix_color[3] = GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) ?
- brush->gpencil_settings->vertex_factor :
- 0.0f;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt);
if (dvert != NULL) {
dvert->totweight = 0;
@@ -1202,8 +1129,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
float reduce = 0.0f;
for (int r = 0; r < brush->gpencil_settings->draw_smoothlvl; r++) {
for (i = 0; i < gps->totpoints - 1; i++) {
- BKE_gpencil_smooth_stroke(gps, i, brush->gpencil_settings->draw_smoothfac - reduce);
- BKE_gpencil_smooth_stroke_strength(gps, i, brush->gpencil_settings->draw_smoothfac);
+ BKE_gpencil_stroke_smooth(gps, i, brush->gpencil_settings->draw_smoothfac - reduce);
+ BKE_gpencil_stroke_smooth_strength(gps, i, brush->gpencil_settings->draw_smoothfac);
}
reduce += 0.25f; /* reduce the factor */
}
@@ -1212,7 +1139,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* Simplify adaptive */
if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
(brush->gpencil_settings->simplify_f > 0.0f)) {
- BKE_gpencil_simplify_stroke(gps, brush->gpencil_settings->simplify_f);
+ BKE_gpencil_stroke_simplify(gps, brush->gpencil_settings->simplify_f);
}
/* reproject to plane (only in 3d space) */
@@ -1240,9 +1167,6 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
}
- /* calculate UVs along the stroke */
- ED_gpencil_calc_stroke_uv(obact, gps);
-
/* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke
* is added on listbase head because the drawing order is inverse and the head stroke is the
* first to draw. This is very useful for artist when drawing the background.
@@ -1268,9 +1192,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* post process stroke */
if ((p->brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
p->brush->gpencil_settings->flag & GP_BRUSH_TRIM_STROKE) {
- BKE_gpencil_trim_stroke(gps);
+ BKE_gpencil_stroke_trim(gps);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
gp_stroke_added_enable(p);
}
@@ -1316,7 +1243,7 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p,
float diff_mat[4][4];
/* calculate difference matrix if parent object */
- ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(p->depsgraph, obact, gpl, diff_mat);
if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) {
const float depth_mval = view3d_point_depth(rv3d, mval_3d);
@@ -1441,7 +1368,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
round_v2i_v2fl(mval_i, mval);
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, p->gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
if (gps->totpoints == 0) {
/* just free stroke */
@@ -1638,7 +1565,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* erase strokes which fall under the eraser strokes */
static void gp_stroke_doeraser(tGPsdata *p)
{
- bGPDlayer *gpl;
bGPDstroke *gps, *gpn;
rcti rect;
Brush *brush = p->brush;
@@ -1679,11 +1605,11 @@ static void gp_stroke_doeraser(tGPsdata *p)
* only a subset of layers, it is harder to perform the same erase operation
* on multiple layers...
*/
- for (gpl = p->gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) {
bGPDframe *gpf = gpl->actframe;
/* only affect layer if it's editable (and visible) */
- if (gpencil_layer_is_editable(gpl) == false) {
+ if (BKE_gpencil_layer_is_editable(gpl) == false) {
continue;
}
else if (gpf == NULL) {
@@ -1841,51 +1767,12 @@ static void gp_init_colors(tGPsdata *p)
{
bGPdata *gpd = p->gpd;
Brush *brush = p->brush;
- ToolSettings *ts = p->scene->toolsettings;
-
- MaterialGPencilStyle *gp_style = NULL;
/* use brush material */
p->material = BKE_gpencil_object_material_ensure_from_active_input_brush(p->bmain, p->ob, brush);
- /* assign color information to temp tGPsdata */
- gp_style = p->material->gp_style;
- if (gp_style) {
-
- /* set colors */
- if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
- copy_v4_v4(gpd->runtime.scolor, gp_style->stroke_rgba);
- }
- else {
- /* if no stroke, use fill */
- copy_v4_v4(gpd->runtime.scolor, gp_style->fill_rgba);
- }
- copy_v4_v4(gpd->runtime.sfill, gp_style->fill_rgba);
- /* add some alpha to make easy the filling without hide strokes */
- if (gpd->runtime.sfill[3] > 0.8f) {
- gpd->runtime.sfill[3] = 0.8f;
- }
-
- /* Apply the mix color to fill. */
- if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
- interp_v3_v3v3(gpd->runtime.sfill,
- gpd->runtime.sfill,
- brush->rgb,
- brush->gpencil_settings->vertex_factor);
- }
-
- gpd->runtime.mode = (short)gp_style->mode;
- gpd->runtime.bstroke_style = gp_style->stroke_style;
- gpd->runtime.bfill_style = gp_style->fill_style;
-
- /* Apply the mix color to stroke. */
- if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) {
- interp_v3_v3v3(gpd->runtime.scolor,
- gpd->runtime.scolor,
- brush->rgb,
- brush->gpencil_settings->vertex_factor);
- }
- }
+ gpd->runtime.matid = BKE_object_material_slot_find_index(p->ob, p->material);
+ gpd->runtime.brush_size = brush->size;
}
/* (re)init new painting data */
@@ -2091,7 +1978,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
ToolSettings *ts = scene->toolsettings;
/* get active layer (or add a new one if non-existent) */
- p->gpl = BKE_gpencil_layer_getactive(p->gpd);
+ p->gpl = BKE_gpencil_layer_active_get(p->gpd);
if (p->gpl == NULL) {
p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true);
@@ -2116,9 +2003,9 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
*/
bool has_layer_to_erase = false;
- for (bGPDlayer *gpl = p->gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) {
/* Skip if layer not editable */
- if (gpencil_layer_is_editable(gpl) == false) {
+ if (BKE_gpencil_layer_is_editable(gpl) == false) {
continue;
}
@@ -2130,7 +2017,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
* -> If there are no strokes in that frame, don't add a new empty frame
*/
if (gpl->actframe && gpl->actframe->strokes.first) {
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY);
has_layer_to_erase = true;
}
@@ -2159,7 +2046,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_frame_get(p->gpl, CFRA, add_frame_mode);
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
@@ -2186,8 +2073,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* set special fill stroke mode */
if (p->disable_fill == true) {
p->gpd->runtime.sbuffer_sflag |= GP_STROKE_NOFILL;
- /* replace stroke color with fill color */
- copy_v4_v4(p->gpd->runtime.scolor, p->gpd->runtime.sfill);
}
/* set 'initial run' flag, which is only used to denote when a new stroke is starting */
@@ -2232,6 +2117,8 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
}
}
}
+ /* Tag datablock. */
+ gp_update_cache(p->gpd);
}
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
@@ -2276,7 +2163,6 @@ static void gp_paint_cleanup(tGPsdata *p)
p->gpf->flag &= ~GP_FRAME_PAINT;
}
}
-
/* ------------------------------- */
/* Helper callback for drawing the cursor itself */
@@ -2451,23 +2337,6 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
/* ------------------------------- */
-/* ensure that the correct cursor icon is set */
-static void gpencil_draw_cursor_set(tGPsdata *p)
-{
- UNUSED_VARS(p);
- return;
- /* Disable while we get a better cursor handling for direct input devices (Cintiq/Ipad)*/
-#if 0
- Brush *brush = p->brush;
- if ((p->paintmode == GP_PAINTMODE_ERASER) || (brush->gpencil_tool == GPAINT_TOOL_ERASE)) {
- WM_cursor_modal_set(p->win, WM_CURSOR_CROSS); /* XXX need a better cursor */
- }
- else {
- WM_cursor_modal_set(p->win, WM_CURSOR_NONE);
- }
-#endif
-}
-
/* update UI indicators of status, including cursor and header prints */
static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
{
@@ -3162,9 +3031,9 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
else {
/* don't erase empty frames */
bool has_layer_to_erase = false;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Skip if layer not editable */
- if (gpencil_layer_is_editable(gpl)) {
+ if (BKE_gpencil_layer_is_editable(gpl)) {
if (gpl->actframe && gpl->actframe->strokes.first) {
has_layer_to_erase = true;
break;
@@ -3192,18 +3061,13 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
}
/* TODO: set any additional settings that we can take from the events?
- /* if eraser is on, draw radial aid */
+ * if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
gpencil_draw_toggle_eraser_cursor(C, p, true);
}
else {
ED_gpencil_toggle_brush_cursor(C, true, NULL);
}
- /* set cursor
- * NOTE: This may change later (i.e. intentionally via brush toggle,
- * or unintentionally if the user scrolls outside the area)...
- */
- gpencil_draw_cursor_set(p);
/* only start drawing immediately if we're allowed to do so... */
if (RNA_boolean_get(op->ptr, "wait_for_input") == false) {
@@ -3280,27 +3144,9 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
return op->customdata;
}
-static void gpencil_stroke_end(wmOperator *op)
-{
- tGPsdata *p = op->customdata;
-
- gp_paint_cleanup(p);
-
- gpencil_undo_push(p->gpd);
-
- gp_session_cleanup(p);
-
- p->status = GP_STATUS_IDLING;
- op->flag |= OP_IS_MODAL_CURSOR_REGION;
-
- p->gpd = NULL;
- p->gpl = NULL;
- p->gpf = NULL;
-}
-
/* Add arc points between two mouse events using the previous segment to determine the vertice of
* the arc.
- * /* CTL
+ * /+ CTL
* / |
* / |
* PtA +...|...+ PtB
@@ -3807,7 +3653,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
else {
/* update status indicators - cursor, header, etc. */
gpencil_draw_status_indicators(C, p);
- gpencil_draw_cursor_set(p); /* cursor may have changed outside our control - T44084 */
}
/* process last operations before exiting */
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index f106138b42a..7d9c3b7785c 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -122,6 +122,9 @@ static void gp_session_validatebuffer(tGPDprimitive *p)
gpd->runtime.sbuffer_sflag = 0;
gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
+ /* Set vertex colors for buffer. */
+ ED_gpencil_sbuffer_vertex_color_set(p->scene->toolsettings, p->brush, gpd);
+
if (ELEM(p->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
gpd->runtime.sbuffer_sflag |= GP_STROKE_CYCLIC;
}
@@ -131,51 +134,12 @@ static void gp_init_colors(tGPDprimitive *p)
{
bGPdata *gpd = p->gpd;
Brush *brush = p->brush;
- ToolSettings *ts = p->scene->toolsettings;
-
- MaterialGPencilStyle *gp_style = NULL;
/* use brush material */
p->mat = BKE_gpencil_object_material_ensure_from_active_input_brush(p->bmain, p->ob, brush);
- /* assign color information to temp data */
- gp_style = p->mat->gp_style;
- if (gp_style) {
-
- /* set colors */
- if (gp_style->flag & GP_STYLE_STROKE_SHOW) {
- copy_v4_v4(gpd->runtime.scolor, gp_style->stroke_rgba);
- }
- else {
- /* if no stroke, use fill */
- copy_v4_v4(gpd->runtime.scolor, gp_style->fill_rgba);
- }
-
- copy_v4_v4(gpd->runtime.sfill, gp_style->fill_rgba);
- /* add some alpha to make easy the filling without hide strokes */
- if (gpd->runtime.sfill[3] > 0.8f) {
- gpd->runtime.sfill[3] = 0.8f;
- }
- /* Apply the mix color to fill. */
- if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
- interp_v3_v3v3(gpd->runtime.sfill,
- gpd->runtime.sfill,
- brush->rgb,
- brush->gpencil_settings->vertex_factor);
- }
-
- gpd->runtime.mode = (short)gp_style->mode;
- gpd->runtime.bstroke_style = gp_style->stroke_style;
- gpd->runtime.bfill_style = gp_style->fill_style;
-
- /* Apply the mix color to stroke. */
- if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) {
- interp_v3_v3v3(gpd->runtime.scolor,
- gpd->runtime.scolor,
- brush->rgb,
- brush->gpencil_settings->vertex_factor);
- }
- }
+ gpd->runtime.matid = BKE_object_material_slot_find_index(p->ob, p->mat);
+ gpd->runtime.brush_size = brush->size;
}
/* Helper to square a primitive */
@@ -270,18 +234,6 @@ static void gp_primitive_update_cps(tGPDprimitive *tgpi)
}
}
-/* Helper to reflect point */
-static void UNUSED_FUNCTION(gp_reflect_point_v2_v2v2v2)(float va[2],
- const float p[2],
- const float a[2],
- const float b[2])
-{
- float point[2];
- closest_to_line_v2(point, p, a, b);
- va[0] = point[0] - (p[0] - point[0]);
- va[1] = point[1] - (p[1] - point[1]);
-}
-
/* Poll callback for primitive operators */
static bool gpencil_primitive_add_poll(bContext *C)
{
@@ -310,7 +262,7 @@ static bool gpencil_primitive_add_poll(bContext *C)
/* don't allow operator to function if the active layer is locked/hidden
* (BUT, if there isn't an active layer, we are free to add new layer when the time comes)
*/
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if ((gpl) && (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_HIDE))) {
CTX_wm_operator_poll_msg_set(C,
"Primitives cannot be added as active layer is locked or hidden");
@@ -357,20 +309,16 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* create new temp stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "Temp bGPDstroke");
gps->thickness = 2.0f;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_f = 1.0f;
gps->gradient_s[0] = 1.0f;
gps->gradient_s[1] = 1.0f;
gps->uv_scale = 1.0f;
gps->inittime = 0.0f;
- /* Apply the mix color to fill. */
- if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
- copy_v3_v3(gps->mix_color_fill, brush->rgb);
- gps->mix_color_fill[3] = brush->gpencil_settings->vertex_factor;
- }
+ /* Apply the vertex color to fill. */
+ ED_gpencil_fill_vertex_color_set(ts, brush, gps);
- /* enable recalculation flag by default */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
gps->flag &= ~GP_STROKE_SELECT;
/* the polygon must be closed, so enabled cyclic */
if (ELEM(tgpi->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) {
@@ -393,10 +341,10 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
gps->totpoints = 0;
gps->points = MEM_callocN(sizeof(bGPDspoint), "gp_stroke_points");
gps->dvert = NULL;
+
/* initialize triangle memory to dummy data */
gps->tot_triangles = 0;
gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* add to strokes */
BLI_addtail(&tgpi->gpf->strokes, gps);
@@ -407,6 +355,8 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* Random generator, only init once. */
uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
tgpi->rng = BLI_rng_new(rng_seed);
+
+ DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
}
/* add new segment to curve */
@@ -998,14 +948,13 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* point uv */
if (gpd->runtime.sbuffer_used > 0) {
- MaterialGPencilStyle *gp_style = tgpi->mat->gp_style;
- const float pixsize = gp_style->texture_pixsize / 1000000.0f;
tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1;
bGPDspoint spt, spt2;
/* get origin to reproject point */
float origin[3];
- ED_gp_get_drawing_reference(tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(
+ tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin);
/* reproject current */
ED_gpencil_tpoint_to_point(tgpi->ar, origin, tpt, &spt);
ED_gp_project_point_to_plane(
@@ -1015,11 +964,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
ED_gpencil_tpoint_to_point(tgpi->ar, origin, tptb, &spt2);
ED_gp_project_point_to_plane(
tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2);
- tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
+ tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x);
tpt->uv_fac = tgpi->totpixlen;
- if ((gp_style) && (gp_style->sima)) {
- tpt->uv_fac /= gp_style->sima->gen_x;
- }
}
else {
tgpi->totpixlen = 0.0f;
@@ -1048,11 +994,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
pt->time = 0.0f;
pt->flag = 0;
pt->uv_fac = tpt->uv_fac;
- /* Point mix color. */
- copy_v3_v3(pt->mix_color, brush->rgb);
- pt->mix_color[3] = GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush) ?
- brush->gpencil_settings->vertex_factor :
- 0.0f;
+ /* Apply the vertex color to point. */
+ ED_gpencil_point_vertex_color_set(ts, brush, pt);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];
@@ -1077,7 +1020,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* reproject to plane */
if (!is_depth) {
float origin[3];
- ED_gp_get_drawing_reference(tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin);
+ ED_gpencil_drawing_reference_get(
+ tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin);
ED_gp_project_stroke_to_plane(
tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1);
}
@@ -1093,8 +1037,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
ED_gpencil_project_stroke_to_view(C, tgpi->gpl, gps);
}
- /* force fill recalc */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
+ /* Update evaluated data. */
+ ED_gpencil_sbuffer_update_eval(tgpi->depsgraph, tgpi->ob);
MEM_SAFE_FREE(depth_arr);
@@ -1334,7 +1281,7 @@ static void gpencil_primitive_interaction_end(bContext *C,
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- gpf = BKE_gpencil_layer_getframe(tgpi->gpl, tgpi->cframe, add_frame_mode);
+ gpf = BKE_gpencil_layer_frame_get(tgpi->gpl, tgpi->cframe, add_frame_mode);
/* prepare stroke to get transferred */
gps = tgpi->gpf->strokes.first;
@@ -1343,11 +1290,8 @@ static void gpencil_primitive_interaction_end(bContext *C,
gps->gradient_f = brush->gpencil_settings->gradient_f;
copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
-
- /* calculate UVs along the stroke */
- ED_gpencil_calc_stroke_uv(tgpi->ob, gps);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* transfer stroke from temporary buffer to the actual frame */
@@ -1373,7 +1317,7 @@ static void gpencil_primitive_interaction_end(bContext *C,
/* Close stroke with geometry */
if ((tgpi->type == GP_STROKE_BOX) || (tgpi->type == GP_STROKE_CIRCLE)) {
- BKE_gpencil_close_stroke(gps);
+ BKE_gpencil_stroke_close(gps);
}
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 94598314ba3..31227b8254b 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -85,7 +85,7 @@
/* Context for brush operators */
typedef struct tGP_BrushEditData {
/* Current editor/region/etc. */
- /* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */
+ Depsgraph *depsgraph;
Main *bmain;
Scene *scene;
Object *object;
@@ -175,10 +175,6 @@ static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso,
bGPDspoint *pt,
const float save_pt[3])
{
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- return;
- }
-
const ToolSettings *ts = gso->scene->toolsettings;
const View3DCursor *cursor = &gso->scene->cursor;
const int axis = ts->gp_sculpt.lock_axis;
@@ -282,18 +278,36 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
return influence;
}
-/* Force recal filling data */
-static void gp_recalc_geometry(bGPDstroke *gps)
+/* Tag stroke to be recalculated. */
+static void gpencil_recalc_geometry_tag(bGPDstroke *gps)
{
- bGPDstroke *gps_orig = gps->runtime.gps_orig;
- if (gps_orig) {
- gps_orig->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps_orig->tot_triangles = 0;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ gps_active->flag |= GP_STROKE_TAG;
+}
+
+/* Recalc any stroke tagged. */
+static void gpencil_update_geometry(bGPdata *gpd)
+{
+ if (gpd == NULL) {
+ return;
}
- else {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ if ((gpl->actframe != gpf) && ((gpf->flag & GP_FRAME_SELECT) == 0)) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_TAG) {
+ BKE_gpencil_stroke_geometry_update(gps);
+ gps->flag &= ~GP_STROKE_TAG;
+ }
+ }
+ }
}
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
/* ************************************************ */
@@ -318,20 +332,18 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso,
/* perform smoothing */
if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) {
- BKE_gpencil_smooth_stroke(gps, pt_index, inf);
+ BKE_gpencil_stroke_smooth(gps, pt_index, inf);
}
if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) {
- BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
+ BKE_gpencil_stroke_smooth_strength(gps, pt_index, inf);
}
if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) {
- BKE_gpencil_smooth_stroke_thickness(gps, pt_index, inf);
+ BKE_gpencil_stroke_smooth_thickness(gps, pt_index, inf);
}
if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) {
- BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf);
+ BKE_gpencil_stroke_smooth_uv(gps, pt_index, inf);
}
- gp_recalc_geometry(gps);
-
return true;
}
@@ -413,7 +425,7 @@ static bool gp_brush_strength_apply(tGP_BrushEditData *gso,
CLAMP(pt->strength, 0.0f, 1.0f);
/* smooth the strength */
- BKE_gpencil_smooth_stroke_strength(gps, pt_index, inf);
+ BKE_gpencil_stroke_smooth_strength(gps, pt_index, inf);
return true;
}
@@ -507,38 +519,27 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso,
static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso)
{
/* Convert mouse-movements to movement vector */
- // TODO: incorporate pressure into this?
- // XXX: screen-space strokes in 3D space will suffer!
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- RegionView3D *rv3d = gso->ar->regiondata;
- float *rvec = gso->object->loc;
- float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-
- float mval_f[2];
-
- /* convert from 2D screenspace to 3D... */
- mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
- mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
-
- /* apply evaluated data transformation */
- if (gso->rot_eval != 0.0f) {
- const float cval = cos(gso->rot_eval);
- const float sval = sin(gso->rot_eval);
- float r[2];
- r[0] = (mval_f[0] * cval) - (mval_f[1] * sval);
- r[1] = (mval_f[0] * sval) + (mval_f[1] * cval);
- copy_v2_v2(mval_f, r);
- }
+ RegionView3D *rv3d = gso->ar->regiondata;
+ float *rvec = gso->object->loc;
+ float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
- ED_view3d_win_to_delta(gso->ar, mval_f, gso->dvec, zfac);
- }
- else {
- /* 2D - just copy */
- // XXX: view2d?
- gso->dvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
- gso->dvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
- gso->dvec[2] = 0.0f; /* unused */
+ float mval_f[2];
+
+ /* convert from 2D screenspace to 3D... */
+ mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
+ mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
+
+ /* apply evaluated data transformation */
+ if (gso->rot_eval != 0.0f) {
+ const float cval = cos(gso->rot_eval);
+ const float sval = sin(gso->rot_eval);
+ float r[2];
+ r[0] = (mval_f[0] * cval) - (mval_f[1] * sval);
+ r[1] = (mval_f[0] * sval) + (mval_f[1] * cval);
+ copy_v2_v2(mval_f, r);
}
+
+ ED_view3d_win_to_delta(gso->ar, mval_f, gso->dvec, zfac);
}
/* Apply grab transform to all relevant points of the affected strokes */
@@ -548,6 +549,8 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
{
tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
int i;
+ float inverse_diff_mat[4][4];
+ invert_m4_m4(inverse_diff_mat, diff_mat);
/* Apply dvec to all of the stored points */
for (i = 0; i < data->size; i++) {
@@ -569,14 +572,11 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
/* apply */
add_v3_v3v3(&pt->x, fpt, delta);
/* undo transformation to the init parent position */
- float inverse_diff_mat[4][4];
- invert_m4_m4(inverse_diff_mat, diff_mat);
mul_m4_v3(inverse_diff_mat, &pt->x);
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
- gp_recalc_geometry(gps);
}
/* free customdata used for handling this stroke */
@@ -620,8 +620,6 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso,
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
-
/* done */
return true;
}
@@ -631,35 +629,26 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso,
/* Compute reference midpoint for the brush - this is what we'll be moving towards */
static void gp_brush_calc_midpoint(tGP_BrushEditData *gso)
{
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- /* Convert mouse position to 3D space
- * See: gpencil_paint.c :: gp_stroke_convertcoords()
- */
- RegionView3D *rv3d = gso->ar->regiondata;
- const float *rvec = gso->object->loc;
- float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-
- float mval_f[2];
- copy_v2_v2(mval_f, gso->mval);
- float mval_prj[2];
- float dvec[3];
-
- if (ED_view3d_project_float_global(gso->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
- V3D_PROJ_RET_OK) {
- sub_v2_v2v2(mval_f, mval_prj, mval_f);
- ED_view3d_win_to_delta(gso->ar, mval_f, dvec, zfac);
- sub_v3_v3v3(gso->dvec, rvec, dvec);
- }
- else {
- zero_v3(gso->dvec);
- }
+ /* Convert mouse position to 3D space
+ * See: gpencil_paint.c :: gp_stroke_convertcoords()
+ */
+ RegionView3D *rv3d = gso->ar->regiondata;
+ const float *rvec = gso->object->loc;
+ float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
+
+ float mval_f[2];
+ copy_v2_v2(mval_f, gso->mval);
+ float mval_prj[2];
+ float dvec[3];
+
+ if (ED_view3d_project_float_global(gso->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
+ sub_v2_v2v2(mval_f, mval_prj, mval_f);
+ ED_view3d_win_to_delta(gso->ar, mval_f, dvec, zfac);
+ sub_v3_v3v3(gso->dvec, rvec, dvec);
}
else {
- /* Just 2D coordinates */
- // XXX: fix View2D offsets later
- gso->dvec[0] = (float)gso->mval[0];
- gso->dvec[1] = (float)gso->mval[1];
- gso->dvec[2] = 0.0f;
+ zero_v3(gso->dvec);
}
}
@@ -711,8 +700,6 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso,
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
- gp_recalc_geometry(gps);
-
/* done */
return true;
}
@@ -799,8 +786,6 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso,
}
}
- gp_recalc_geometry(gps);
-
/* done */
return true;
}
@@ -853,32 +838,17 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
/* convert to dataspace */
if (gps->flag & GP_STROKE_3DSPACE) {
/* 3D: Project to 3D space */
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- bool flip;
- RegionView3D *rv3d = gso->ar->regiondata;
- float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip);
- if (flip == false) {
- float dvec[3];
- ED_view3d_win_to_delta(gso->gsc.ar, svec, dvec, zfac);
- add_v3_v3(&pt->x, dvec);
- /* compute lock axis */
- gpsculpt_compute_lock_axis(gso, pt, save_pt);
- }
- }
- else {
- /* ERROR */
- BLI_assert(!"3D stroke being sculpted in non-3D view");
+ bool flip;
+ RegionView3D *rv3d = gso->ar->regiondata;
+ float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip);
+ if (flip == false) {
+ float dvec[3];
+ ED_view3d_win_to_delta(gso->gsc.ar, svec, dvec, zfac);
+ add_v3_v3(&pt->x, dvec);
+ /* compute lock axis */
+ gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
}
- else {
- /* 2D: As-is */
- // XXX: v2d scaling/offset?
- float nco[2];
- nco[0] = (float)co[0] + svec[0];
- nco[1] = (float)co[1] + svec[1];
-
- copy_v2_v2(&pt->x, nco);
- }
}
/* apply random to strength */
if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) {
@@ -913,69 +883,10 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
}
- gp_recalc_geometry(gps);
-
/* done */
return true;
}
-/* Weight Paint Brush */
-/* Change weight paint for vertex groups */
-static bool gp_brush_weight_apply(tGP_BrushEditData *gso,
- bGPDstroke *gps,
- float UNUSED(rot_eval),
- int pt_index,
- const int radius,
- const int co[2])
-{
- /* create dvert */
- BKE_gpencil_dvert_ensure(gps);
-
- MDeformVert *dvert = gps->dvert + pt_index;
- float inf;
-
- /* Compute strength of effect
- * - We divide the strength by 10, so that users can set "sane" values.
- * Otherwise, good default values are in the range of 0.093
- */
- inf = gp_brush_influence_calc(gso, radius, co) / 10.0f;
-
- /* need a vertex group */
- if (gso->vrgroup == -1) {
- if (gso->object) {
- BKE_object_defgroup_add(gso->object);
- DEG_relations_tag_update(gso->bmain);
- gso->vrgroup = 0;
- }
- }
- else {
- bDeformGroup *defgroup = BLI_findlink(&gso->object->defbase, gso->vrgroup);
- if (defgroup->flag & DG_LOCK_WEIGHT) {
- return false;
- }
- }
- /* get current weight */
- MDeformWeight *dw = defvert_verify_index(dvert, gso->vrgroup);
- float curweight = dw ? dw->weight : 0.0f;
-
- if (gp_brush_invert_check(gso)) {
- curweight -= inf;
- }
- else {
- /* increase weight */
- curweight += inf;
- /* verify maximum target weight */
- CLAMP_MAX(curweight, gso->brush->weight);
- }
-
- CLAMP(curweight, 0.0f, 1.0f);
- if (dw) {
- dw->weight = curweight;
- }
-
- return true;
-}
-
/* ************************************************ */
/* Non Callback-Based Brushes */
/* Clone Brush ------------------------------------- */
@@ -1079,9 +990,9 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
{
tGPSB_CloneBrushData *data = gso->customdata;
- Object *ob = CTX_data_active_object(C);
+ Object *ob = gso->object;
bGPdata *gpd = (bGPdata *)ob->data;
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = gso->scene;
bGPDstroke *gps;
float delta[3];
@@ -1110,24 +1021,17 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
if (gpl == NULL) {
gpl = CTX_data_active_gpencil_layer(C);
}
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
/* Make a new stroke */
- new_stroke = MEM_dupallocN(gps);
-
- new_stroke->points = MEM_dupallocN(gps->points);
- if (gps->dvert != NULL) {
- new_stroke->dvert = MEM_dupallocN(gps->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps, new_stroke);
- }
- new_stroke->triangles = MEM_dupallocN(gps->triangles);
+ new_stroke = BKE_gpencil_stroke_duplicate(gps, true);
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
/* Fix color references */
Material *ma = BLI_ghash_lookup(data->new_colors, POINTER_FROM_INT(new_stroke->mat_nr));
- new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
+ new_stroke->mat_nr = BKE_gpencil_object_material_index_get(ob, ma);
if (!ma || new_stroke->mat_nr < 0) {
new_stroke->mat_nr = 0;
}
@@ -1240,7 +1144,7 @@ static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso)
static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
+ ToolSettings *ts = scene->toolsettings;
Object *ob = CTX_data_active_object(C);
/* set the brush using the tool */
@@ -1250,6 +1154,7 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData");
op->customdata = gso;
+ gso->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
gso->bmain = CTX_data_main(C);
/* store state */
gso->settings = gpsculpt_get_settings(scene);
@@ -1352,11 +1257,6 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
/* update header */
gpsculpt_brush_header_set(C, gso);
- /* setup cursor drawing */
- // WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_CROSS);
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- ED_gpencil_toggle_brush_cursor(C, true, NULL);
- }
return true;
}
@@ -1396,16 +1296,15 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
BLI_rng_free(gso->rng);
}
- /* disable cursor and headerprints */
+ /* Disable headerprints. */
ED_workspace_status_text(C, NULL);
- WM_cursor_modal_restore(win);
- if (gso->sa->spacetype != SPACE_VIEW3D) {
- ED_gpencil_toggle_brush_cursor(C, false, NULL);
- }
/* disable temp invert flag */
gso->brush->gpencil_settings->sculpt_flag &= ~GP_SCULPT_FLAG_TMP_INVERT;
+ /* Update geometry data for tagged strokes. */
+ gpencil_update_geometry(gso->gpd);
+
/* free operator data */
MEM_freeN(gso);
op->customdata = NULL;
@@ -1414,6 +1313,11 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
/* poll callback for stroke sculpting operator(s) */
static bool gpsculpt_brush_poll(bContext *C)
{
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+
/* NOTE: this is a bit slower, but is the most accurate... */
return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
}
@@ -1424,7 +1328,6 @@ static void gpsculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso)
{
bGPdata *gpd = gso->gpd;
- bGPDlayer *gpl;
Scene *scene = gso->scene;
int cfra = CFRA;
@@ -1434,9 +1337,9 @@ static void gpsculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso)
}
/* go through each layer, and ensure that we've got a valid frame to use */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf = gpl->actframe;
/* Make a new frame to work on if the layer's frame
@@ -1528,8 +1431,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
gso->brush->size;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
bGPDspoint *pt1, *pt2;
@@ -1541,13 +1443,19 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
bool include_last = false;
bool changed = false;
float rot_eval = 0.0f;
+
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
+ return false;
+ }
+
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
/* only check if point is inside */
@@ -1600,8 +1508,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
/* To each point individually... */
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i);
ok = apply(gso, gps_active, rot_eval, index, radius, pc1);
@@ -1617,8 +1525,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
*/
if (i + 1 == gps->totpoints - 1) {
pt = &gps->points[i + 1];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i + 1;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
if (pt_active != NULL) {
rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i + 1);
ok |= apply(gso, gps_active, rot_eval, index, radius, pc2);
@@ -1638,8 +1546,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
* (but wasn't added then, to avoid double-ups).
*/
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i);
changed |= apply(gso, gps_active, rot_eval, index, radius, pc1);
@@ -1661,11 +1569,11 @@ static bool gpsculpt_brush_do_frame(bContext *C,
const float diff_mat[4][4])
{
bool changed = false;
- Object *ob = CTX_data_active_object(C);
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
+ bool redo_geom = false;
+ Object *ob = gso->object;
char tool = gso->brush->gpencil_sculpt_tool;
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -1679,6 +1587,7 @@ static bool gpsculpt_brush_do_frame(bContext *C,
case GPSCULPT_TOOL_SMOOTH: /* Smooth strokes */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_smooth_apply);
+ redo_geom |= changed;
break;
}
@@ -1696,7 +1605,7 @@ static bool gpsculpt_brush_do_frame(bContext *C,
case GPSCULPT_TOOL_GRAB: /* Grab points */
{
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
if (gps_active != NULL) {
if (gso->first) {
/* First time this brush stroke is being applied:
@@ -1712,30 +1621,35 @@ static bool gpsculpt_brush_do_frame(bContext *C,
changed |= true;
}
}
+ redo_geom |= changed;
break;
}
case GPSCULPT_TOOL_PUSH: /* Push points */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_push_apply);
+ redo_geom |= changed;
break;
}
case GPSCULPT_TOOL_PINCH: /* Pinch points */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_pinch_apply);
+ redo_geom |= changed;
break;
}
case GPSCULPT_TOOL_TWIST: /* Twist points around midpoint */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_twist_apply);
+ redo_geom |= changed;
break;
}
case GPSCULPT_TOOL_RANDOMIZE: /* Apply jitter */
{
changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_randomize_apply);
+ redo_geom |= changed;
break;
}
@@ -1743,8 +1657,25 @@ static bool gpsculpt_brush_do_frame(bContext *C,
printf("ERROR: Unknown type of GPencil Sculpt brush \n");
break;
}
- /* Triangulation must be calculated if changed */
- gp_recalc_geometry(gps);
+
+ /* Triangulation must be calculated. */
+ if (redo_geom) {
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ if (gpl->actframe == gpf) {
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ /* Update active frame now, only if material has fill. */
+ if (gp_style->flag & GP_MATERIAL_FILL_SHOW) {
+ BKE_gpencil_stroke_geometry_update(gps_active);
+ }
+ else {
+ gpencil_recalc_geometry_tag(gps_active);
+ }
+ }
+ else {
+ /* Delay a full recalculation for other frames. */
+ gpencil_recalc_geometry_tag(gps_active);
+ }
+ }
}
return changed;
@@ -1753,13 +1684,14 @@ static bool gpsculpt_brush_do_frame(bContext *C,
/* Perform two-pass brushes which modify the existing strokes */
static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ToolSettings *ts = gso->scene->toolsettings;
+ Depsgraph *depsgraph = gso->depsgraph;
Object *obact = gso->object;
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, obact);
- bGPdata *gpd = gso->gpd;
bool changed = false;
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
+
/* Calculate brush-specific data which applies equally to all points */
char tool = gso->brush->gpencil_sculpt_tool;
switch (tool) {
@@ -1793,21 +1725,15 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
}
/* Find visible strokes, and perform operations on those if hit */
- CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* If no active frame, don't do anything... */
- if (gpl->actframe == NULL) {
- continue;
- }
- /* Get evaluated frames array data */
- int idx_eval = BLI_findindex(&gpd->layers, gpl);
- bGPDframe *gpf_eval = &ob_eval->runtime.gpencil_evaluated_frames[idx_eval];
- if (gpf_eval == NULL) {
+ if ((!BKE_gpencil_layer_is_editable(gpl)) || (gpl->actframe == NULL)) {
continue;
}
/* calculate difference matrix */
float diff_mat[4][4];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* Active Frame or MultiFrame? */
if (gso->is_multiframe) {
@@ -1819,7 +1745,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
}
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* Always do active frame; Otherwise, only include selected frames */
if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
/* compute multiframe falloff factor */
@@ -1839,12 +1765,13 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
}
}
else {
- /* Apply to active frame's strokes */
- gso->mf_falloff = 1.0f;
- changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpf_eval, diff_mat);
+ if (gpl->actframe != NULL) {
+ /* Apply to active frame's strokes */
+ gso->mf_falloff = 1.0f;
+ changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
}
}
- CTX_DATA_END;
return changed;
}
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 82de633dbd7..6a2012b99ee 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -373,7 +373,7 @@ static void gp_select_same_layer(bContext *C)
Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
bGPDstroke *gps;
bool found = false;
@@ -868,13 +868,12 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
const int selectmode,
const float scale)
{
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bGPDspoint *pt1 = NULL;
bGPDspoint *pt2 = NULL;
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
int i;
bool changed = false;
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
if (gps->totpoints == 1) {
@@ -933,22 +932,22 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
*/
hit = true;
if (select) {
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = pt1->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag |= GP_SPOINT_SELECT;
}
- pt_active = (!is_multiedit) ? pt2->runtime.pt_orig : pt2;
+ pt_active = pt2->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag |= GP_SPOINT_SELECT;
}
changed = true;
}
else {
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = pt1->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag &= ~GP_SPOINT_SELECT;
}
- pt_active = (!is_multiedit) ? pt2->runtime.pt_orig : pt2;
+ pt_active = pt2->runtime.pt_orig;
if (pt_active != NULL) {
pt_active->flag &= ~GP_SPOINT_SELECT;
}
@@ -965,7 +964,7 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
/* if stroke mode expand selection */
if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = (pt1->runtime.pt_orig) ? pt1->runtime.pt_orig : pt1;
if (pt_active != NULL) {
if (select) {
pt_active->flag |= GP_SPOINT_SELECT;
@@ -978,7 +977,7 @@ static bool gp_stroke_do_circle_sel(bGPdata *gpd,
}
/* expand selection to segment */
- pt_active = (!is_multiedit) ? pt1->runtime.pt_orig : pt1;
+ pt_active = (pt1->runtime.pt_orig) ? pt1->runtime.pt_orig : pt1;
if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select) && (pt_active != NULL)) {
float r_hita[3], r_hitb[3];
bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT);
@@ -1183,16 +1182,16 @@ static int gpencil_generic_select_exec(bContext *C,
/* select/deselect points */
GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
{
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt;
int i;
bool hit = false;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
+ if (pt->runtime.pt_orig == NULL) {
continue;
}
- bGPDspoint *pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ bGPDspoint *pt_active = pt->runtime.pt_orig;
/* convert point coords to screenspace */
const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
@@ -1230,7 +1229,7 @@ static int gpencil_generic_select_exec(bContext *C,
if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
continue;
}
- bGPDspoint *pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
if (sel_op_result) {
pt_active->flag |= GP_SPOINT_SELECT;
@@ -1475,7 +1474,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
/* XXX: maybe we should go from the top of the stack down instead... */
GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
{
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt;
int i;
@@ -1704,11 +1703,11 @@ static int gpencil_select_color_exec(bContext *C, wmOperator *op)
bool gps_selected = false;
/* Check all stroke points. */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->mix_color[3] < 0.03f) {
+ if (pt->vert_color[3] < 0.03f) {
continue;
}
- rgb_to_hsv_compat_v(pt->mix_color, hsv_stroke);
+ rgb_to_hsv_compat_v(pt->vert_color, hsv_stroke);
/* Only check Hue to get full value and saturation ranges. */
if (compare_ff(hsv_stroke[0], hsv_brush[0], threshold)) {
pt->flag |= GP_SPOINT_SELECT;
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index 7b57dacd3e4..f9403fd94b0 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -90,14 +90,14 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name)
if (gpd_ptr) {
if (*gpd_ptr) {
bGPdata *gpd = *gpd_ptr;
- bGPDlayer *gpl, *gpld;
+ bGPDlayer *gpld;
BKE_gpencil_free_layers(&gpd->layers);
/* copy layers */
BLI_listbase_clear(&gpd->layers);
- for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* make a copy of source layer and its data */
gpld = BKE_gpencil_layer_duplicate(gpl);
BLI_addtail(&gpd->layers, gpld);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 8eed1a634f0..6995f7074e8 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -328,7 +328,7 @@ bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
{
if (ob && ob->data && (ob->type == OB_GPENCIL)) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(ob->data);
if (gpl) {
if (gpl->actframe) {
// XXX: assumes that frame has been fetched already
@@ -336,7 +336,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
}
else {
/* XXX: disabled as could be too much of a penalty */
- /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
+ /* return BKE_gpencil_layer_frame_find(gpl, cfra); */
}
}
}
@@ -367,7 +367,7 @@ bool gp_active_layer_poll(bContext *C)
return false;
}
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != NULL);
}
@@ -553,10 +553,10 @@ bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstr
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
if (gp_style != NULL) {
- if (gp_style->flag & GP_STYLE_COLOR_HIDE) {
+ if (gp_style->flag & GP_MATERIAL_HIDE) {
return false;
}
- if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_MATERIAL_LOCKED)) {
return false;
}
}
@@ -640,7 +640,7 @@ void gp_apply_parent(
float inverse_diff_mat[4][4];
float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
for (i = 0; i < gps->totpoints; i++) {
@@ -661,7 +661,7 @@ void gp_apply_parent_point(
float inverse_diff_mat[4][4];
float fpt[3];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
@@ -867,7 +867,7 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
const RegionView3D *rv3d = gsc->ar->regiondata;
float rvec[3];
- ED_gp_get_drawing_reference(
+ ED_gpencil_drawing_reference_get(
scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec);
float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
@@ -927,7 +927,7 @@ void gp_stroke_convertcoords_tpoint(Scene *scene,
/* Current method just converts each point in screen-coordinates to
* 3D-coordinates using the 3D-cursor as reference.
*/
- ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
+ ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
@@ -945,7 +945,7 @@ void gp_stroke_convertcoords_tpoint(Scene *scene,
* Get drawing reference point for conversion or projection of the stroke
* \param[out] r_vec : Reference point found
*/
-void ED_gp_get_drawing_reference(
+void ED_gpencil_drawing_reference_get(
const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3])
{
const float *fp = scene->cursor.location;
@@ -975,7 +975,6 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (bGPdata *)ob->data;
GP_SpaceConversion gsc = {NULL};
bGPDspoint *pt;
@@ -986,7 +985,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
/* Adjust each point */
@@ -1178,7 +1177,6 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* move points from last to first to new place */
i2 = gps->totpoints - 1;
@@ -1193,7 +1191,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
pt_final->flag = pt->flag;
pt_final->uv_fac = pt->uv_fac;
pt_final->uv_rot = pt->uv_rot;
- copy_v4_v4(pt_final->mix_color, pt->mix_color);
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];
@@ -1220,7 +1218,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
- interp_v4_v4v4(pt_final->mix_color, pt->mix_color, next->mix_color, 0.5f);
+ interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
if (gps->dvert != NULL) {
MDeformVert *dvert_final = &gps->dvert[i2];
@@ -1249,63 +1247,11 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
/* free temp memory */
MEM_SAFE_FREE(temp_points);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
-/* ******************************************************** */
-/* Layer Parenting - Compute Parent Transforms */
-
-/* calculate difference matrix */
-void ED_gpencil_parent_location(const Depsgraph *depsgraph,
- Object *obact,
- bGPdata *UNUSED(gpd),
- bGPDlayer *gpl,
- float diff_mat[4][4])
-{
- Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
- Object *obparent = gpl->parent;
- Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
- obparent;
-
- /* if not layer parented, try with object parented */
- if (obparent_eval == NULL) {
- if (ob_eval != NULL) {
- if (ob_eval->type == OB_GPENCIL) {
- copy_m4_m4(diff_mat, ob_eval->obmat);
- return;
- }
- }
- /* not gpencil object */
- unit_m4(diff_mat);
- return;
- }
- else {
- if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
- return;
- }
- else if (gpl->partype == PARBONE) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
- if (pchan) {
- float tmp_mat[4][4];
- mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
- mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
- }
- else {
- /* if bone not found use object (armature) */
- mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
- add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
- }
- return;
- }
- else {
- unit_m4(diff_mat); /* not defined type */
- }
- }
-}
-
-/* reset parent matrix for all layers */
+/* Reset parent matrix for all layers. */
void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
{
bGPDspoint *pt;
@@ -1315,7 +1261,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata
float gpl_loc[3];
zero_v3(gpl_loc);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->parent != NULL) {
/* calculate new matrix */
if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
@@ -1335,12 +1281,12 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata
/* only redo if any change */
if (!equals_m4m4(gpl->inverse, cur_mat)) {
/* first apply current transformation to all strokes */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo local object */
sub_v3_v3(diff_mat[3], gpl_loc);
- 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) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
mul_m4_v3(diff_mat, &pt->x);
}
@@ -1742,7 +1688,7 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
}
/* get current drawing color */
- ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
+ ma = BKE_gpencil_object_material_from_brush_get(ob, brush);
if (ma) {
gp_style = ma->gp_style;
@@ -1995,6 +1941,7 @@ void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *t
/* conversion to 3d format */
gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
copy_v3_v3(&pt->x, p3d);
+ zero_v4(pt->vert_color);
pt->pressure = tpt->pressure;
pt->strength = tpt->strength;
@@ -2002,63 +1949,6 @@ void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *t
pt->uv_rot = tpt->uv_rot;
}
-/* texture coordinate utilities */
-void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
-{
- if (gps == NULL) {
- return;
- }
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- float pixsize;
- if (gp_style) {
- pixsize = gp_style->texture_pixsize / 1000000.0f;
- }
- else {
- /* use this value by default */
- pixsize = 0.0001f;
- }
- pixsize = MAX2(pixsize, 0.0000001f);
-
- bGPDspoint *pt = NULL;
- bGPDspoint *ptb = NULL;
- int i;
- float totlen = 0.0f;
-
- /* first read all points and calc distance */
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- /* first point */
- if (i == 0) {
- pt->uv_fac = 0.0f;
- continue;
- }
-
- ptb = &gps->points[i - 1];
- totlen += len_v3v3(&pt->x, &ptb->x) / pixsize;
- pt->uv_fac = totlen;
- }
-
- /* normalize the distance using a factor */
- float factor;
-
- /* if image, use texture width */
- if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
- (gp_style->sima)) {
- factor = gp_style->sima->gen_x;
- }
- else if (totlen == 0) {
- return;
- }
- else {
- factor = totlen;
- }
-
- for (i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- pt->uv_fac /= factor;
- }
-}
-
/* recalc uv for any stroke using the material */
void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
{
@@ -2071,11 +1961,11 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
continue;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl)) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (BKE_gpencil_layer_is_editable(gpl)) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* check if it is editable */
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
@@ -2083,7 +1973,7 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
gps_ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
/* update */
if ((gps_ma) && (gps_ma == mat)) {
- ED_gpencil_calc_stroke_uv(ob, gps);
+ BKE_gpencil_stroke_uv_update(gps);
}
}
}
@@ -2160,7 +2050,7 @@ static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final
pt_final->flag = pt->flag;
pt_final->uv_fac = pt->uv_fac;
pt_final->uv_rot = pt->uv_rot;
- copy_v4_v4(pt_final->mix_color, pt->mix_color);
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
MDeformVert *dvert = &gps->dvert[i];
@@ -2215,7 +2105,6 @@ static void gp_insert_point(
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
/* copy all points */
int i2 = 0;
@@ -2239,6 +2128,8 @@ static void gp_insert_point(
i2++;
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
MEM_SAFE_FREE(temp_points);
}
@@ -2482,10 +2373,9 @@ void ED_gpencil_select_toggle_all(bContext *C, int action)
* nothing should be able to touch it
*/
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf;
/* deselect all strokes on all frames */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
@@ -2582,6 +2472,21 @@ tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
return buffer_array;
}
+void ED_gpencil_sbuffer_update_eval(Depsgraph *depsgraph, Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id);
+ bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
+
+ gpd_eval->runtime.sbuffer = gpd->runtime.sbuffer;
+ gpd_eval->runtime.sbuffer_sflag = gpd->runtime.sbuffer_sflag;
+ gpd_eval->runtime.sbuffer_used = gpd->runtime.sbuffer_used;
+ gpd_eval->runtime.sbuffer_size = gpd->runtime.sbuffer_size;
+ gpd_eval->runtime.tot_cp_points = gpd->runtime.tot_cp_points;
+ gpd_eval->runtime.cp_points = gpd->runtime.cp_points;
+}
+
/* Tag all scene grease pencil object to update. */
void ED_gpencil_tag_scene_gpencil(Scene *scene)
{
@@ -2602,3 +2507,87 @@ void ED_gpencil_tag_scene_gpencil(Scene *scene)
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+
+void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke *gps)
+{
+ if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
+ copy_v3_v3(gps->vert_color_fill, brush->rgb);
+ gps->vert_color_fill[3] = brush->gpencil_settings->vertex_factor;
+ srgb_to_linearrgb_v4(gps->vert_color_fill, gps->vert_color_fill);
+ }
+ else {
+ zero_v4(gps->vert_color_fill);
+ }
+}
+
+void ED_gpencil_point_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDspoint *pt)
+{
+ if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) {
+ copy_v3_v3(pt->vert_color, brush->rgb);
+ pt->vert_color[3] = brush->gpencil_settings->vertex_factor;
+ srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color);
+ }
+ else {
+ zero_v4(pt->vert_color);
+ }
+}
+
+void ED_gpencil_sbuffer_vertex_color_set(ToolSettings *ts, Brush *brush, bGPdata *gpd)
+{
+ float vertex_color[4];
+ copy_v3_v3(vertex_color, brush->rgb);
+ vertex_color[3] = brush->gpencil_settings->vertex_factor;
+ srgb_to_linearrgb_v4(vertex_color, vertex_color);
+
+ /* Copy fill vertex color. */
+ if (GPENCIL_USE_VERTEX_COLOR_FILL(ts, brush)) {
+ copy_v4_v4(gpd->runtime.vert_color_fill, vertex_color);
+ }
+ else {
+ zero_v4(gpd->runtime.vert_color_fill);
+ }
+ /* Copy stroke vertex color. */
+ if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) {
+ copy_v4_v4(gpd->runtime.vert_color, vertex_color);
+ }
+ else {
+ zero_v4(gpd->runtime.vert_color);
+ }
+}
+
+/* Check if the stroke collides with brush. */
+bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
+ bGPDstroke *gps,
+ float mouse[2],
+ const int radius,
+ const float diff_mat[4][4])
+{
+ const int offset = (int)ceil(sqrt((radius * radius) * 2));
+ bGPDspoint pt_dummy, pt_dummy_ps;
+ float gps_collision_min[2] = {0.0f};
+ float gps_collision_max[2] = {0.0f};
+ float zerov3[3];
+
+ /* Check we have something to use (only for old files). */
+ if (equals_v3v3(zerov3, gps->collision_min)) {
+ BKE_gpencil_stroke_collision_get(gps);
+ }
+
+ /* Convert bound box to 2d */
+ copy_v3_v3(&pt_dummy.x, gps->collision_min);
+ gp_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
+ gp_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &gps_collision_min[0], &gps_collision_min[1]);
+
+ copy_v3_v3(&pt_dummy.x, gps->collision_max);
+ gp_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
+ gp_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &gps_collision_max[0], &gps_collision_max[1]);
+
+ rcti rect_stroke = {
+ gps_collision_min[0], gps_collision_max[0], gps_collision_min[1], gps_collision_max[1]};
+
+ /* For mouse, add a small offet to avoid false negative in corners. */
+ rcti rect_mouse = {mouse[0] - offset, mouse[0] + offset, mouse[1] - offset, mouse[1] + offset};
+
+ /* Check collision between both rectangles. */
+ return BLI_rcti_isect(&rect_stroke, &rect_mouse, NULL);
+}
diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c
index e5f2bd76d0a..b38b2d9fb7d 100644
--- a/source/blender/editors/gpencil/gpencil_uv.c
+++ b/source/blender/editors/gpencil/gpencil_uv.c
@@ -171,7 +171,6 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is
}
/* Calc selected strokes center. */
- bGPdata *gpd = opdata->gpd;
zero_v2(opdata->mcenter);
float center[3] = {0.0f};
int i = 0;
@@ -240,9 +239,9 @@ static void gpencil_uv_transform_exit(bContext *C, wmOperator *op)
static void gpencil_transform_fill_cancel(bContext *C, wmOperator *op)
{
- GpUvData *opdata;
+ GpUvData *opdata = op->customdata;
+ UNUSED_VARS(opdata);
- opdata = op->customdata;
gpencil_uv_transform_exit(C, op);
/* need to force redisplay or we may still view the modified result */
@@ -299,7 +298,8 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
else {
copy_v2_v2(gps->uv_translation, location);
}
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
i++;
}
}
@@ -313,7 +313,8 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
gps->uv_rotation = (opdata->is_modal) ? opdata->array_rot[i] + uv_rotation : uv_rotation;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
i++;
}
}
@@ -340,7 +341,8 @@ static bool gpencil_uv_transform_calc(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
gps->uv_scale = (opdata->is_modal) ? opdata->array_scale[i] + scale : scale;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
i++;
}
}
@@ -384,7 +386,7 @@ static bool gpencil_transform_fill_poll(bContext *C)
return false;
}
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if ((gpl == NULL) || (ob->mode != OB_MODE_EDIT_GPENCIL)) {
return false;
@@ -542,7 +544,8 @@ static int gpencil_reset_transform_fill_exec(bContext *C, wmOperator *op)
if ((mode == GP_UV_SCALE) || (mode == GP_UV_ALL)) {
gps->uv_scale = 1.0f;
}
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
changed = true;
}
}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c
index 2226257f6a6..348655d5fe9 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_ops.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c
@@ -137,9 +137,9 @@ static int gp_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator *op)
if (gps->flag & GP_STROKE_SELECT) {
changed = true;
if (mode != GP_PAINT_VERTEX_STROKE) {
- if (gps->mix_color_fill[3] > 0.0f) {
+ if (gps->vert_color_fill[3] > 0.0f) {
for (int i2 = 0; i2 < 3; i2++) {
- gps->mix_color_fill[i2] = gain * gps->mix_color_fill[i2] + offset;
+ gps->vert_color_fill[i2] = gain * gps->vert_color_fill[i2] + offset;
}
}
}
@@ -148,9 +148,9 @@ static int gp_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator *op)
/* Stroke points. */
if (mode != GP_PAINT_VERTEX_FILL) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) && (pt->mix_color[3] > 0.0f)) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
for (int i2 = 0; i2 < 3; i2++) {
- pt->mix_color[i2] = gain * pt->mix_color[i2] + offset;
+ pt->vert_color[i2] = gain * pt->vert_color[i2] + offset;
}
}
}
@@ -214,9 +214,9 @@ static int gp_vertexpaint_hsv_exec(bContext *C, wmOperator *op)
/* Fill color. */
if (mode != GP_PAINT_VERTEX_STROKE) {
- if (gps->mix_color_fill[3] > 0.0f) {
+ if (gps->vert_color_fill[3] > 0.0f) {
- rgb_to_hsv_v(gps->mix_color_fill, hsv);
+ rgb_to_hsv_v(gps->vert_color_fill, hsv);
hsv[0] += (hue - 0.5f);
if (hsv[0] > 1.0f) {
@@ -228,15 +228,15 @@ static int gp_vertexpaint_hsv_exec(bContext *C, wmOperator *op)
hsv[1] *= sat;
hsv[2] *= val;
- hsv_to_rgb_v(hsv, gps->mix_color_fill);
+ hsv_to_rgb_v(hsv, gps->vert_color_fill);
}
}
/* Stroke points. */
if (mode != GP_PAINT_VERTEX_FILL) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) && (pt->mix_color[3] > 0.0f)) {
- rgb_to_hsv_v(pt->mix_color, hsv);
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
+ rgb_to_hsv_v(pt->vert_color, hsv);
hsv[0] += (hue - 0.5f);
if (hsv[0] > 1.0f) {
@@ -248,7 +248,7 @@ static int gp_vertexpaint_hsv_exec(bContext *C, wmOperator *op)
hsv[1] *= sat;
hsv[2] *= val;
- hsv_to_rgb_v(hsv, pt->mix_color);
+ hsv_to_rgb_v(hsv, pt->vert_color);
}
}
}
@@ -305,9 +305,9 @@ static int gp_vertexpaint_invert_exec(bContext *C, wmOperator *op)
if (gps->flag & GP_STROKE_SELECT) {
changed = true;
if (mode != GP_PAINT_VERTEX_STROKE) {
- if (gps->mix_color_fill[3] > 0.0f) {
+ if (gps->vert_color_fill[3] > 0.0f) {
for (int i2 = 0; i2 < 3; i2++) {
- gps->mix_color_fill[i2] = 1.0f - gps->mix_color_fill[i2];
+ gps->vert_color_fill[i2] = 1.0f - gps->vert_color_fill[i2];
}
}
}
@@ -316,9 +316,9 @@ static int gp_vertexpaint_invert_exec(bContext *C, wmOperator *op)
/* Stroke points. */
if (mode != GP_PAINT_VERTEX_FILL) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) && (pt->mix_color[3] > 0.0f)) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
for (int i2 = 0; i2 < 3; i2++) {
- pt->mix_color[i2] = 1.0f - pt->mix_color[i2];
+ pt->vert_color[i2] = 1.0f - pt->vert_color[i2];
}
}
}
@@ -374,9 +374,9 @@ static int gp_vertexpaint_levels_exec(bContext *C, wmOperator *op)
if (gps->flag & GP_STROKE_SELECT) {
changed = true;
if (mode != GP_PAINT_VERTEX_STROKE) {
- if (gps->mix_color_fill[3] > 0.0f) {
+ if (gps->vert_color_fill[3] > 0.0f) {
for (int i2 = 0; i2 < 3; i2++) {
- gps->mix_color_fill[i2] = gain * (gps->mix_color_fill[i2] + offset);
+ gps->vert_color_fill[i2] = gain * (gps->vert_color_fill[i2] + offset);
}
}
}
@@ -385,9 +385,9 @@ static int gp_vertexpaint_levels_exec(bContext *C, wmOperator *op)
/* Stroke points. */
if (mode != GP_PAINT_VERTEX_FILL) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((pt->flag & GP_SPOINT_SELECT) && (pt->mix_color[3] > 0.0f)) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) {
for (int i2 = 0; i < 3; i2++) {
- pt->mix_color[i2] = gain * (pt->mix_color[i2] + offset);
+ pt->vert_color[i2] = gain * (pt->vert_color[i2] + offset);
}
}
}
@@ -450,8 +450,8 @@ static int gp_vertexpaint_set_exec(bContext *C, wmOperator *op)
if (gps->flag & GP_STROKE_SELECT) {
changed = true;
if (mode != GP_PAINT_VERTEX_STROKE) {
- copy_v3_v3(gps->mix_color_fill, brush->rgb);
- gps->mix_color_fill[3] = factor;
+ copy_v3_v3(gps->vert_color_fill, brush->rgb);
+ gps->vert_color_fill[3] = factor;
}
}
@@ -459,8 +459,8 @@ static int gp_vertexpaint_set_exec(bContext *C, wmOperator *op)
if (mode != GP_PAINT_VERTEX_FILL) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
- copy_v3_v3(pt->mix_color, brush->rgb);
- pt->mix_color[3] = factor;
+ copy_v3_v3(pt->vert_color, brush->rgb);
+ pt->vert_color[3] = factor;
}
}
}
@@ -509,8 +509,8 @@ static bool gp_extract_palette_from_vertex(bContext *C, const bool selected, con
/* Extract all colors. */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- 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 (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
@@ -526,8 +526,8 @@ static bool gp_extract_palette_from_vertex(bContext *C, const bool selected, con
continue;
}
- bool use_stroke = (gp_style->flag & GP_STYLE_STROKE_SHOW);
- bool use_fill = (gp_style->flag & GP_STYLE_FILL_SHOW);
+ bool use_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
+ bool use_fill = (gp_style->flag & GP_MATERIAL_FILL_SHOW);
/* Material is disabled. */
if ((!use_fill) && (!use_stroke)) {
@@ -535,21 +535,21 @@ static bool gp_extract_palette_from_vertex(bContext *C, const bool selected, con
}
/* Only solid strokes or stencil. */
- if ((use_stroke) && ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
- ((gp_style->flag & GP_STYLE_STROKE_PATTERN) == 0))) {
+ if ((use_stroke) && ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) &&
+ ((gp_style->flag & GP_MATERIAL_STROKE_PATTERN) == 0))) {
continue;
}
/* Only solid fill. */
- if ((use_fill) && (gp_style->fill_style != GP_STYLE_FILL_STYLE_SOLID)) {
+ if ((use_fill) && (gp_style->fill_style != GP_MATERIAL_FILL_STYLE_SOLID)) {
continue;
}
/* Fill color. */
- if (gps->mix_color_fill[3] > 0.0f) {
- col[0] = truncf(gps->mix_color_fill[0] * range) / range;
- col[1] = truncf(gps->mix_color_fill[1] * range) / range;
- col[2] = truncf(gps->mix_color_fill[2] * range) / range;
+ if (gps->vert_color_fill[3] > 0.0f) {
+ col[0] = truncf(gps->vert_color_fill[0] * range) / range;
+ col[1] = truncf(gps->vert_color_fill[1] * range) / range;
+ col[2] = truncf(gps->vert_color_fill[2] * range) / range;
uint key = rgb_to_cpack(col[0], col[1], col[2]);
@@ -562,9 +562,9 @@ static bool gp_extract_palette_from_vertex(bContext *C, const bool selected, con
bGPDspoint *pt;
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- col[0] = truncf(pt->mix_color[0] * range) / range;
- col[1] = truncf(pt->mix_color[1] * range) / range;
- col[2] = truncf(pt->mix_color[2] * range) / range;
+ col[0] = truncf(pt->vert_color[0] * range) / range;
+ col[1] = truncf(pt->vert_color[1] * range) / range;
+ col[2] = truncf(pt->vert_color[2] * range) / range;
uint key = rgb_to_cpack(col[0], col[1], col[2]);
if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) {
@@ -600,17 +600,17 @@ static uint get_material_type(MaterialGPencilStyle *gp_style,
uint r_i = 0;
if ((use_stroke) && (use_fill)) {
switch (gp_style->mode) {
- case GP_STYLE_MODE_LINE: {
+ case GP_MATERIAL_MODE_LINE: {
r_i = 1;
strcpy(name, "Line Stroke-Fill");
break;
}
- case GP_STYLE_MODE_DOTS: {
+ case GP_MATERIAL_MODE_DOT: {
r_i = 2;
strcpy(name, "Dots Stroke-Fill");
break;
}
- case GP_STYLE_MODE_BOX: {
+ case GP_MATERIAL_MODE_SQUARE: {
r_i = 3;
strcpy(name, "Boxes Stroke-Fill");
break;
@@ -621,17 +621,17 @@ static uint get_material_type(MaterialGPencilStyle *gp_style,
}
else if (use_stroke) {
switch (gp_style->mode) {
- case GP_STYLE_MODE_LINE: {
+ case GP_MATERIAL_MODE_LINE: {
r_i = 4;
strcpy(name, "Line Stroke");
break;
}
- case GP_STYLE_MODE_DOTS: {
+ case GP_MATERIAL_MODE_DOT: {
r_i = 5;
strcpy(name, "Dots Stroke");
break;
}
- case GP_STYLE_MODE_BOX: {
+ case GP_MATERIAL_MODE_SQUARE: {
r_i = 6;
strcpy(name, "Boxes Stroke");
break;
@@ -695,8 +695,8 @@ static int gp_material_to_vertex_exec(bContext *C, wmOperator *op)
/* Update stroke material index. */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- 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 (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
@@ -713,23 +713,25 @@ static int gp_material_to_vertex_exec(bContext *C, wmOperator *op)
continue;
}
- bool use_stroke = (gp_style->flag & GP_STYLE_STROKE_SHOW);
- bool use_fill = (gp_style->flag & GP_STYLE_FILL_SHOW);
- bool is_stencil = ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
- (gp_style->flag & GP_STYLE_STROKE_PATTERN));
+ bool use_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) &&
+ (gp_style->stroke_rgba[3] > 0.0f));
+ bool use_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) &&
+ (gp_style->fill_rgba[3] > 0.0f));
+ bool is_stencil = ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) &&
+ (gp_style->flag & GP_MATERIAL_STROKE_PATTERN));
/* Material is disabled. */
if ((!use_fill) && (!use_stroke)) {
continue;
}
/* Only solid strokes or stencil. */
- if ((use_stroke) && ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
- ((gp_style->flag & GP_STYLE_STROKE_PATTERN) == 0))) {
+ if ((use_stroke) && ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) &&
+ ((gp_style->flag & GP_MATERIAL_STROKE_PATTERN) == 0))) {
continue;
}
/* Only solid fill. */
- if ((use_fill) && (gp_style->fill_style != GP_STYLE_FILL_STYLE_SOLID)) {
+ if ((use_fill) && (gp_style->fill_style != GP_MATERIAL_FILL_STYLE_SOLID)) {
continue;
}
@@ -755,17 +757,17 @@ static int gp_material_to_vertex_exec(bContext *C, wmOperator *op)
if (!found) {
ma = BKE_gpencil_material_add(bmain, name);
if (use_stroke) {
- ma->gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ ma->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
else {
- ma->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ ma->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
if (use_fill) {
- ma->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
else {
- ma->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ ma->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
}
ma->gp_style->stroke_rgba[3] = gp_style->stroke_rgba[3];
@@ -787,14 +789,14 @@ static int gp_material_to_vertex_exec(bContext *C, wmOperator *op)
}
changed = true;
- copy_v3_v3(gps->mix_color_fill, gp_style->fill_rgba);
- gps->mix_color_fill[3] = 1.0f;
+ copy_v3_v3(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
/* Update all points. */
bGPDspoint *pt;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- copy_v3_v3(pt->mix_color, gp_style->stroke_rgba);
- pt->mix_color[3] = 1.0f;
+ copy_v3_v3(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
}
}
}
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index a9fc9513b15..7b590a7c052 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -386,7 +386,7 @@ static void gp_grid_colors_calc(tGP_BrushVertexpaintData *gso)
if (grid_index > -1) {
grid = &gso->grid[grid_index];
/* Add stroke mix color (only if used). */
- if (pt->mix_color[3] > 0.0f) {
+ if (pt->vert_color[3] > 0.0f) {
add_v3_v3(grid->color, selected->color);
grid->color[3] = 1.0f;
grid->totcol++;
@@ -412,7 +412,7 @@ static void gp_grid_colors_calc(tGP_BrushVertexpaintData *gso)
/* ************************************************ */
/* Brush Callbacks
-/* This section defines the callbacks used by each brush to perform their magic.
+ * This section defines the callbacks used by each brush to perform their magic.
* These are called on each point within the brush's radius. */
/* Tint Brush */
@@ -434,35 +434,42 @@ static bool brush_tint_apply(tGP_BrushVertexpaintData *gso,
bGPDspoint *pt = &gps->points[pt_index];
- float alpha = pt->mix_color[3];
- float alpha_fill = gps->mix_color_fill[3];
-
- if (brush_invert_check(gso)) {
- alpha -= inf;
- alpha_fill -= inf_fill;
- }
- else {
- alpha += inf;
- alpha_fill += inf_fill;
- }
-
/* Apply color to Stroke point. */
if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
- CLAMP(alpha, 0.0f, 1.0f);
- interp_v3_v3v3(pt->mix_color, pt->mix_color, brush->rgb, inf);
- pt->mix_color[3] = alpha;
+ if (brush_invert_check(gso)) {
+ pt->vert_color[3] -= inf;
+ CLAMP_MIN(pt->vert_color[3], 0.0f);
+ }
+ else {
+ /* Premult. */
+ mul_v3_fl(pt->vert_color, pt->vert_color[3]);
+ /* "Alpha over" blending. */
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, brush->rgb, inf);
+ pt->vert_color[3] = pt->vert_color[3] * (1.0 - inf) + inf;
+ /* Un-premult. */
+ if (pt->vert_color[3] > 0.0f) {
+ mul_v3_fl(pt->vert_color, 1.0f / pt->vert_color[3]);
+ }
+ }
}
/* Apply color to Fill area (all with same color and factor). */
if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
- CLAMP(alpha_fill, 0.0f, 1.0f);
- if (equals_v3v3(gps->mix_color_fill, brush->rgb)) {
- copy_v3_v3(gps->mix_color_fill, brush->rgb);
+ if (brush_invert_check(gso)) {
+ gps->vert_color_fill[3] -= inf_fill;
+ CLAMP_MIN(gps->vert_color_fill[3], 0.0f);
}
else {
- interp_v3_v3v3(gps->mix_color_fill, gps->mix_color_fill, brush->rgb, inf_fill);
+ /* Premult. */
+ mul_v3_fl(gps->vert_color_fill, gps->vert_color_fill[3]);
+ /* "Alpha over" blending. */
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, brush->rgb, inf_fill);
+ gps->vert_color_fill[3] = gps->vert_color_fill[3] * (1.0 - inf_fill) + inf_fill;
+ /* Un-premult. */
+ if (gps->vert_color_fill[3] > 0.0f) {
+ mul_v3_fl(gps->vert_color_fill, 1.0f / gps->vert_color_fill[3]);
+ }
}
- gps->mix_color_fill[3] = alpha_fill;
}
return true;
@@ -476,19 +483,19 @@ static bool brush_replace_apply(tGP_BrushVertexpaintData *gso, bGPDstroke *gps,
/* Apply color to Stroke point. */
if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
- copy_v3_v3(pt->mix_color, brush->rgb);
+ copy_v3_v3(pt->vert_color, brush->rgb);
/* If not mix color, full replace. */
- if (pt->mix_color[3] == 0.0f) {
- pt->mix_color[3] = 1.0f;
+ if (pt->vert_color[3] == 0.0f) {
+ pt->vert_color[3] = 1.0f;
}
}
/* Apply color to Fill area (all with same color and factor). */
if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
- copy_v3_v3(gps->mix_color_fill, brush->rgb);
+ copy_v3_v3(gps->vert_color_fill, brush->rgb);
/* If not mix color, full replace. */
- if (gps->mix_color_fill[3] == 0.0f) {
- gps->mix_color_fill[3] = 1.0f;
+ if (gps->vert_color_fill[3] == 0.0f) {
+ gps->vert_color_fill[3] = 1.0f;
}
}
@@ -520,7 +527,7 @@ static bool get_surrounding_color(tGP_BrushVertexpaintData *gso,
pt = &gps_selected->points[selected->pt_index];
/* Add stroke mix color (only if used). */
- if (pt->mix_color[3] > 0.0f) {
+ if (pt->vert_color[3] > 0.0f) {
add_v3_v3(r_color, selected->color);
totcol++;
}
@@ -554,12 +561,12 @@ static bool brush_blur_apply(tGP_BrushVertexpaintData *gso,
if (get_surrounding_color(gso, gps, pt_index, blur_color)) {
/* Apply color to Stroke point. */
if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
- interp_v3_v3v3(pt->mix_color, pt->mix_color, blur_color, inf);
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, blur_color, inf);
}
/* Apply color to Fill area (all with same color and factor). */
if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
- interp_v3_v3v3(gps->mix_color_fill, gps->mix_color_fill, blur_color, inf_fill);
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, blur_color, inf_fill);
}
return true;
}
@@ -584,8 +591,8 @@ static bool brush_average_apply(tGP_BrushVertexpaintData *gso,
bGPDspoint *pt = &gps->points[pt_index];
- float alpha = pt->mix_color[3];
- float alpha_fill = gps->mix_color_fill[3];
+ float alpha = pt->vert_color[3];
+ float alpha_fill = gps->vert_color_fill[3];
if (brush_invert_check(gso)) {
alpha -= inf;
@@ -599,15 +606,15 @@ static bool brush_average_apply(tGP_BrushVertexpaintData *gso,
/* Apply color to Stroke point. */
if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
CLAMP(alpha, 0.0f, 1.0f);
- interp_v3_v3v3(pt->mix_color, pt->mix_color, average_color, inf);
- pt->mix_color[3] = alpha;
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, average_color, inf);
+ pt->vert_color[3] = alpha;
}
/* Apply color to Fill area (all with same color and factor). */
if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
CLAMP(alpha_fill, 0.0f, 1.0f);
- copy_v3_v3(gps->mix_color_fill, average_color);
- gps->mix_color_fill[3] = alpha_fill;
+ copy_v3_v3(gps->vert_color_fill, average_color);
+ gps->vert_color_fill[3] = alpha_fill;
}
return true;
@@ -672,8 +679,8 @@ static bool brush_smear_apply(tGP_BrushVertexpaintData *gso,
if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) {
if (grid_index > -1) {
if (grid->color[3] > 0.0f) {
- // copy_v3_v3(pt->mix_color, grid->color);
- interp_v3_v3v3(pt->mix_color, pt->mix_color, grid->color, inf);
+ // copy_v3_v3(pt->vert_color, grid->color);
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, grid->color, inf);
changed = true;
}
}
@@ -683,7 +690,7 @@ static bool brush_smear_apply(tGP_BrushVertexpaintData *gso,
if (GPENCIL_TINT_VERTEX_COLOR_FILL(brush)) {
if (grid_index > -1) {
if (grid->color[3] > 0.0f) {
- interp_v3_v3v3(gps->mix_color_fill, gps->mix_color_fill, grid->color, inf);
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, grid->color, inf);
changed = true;
}
}
@@ -810,7 +817,7 @@ static void gp_save_selected_point(tGP_BrushVertexpaintData *gso,
selected->gps = gps;
selected->pt_index = index;
copy_v2_v2_int(selected->pc, pc);
- copy_v4_v4(selected->color, pt->mix_color);
+ copy_v4_v4(selected->color, pt->vert_color);
gso->pbuffer_used++;
}
@@ -825,8 +832,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
Brush *brush = gso->brush;
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
gso->brush->size;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
bGPDspoint *pt1, *pt2;
@@ -837,13 +843,18 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
int index;
bool include_last = false;
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
+ return;
+ }
+
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
/* only check if point is inside */
@@ -894,8 +905,8 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
/* To each point individually... */
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
gp_save_selected_point(gso, gps_active, index, pc1);
}
@@ -910,8 +921,8 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
*/
if (i + 1 == gps->totpoints - 1) {
pt = &gps->points[i + 1];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i + 1;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
if (pt_active != NULL) {
gp_save_selected_point(gso, gps_active, index, pc2);
include_last = false;
@@ -928,8 +939,8 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso,
* (but wasn't added then, to avoid double-ups).
*/
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
gp_save_selected_point(gso, gps_active, index, pc1);
@@ -962,7 +973,7 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C,
* all selected points before apply the effect, because it could be
* required to average data.
*--------------------------------------------------------------------- */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Skip strokes that are invalid for current view. */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -987,14 +998,14 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C,
bGPDspoint *pt = &gps->points[selected->pt_index];
/* Add stroke mix color (only if used). */
- if (pt->mix_color[3] > 0.0f) {
- add_v3_v3(average_color, pt->mix_color);
+ if (pt->vert_color[3] > 0.0f) {
+ add_v3_v3(average_color, pt->vert_color);
totcol++;
}
/* If Fill color mix, add to average. */
- if (gps->mix_color_fill[3] > 0.0f) {
- add_v3_v3(average_color, gps->mix_color_fill);
+ if (gps->vert_color_fill[3] > 0.0f) {
+ add_v3_v3(average_color, gps->vert_color_fill);
totcol++;
}
}
@@ -1060,26 +1071,21 @@ static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpai
ToolSettings *ts = CTX_data_tool_settings(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *obact = gso->object;
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, obact);
- bGPdata *gpd = gso->gpd;
bool changed = false;
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
+
/* Find visible strokes, and perform operations on those if hit */
- CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- /* If no active frame, don't do anything... */
- if (gpl->actframe == NULL) {
- continue;
- }
- /* Get evaluated frames array data */
- int idx_eval = BLI_findindex(&gpd->layers, gpl);
- bGPDframe *gpf_eval = &ob_eval->runtime.gpencil_evaluated_frames[idx_eval];
- if (gpf_eval == NULL) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* If locked or no active frame, don't do anything. */
+ if ((!BKE_gpencil_layer_is_editable(gpl)) || (gpl->actframe == NULL)) {
continue;
}
/* calculate difference matrix */
float diff_mat[4][4];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* Active Frame or MultiFrame? */
if (gso->is_multiframe) {
@@ -1091,7 +1097,7 @@ static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpai
BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
}
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* Always do active frame; Otherwise, only include selected frames */
if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
/* compute multiframe falloff factor */
@@ -1113,11 +1119,12 @@ static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpai
}
else {
/* Apply to active frame's strokes */
- gso->mf_falloff = 1.0f;
- changed |= gp_vertexpaint_brush_do_frame(C, gso, gpl, gpf_eval, diff_mat);
+ if (gpl->actframe != NULL) {
+ gso->mf_falloff = 1.0f;
+ changed |= gp_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
}
}
- CTX_DATA_END;
return changed;
}
diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c
index 8a07af5c6f4..3d8073ec045 100644
--- a/source/blender/editors/gpencil/gpencil_weight_paint.c
+++ b/source/blender/editors/gpencil/gpencil_weight_paint.c
@@ -246,7 +246,7 @@ static void brush_calc_dvec_2d(tGP_BrushWeightpaintData *gso)
/* ************************************************ */
/* Brush Callbacks
-/* This section defines the callbacks used by each brush to perform their magic.
+ * This section defines the callbacks used by each brush to perform their magic.
* These are called on each point within the brush's radius. */
/* Draw Brush */
@@ -421,7 +421,7 @@ static void gp_save_selected_point(tGP_BrushWeightpaintData *gso,
selected->gps = gps;
selected->pt_index = index;
copy_v2_v2_int(selected->pc, pc);
- copy_v4_v4(selected->color, pt->mix_color);
+ copy_v4_v4(selected->color, pt->vert_color);
gso->pbuffer_used++;
}
@@ -436,8 +436,7 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
Brush *brush = gso->brush;
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
gso->brush->size;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
- bGPDstroke *gps_active = (!is_multiedit) ? gps->runtime.gps_orig : gps;
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
bGPDspoint *pt1, *pt2;
@@ -448,13 +447,18 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
int index;
bool include_last = false;
+ /* Check if the stroke collide with brush. */
+ if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) {
+ return;
+ }
+
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
gp_point_to_parent_space(gps->points, diff_mat, &pt_temp);
gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* do boundbox check first */
if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
/* only check if point is inside */
@@ -496,8 +500,8 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
/* To each point individually... */
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
gp_save_selected_point(gso, gps_active, index, pc1);
}
@@ -512,8 +516,8 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
*/
if (i + 1 == gps->totpoints - 1) {
pt = &gps->points[i + 1];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i + 1;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1;
if (pt_active != NULL) {
gp_save_selected_point(gso, gps_active, index, pc2);
include_last = false;
@@ -530,8 +534,8 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso,
* (but wasn't added then, to avoid double-ups).
*/
pt = &gps->points[i];
- pt_active = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- index = (!is_multiedit) ? pt->runtime.idx_orig : i;
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i;
if (pt_active != NULL) {
gp_save_selected_point(gso, gps_active, index, pc1);
@@ -563,7 +567,7 @@ static bool gp_weightpaint_brush_do_frame(bContext *C,
* all selected points before apply the effect, because it could be
* required to do some step. Now is not used, but the operator is ready.
*--------------------------------------------------------------------- */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Skip strokes that are invalid for current view. */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -609,26 +613,21 @@ static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpai
ToolSettings *ts = CTX_data_tool_settings(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *obact = gso->object;
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, obact);
- bGPdata *gpd = gso->gpd;
bool changed = false;
+ Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &obact->id);
+ bGPdata *gpd = (bGPdata *)ob_eval->data;
+
/* Find visible strokes, and perform operations on those if hit */
- CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- /* If no active frame, don't do anything... */
- if (gpl->actframe == NULL) {
- continue;
- }
- /* Get evaluated frames array data */
- int idx_eval = BLI_findindex(&gpd->layers, gpl);
- bGPDframe *gpf_eval = &ob_eval->runtime.gpencil_evaluated_frames[idx_eval];
- if (gpf_eval == NULL) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* If locked or no active frame, don't do anything. */
+ if ((!BKE_gpencil_layer_is_editable(gpl)) || (gpl->actframe == NULL)) {
continue;
}
/* calculate difference matrix */
float diff_mat[4][4];
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* Active Frame or MultiFrame? */
if (gso->is_multiframe) {
@@ -640,7 +639,7 @@ static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpai
BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
}
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* Always do active frame; Otherwise, only include selected frames */
if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) {
/* compute multiframe falloff factor */
@@ -661,12 +660,13 @@ static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpai
}
}
else {
- /* Apply to active frame's strokes */
- gso->mf_falloff = 1.0f;
- changed |= gp_weightpaint_brush_do_frame(C, gso, gpl, gpf_eval, diff_mat);
+ if (gpl->actframe != NULL) {
+ /* Apply to active frame's strokes */
+ gso->mf_falloff = 1.0f;
+ changed |= gp_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat);
+ }
}
}
- CTX_DATA_END;
return changed;
}
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index e7bc61d5a4b..937ca83899f 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -35,6 +35,7 @@ struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
struct tGPspoint;
+struct GP_SpaceConversion;
struct ARegion;
struct Depsgraph;
@@ -42,6 +43,7 @@ struct Main;
struct RegionView3D;
struct ReportList;
struct Scene;
+struct ToolSettings;
struct ScrArea;
struct View3D;
struct ViewLayer;
@@ -201,12 +203,6 @@ bool ED_gpencil_add_lattice_modifier(const struct bContext *C,
/* ------------ Transformation Utilities ------------ */
-/* get difference matrix */
-void ED_gpencil_parent_location(const struct Depsgraph *depsgraph,
- struct Object *obact,
- struct bGPdata *gpd,
- struct bGPDlayer *gpl,
- float diff_mat[4][4]);
/* reset parent matrix for all layers */
void ED_gpencil_reset_layers_parent(struct Depsgraph *depsgraph,
struct Object *obact,
@@ -241,11 +237,11 @@ void ED_gp_project_point_to_plane(const struct Scene *scene,
const float origin[3],
const int axis,
struct bGPDspoint *pt);
-void ED_gp_get_drawing_reference(const struct Scene *scene,
- const struct Object *ob,
- struct bGPDlayer *gpl,
- char align_flag,
- float vec[3]);
+void ED_gpencil_drawing_reference_get(const struct Scene *scene,
+ const struct Object *ob,
+ struct bGPDlayer *gpl,
+ char align_flag,
+ float vec[3]);
void ED_gpencil_project_stroke_to_view(struct bContext *C,
struct bGPDlayer *gpl,
struct bGPDstroke *gps);
@@ -267,7 +263,6 @@ void ED_gpencil_tpoint_to_point(struct ARegion *ar,
float origin[3],
const struct tGPspoint *tpt,
struct bGPDspoint *pt);
-void ED_gpencil_calc_stroke_uv(struct Object *ob, struct bGPDstroke *gps);
void ED_gpencil_update_color_uv(struct Main *bmain, struct Material *mat);
/* extend selection to stroke intersections
@@ -293,7 +288,26 @@ struct tGPspoint *ED_gpencil_sbuffer_ensure(struct tGPspoint *buffer_array,
int *buffer_size,
int *buffer_used,
const bool clear);
+void ED_gpencil_sbuffer_update_eval(struct Depsgraph *depsgraph, struct Object *ob);
+
/* Tag all scene grease pencil object to update. */
void ED_gpencil_tag_scene_gpencil(struct Scene *scene);
+/* Vertex color set. */
+void ED_gpencil_fill_vertex_color_set(struct ToolSettings *ts,
+ struct Brush *brush,
+ struct bGPDstroke *gps);
+void ED_gpencil_point_vertex_color_set(struct ToolSettings *ts,
+ struct Brush *brush,
+ struct bGPDspoint *pt);
+void ED_gpencil_sbuffer_vertex_color_set(struct ToolSettings *ts,
+ struct Brush *brush,
+ struct bGPdata *gpd);
+
+bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc,
+ struct bGPDstroke *gps,
+ float mouse[2],
+ const int radius,
+ const float diff_mat[4][4]);
+
#endif /* __ED_GPENCIL_H__ */
diff --git a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
index 3acae220a54..f62efcfc766 100644
--- a/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_gpencil_color.c
@@ -126,15 +126,15 @@ static void eyedropper_add_material(
if (gp_style != NULL) {
/* Check stroke color. */
bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
- (gp_style->flag & GP_STYLE_STROKE_SHOW);
+ (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
/* Check fill color. */
bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
- (gp_style->flag & GP_STYLE_FILL_SHOW);
+ (gp_style->flag & GP_MATERIAL_FILL_SHOW);
- if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
+ if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
found = true;
}
- else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0)) {
+ else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0)) {
found = true;
}
else if ((both) && (found_stroke) && (found_fill)) {
@@ -168,22 +168,22 @@ static void eyedropper_add_material(
/* Only create Stroke (default option). */
if (only_stroke) {
/* Stroke color. */
- gp_style_new->flag |= GP_STYLE_STROKE_SHOW;
- gp_style_new->flag &= ~GP_STYLE_FILL_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW;
+ gp_style_new->flag &= ~GP_MATERIAL_FILL_SHOW;
copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
zero_v4(gp_style_new->fill_rgba);
}
/* Fill Only. */
else if (only_fill) {
/* Fill color. */
- gp_style_new->flag &= ~GP_STYLE_STROKE_SHOW;
- gp_style_new->flag |= GP_STYLE_FILL_SHOW;
+ gp_style_new->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_FILL_SHOW;
zero_v4(gp_style_new->stroke_rgba);
copy_v3_v3(gp_style_new->fill_rgba, col_conv);
}
/* Stroke and Fill. */
else if (both) {
- gp_style_new->flag |= GP_STYLE_STROKE_SHOW | GP_STYLE_FILL_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW | GP_MATERIAL_FILL_SHOW;
copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
copy_v3_v3(gp_style_new->fill_rgba, col_conv);
}
@@ -234,16 +234,7 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed
float col_conv[4];
- /* Convert from linear rgb space to display space because grease pencil colors are in display
- * space, and this conversion is needed to undo the conversion to linear performed by
- * eyedropper_color_sample_fl. */
- if (eye->display) {
- copy_v3_v3(col_conv, eye->color);
- IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
- }
- else {
- copy_v3_v3(col_conv, eye->color);
- }
+ copy_v3_v3(col_conv, eye->color);
/* Add material or Palette color*/
if (eye->mode == 0) {
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 2be0fed443b..6f7f53a50a3 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1528,7 +1528,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
* Will also remove parent from grease pencil from other scenes,
* even when use_global is false... */
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) {
if (gpl->parent != NULL) {
if (gpl->parent == ob) {
gpl->parent = NULL;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 4f56664ec99..ddd9137add4 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -696,7 +696,7 @@ static int apply_objects_internal(bContext *C,
/* Unsupported configuration */
bool has_unparented_layers = false;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Parented layers aren't supported as we can't easily re-evaluate
* the scene to sample parent movement */
if (gpl->parent == NULL) {
@@ -1394,13 +1394,13 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* recalculate all strokes
* (all layers are considered without evaluating lock attributes) */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo matrix */
invert_m4_m4(inverse_diff_mat, diff_mat);
- 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) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
float mpt[3];
mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index a840d199823..540a4c05247 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -555,7 +555,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
@@ -567,7 +567,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPdata *gpd = ED_annotation_data_get_active_direct((ID *)sc, sa, scene);
if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl);
@@ -579,7 +579,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPdata *gpd = ED_gpencil_data_get_active_direct(sa, obact);
if (gpd) {
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl) {
CTX_data_pointer_set(result, &gpd->id, &RNA_GPencilLayer, gpl->actframe);
@@ -609,7 +609,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpencil_layer_is_editable(gpl)) {
+ if (BKE_gpencil_layer_is_editable(gpl)) {
CTX_data_list_add(result, &gpd->id, &RNA_GPencilLayer, gpl);
}
}
@@ -625,7 +625,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe)) {
bGPDframe *gpf;
bGPDstroke *gps;
bGPDframe *init_gpf = gpl->actframe;
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 68d26cc5c74..beeac6f3fda 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -358,7 +358,7 @@ static int palette_extract_img_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void PALETTE_OT_extract_from_image(wmOperatorType *ot)
+static void PALETTE_OT_extract_from_image(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Extract Palette from Image";
@@ -454,7 +454,7 @@ static int palette_sort_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void PALETTE_OT_sort(wmOperatorType *ot)
+static void PALETTE_OT_sort(wmOperatorType *ot)
{
static const EnumPropertyItem sort_type[] = {
{-1, "HSV", 0, "Hue, Saturation, Value", ""},
@@ -499,7 +499,7 @@ static int palette_color_move_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void PALETTE_OT_color_move(wmOperatorType *ot)
+static void PALETTE_OT_color_move(wmOperatorType *ot)
{
static const EnumPropertyItem slot_move[] = {
{-1, "UP", 0, "Up", ""},
@@ -582,7 +582,7 @@ static int palette_join_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void PALETTE_OT_join(wmOperatorType *ot)
+static void PALETTE_OT_join(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Join Palette Swatches";
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 6e44992ea6e..18cb90fd774 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -803,7 +803,7 @@ static void insert_gpencil_keys(bAnimContext *ac, short mode)
/* insert gp frames */
for (ale = anim_data.first; ale; ale = ale->next) {
bGPDlayer *gpl = (bGPDlayer *)ale->data;
- BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode);
+ BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
}
ANIM_animdata_update(ac, &anim_data);
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 095b30aa57b..0b396bcd2b1 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1759,8 +1759,8 @@ static int mouse_action_keys(bAnimContext *ac,
gpl->flag |= GP_LAYER_SELECT;
/* Update other layer status. */
- if (BKE_gpencil_layer_getactive(gpd) != gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
+ if (BKE_gpencil_layer_active_get(gpd) != gpl) {
+ BKE_gpencil_layer_active_set(gpd, gpl);
BKE_gpencil_layer_autolock_set(gpd, false);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 67e5b5045d4..5cf6c732a71 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -816,7 +816,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
bGPDlayer *gpl = te->directdata;
/* always make layer active */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
// XXX: name needs translation stuff
BLI_uniquename(
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 51e837db4c2..7e3cc15729b 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -556,7 +556,7 @@ static eOLDrawState tree_element_active_gplayer(bContext *C,
*/
if (set != OL_SETSEL_NONE) {
if (gpl) {
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, gpd);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 648c77fbcbf..45c9186b814 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -410,7 +410,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
/* Helper: Find the layer created as ruler. */
static bGPDlayer *view3d_ruler_layer_get(bGPdata *gpd)
{
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_IS_RULER) {
return gpl;
}
@@ -446,7 +446,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
gpl->flag |= GP_LAYER_HIDE | GP_LAYER_IS_RULER;
}
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
BKE_gpencil_free_strokes(gpf);
for (ruler_item = gzgroup->gizmos.first; ruler_item;
@@ -479,6 +479,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
gps->flag = GP_STROKE_3DSPACE;
gps->thickness = 3;
gps->gradient_f = 1.0f;
+ gps->fill_opacity_fac = 1.0f;
gps->gradient_s[0] = 1.0f;
gps->gradient_s[1] = 1.0f;
gps->uv_scale = 1.0f;
@@ -500,7 +501,7 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
gpl = view3d_ruler_layer_get(scene->gpd);
if (gpl) {
bGPDframe *gpf;
- gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
if (gpf) {
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 8feafc85c2f..1f24b55d083 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -862,7 +862,7 @@ static void posttrans_gpd_clean(bGPdata *gpd)
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
gpfn = gpf->next;
if (gpfn && gpf->framenum == gpfn->framenum) {
- BKE_gpencil_layer_delframe(gpl, gpf);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
}
}
}
diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c
index 2547e486a6a..cf3a6865c7e 100644
--- a/source/blender/editors/transform/transform_convert_gpencil.c
+++ b/source/blender/editors/transform/transform_convert_gpencil.c
@@ -111,7 +111,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
*/
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf;
bGPDstroke *gps;
bGPDframe *init_gpf = gpl->actframe;
@@ -183,7 +183,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
/* Second Pass: Build transdata array */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
bGPDframe *gpf = gpl->actframe;
bGPDstroke *gps;
@@ -203,7 +203,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
}
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
/* undo matrix */
invert_m4_m4(inverse_diff_mat, diff_mat);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 5595c3a0e38..8142f9f99c2 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1215,12 +1215,15 @@ static void recalcData_sequencer(TransInfo *t)
static void recalcData_gpencil_strokes(TransInfo *t)
{
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ bGPDstroke *gps_prev = NULL;
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
bGPDstroke *gps = td->extra;
- if (gps != NULL) {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ if ((gps != NULL) && (gps != gps_prev)) {
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+ gps_prev = gps;
}
}
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 3d3aa58a0de..ab29e3895f6 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -792,13 +792,13 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
if (is_gp_edit) {
float diff_mat[4][4];
const bool use_mat_local = true;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
/* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat);
for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
/* skip strokes that are invalid for current view */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 44c59f60377..400fb256128 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -187,44 +187,3 @@ float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
return weight;
}
-
-/* set material when apply modifiers (used in tint and color modifier) */
-void gpencil_apply_modifier_material(
- Main *bmain, Object *ob, Material *mat, GHash *gh_color, bGPDstroke *gps, bool crt_material)
-{
- MaterialGPencilStyle *gp_style = mat->gp_style;
-
- /* look for color */
- if (crt_material) {
- Material *newmat = BLI_ghash_lookup(gh_color, mat->id.name);
- if (newmat == NULL) {
- BKE_object_material_slot_add(bmain, ob);
- newmat = BKE_material_copy(bmain, mat);
- newmat->preview = NULL;
-
- BKE_object_material_assign(bmain, ob, newmat, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
-
- copy_v4_v4(newmat->gp_style->stroke_rgba, gps->runtime.tmp_stroke_rgba);
- copy_v4_v4(newmat->gp_style->fill_rgba, gps->runtime.tmp_fill_rgba);
-
- BLI_ghash_insert(gh_color, mat->id.name, newmat);
- DEG_id_tag_update(&newmat->id, ID_RECALC_COPY_ON_WRITE);
- }
- /* Reassign color index. */
- gps->mat_nr = BKE_gpencil_object_material_get_index(ob, newmat);
- }
- else {
- /* reuse existing color (but update only first time) */
- if (BLI_ghash_lookup(gh_color, mat->id.name) == NULL) {
- copy_v4_v4(gp_style->stroke_rgba, gps->runtime.tmp_stroke_rgba);
- copy_v4_v4(gp_style->fill_rgba, gps->runtime.tmp_fill_rgba);
- BLI_ghash_insert(gh_color, mat->id.name, mat);
- }
- /* update previews (icon and thumbnail) */
- if (mat->preview != NULL) {
- mat->preview->flag[ICON_SIZE_ICON] |= PRV_CHANGED;
- mat->preview->flag[ICON_SIZE_PREVIEW] |= PRV_CHANGED;
- }
- DEG_id_tag_update(&mat->id, ID_RECALC_COPY_ON_WRITE);
- }
-}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
index 2b1f8dbc71a..fc4522bc028 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
@@ -47,11 +47,4 @@ bool is_stroke_affected_by_modifier(struct Object *ob,
float get_modifier_point_weight(struct MDeformVert *dvert, bool inverse, int def_nr);
-void gpencil_apply_modifier_material(struct Main *bmain,
- struct Object *ob,
- struct Material *mat,
- struct GHash *gh_color,
- struct bGPDstroke *gps,
- bool crt_material);
-
#endif /* __MOD_GPENCIL_UTIL_H__ */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 27c8175af3f..9252629865c 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -116,6 +117,8 @@ static void deformStroke(GpencilModifierData *md,
}
gpencil_deform_verts(mmd, ob, gps);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
@@ -131,8 +134,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply armature effects on this frame
* NOTE: this assumes that we don't want armature animation on non-keyframed frames
*/
@@ -140,7 +143,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* compute armature effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md_eval, depsgraph, object_eval, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index e258fbdccd1..2014c965e6c 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -291,8 +291,8 @@ static void bakeModifier(Main *UNUSED(bmain),
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
generate_geometry(md, depsgraph, ob, gpl, gpf);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index e3e7168330d..2437beb1992 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -174,10 +174,8 @@ static void reduce_stroke_points(bGPDstroke *gps,
gps->dvert = new_dvert;
gps->totpoints = num_points;
- /* mark stroke as needing to have its geometry caches rebuilt */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
- MEM_SAFE_FREE(gps->triangles);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* --------------------------------------------- */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
index c383225368e..9e7edd536cb 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
@@ -26,7 +26,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
@@ -52,7 +51,6 @@ static void initData(GpencilModifierData *md)
ARRAY_SET_ITEMS(gpmd->hsv, 0.5f, 1.0f, 1.0f);
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
- gpmd->flag |= GP_COLOR_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
}
@@ -94,76 +92,54 @@ static void deformStroke(GpencilModifierData *md,
factor[1] -= 1.0f;
factor[2] -= 1.0f;
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- rgb_to_hsv_v(gps->runtime.tmp_stroke_rgba, hsv);
- add_v3_v3(hsv, factor);
- CLAMP3(hsv, 0.0f, 1.0f);
- hsv_to_rgb_v(hsv, gps->runtime.tmp_stroke_rgba);
- }
-
- if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- rgb_to_hsv_v(gps->runtime.tmp_fill_rgba, hsv);
- add_v3_v3(hsv, factor);
- CLAMP3(hsv, 0.0f, 1.0f);
- hsv_to_rgb_v(hsv, gps->runtime.tmp_fill_rgba);
- }
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- /* Apply to mix color. */
+ /* Apply to Vertex Color. */
/* Fill */
if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- rgb_to_hsv_v(gps->mix_color_fill, hsv);
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
+ (gp_style->fill_rgba[3] > 0.0f)) {
+ copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
+ }
+
+ rgb_to_hsv_v(gps->vert_color_fill, hsv);
add_v3_v3(hsv, factor);
CLAMP3(hsv, 0.0f, 1.0f);
- hsv_to_rgb_v(hsv, gps->mix_color_fill);
+ hsv_to_rgb_v(hsv, gps->vert_color_fill);
}
/* Stroke */
if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
+
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
- rgb_to_hsv_v(pt->mix_color, hsv);
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
+ copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
+ }
+
+ rgb_to_hsv_v(pt->vert_color, hsv);
add_v3_v3(hsv, factor);
CLAMP3(hsv, 0.0f, 1.0f);
- hsv_to_rgb_v(hsv, pt->mix_color);
+ hsv_to_rgb_v(hsv, pt->vert_color);
}
}
}
static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
{
- ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md;
bGPdata *gpd = ob->data;
- GHash *gh_color = BLI_ghash_str_new("GP_Color modifier");
- 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) {
-
- Material *mat = BKE_gpencil_material(ob, gps->mat_nr + 1);
- if (mat == NULL) {
- continue;
- }
- MaterialGPencilStyle *gp_style = mat->gp_style;
- /* skip stroke if it doesn't have color info */
- if (ELEM(NULL, gp_style)) {
- continue;
- }
-
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
-
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_COLOR_CREATE_COLORS));
}
}
}
- /* free hash buffers */
- if (gh_color) {
- BLI_ghash_free(gh_color, NULL, NULL);
- gh_color = NULL;
- }
}
GpencilModifierTypeInfo modifierType_Gpencil_Color = {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index bc62d0d69bb..942b0490ce0 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -263,6 +264,8 @@ static void deformStroke(GpencilModifierData *md,
}
gp_hook_co_apply(&tData, weight, pt);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* FIXME: Ideally we be doing this on a copy of the main depsgraph
@@ -279,8 +282,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply hook effects on this frame
* NOTE: this assumes that we don't want hook animation on non-keyframed frames
*/
@@ -288,7 +291,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* compute hook effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index 9dbf7b35bc5..ef3b1343827 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -108,6 +109,8 @@ static void deformStroke(GpencilModifierData *md,
}
calc_latt_deform((struct LatticeDeformData *)mmd->cache_data, &pt->x, mmd->strength * weight);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* FIXME: Ideally we be doing this on a copy of the main depsgraph
@@ -125,8 +128,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply lattice effects on this frame
* NOTE: this assumes that we don't want lattice animation on non-keyframed frames
*/
@@ -137,7 +140,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_gpencil_lattice_init(ob);
/* compute lattice effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index ef06e14b3d7..7a2ec889082 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -145,7 +145,7 @@ static void generateStrokes(GpencilModifierData *md,
mmd->flag & GP_MIRROR_INVERT_PASS,
mmd->flag & GP_MIRROR_INVERT_LAYERPASS,
mmd->flag & GP_MIRROR_INVERT_MATERIAL)) {
- gps_new = BKE_gpencil_stroke_duplicate(gps);
+ gps_new = BKE_gpencil_stroke_duplicate(gps, true);
update_position(ob, mmd, gps_new, xi);
BLI_addtail(&gpf->strokes, gps_new);
}
@@ -160,8 +160,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
bGPdata *gpd = ob->data;
int oldframe = (int)DEG_get_ctime(depsgraph);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply mirror effects on this frame */
CFRA = gpf->framenum;
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
index bc545ce6ce8..3c46281a3ea 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c
@@ -88,7 +88,7 @@ static void splitStroke(bGPDframe *gpf, bGPDstroke *gps, float split_angle)
for (i = 1; i < new_gps->totpoints - 1; i++) {
angle = angle_v3v3v3(&pt[i - 1].x, &pt[i].x, &pt[i + 1].x);
if (angle < split_angle) {
- if (BKE_gpencil_split_stroke(gpf, new_gps, i, &new_gps)) {
+ if (BKE_gpencil_stroke_split(gpf, new_gps, i, &new_gps)) {
pt = new_gps->points;
i = 0;
continue; /* then i == 1 again */
@@ -177,8 +177,8 @@ static void duplicateStroke(bGPDstroke *gps,
/* This ensures the original stroke is the last one to be processed. */
for (i = count - 1; i >= 0; i--) {
if (i != 0) {
- new_gps = BKE_gpencil_stroke_duplicate(gps);
- new_gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ new_gps = BKE_gpencil_stroke_duplicate(gps, true);
+
BLI_addtail(results, new_gps);
}
else {
@@ -215,6 +215,9 @@ static void duplicateStroke(bGPDstroke *gps,
}
}
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(new_gps);
+
MEM_freeN(t1_array);
MEM_freeN(t2_array);
}
@@ -227,8 +230,8 @@ static void bakeModifier(Main *UNUSED(bmain),
bGPdata *gpd = ob->data;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
ListBase duplicates = {0};
MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md;
bGPDstroke *gps;
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index f34477aaab2..a6e50362b34 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
@@ -243,9 +244,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
index 70d463fff76..97f78088530 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -108,6 +109,8 @@ static void deformStroke(GpencilModifierData *md,
mul_m4_v3(mat, &pt->x);
}
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
static void bakeModifier(struct Main *UNUSED(bmain),
@@ -117,9 +120,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index b0fab5e8d69..e1aeec94574 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -26,7 +26,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math_vector.h"
#include "DNA_meshdata_types.h"
@@ -54,7 +53,6 @@ static void initData(GpencilModifierData *md)
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
- gpmd->flag |= GP_OPACITY_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
}
@@ -89,40 +87,12 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- if (mmd->opacity_mode == GP_OPACITY_MODE_MATERIAL) {
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- gps->runtime.tmp_stroke_rgba[3] *= mmd->factor;
- /* if factor is > 1, then force opacity */
- if (mmd->factor > 1.0f) {
- gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
- }
- CLAMP(gps->runtime.tmp_stroke_rgba[3], 0.0f, 1.0f);
- }
-
- if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- gps->runtime.tmp_fill_rgba[3] *= mmd->factor;
- /* if factor is > 1, then force opacity */
- if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
- gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
- }
- CLAMP(gps->runtime.tmp_fill_rgba[3], 0.0f, 1.0f);
- }
-
- /* if opacity > 1.0, affect the strength of the stroke */
- if (mmd->factor > 1.0f) {
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- pt->strength += mmd->factor - 1.0f;
- CLAMP(pt->strength, 0.0f, 1.0f);
- }
- }
- }
- /* Apply opacity by strength */
- else {
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ /* Stroke using strength. */
+ if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
/* verify vertex group */
float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
@@ -143,45 +113,24 @@ static void deformStroke(GpencilModifierData *md,
CLAMP(pt->strength, 0.0f, 1.0f);
}
}
+
+ /* Fill using opacity factor. */
+ if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
+ gps->fill_opacity_fac = mmd->factor;
+ }
}
static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
{
- OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
bGPdata *gpd = ob->data;
- GHash *gh_color = BLI_ghash_str_new("GP_Opacity modifier");
- 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) {
-
- Material *mat = BKE_gpencil_material(ob, gps->mat_nr + 1);
- if (mat == NULL) {
- continue;
- }
- MaterialGPencilStyle *gp_style = mat->gp_style;
- /* skip stroke if it doesn't have color info */
- if (ELEM(NULL, gp_style)) {
- continue;
- }
-
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
-
- if (mmd->opacity_mode == GP_OPACITY_MODE_MATERIAL) {
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS));
- }
}
}
}
- /* free hash buffers */
- if (gh_color) {
- BLI_ghash_free(gh_color, NULL, NULL);
- gh_color = NULL;
- }
}
GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
index 9594fc8581e..3d07ba85430 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
@@ -84,21 +85,21 @@ static void deformStroke(GpencilModifierData *md,
switch (mmd->mode) {
case GP_SIMPLIFY_FIXED: {
for (int i = 0; i < mmd->step; i++) {
- BKE_gpencil_simplify_fixed(gps);
+ BKE_gpencil_stroke_simplify_fixed(gps);
}
break;
}
case GP_SIMPLIFY_ADAPTIVE: {
/* simplify stroke using Ramer-Douglas-Peucker algorithm */
- BKE_gpencil_simplify_stroke(gps, mmd->factor);
+ BKE_gpencil_stroke_simplify(gps, mmd->factor);
break;
}
case GP_SIMPLIFY_SAMPLE: {
- BKE_gpencil_sample_stroke(gps, mmd->length, false);
+ BKE_gpencil_stroke_sample(gps, mmd->length, false);
break;
}
case GP_SIMPLIFY_MERGE: {
- BKE_gpencil_merge_distance_stroke(gpf, gps, mmd->distance, true);
+ BKE_gpencil_stroke_merge_distance(gpf, gps, mmd->distance, true);
break;
}
default:
@@ -113,9 +114,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index 68060711681..59223c3ae68 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -98,19 +99,19 @@ static void deformStroke(GpencilModifierData *md,
const float val = mmd->factor * weight;
/* perform smoothing */
if (mmd->flag & GP_SMOOTH_MOD_LOCATION) {
- BKE_gpencil_smooth_stroke(gps, i, val);
+ BKE_gpencil_stroke_smooth(gps, i, val);
}
if (mmd->flag & GP_SMOOTH_MOD_STRENGTH) {
- BKE_gpencil_smooth_stroke_strength(gps, i, val);
+ BKE_gpencil_stroke_smooth_strength(gps, i, val);
}
if ((mmd->flag & GP_SMOOTH_MOD_THICKNESS) && (val > 0.0f)) {
/* thickness need to repeat process several times */
for (int r2 = 0; r2 < r * 10; r2++) {
- BKE_gpencil_smooth_stroke_thickness(gps, i, val);
+ BKE_gpencil_stroke_smooth_thickness(gps, i, val);
}
}
if (mmd->flag & GP_SMOOTH_MOD_UV) {
- BKE_gpencil_smooth_stroke_uv(gps, i, val);
+ BKE_gpencil_stroke_smooth_uv(gps, i, val);
}
}
}
@@ -124,9 +125,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index 89d6565d0dd..71b2bd2e040 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -84,7 +85,7 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- BKE_gpencil_subdivide(gps, mmd->level, mmd->flag);
+ BKE_gpencil_stroke_subdivide(gps, mmd->level, mmd->flag);
}
static void bakeModifier(struct Main *UNUSED(bmain),
@@ -94,9 +95,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index 036464e718d..0f9b2ea52d2 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -23,6 +23,7 @@
#include <stdio.h>
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
@@ -179,9 +180,9 @@ static void bakeModifier(struct Main *UNUSED(bmain),
{
bGPdata *gpd = ob->data;
- 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) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index cc3d17ded3e..775793e423f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -26,7 +26,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math_vector.h"
#include "DNA_scene_types.h"
@@ -52,7 +51,6 @@ static void initData(GpencilModifierData *md)
gpmd->layername[0] = '\0';
gpmd->materialname[0] = '\0';
ARRAY_SET_ITEMS(gpmd->rgb, 1.0f, 1.0f, 1.0f);
- gpmd->flag |= GP_TINT_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
}
@@ -86,24 +84,7 @@ static void deformStroke(GpencilModifierData *md,
return;
}
- if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
- interp_v3_v3v3(
- gps->runtime.tmp_stroke_rgba, gps->runtime.tmp_stroke_rgba, mmd->rgb, mmd->factor);
- /* if factor is > 1, the alpha must be changed to get full tint */
- if (mmd->factor > 1.0f) {
- gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
- }
- CLAMP4(gps->runtime.tmp_stroke_rgba, 0.0f, 1.0f);
- }
-
- if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- interp_v3_v3v3(gps->runtime.tmp_fill_rgba, gps->runtime.tmp_fill_rgba, mmd->rgb, mmd->factor);
- /* if factor is > 1, the alpha must be changed to get full tint */
- if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
- gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
- }
- CLAMP4(gps->runtime.tmp_fill_rgba, 0.0f, 1.0f);
- }
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
/* if factor > 1.0, affect the strength of the stroke */
if (mmd->factor > 1.0f) {
@@ -114,58 +95,47 @@ static void deformStroke(GpencilModifierData *md,
}
}
- /* Apply to mix color. */
+ /* Apply to Vertex Color. */
float mixfac = mmd->factor;
CLAMP(mixfac, 0.0, 1.0f);
/* Fill */
if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
- interp_v3_v3v3(gps->mix_color_fill, gps->mix_color_fill, mmd->rgb, mixfac);
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (gps->vert_color_fill[3] == 0.0f) &&
+ (gp_style->fill_rgba[3] > 0.0f)) {
+ copy_v4_v4(gps->vert_color_fill, gp_style->fill_rgba);
+ gps->vert_color_fill[3] = 1.0f;
+ }
+
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, mmd->rgb, mixfac);
}
/* Stroke */
if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
- interp_v3_v3v3(pt->mix_color, pt->mix_color, mmd->rgb, mixfac);
+ /* If not using Vertex Color, use the material color. */
+ if ((gp_style != NULL) && (pt->vert_color[3] == 0.0f) && (gp_style->stroke_rgba[3] > 0.0f)) {
+ copy_v4_v4(pt->vert_color, gp_style->stroke_rgba);
+ pt->vert_color[3] = 1.0f;
+ }
+
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, mmd->rgb, mixfac);
}
}
}
static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
{
- TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
bGPdata *gpd = ob->data;
- GHash *gh_color = BLI_ghash_str_new("GP_Tint modifier");
- 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) {
-
- Material *mat = BKE_gpencil_material(ob, gps->mat_nr + 1);
- if (mat == NULL) {
- continue;
- }
- MaterialGPencilStyle *gp_style = mat->gp_style;
- /* skip stroke if it doesn't have color info */
- if (ELEM(NULL, gp_style)) {
- continue;
- }
-
- copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
-
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_TINT_CREATE_COLORS));
}
}
}
- /* free hash buffers */
- if (gh_color) {
- BLI_ghash_free(gh_color, NULL, NULL);
- gh_color = NULL;
- }
}
GpencilModifierTypeInfo modifierType_Gpencil_Tint = {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
index d33bc12144d..502935fddd0 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilvertexcolor.c
@@ -26,6 +26,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
@@ -230,8 +231,8 @@ static void deformStroke(GpencilModifierData *md,
/* Apply to fill. */
if (mmd->mode != GPPAINT_MODE_STROKE) {
BKE_colorband_evaluate(mmd->colorband, 1.0f, coba_res);
- interp_v3_v3v3(gps->mix_color_fill, gps->mix_color_fill, coba_res, mmd->factor);
- gps->mix_color_fill[3] = mmd->factor;
+ interp_v3_v3v3(gps->vert_color_fill, gps->vert_color_fill, coba_res, mmd->factor);
+ gps->vert_color_fill[3] = mmd->factor;
/* If no stroke, cancel loop. */
if (mmd->mode != GPPAINT_MODE_BOTH) {
break;
@@ -252,11 +253,11 @@ static void deformStroke(GpencilModifierData *md,
float mix_factor = dist_sqr / radius_sqr;
BKE_colorband_evaluate(mmd->colorband, mix_factor, coba_res);
- interp_v3_v3v3(pt->mix_color, pt->mix_color, coba_res, mmd->factor * weight);
- pt->mix_color[3] = mmd->factor;
+ interp_v3_v3v3(pt->vert_color, pt->vert_color, coba_res, mmd->factor * weight);
+ pt->vert_color[3] = mmd->factor;
/* Apply Decay. */
if (mmd->flag & GP_VERTEXCOL_DECAY_COLOR) {
- pt->mix_color[3] *= (1.0f - mix_factor);
+ pt->vert_color[3] *= (1.0f - mix_factor);
}
}
}
@@ -276,8 +277,8 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
return;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
/* apply effects on this frame
* NOTE: this assumes that we don't want animation on non-keyframed frames
*/
@@ -285,7 +286,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
/* compute effects on this frame */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
}
}
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 7d0f8b0bcbf..213cbe30794 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -173,6 +173,8 @@ void GPU_framebuffer_clear(GPUFrameBuffer *fb,
#define GPU_framebuffer_clear_color_depth_stencil(fb, col, depth, stencil) \
GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil)
+void GPU_framebuffer_multi_clear(GPUFrameBuffer *fb, const float (*clear_cols)[4]);
+
void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data);
void GPU_framebuffer_read_color(
GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data);
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index e336aa53d24..2e06c1c3594 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -51,6 +51,7 @@ typedef enum {
GPU_UNIFORM_COLOR, /* vec4 color */
GPU_UNIFORM_BASE_INSTANCE, /* int baseInstance */
GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */
+ GPU_UNIFORM_RESOURCE_ID, /* int resourceId */
GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index bb6af227369..456d5941bfb 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -95,6 +95,7 @@ typedef enum eGPUTextureFormat {
#if 0
GPU_RGB10_A2,
GPU_RGB10_A2UI,
+ GPU_SRGB8_A8,
#endif
GPU_R11F_G11F_B10F,
GPU_DEPTH32F_STENCIL8,
@@ -124,7 +125,6 @@ typedef enum eGPUTextureFormat {
/* Special formats texture only */
#if 0
- GPU_SRGB8_A8,
GPU_SRGB8,
GPU_RGB9_E5,
GPU_COMPRESSED_RG_RGTC2,
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index b50665d0256..7e10bdbdc1f 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -108,6 +108,8 @@ uint GPU_vertformat_attr_add(
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias);
+void GPU_vertformat_multiload_enable(GPUVertFormat *format, int load_count);
+
void GPU_vertformat_deinterleave(GPUVertFormat *format);
int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index a531c22365c..b04cce095b7 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -612,6 +612,21 @@ void GPU_framebuffer_clear(GPUFrameBuffer *fb,
glClear(mask);
}
+/* Clear all textures bound to this framebuffer with a different color. */
+void GPU_framebuffer_multi_clear(GPUFrameBuffer *fb, const float (*clear_cols)[4])
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ GPUAttachmentType type = GPU_FB_COLOR_ATTACHMENT0;
+ for (int i = 0; type < GPU_FB_MAX_ATTACHEMENT; i++, type++) {
+ if (fb->attachments[type].tex != NULL) {
+ glClearBufferfv(GL_COLOR, i, clear_cols[i]);
+ }
+ }
+}
+
void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
{
CHECK_FRAMEBUFFER_IS_BOUND(fb);
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 983c5dfc27a..f895993a27d 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -67,6 +67,7 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_COLOR] = "color",
[GPU_UNIFORM_BASE_INSTANCE] = "baseInstance",
[GPU_UNIFORM_RESOURCE_CHUNK] = "resourceChunk",
+ [GPU_UNIFORM_RESOURCE_ID] = "resourceId",
[GPU_UNIFORM_CUSTOM] = NULL,
[GPU_NUM_UNIFORMS] = NULL,
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index 65573b71c76..16d8f8f875b 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -206,6 +206,47 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
attr->names[attr->name_len++] = copy_attr_name(format, alias);
}
+/**
+ * Makes vertex attrib from the next vertices to be accessible in the vertex shader.
+ * For an attrib named "attr" you can access the next nth vertex using "attrn".
+ * Use this function after specifying all the attribs in the format.
+ *
+ * NOTE: This does NOT work when using indexed rendering.
+ * NOTE: Only works for first attrib name. (this limitation can be changed if needed)
+ *
+ * WARNING: this function creates a lot of aliases/attribs, make sure to keep the attrib name
+ * short to avoid overflowing the namebuffer.
+ * */
+void GPU_vertformat_multiload_enable(GPUVertFormat *format, int load_count)
+{
+ /* Sanity check. Maximum can be upgraded if needed. */
+ BLI_assert(load_count > 1 && load_count < 5);
+ /* We need a packed format because of format->stride. */
+ if (!format->packed) {
+ VertexFormat_pack(format);
+ }
+
+ BLI_assert((format->name_len + 1) * load_count < GPU_VERT_FORMAT_MAX_NAMES);
+ BLI_assert(format->attr_len * load_count <= GPU_VERT_ATTR_MAX_LEN);
+ BLI_assert(format->name_offset * load_count < GPU_VERT_ATTR_NAMES_BUF_LEN);
+
+ const GPUVertAttr *attr = format->attrs;
+ int attr_len = format->attr_len;
+ for (int i = 0; i < attr_len; i++, attr++) {
+ const char *attr_name = GPU_vertformat_attr_name_get(format, attr, 0);
+ for (int j = 1; j < load_count; j++) {
+ char load_name[64];
+ BLI_snprintf(load_name, sizeof(load_name), "%s%d", attr_name, j);
+ GPUVertAttr *dst_attr = &format->attrs[format->attr_len++];
+ *dst_attr = *attr;
+
+ dst_attr->names[0] = copy_attr_name(format, load_name);
+ dst_attr->name_len = 1;
+ dst_attr->offset += format->stride * j;
+ }
+ }
+}
+
int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
{
for (int i = 0; i < format->attr_len; i++) {
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 8abae5de498..45e98c9f6e0 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -230,7 +230,6 @@ typedef struct TintGpencilModifierData {
} TintGpencilModifierData;
typedef enum eTintGpencil_Flag {
- GP_TINT_CREATE_COLORS = (1 << 0),
GP_TINT_INVERT_LAYER = (1 << 1),
GP_TINT_INVERT_PASS = (1 << 2),
GP_TINT_INVERT_LAYERPASS = (1 << 3),
@@ -258,7 +257,6 @@ typedef struct ColorGpencilModifierData {
} ColorGpencilModifierData;
typedef enum eColorGpencil_Flag {
- GP_COLOR_CREATE_COLORS = (1 << 0),
GP_COLOR_INVERT_LAYER = (1 << 1),
GP_COLOR_INVERT_PASS = (1 << 2),
GP_COLOR_INVERT_LAYERPASS = (1 << 3),
@@ -281,9 +279,7 @@ typedef struct OpacityGpencilModifierData {
float factor;
/** Modify stroke, fill or both. */
char modify_color;
- /** Mode of opacity, colors or strength */
- char opacity_mode;
- char _pad[2];
+ char _pad[3];
/** Custom index for passes. */
int layer_pass;
char _pad1[4];
@@ -293,7 +289,6 @@ typedef enum eOpacityGpencil_Flag {
GP_OPACITY_INVERT_LAYER = (1 << 0),
GP_OPACITY_INVERT_PASS = (1 << 1),
GP_OPACITY_INVERT_VGROUP = (1 << 2),
- GP_OPACITY_CREATE_COLORS = (1 << 3),
GP_OPACITY_INVERT_LAYERPASS = (1 << 4),
GP_OPACITY_INVERT_MATERIAL = (1 << 5),
} eOpacityGpencil_Flag;
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 44f7c3733ef..409b758d570 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -36,6 +36,8 @@ struct MDeformVert;
#define GP_DEFAULT_GRID_LINES 4
#define GP_MAX_INPUT_SAMPLES 10
+#define GP_MATERIAL_BUFFER_LEN 256
+
/* ***************************************** */
/* GP Stroke Points */
@@ -78,9 +80,11 @@ typedef struct bGPDspoint {
float uv_fac;
/** Uv rotation for dot mode. */
float uv_rot;
+ /** Uv for fill mode */
+ float uv_fill[2];
- /** Mix color RGBA (A=mix factor) */
- float mix_color[4];
+ /** Vertex Color RGBA (A=mix factor). */
+ float vert_color[4];
/** Runtime data */
char _pad2[4];
@@ -109,8 +113,6 @@ typedef enum eGPDspoint_Flag {
typedef struct bGPDtriangle {
/* indices for tessellated triangle used for GP Fill */
unsigned int verts[3];
- /* texture coordinates for verts */
- float uv[3][2];
} bGPDtriangle;
/* ***************************************** */
@@ -170,18 +172,17 @@ typedef enum eGPDpalette_Flag {
/* Runtime temp data for bGPDstroke */
typedef struct bGPDstroke_Runtime {
- /** runtime final colors (result of original colors and modifiers) */
- float tmp_stroke_rgba[4];
-
- /** runtime final fill colors (result of original colors and modifiers) */
- float tmp_fill_rgba[4];
-
/** temporary layer name only used during copy/paste to put the stroke in the original layer */
char tmp_layerinfo[128];
/** Runtime falloff factor (only for transform). */
float multi_frame_falloff;
- char _pad[4];
+
+ /** Vertex offset in the vbo where this stroke starts. */
+ int stroke_start;
+ /** Triangle offset in the ibo where this fill starts. */
+ int fill_start;
+ int _pad[1];
/** Original stroke (used to dereference evaluated data) */
struct bGPDstroke *gps_orig;
@@ -224,7 +225,14 @@ typedef struct bGPDstroke {
float gradient_f;
/** factor xy of shape for dots gradients */
float gradient_s[2];
- char _pad_3[4];
+
+ /** Factor of opacity for Fill color (used by opacity modifier). */
+ float fill_opacity_fac;
+
+ /** Min of the collision bound box used to speedup painting. */
+ float collision_min[3];
+ /** Max of the collision bound box used to speedup painting. */
+ float collision_max[3];
/** UV rotation */
float uv_rotation;
@@ -236,8 +244,8 @@ typedef struct bGPDstroke {
struct MDeformVert *dvert;
void *_pad3;
- /** Vertex mix color for Fill (one for all stroke). */
- float mix_color_fill[4];
+ /** Vertex Color for Fill (one for all stroke, A=mix factor). */
+ float vert_color_fill[4];
bGPDstroke_Runtime runtime;
} bGPDstroke;
@@ -252,14 +260,13 @@ typedef enum eGPDstroke_Flag {
GP_STROKE_2DIMAGE = (1 << 2),
/* stroke is selected */
GP_STROKE_SELECT = (1 << 3),
- /* Recalculate geometry data (triangulation, UVs, Bound Box,...
- * (when true, force a new recalc) */
- GP_STROKE_RECALC_GEOMETRY = (1 << 4),
/* Flag used to indicate that stroke is closed and draw edge between last and first point */
GP_STROKE_CYCLIC = (1 << 7),
/* Flag used to indicate that stroke is used for fill close and must use
* fill color for stroke and no fill area */
GP_STROKE_NOFILL = (1 << 8),
+ /* Tag for update geometry */
+ GP_STROKE_TAG = (1 << 14),
/* only for use with stroke-buffer (while drawing eraser) */
GP_STROKE_ERASER = (1 << 15),
} eGPDstroke_Flag;
@@ -278,8 +285,13 @@ typedef enum eGPDstroke_Caps {
/* Runtime temp data for bGPDframe */
typedef struct bGPDframe_Runtime {
- /** Parent matrix for drawing. */
- float parent_obmat[4][4];
+ /** Index of this frame in the listbase of frames. */
+ int frameid;
+ /** Onion offset from active frame. 0 if not onion. INT_MAX to bypass frame. */
+ int onion_id;
+
+ /** Original frame (used to dereference evaluated data) */
+ struct bGPDframe *gpf_orig;
} bGPDframe_Runtime;
/* Grease-Pencil Annotations - 'Frame'
@@ -318,6 +330,8 @@ typedef struct bGPDlayer_Runtime {
/** Id for dynamic icon used to show annotation color preview for layer. */
int icon_id;
char _pad[4];
+ /** Original layer (used to dereference evaluated data) */
+ struct bGPDlayer *gpl_orig;
} bGPDlayer_Runtime;
/* Grease-Pencil Annotations - 'Layer' */
@@ -389,6 +403,9 @@ typedef struct bGPDlayer {
float gcolor_next[3];
char _pad1[4];
+ /** Mask Layer name. */
+ char mask_layer[64];
+
bGPDlayer_Runtime runtime;
} bGPDlayer;
@@ -402,6 +419,8 @@ typedef enum eGPDlayer_Flag {
GP_LAYER_ACTIVE = (1 << 2),
/* draw points of stroke for debugging purposes */
GP_LAYER_DRAWDEBUG = (1 << 3),
+ /* Flag used to display in Paint mode only layers with keyframe */
+ GP_LAYER_SOLO_MODE = (1 << 4),
/* for editing in Action Editor */
GP_LAYER_SELECT = (1 << 5),
/* current frame for layer can't be changed */
@@ -410,14 +429,16 @@ typedef enum eGPDlayer_Flag {
GP_LAYER_NO_XRAY = (1 << 7),
/* "volumetric" strokes */
GP_LAYER_VOLUMETRIC = (1 << 10),
+ /* Use Scene lights */
+ GP_LAYER_USE_LIGHTS = (1 << 11),
/* Unlock color */
GP_LAYER_UNLOCK_COLOR = (1 << 12),
/* Mask Layer */
- GP_LAYER_USE_MASK = (1 << 13),
- /* Flag used to display in Paint mode only layers with keyframe */
- GP_LAYER_SOLO_MODE = (1 << 4),
+ GP_LAYER_USE_MASK = (1 << 13), /*TODO: DEPRECATED */
/* Ruler Layer */
GP_LAYER_IS_RULER = (1 << 14),
+ /* Invert masking behavior */
+ GP_LAYER_MASK_INVERT = (1 << 15),
} eGPDlayer_Flag;
/* bGPDlayer->onion_flag */
@@ -445,18 +466,19 @@ typedef struct bGPdata_Runtime {
struct ARegion *ar;
/** Stroke buffer. */
void *sbuffer;
+ /** Temp batches cleared after drawing. */
+ struct GPUBatch *sbuffer_stroke_batch;
+ struct GPUBatch *sbuffer_fill_batch;
+ /** Temp stroke used for drawing. */
+ struct bGPDstroke *sbuffer_gps;
/* GP Object drawing */
- /** Buffer stroke color. */
- float scolor[4];
- /** Buffer fill color. */
- float sfill[4];
- /** Settings for color. */
- short mode;
- /** Buffer style for drawing strokes (used to select shader type). */
- short bstroke_style;
- /** Buffer style for filling areas (used to select shader type). */
- short bfill_style;
+ char _pad[2];
+ /** Material index of the stroke. */
+ short matid;
+ /** Brush size of stroke. */
+ float brush_size;
+ char _pad1[2];
/* Stroke Buffer data (only used during paint-session)
* - buffer must be initialized before use, but freed after
@@ -469,11 +491,18 @@ typedef struct bGPdata_Runtime {
/** Number of total elements available in cache. */
int sbuffer_size;
+ /** Vertex Color applied to point (while drawing). */
+ float vert_color[4];
+
+ /** Vertex Color applied to Fill (while drawing). */
+ float vert_color_fill[4];
+
/** Number of control-points for stroke. */
int tot_cp_points;
- char _pad_[4];
/** Array of control-points for stroke. */
bGPDcontrolpoint *cp_points;
+ /** Runtime grease pencil drawing data */
+ struct GpencilBatchCache *gpencil_cache;
} bGPdata_Runtime;
/* grid configuration */
@@ -495,7 +524,7 @@ typedef struct bGPdata {
struct AnimData *adt;
/* Grease-Pencil data */
- /** BGPDlayers. */
+ /** bGPDlayer. */
ListBase layers;
/** Settings for this data-block. */
int flag;
@@ -595,8 +624,6 @@ typedef enum eGPdata_Flag {
/* Main flag to switch onion skinning on/off */
GP_DATA_SHOW_ONIONSKINS = (1 << 9),
- /* Draw a green and red point to indicate start and end of the stroke */
- GP_DATA_SHOW_DIRECTION = (1 << 10),
/* Batch drawing cache need to be recalculated */
GP_DATA_CACHE_IS_DIRTY = (1 << 11),
@@ -614,17 +641,9 @@ typedef enum eGPdata_Flag {
/* Allow edit several frames at the same time */
GP_DATA_STROKE_MULTIEDIT = (1 << 16),
- /* Force fill recalc if use deformation modifiers.
- * this is required if the stroke is deformed and the triangulation data is
- * not valid.
- */
- GP_DATA_STROKE_FORCE_RECALC = (1 << 17),
-
/* Vertex Paint Mode - Toggle paint mode */
GP_DATA_STROKE_VERTEXMODE = (1 << 18),
- /* Use adaptive UV scales */
- GP_DATA_UV_ADAPTIVE = (1 << 19),
/* Autolock not active layers */
GP_DATA_AUTOLOCK_LAYERS = (1 << 20),
/* Internal flag for python update */
@@ -679,7 +698,7 @@ typedef enum eGP_DrawMode {
((gpd) && \
(gpd->flag & (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | \
GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE)))
-#define GPENCIL_EDIT_MODE(gpd) ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE))
+#define GPENCIL_EDIT_MODE(gpd) ((gpd) && ((gpd)->flag & GP_DATA_STROKE_EDITMODE))
#define GPENCIL_ANY_EDIT_MODE(gpd) \
((gpd) && (gpd->flag & \
(GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | GP_DATA_STROKE_WEIGHTMODE)))
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 1d1ccef8846..0db7feffa99 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -72,15 +72,14 @@ typedef struct MaterialGPencilStyle {
/** Factor used to define shader behavior (several uses). */
float mix_factor;
/** Angle used for gradients orientation. */
- float gradient_angle;
+ float gradient_angle DNA_DEPRECATED;
/** Radius for radial gradients. */
- float gradient_radius;
- /** Cheesboard size. */
- float pattern_gridsize;
+ float gradient_radius DNA_DEPRECATED;
+ char _pad2[4];
/** Uv coordinates scale. */
- float gradient_scale[2];
+ float gradient_scale[2] DNA_DEPRECATED;
/** Factor to shift filling in 2d space. */
- float gradient_shift[2];
+ float gradient_shift[2] DNA_DEPRECATED;
/** Angle used for texture orientation. */
float texture_angle;
/** Texture scale (separated of uv scale). */
@@ -107,35 +106,35 @@ typedef struct MaterialGPencilStyle {
/* MaterialGPencilStyle->flag */
typedef enum eMaterialGPencilStyle_Flag {
/* Fill Texture is a pattern */
- GP_STYLE_FILL_PATTERN = (1 << 0),
+ GP_MATERIAL_FILL_PATTERN = (1 << 0),
/* don't display color */
- GP_STYLE_COLOR_HIDE = (1 << 1),
+ GP_MATERIAL_HIDE = (1 << 1),
/* protected from further editing */
- GP_STYLE_COLOR_LOCKED = (1 << 2),
+ GP_MATERIAL_LOCKED = (1 << 2),
/* do onion skinning */
- GP_STYLE_COLOR_ONIONSKIN = (1 << 3),
+ GP_MATERIAL_ONIONSKIN = (1 << 3),
/* clamp texture */
- GP_STYLE_COLOR_TEX_CLAMP = (1 << 4),
+ GP_MATERIAL_TEX_CLAMP = (1 << 4),
/* mix fill texture */
- GP_STYLE_FILL_TEX_MIX = (1 << 5),
+ GP_MATERIAL_FILL_TEX_MIX = (1 << 5),
/* Flip fill colors */
- GP_STYLE_COLOR_FLIP_FILL = (1 << 6),
+ GP_MATERIAL_FLIP_FILL = (1 << 6),
/* Stroke Texture is a pattern */
- GP_STYLE_STROKE_PATTERN = (1 << 7),
+ GP_MATERIAL_STROKE_PATTERN = (1 << 7),
/* Stroke show main switch */
- GP_STYLE_STROKE_SHOW = (1 << 8),
- /* Fill show main switch */
- GP_STYLE_FILL_SHOW = (1 << 9),
+ GP_MATERIAL_STROKE_SHOW = (1 << 8),
+ /* Fill show main switch */
+ GP_MATERIAL_FILL_SHOW = (1 << 9),
/* mix stroke texture */
- GP_STYLE_STROKE_TEX_MIX = (1 << 11),
+ GP_MATERIAL_STROKE_TEX_MIX = (1 << 11),
/* disable stencil clipping (overlap) */
- GP_STYLE_DISABLE_STENCIL = (1 << 12),
+ GP_MATERIAL_DISABLE_STENCIL = (1 << 12),
} eMaterialGPencilStyle_Flag;
typedef enum eMaterialGPencilStyle_Mode {
- GP_STYLE_MODE_LINE = 0, /* line */
- GP_STYLE_MODE_DOTS = 1, /* dots */
- GP_STYLE_MODE_BOX = 2, /* rectangles */
+ GP_MATERIAL_MODE_LINE = 0,
+ GP_MATERIAL_MODE_DOT = 1,
+ GP_MATERIAL_MODE_SQUARE = 2,
} eMaterialGPencilStyle_Mode;
typedef struct Material {
@@ -332,28 +331,28 @@ enum {
/* Grease Pencil Stroke styles */
enum {
- GP_STYLE_STROKE_STYLE_SOLID = 0,
- GP_STYLE_STROKE_STYLE_TEXTURE,
+ GP_MATERIAL_STROKE_STYLE_SOLID = 0,
+ GP_MATERIAL_STROKE_STYLE_TEXTURE,
};
/* Grease Pencil Fill styles */
enum {
- GP_STYLE_FILL_STYLE_SOLID = 0,
- GP_STYLE_FILL_STYLE_GRADIENT,
- GP_STYLE_FILL_STYLE_CHECKER,
- GP_STYLE_FILL_STYLE_TEXTURE,
+ GP_MATERIAL_FILL_STYLE_SOLID = 0,
+ GP_MATERIAL_FILL_STYLE_GRADIENT,
+ GP_MATERIAL_FILL_STYLE_CHECKER, /* DEPRECATED (only for convert old files) */
+ GP_MATERIAL_FILL_STYLE_TEXTURE,
};
/* Grease Pencil Gradient Types */
enum {
- GP_STYLE_GRADIENT_LINEAR = 0,
- GP_STYLE_GRADIENT_RADIAL,
+ GP_MATERIAL_GRADIENT_LINEAR = 0,
+ GP_MATERIAL_GRADIENT_RADIAL,
};
/* Grease Pencil Follow Drawing Modes */
enum {
- GP_STYLE_FOLLOW_PATH = 0,
- GP_STYLE_FOLLOW_OBJ,
- GP_STYLE_FOLLOW_FIXED,
+ GP_MATERIAL_FOLLOW_PATH = 0,
+ GP_MATERIAL_FOLLOW_OBJ,
+ GP_MATERIAL_FOLLOW_FIXED,
};
#endif
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index cbed2af7df2..06876048d98 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -167,6 +167,18 @@ typedef struct Object_Runtime {
struct Mesh *mesh_deform_eval;
/**
+ * Original grease pencil bGPdata pointer, before object->data was changed to point
+ * to gpd_eval.
+ * Is assigned by dependency graph's copy-on-write evaluation.
+ */
+ struct bGPdata *gpd_orig;
+ /**
+ * bGPdata structure created during object evaluation.
+ * It has all modifiers applied.
+ */
+ struct bGPdata *gpd_eval;
+
+ /**
* This is a mesh representation of corresponding object.
* It created when Python calls `object.to_mesh()`.
*/
@@ -175,14 +187,6 @@ typedef struct Object_Runtime {
/** Runtime evaluated curve-specific data, not stored in the file. */
struct CurveCache *curve_cache;
- /** Runtime grease pencil drawing data */
- struct GpencilBatchCache *gpencil_cache;
- /** Runtime grease pencil total layers used for evaluated data created by modifiers */
- int gpencil_tot_layers;
- char _pad4[4];
- /** Runtime grease pencil evaluated data created by modifiers */
- struct bGPDframe *gpencil_evaluated_frames;
-
unsigned short local_collections_bits;
short _pad2[3];
} Object_Runtime;
@@ -552,6 +556,8 @@ enum {
OB_DRAWTRANSP = 1 << 7,
OB_DRAW_ALL_EDGES = 1 << 8, /* only for meshes currently */
OB_DRAW_NO_SHADOW_CAST = 1 << 9,
+ /* Enable lights for grease pencil. */
+ OB_USE_GPENCIL_LIGHTS = 1 << 10,
};
/* empty_drawtype: no flags */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 294486bdf75..486a2cf455e 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -2278,14 +2278,12 @@ typedef enum eGPencil_SimplifyFlags {
SIMPLIFY_GPENCIL_FILL = (1 << 2),
/* Simplify modifier on viewport */
SIMPLIFY_GPENCIL_MODIFIER = (1 << 3),
- /* Remove fill external line */
- SIMPLIFY_GPENCIL_REMOVE_FILL_LINE = (1 << 4),
/* Simplify Shader FX */
SIMPLIFY_GPENCIL_FX = (1 << 5),
- /* Simplify layer blending */
- SIMPLIFY_GPENCIL_BLEND = (1 << 6),
/* Simplify layer tint */
SIMPLIFY_GPENCIL_TINT = (1 << 7),
+ /* Simplify Antialiasing */
+ SIMPLIFY_GPENCIL_AA = (1 << 8),
} eGPencil_SimplifyFlags;
/* ToolSettings.gpencil_*_align - Stroke Placement mode flags */
diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h
index 6cda58a3279..b6a82854f83 100644
--- a/source/blender/makesdna/DNA_shader_fx_types.h
+++ b/source/blender/makesdna/DNA_shader_fx_types.h
@@ -34,7 +34,7 @@ typedef enum ShaderFxType {
eShaderFxType_None = 0,
eShaderFxType_Blur = 1,
eShaderFxType_Flip = 2,
- eShaderFxType_Light = 3,
+ eShaderFxType_Light_deprecated = 3, /* DEPRECATED (replaced by scene lights) */
eShaderFxType_Pixel = 4,
eShaderFxType_Swirl = 5,
eShaderFxType_Wave = 6,
@@ -156,19 +156,6 @@ typedef enum eGlowShaderFx_Flag {
FX_GLOW_USE_ALPHA = (1 << 0),
} eGlowShaderFx_Flag;
-typedef struct LightShaderFxData {
- ShaderFxData shaderfx;
- struct Object *object;
- /** Flags. */
- int flag;
- float energy;
- float ambient;
- /** Internal, not visible in rna. */
- float loc[4];
- char _pad[4];
- ShaderFxData_Runtime runtime;
-} LightShaderFxData;
-
typedef struct PixelShaderFxData {
ShaderFxData shaderfx;
/** Last element used for shader only. */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index d741f22cc4f..f99699e0bcc 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -842,8 +842,7 @@ typedef struct UserDef {
short pie_menu_threshold;
short opensubdiv_compute_type;
- /** #eMultiSample_Type, amount of samples for Grease Pencil. */
- short gpencil_multisamples;
+ short _pad6;
char factor_display_type;
@@ -1227,7 +1226,7 @@ typedef enum eNdof_Flag {
#define NDOF_PIXELS_PER_SECOND 600.0f
-/** UserDef.ogl_multisamples and gpencil_multisamples */
+/** UserDef.ogl_multisamples */
typedef enum eMultiSample_Type {
USER_MULTISAMPLE_NONE = 0,
USER_MULTISAMPLE_2 = 2,
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 7ff2d76bbf4..3aaadd9fa96 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -400,13 +400,15 @@ typedef struct View3D {
#define V3D_FLAG2_UNUSED_15 (1 << 15) /* cleared */
/** #View3D.gp_flag (short) */
-#define V3D_GP_SHOW_PAPER (1 << 0) /* Activate paper to cover all viewport */
-#define V3D_GP_SHOW_GRID (1 << 1) /* Activate paper grid */
+#define V3D_GP_FADE_OBJECTS (1 << 0) /* Fade all non GP objects */
+#define V3D_GP_SHOW_GRID (1 << 1) /* Activate paper grid */
#define V3D_GP_SHOW_EDIT_LINES (1 << 2)
#define V3D_GP_SHOW_MULTIEDIT_LINES (1 << 3)
#define V3D_GP_SHOW_ONION_SKIN (1 << 4) /* main switch at view level */
#define V3D_GP_FADE_NOACTIVE_LAYERS (1 << 5) /* fade layers not active */
#define V3D_GP_FADE_NOACTIVE_GPENCIL (1 << 6) /* Fade other GPencil objects */
+#define V3D_GP_SHOW_STROKE_DIRECTION (1 << 7) /* Show Strokes Directions */
+#define V3D_GP_SHOW_MATERIAL_NAME (1 << 8) /* Show Material names */
/** #View3DShading.light */
enum {
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 125f0546adf..ffe8845b6d5 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -141,6 +141,7 @@ static EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = {
# include "BKE_icons.h"
# include "DEG_depsgraph.h"
+# include "DEG_depsgraph_build.h"
static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -148,11 +149,23 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+static void rna_GPencil_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->owner_id);
+
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
+}
+
static void rna_GPencil_uv_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
/* Force to recalc the UVs. */
bGPDstroke *gps = (bGPDstroke *)ptr->data;
- gps->tot_triangles = 0;
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
@@ -182,10 +195,10 @@ static void rna_GPencil_strokes_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
{
bGPdata *gpd = (bGPdata *)ptr->owner_id;
if (gpd) {
- 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) {
- BKE_gpencil_triangulate_stroke_fill(gpd, gps);
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ BKE_gpencil_stroke_fill_triangulate(gps);
}
}
}
@@ -393,7 +406,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr,
static int rna_GPencil_active_layer_index_get(PointerRNA *ptr)
{
bGPdata *gpd = (bGPdata *)ptr->owner_id;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return BLI_findindex(&gpd->layers, gpl);
}
@@ -403,7 +416,7 @@ static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value)
bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDlayer *gpl = BLI_findlink(&gpd->layers, value);
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
/* Now do standard updates... */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
@@ -472,6 +485,25 @@ static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
BKE_animdata_fix_paths_rename_all(&gpd->id, "layers", oldname, gpl->info);
}
+static void rna_GPencil_layer_mask_set(PointerRNA *ptr, const bool value)
+{
+ bGPDlayer *gpl = ptr->data;
+
+ const bool use_mask = gpl->flag & GP_LAYER_USE_MASK;
+
+ /* Cycle through the 3 options */
+ if (value != use_mask) {
+ if (use_mask && (gpl->flag & GP_LAYER_MASK_INVERT) == 0) {
+ /* Switch to invert mask instead of removing the masking. */
+ gpl->flag |= GP_LAYER_MASK_INVERT;
+ }
+ else {
+ SET_FLAG_FROM_TEST(gpl->flag, value, GP_LAYER_USE_MASK);
+ gpl->flag &= ~GP_LAYER_MASK_INVERT;
+ }
+ }
+}
+
static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd,
const bGPDspoint *pt,
bGPDlayer **r_gpl,
@@ -568,7 +600,8 @@ static void rna_GPencil_stroke_point_add(
stroke->totpoints += count;
- stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(stroke);
gpd->flag |= GP_DATA_PYTHON_UPDATED;
DEG_id_tag_update(&gpd->id,
@@ -629,7 +662,8 @@ static void rna_GPencil_stroke_point_pop(ID *id,
MEM_freeN(pt_dvert);
}
- stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(stroke);
gpd->flag |= GP_DATA_PYTHON_UPDATED;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -676,7 +710,7 @@ static void rna_GPencil_stroke_close(ID *id,
return;
}
- BKE_gpencil_close_stroke(stroke);
+ BKE_gpencil_stroke_close(stroke);
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -714,14 +748,14 @@ static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer,
{
bGPDframe *frame;
- if (BKE_gpencil_layer_find_frame(layer, frame_number)) {
+ if (BKE_gpencil_layer_frame_find(layer, frame_number)) {
BKE_reportf(reports, RPT_ERROR, "Frame already exists on this frame number %d", frame_number);
return NULL;
}
frame = BKE_gpencil_frame_addnew(layer, frame_number);
if (active) {
- layer->actframe = BKE_gpencil_layer_getframe(layer, frame_number, GP_GETFRAME_USE_PREV);
+ layer->actframe = BKE_gpencil_layer_frame_get(layer, frame_number, GP_GETFRAME_USE_PREV);
}
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
@@ -736,7 +770,7 @@ static void rna_GPencil_frame_remove(bGPDlayer *layer, ReportList *reports, Poin
return;
}
- BKE_gpencil_layer_delframe(layer, frame);
+ BKE_gpencil_layer_frame_delete(layer, frame);
RNA_POINTER_INVALIDATE(frame_ptr);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
@@ -746,7 +780,7 @@ static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src)
{
bGPDframe *frame = BKE_gpencil_frame_duplicate(src);
- while (BKE_gpencil_layer_find_frame(layer, frame->framenum)) {
+ while (BKE_gpencil_layer_frame_find(layer, frame->framenum)) {
frame->framenum++;
}
@@ -891,14 +925,14 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Select", "Point is selected for viewport editing");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- /* Mix color. */
- prop = RNA_def_property(srna, "mix_color", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "mix_color");
+ /* Vertex color. */
+ prop = RNA_def_property(srna, "vertex_color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "vert_color");
RNA_def_property_array(prop, 4);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
- prop, "Mix Color", "Color used to mix with point color to get final color");
+ prop, "Vertex Color", "Color used to mix with point color to get final color");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
}
@@ -972,27 +1006,6 @@ static void rna_def_gpencil_triangle(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "verts[2]");
RNA_def_property_ui_text(prop, "v3", "Third triangle vertex index");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- /* texture coord for point v1 */
- prop = RNA_def_property(srna, "uv1", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_float_sdna(prop, NULL, "uv[0]");
- RNA_def_property_array(prop, 2);
- RNA_def_property_ui_text(prop, "uv1", "First triangle vertex texture coordinates");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- /* texture coord for point v2 */
- prop = RNA_def_property(srna, "uv2", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_float_sdna(prop, NULL, "uv[1]");
- RNA_def_property_array(prop, 2);
- RNA_def_property_ui_text(prop, "uv2", "Second triangle vertex texture coordinates");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- /* texture coord for point v3 */
- prop = RNA_def_property(srna, "uv3", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_float_sdna(prop, NULL, "uv[2]");
- RNA_def_property_array(prop, 2);
- RNA_def_property_ui_text(prop, "uv3", "Third triangle vertex texture coordinates");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
static void rna_def_gpencil_mvert_group(BlenderRNA *brna)
@@ -1168,14 +1181,14 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna)
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_uv_update");
- /* Mix Vertex Color for Fill. */
- prop = RNA_def_property(srna, "mix_color_fill", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "mix_color_fill");
+ /* Vertex Color for Fill. */
+ prop = RNA_def_property(srna, "vertex_color_fill", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "vert_color_fill");
RNA_def_property_array(prop, 4);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
- prop, "Mix Fill Color", "Color used to mix with fill color to get final color");
+ prop, "Vertex Fill Color", "Color used to mix with fill color to get final color");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
}
@@ -1365,7 +1378,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Tint Color */
- prop = RNA_def_property(srna, "tint_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "tint_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "tintcolor");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -1373,14 +1386,14 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Tint factor */
- prop = RNA_def_property(srna, "tint_factor", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "tint_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "tintcolor[3]");
RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_property_ui_text(prop, "Tint Factor", "Factor of tinting color");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Vertex Paint opacity factor */
- prop = RNA_def_property(srna, "vertex_paint_opacity", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "vertex_paint_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "vertex_paint_opacity");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_default(prop, 1.0f);
@@ -1464,6 +1477,11 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Blend Mode", "Blend mode");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ prop = RNA_def_property(srna, "mask_layer_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "mask_layer");
+ RNA_def_property_ui_text(prop, "Mask", "Name of the masking layer");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE);
@@ -1499,11 +1517,25 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop, "Disallow Locked Materials Editing", "Avoids editing locked materials in the layer");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+# /* TODO: Deprecated */
prop = RNA_def_property(srna, "mask_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_MASK);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencil_layer_mask_set");
+ RNA_def_property_ui_text(prop, "Mask Layer", "Mask pixels from underlying layers drawing");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+#
+ prop = RNA_def_property(srna, "invert_mask", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_MASK_INVERT);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Invert Mask", "Invert the masking behavior of the layer");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_lights", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_LIGHTS);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
- prop, "Mask Layer", "Remove any pixel outside underlying layers drawing");
+ prop, "Use Lights", "Enable the use of lights on stroke and fill materials");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* solo mode: Only display frames with keyframe */
@@ -1551,7 +1583,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Parent", "Parent Object");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_dependency_update");
/* parent type */
prop = RNA_def_property(srna, "parent_type", PROP_ENUM, PROP_NONE);
@@ -1799,14 +1831,6 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_update(
prop, NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL, "rna_GPencil_update");
- prop = RNA_def_property(srna, "show_stroke_direction", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_SHOW_DIRECTION);
- RNA_def_property_ui_text(prop,
- "Show Direction",
- "Show stroke drawing direction with a bigger green dot (start) "
- "and smaller red dot (end) points");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
prop = RNA_def_property(srna, "stroke_thickness_space", PROP_ENUM, PROP_NONE); /* as an enum */
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, stroke_thickness_items);
@@ -1832,20 +1856,6 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
"(keyframes must be selected to be included)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- prop = RNA_def_property(srna, "use_force_fill_recalc", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_STROKE_FORCE_RECALC);
- RNA_def_property_ui_text(
- prop,
- "Force Fill Update",
- "Force recalc of fill data after use deformation modifiers (reduce FPS)");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "use_adaptive_uv", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_UV_ADAPTIVE);
- RNA_def_property_ui_text(
- prop, "Adaptive UV", "Automatic UVs are calculated depending of the stroke size");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_strokes_update");
-
prop = RNA_def_property(srna, "use_autolock_layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_AUTOLOCK_LAYERS);
RNA_def_property_ui_text(
@@ -1892,7 +1902,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "gcolor_prev");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -1901,7 +1911,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_update(
prop, NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL, "rna_GPencil_update");
- prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "gcolor_next");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index cb51b8c8b42..fe5e8f5bdc1 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -144,16 +144,6 @@ static const EnumPropertyItem modifier_modify_color_items[] = {
{0, NULL, 0, NULL, NULL},
};
-static const EnumPropertyItem modifier_opacity_mode_items[] = {
- {GP_OPACITY_MODE_MATERIAL,
- "MATERIAL",
- 0,
- "Material",
- "Modify opacity using alpha channel of material"},
- {GP_OPACITY_MODE_STRENGTH, "STRENGTH", 0, "Strength", "Modify opacity using point strength"},
- {0, NULL, 0, NULL, NULL},
-};
-
static const EnumPropertyItem modifier_gphook_falloff_items[] = {
{eGPHook_Falloff_None, "NONE", 0, "No Falloff", ""},
{eGPHook_Falloff_Curve, "CURVE", 0, "Curve", ""},
@@ -969,7 +959,7 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Material", "Material name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_array(prop, 3);
@@ -982,11 +972,6 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Factor", "Factor for mixing color");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "create_materials", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_CREATE_COLORS);
- RNA_def_property_ui_text(prop, "Create Materials", "When apply modifier, create new material");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "pass_index");
RNA_def_property_range(prop, 0, 100);
@@ -1147,11 +1132,6 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Value", "Color Value");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "create_materials", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_CREATE_COLORS);
- RNA_def_property_ui_text(prop, "Create Materials", "When apply modifier, create new material");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "pass_index");
RNA_def_property_range(prop, 0, 100);
@@ -1200,11 +1180,6 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mode", "Set what colors of the stroke are affected");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "opacity_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, modifier_opacity_mode_items);
- RNA_def_property_ui_text(prop, "Opacity Mode", "Set what mode used to define opacity");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "layername");
RNA_def_property_ui_text(prop, "Layer", "Layer name");
@@ -1227,11 +1202,6 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Factor", "Factor of Opacity");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "create_materials", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_CREATE_COLORS);
- RNA_def_property_ui_text(prop, "Create Materials", "When apply modifier, create new material");
- RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
-
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "pass_index");
RNA_def_property_range(prop, 0, 100);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index a29031900ac..4fb55f02645 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -411,42 +411,45 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
/* mode type styles */
static EnumPropertyItem gpcolordata_mode_types_items[] = {
- {GP_STYLE_MODE_LINE, "LINE", 0, "Line", "Draw strokes using a continuous line"},
- {GP_STYLE_MODE_DOTS, "DOTS", 0, "Dots", "Draw strokes using separated dots"},
- {GP_STYLE_MODE_BOX, "BOX", 0, "Boxes", "Draw strokes using separated rectangle boxes"},
+ {GP_MATERIAL_MODE_LINE, "LINE", 0, "Line", "Draw strokes using a continuous line"},
+ {GP_MATERIAL_MODE_DOT, "DOTS", 0, "Dots", "Draw strokes using separated dots"},
+ {GP_MATERIAL_MODE_SQUARE, "BOX", 0, "Squares", "Draw strokes using separated squares"},
{0, NULL, 0, NULL, NULL},
};
/* stroke styles */
static EnumPropertyItem stroke_style_items[] = {
- {GP_STYLE_STROKE_STYLE_SOLID, "SOLID", 0, "Solid", "Draw strokes with solid color"},
- {GP_STYLE_STROKE_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Draw strokes using texture"},
+ {GP_MATERIAL_STROKE_STYLE_SOLID, "SOLID", 0, "Solid", "Draw strokes with solid color"},
+ {GP_MATERIAL_STROKE_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Draw strokes using texture"},
{0, NULL, 0, NULL, NULL},
};
/* fill styles */
static EnumPropertyItem fill_style_items[] = {
- {GP_STYLE_FILL_STYLE_SOLID, "SOLID", 0, "Solid", "Fill area with solid color"},
- {GP_STYLE_FILL_STYLE_GRADIENT, "GRADIENT", 0, "Gradient", "Fill area with gradient color"},
- {GP_STYLE_FILL_STYLE_CHECKER,
- "CHECKER",
+ {GP_MATERIAL_FILL_STYLE_SOLID, "SOLID", 0, "Solid", "Fill area with solid color"},
+ {GP_MATERIAL_FILL_STYLE_GRADIENT,
+ "GRADIENT",
0,
- "Checker Board",
- "Fill area with checkerboard pattern"},
- {GP_STYLE_FILL_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Fill area with image texture"},
+ "Gradient",
+ "Fill area with gradient color"},
+ {GP_MATERIAL_FILL_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Fill area with image texture"},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem fill_gradient_items[] = {
- {GP_STYLE_GRADIENT_LINEAR, "LINEAR", 0, "Linear", "Fill area with gradient color"},
- {GP_STYLE_GRADIENT_RADIAL, "RADIAL", 0, "Radial", "Fill area with radial gradient"},
+ {GP_MATERIAL_GRADIENT_LINEAR, "LINEAR", 0, "Linear", "Fill area with gradient color"},
+ {GP_MATERIAL_GRADIENT_RADIAL, "RADIAL", 0, "Radial", "Fill area with radial gradient"},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem alignment_draw_items[] = {
- {GP_STYLE_FOLLOW_PATH, "PATH", 0, "Path", "Follow stroke drawing path and object rotation"},
- {GP_STYLE_FOLLOW_OBJ, "OBJECT", 0, "Object", "Follow object rotation only"},
- {GP_STYLE_FOLLOW_FIXED,
+ {GP_MATERIAL_FOLLOW_PATH,
+ "PATH",
+ 0,
+ "Path",
+ "Follow stroke drawing path and object rotation"},
+ {GP_MATERIAL_FOLLOW_OBJ, "OBJECT", 0, "Object", "Follow object rotation only"},
+ {GP_MATERIAL_FOLLOW_FIXED,
"FIXED",
0,
"Fixed",
@@ -459,7 +462,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Grease Pencil Color", "");
RNA_def_struct_path_func(srna, "rna_GpencilColorData_path");
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "stroke_rgba");
RNA_def_property_array(prop, 4);
@@ -467,7 +470,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* Fill Drawing Color */
- prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "fill_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "fill_rgba");
RNA_def_property_array(prop, 4);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -475,7 +478,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* Secondary Drawing Color */
- prop = RNA_def_property(srna, "mix_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "mix_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "mix_rgba");
RNA_def_property_array(prop, 4);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -483,51 +486,17 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* Mix factor */
- prop = RNA_def_property(srna, "mix_factor", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "mix_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "mix_factor");
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Mix", "Mix Adjustment Factor");
+ RNA_def_property_ui_text(prop, "Mix", "Mix Factor");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* Stroke Mix factor */
- prop = RNA_def_property(srna, "mix_stroke_factor", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "mix_stroke_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "mix_stroke_factor");
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Mix", "Mix Stroke Color");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- /* Scale factor for uv coordinates */
- prop = RNA_def_property(srna, "pattern_scale", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_float_sdna(prop, NULL, "gradient_scale");
- RNA_def_property_array(prop, 2);
- RNA_def_property_ui_text(prop, "Scale", "Scale Factor for UV coordinates");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- /* Shift factor to move pattern filling in 2d space */
- prop = RNA_def_property(srna, "pattern_shift", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_float_sdna(prop, NULL, "gradient_shift");
- RNA_def_property_array(prop, 2);
- RNA_def_property_ui_text(prop, "Shift", "Shift filling pattern in 2d space");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- /* Gradient angle */
- prop = RNA_def_property(srna, "pattern_angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_float_sdna(prop, NULL, "gradient_angle");
- RNA_def_property_ui_text(prop, "Angle", "Pattern Orientation Angle");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- /* Gradient radius */
- prop = RNA_def_property(srna, "pattern_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "gradient_radius");
- RNA_def_property_range(prop, 0.0001f, 10.0f);
- RNA_def_property_ui_text(prop, "Radius", "Pattern Radius");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- /* Box size */
- prop = RNA_def_property(srna, "pattern_gridsize", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "pattern_gridsize");
- RNA_def_property_range(prop, 0.0001f, 10.0f);
- RNA_def_property_ui_text(prop, "Size", "Box Size");
+ RNA_def_property_ui_text(prop, "Mix", "Mix Stroke Factor");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
/* Texture angle */
@@ -566,68 +535,48 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_HIDE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_HIDE);
RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
RNA_def_property_ui_text(prop, "Hide", "Set color Visibility");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_LOCKED);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_LOCKED);
RNA_def_property_ui_icon(prop, ICON_UNLOCKED, 1);
RNA_def_property_ui_text(
prop, "Locked", "Protect color from further editing and/or frame changes");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
prop = RNA_def_property(srna, "ghost", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_ONIONSKIN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_ONIONSKIN);
RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0);
RNA_def_property_ui_text(
prop, "Show in Ghosts", "Display strokes using this color when showing onion skins");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
prop = RNA_def_property(srna, "texture_clamp", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_TEX_CLAMP);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_TEX_CLAMP);
RNA_def_property_ui_text(prop, "Clamp", "Do not repeat texture and clamp to one instance only");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
- prop = RNA_def_property(srna, "use_fill_texture_mix", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_FILL_TEX_MIX);
- RNA_def_property_ui_text(prop, "Mix Texture", "Mix texture image with filling color");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- prop = RNA_def_property(srna, "use_stroke_texture_mix", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_STROKE_TEX_MIX);
- RNA_def_property_ui_text(prop, "Mix Texture", "Mix texture image with stroke color");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
prop = RNA_def_property(srna, "flip", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_COLOR_FLIP_FILL);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_FLIP_FILL);
RNA_def_property_ui_text(prop, "Flip", "Flip filling colors");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
- prop = RNA_def_property(srna, "use_stroke_pattern", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_STROKE_PATTERN);
- RNA_def_property_ui_text(prop, "Pattern", "Use Stroke Texture as a pattern to apply color");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
- prop = RNA_def_property(srna, "use_fill_pattern", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_FILL_PATTERN);
- RNA_def_property_ui_text(prop, "Pattern", "Use Fill Texture as a pattern to apply color");
- RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
-
prop = RNA_def_property(srna, "use_overlap_strokes", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_DISABLE_STENCIL);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_DISABLE_STENCIL);
RNA_def_property_ui_text(
prop, "Self Overlap", "Disable stencil and overlap self intersections with alpha materials");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
prop = RNA_def_property(srna, "show_stroke", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_STROKE_SHOW);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_STROKE_SHOW);
RNA_def_property_ui_text(prop, "Show Stroke", "Show stroke lines of this material");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
prop = RNA_def_property(srna, "show_fill", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_STYLE_FILL_SHOW);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MATERIAL_FILL_SHOW);
RNA_def_property_ui_text(prop, "Show Fill", "Show stroke fills of this material");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 69dee01a52b..8fbe83374ae 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -353,6 +353,16 @@ static void rna_MaterialIndex_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
}
}
+static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->owner_id;
+ if (ob && ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
+ }
+}
+
static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16])
{
Object *ob = (Object *)ptr->owner_id;
@@ -3077,6 +3087,13 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display All Edges", "Display all edges for mesh objects");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ prop = RNA_def_property(srna, "use_grease_pencil_lights", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_USE_GPENCIL_LIGHTS);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Use Lights", "Lights affect to grease pencil object");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update");
+
prop = RNA_def_property(srna, "show_transparent", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWTRANSP);
RNA_def_property_ui_text(
@@ -3086,7 +3103,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_in_front", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWXRAY);
RNA_def_property_ui_text(prop, "In Front", "Make the object draw in front of others");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update");
/* pose */
prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 85ca851d220..f42f26698c1 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -734,7 +734,7 @@ static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value)
}
}
-static void rna_Gpencil_extend_selection(bContext *C, PointerRNA *ptr)
+static void rna_Gpencil_extend_selection(bContext *C, PointerRNA *UNUSED(ptr))
{
/* Extend selection to all points in all selected strokes. */
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -768,7 +768,7 @@ static void rna_Gpencil_selectmode_update(bContext *C, PointerRNA *ptr)
rna_Gpencil_extend_selection(C, ptr);
}
-static void rna_Gpencil_mask_point_update(bContext *C, PointerRNA *ptr)
+static void rna_Gpencil_mask_point_update(bContext *UNUSED(C), PointerRNA *ptr)
{
ToolSettings *ts = (ToolSettings *)ptr->data;
@@ -786,7 +786,7 @@ static void rna_Gpencil_mask_stroke_update(bContext *C, PointerRNA *ptr)
rna_Gpencil_extend_selection(C, ptr);
}
-static void rna_Gpencil_mask_segment_update(bContext *C, PointerRNA *ptr)
+static void rna_Gpencil_mask_segment_update(bContext *UNUSED(C), PointerRNA *ptr)
{
ToolSettings *ts = (ToolSettings *)ptr->data;
@@ -6303,7 +6303,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "simplify_gpencil_onplay", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_ON_PLAY);
RNA_def_property_ui_text(
- prop, "Simplify Playback", "Simplify Grease Pencil only during animation playback");
+ prop, "Playback Only", "Simplify Grease Pencil only during animation playback");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "simplify_gpencil_antialiasing", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_AA);
+ RNA_def_property_ui_text(prop, "Antialiasing", "Use Antialiasing to smooth stroke edges");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "simplify_gpencil_view_fill", PROP_BOOLEAN, PROP_NONE);
@@ -6311,26 +6316,15 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Fill", "Display fill strokes in the viewport");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
- prop = RNA_def_property(srna, "simplify_gpencil_remove_lines", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(
- prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_REMOVE_FILL_LINE);
- RNA_def_property_ui_text(prop, "Disable Lines", "Display external lines of fill strokes");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "simplify_gpencil_view_modifier", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "simplify_gpencil_modifier", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(
prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_MODIFIER);
- RNA_def_property_ui_text(prop, "Disable Modifiers", "Display modifiers in the viewport");
+ RNA_def_property_ui_text(prop, "Modifiers", "Display modifiers");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "simplify_gpencil_shader_fx", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_FX);
- RNA_def_property_ui_text(prop, "Simplify Shaders", "Display Shader FX");
- RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
- prop = RNA_def_property(srna, "simplify_gpencil_blend", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_BLEND);
- RNA_def_property_ui_text(prop, "Layers Blending", "Display blend layers");
+ RNA_def_property_ui_text(prop, "ShadersFX", "Display Shader FX");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "simplify_gpencil_tint", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index b8d5e09d112..3edb060071f 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -528,11 +528,6 @@ static char *rna_GPencilSculptSettings_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("tool_settings.gpencil_sculpt");
}
-static char *rna_GPencilSculptBrush_path(PointerRNA *UNUSED(ptr))
-{
- return BLI_strdup("tool_settings.gpencil_sculpt.brush");
-}
-
static char *rna_GPencilSculptGuide_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.gpencil_sculpt.guide");
@@ -1374,6 +1369,8 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ UNUSED_VARS(prop_direction_items);
+
StructRNA *srna;
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
index cd4e027ce7c..1d8fd163011 100644
--- a/source/blender/makesrna/intern/rna_shader_fx.c
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -52,7 +52,6 @@ const EnumPropertyItem rna_enum_object_shaderfx_type_items[] = {
"Apply different tint effects"},
{eShaderFxType_Flip, "FX_FLIP", ICON_SHADERFX, "Flip", "Flip image"},
{eShaderFxType_Glow, "FX_GLOW", ICON_SHADERFX, "Glow", "Create a glow effect"},
- {eShaderFxType_Light, "FX_LIGHT", ICON_SHADERFX, "Light", "Simulate illumination"},
{eShaderFxType_Pixel, "FX_PIXEL", ICON_SHADERFX, "Pixelate", "Pixelate image"},
{eShaderFxType_Rim, "FX_RIM", ICON_SHADERFX, "Rim", "Add a rim to the image"},
{eShaderFxType_Shadow, "FX_SHADOW", ICON_SHADERFX, "Shadow", "Create a shadow effect"},
@@ -117,11 +116,10 @@ static StructRNA *rna_ShaderFx_refine(struct PointerRNA *ptr)
return &RNA_ShaderFxFlip;
case eShaderFxType_Glow:
return &RNA_ShaderFxGlow;
- case eShaderFxType_Light:
- return &RNA_ShaderFxLight;
/* Default */
case eShaderFxType_None:
case NUM_SHADER_FX_TYPES:
+ default:
return &RNA_ShaderFx;
}
@@ -192,7 +190,6 @@ static void shaderfx_object_set(Object *self, Object **ob_p, int type, PointerRN
shaderfx_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \
}
-RNA_FX_OBJECT_SET(Light, object, OB_EMPTY);
RNA_FX_OBJECT_SET(Shadow, object, OB_EMPTY);
RNA_FX_OBJECT_SET(Swirl, object, OB_EMPTY);
@@ -256,14 +253,14 @@ static void rna_def_shader_fx_colorize(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Factor", "Mix factor");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "low_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "low_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "low_color");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Low Color", "First color used for effect");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "high_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "high_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "high_color");
RNA_def_property_array(prop, 4);
@@ -334,7 +331,7 @@ static void rna_def_shader_fx_pixel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Size", "Pixel size");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgba");
RNA_def_property_array(prop, 4);
@@ -363,14 +360,14 @@ static void rna_def_shader_fx_rim(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Offset", "Offset of the rim");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "rim_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "rim_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rim_rgb");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Rim Color", "Color used for Rim");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "mask_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "mask_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "mask_rgb");
RNA_def_property_array(prop, 3);
@@ -433,7 +430,7 @@ static void rna_def_shader_fx_shadow(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Scale", "Offset of the shadow");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "shadow_rgba");
RNA_def_property_array(prop, 4);
@@ -507,14 +504,14 @@ static void rna_def_shader_fx_glow(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "GlowShaderFxData");
RNA_def_struct_ui_icon(srna, ICON_SHADERFX);
- prop = RNA_def_property(srna, "glow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "glow_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "glow_color");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Glow Color", "Color used for generated glow");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
- prop = RNA_def_property(srna, "select_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "select_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "select_color");
RNA_def_property_array(prop, 3);
@@ -614,38 +611,6 @@ static void rna_def_shader_fx_flip(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
}
-static void rna_def_shader_fx_light(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ShaderFxLight", "ShaderFx");
- RNA_def_struct_ui_text(srna, "Light Effect", "Light effect");
- RNA_def_struct_sdna(srna, "LightShaderFxData");
- RNA_def_struct_ui_icon(srna, ICON_SHADERFX);
-
- prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "energy");
- RNA_def_property_range(prop, 0, FLT_MAX);
- RNA_def_property_ui_range(prop, 1, FLT_MAX, 1, 2);
- RNA_def_property_ui_text(prop, "Energy", "Strength of light source");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
-
- prop = RNA_def_property(srna, "ambient", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "ambient");
- RNA_def_property_range(prop, 0, FLT_MAX);
- RNA_def_property_ui_range(prop, 0, FLT_MAX, 1, 2);
- RNA_def_property_ui_text(prop, "Ambient", "Strength of ambient light source");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Object", "Object to determine light source location");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_LightShaderFx_object_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
-}
-
void RNA_def_shader_fx(BlenderRNA *brna)
{
StructRNA *srna;
@@ -712,7 +677,6 @@ void RNA_def_shader_fx(BlenderRNA *brna)
rna_def_shader_fx_glow(brna);
rna_def_shader_fx_swirl(brna);
rna_def_shader_fx_flip(brna);
- rna_def_shader_fx_light(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index dbb5c9b0084..c6482b9f8d6 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3697,8 +3697,8 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Annotation", "Show annotations for this view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "use_gpencil_paper", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_PAPER);
+ prop = RNA_def_property(srna, "use_gpencil_fade_objects", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_FADE_OBJECTS);
RNA_def_property_ui_text(
prop,
"Fade Objects",
@@ -3716,12 +3716,26 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop, "Fade Layers", "Toggle fading of Grease Pencil layers except the active one");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
- prop = RNA_def_property(srna, "use_gpencil_fade_objects", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "use_gpencil_fade_gp_objects", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_FADE_NOACTIVE_GPENCIL);
RNA_def_property_ui_text(
prop, "Fade Grease Pencil Objects", "Fade Grease Pencil Objects, except the active one");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
+ prop = RNA_def_property(srna, "use_gpencil_show_directions", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_STROKE_DIRECTION);
+ RNA_def_property_ui_text(prop,
+ "Stroke Direction",
+ "Show stroke drawing direction with a bigger green dot (start) "
+ "and smaller red dot (end) points");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
+
+ prop = RNA_def_property(srna, "use_gpencil_show_material_name", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_MATERIAL_NAME);
+ RNA_def_property_ui_text(
+ prop, "Stroke Material Name", "Show material name assigned to each stroke");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
+
prop = RNA_def_property(srna, "gpencil_grid_opacity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "overlay.gpencil_grid_opacity");
RNA_def_property_range(prop, 0.1f, 1.0f);
@@ -3729,7 +3743,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* Paper opacity factor */
- prop = RNA_def_property(srna, "gpencil_paper_opacity", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "gpencil_fade_objects", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "overlay.gpencil_paper_opacity");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Opacity", "Fade factor");
@@ -3747,12 +3761,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
/* show edit lines */
prop = RNA_def_property(srna, "use_gpencil_edit_lines", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_EDIT_LINES);
- RNA_def_property_ui_text(prop, "Show Edit Lines", "Show edit lines when editing strokes");
+ RNA_def_property_ui_text(prop, "Show Edit Lines", "Show Edit Lines when editing strokes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
prop = RNA_def_property(srna, "use_gpencil_multiedit_line_only", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gp_flag", V3D_GP_SHOW_MULTIEDIT_LINES);
- RNA_def_property_ui_text(prop, "Lines Only", "Only show edit lines for additional frames");
+ RNA_def_property_ui_text(prop, "Lines Only", "Show Edit Lines only in multiframe");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
/* main grease pencil onion switch */
@@ -3763,7 +3777,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
/* vertex opacity */
- prop = RNA_def_property(srna, "vertex_opacity", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "vertex_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "vertex_opacity");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Vertex Opacity", "Opacity for edit vertices");
@@ -3771,7 +3785,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_GPencil_update");
/* Vertex Paint opacity factor */
- prop = RNA_def_property(srna, "gpencil_vertex_paint_opacity", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "gpencil_vertex_paint_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "overlay.gpencil_vertex_paint_opacity");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_default(prop, 1.0f);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index b9fb8638c49..7b4298f2467 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -5010,15 +5010,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- static const EnumPropertyItem multi_sample_levels[] = {
- {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"},
- {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample"},
- {USER_MULTISAMPLE_4, "4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample"},
- {USER_MULTISAMPLE_8, "8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample"},
- {USER_MULTISAMPLE_16, "16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample"},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem image_draw_methods[] = {
{IMAGE_DRAW_METHOD_AUTO,
"AUTO",
@@ -5111,16 +5102,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"Enable Edit-Mode edge smoothing, reducing aliasing, requires restart");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
- /* grease pencil anti-aliasing */
- prop = RNA_def_property(srna, "gpencil_multi_sample", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "gpencil_multisamples");
- RNA_def_property_enum_items(prop, multi_sample_levels);
- RNA_def_property_ui_text(
- prop,
- "Gpencil MultiSample",
- "Enable Grease Pencil OpenGL multi-sampling, only for systems that support it");
- RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
-
prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
RNA_def_property_ui_text(
diff --git a/source/blender/shader_fx/CMakeLists.txt b/source/blender/shader_fx/CMakeLists.txt
index 6d918763996..9835c5c0588 100644
--- a/source/blender/shader_fx/CMakeLists.txt
+++ b/source/blender/shader_fx/CMakeLists.txt
@@ -45,7 +45,6 @@ set(SRC
intern/FX_shader_colorize.c
intern/FX_shader_flip.c
intern/FX_shader_glow.c
- intern/FX_shader_light.c
intern/FX_shader_pixel.c
intern/FX_shader_rim.c
intern/FX_shader_shadow.c
diff --git a/source/blender/shader_fx/FX_shader_types.h b/source/blender/shader_fx/FX_shader_types.h
index 7a87c77f313..f338f9bcc2a 100644
--- a/source/blender/shader_fx/FX_shader_types.h
+++ b/source/blender/shader_fx/FX_shader_types.h
@@ -30,7 +30,6 @@ extern ShaderFxTypeInfo shaderfx_Type_Blur;
extern ShaderFxTypeInfo shaderfx_Type_Colorize;
extern ShaderFxTypeInfo shaderfx_Type_Flip;
extern ShaderFxTypeInfo shaderfx_Type_Glow;
-extern ShaderFxTypeInfo shaderfx_Type_Light;
extern ShaderFxTypeInfo shaderfx_Type_Pixel;
extern ShaderFxTypeInfo shaderfx_Type_Rim;
extern ShaderFxTypeInfo shaderfx_Type_Shadow;
diff --git a/source/blender/shader_fx/intern/FX_shader_blur.c b/source/blender/shader_fx/intern/FX_shader_blur.c
index 72d2a61dafd..70f53995201 100644
--- a/source/blender/shader_fx/intern/FX_shader_blur.c
+++ b/source/blender/shader_fx/intern/FX_shader_blur.c
@@ -30,8 +30,8 @@
static void initData(ShaderFxData *fx)
{
BlurShaderFxData *gpfx = (BlurShaderFxData *)fx;
- ARRAY_SET_ITEMS(gpfx->radius, 1, 1);
- gpfx->samples = 4;
+ ARRAY_SET_ITEMS(gpfx->radius, 5, 5);
+ gpfx->samples = 2;
gpfx->coc = 0.025f;
}
@@ -45,7 +45,7 @@ ShaderFxTypeInfo shaderfx_Type_Blur = {
/* structName */ "BlurShaderFxData",
/* structSize */ sizeof(BlurShaderFxData),
/* type */ eShaderFxType_GpencilType,
- /* flags */ eShaderFxTypeFlag_Single,
+ /* flags */ 0,
/* copyData */ copyData,
diff --git a/source/blender/shader_fx/intern/FX_shader_flip.c b/source/blender/shader_fx/intern/FX_shader_flip.c
index 804b194ed68..41ca903ee08 100644
--- a/source/blender/shader_fx/intern/FX_shader_flip.c
+++ b/source/blender/shader_fx/intern/FX_shader_flip.c
@@ -47,7 +47,7 @@ ShaderFxTypeInfo shaderfx_Type_Flip = {
/* structName */ "FlipShaderFxData",
/* structSize */ sizeof(FlipShaderFxData),
/* type */ eShaderFxType_GpencilType,
- /* flags */ eShaderFxTypeFlag_Single,
+ /* flags */ 0,
/* copyData */ copyData,
diff --git a/source/blender/shader_fx/intern/FX_shader_pixel.c b/source/blender/shader_fx/intern/FX_shader_pixel.c
index e0ea111d121..f39649bba07 100644
--- a/source/blender/shader_fx/intern/FX_shader_pixel.c
+++ b/source/blender/shader_fx/intern/FX_shader_pixel.c
@@ -44,7 +44,7 @@ ShaderFxTypeInfo shaderfx_Type_Pixel = {
/* structName */ "PixelShaderFxData",
/* structSize */ sizeof(PixelShaderFxData),
/* type */ eShaderFxType_GpencilType,
- /* flags */ eShaderFxTypeFlag_Single,
+ /* flags */ 0,
/* copyData */ copyData,
diff --git a/source/blender/shader_fx/intern/FX_shader_shadow.c b/source/blender/shader_fx/intern/FX_shader_shadow.c
index 04160f618eb..68d23d65181 100644
--- a/source/blender/shader_fx/intern/FX_shader_shadow.c
+++ b/source/blender/shader_fx/intern/FX_shader_shadow.c
@@ -44,7 +44,7 @@ static void initData(ShaderFxData *md)
gpfx->rotation = 0.0f;
ARRAY_SET_ITEMS(gpfx->offset, 15, 20);
ARRAY_SET_ITEMS(gpfx->scale, 1.0f, 1.0f);
- ARRAY_SET_ITEMS(gpfx->shadow_rgba, 0.54f, 0.62f, 1.0f, 0.9f);
+ ARRAY_SET_ITEMS(gpfx->shadow_rgba, 0.0f, 0.0f, 0.0f, 0.8f);
gpfx->amplitude = 10.0f;
gpfx->period = 20.0f;
diff --git a/source/blender/shader_fx/intern/FX_shader_util.c b/source/blender/shader_fx/intern/FX_shader_util.c
index 908a2b249b8..c2dcae04b85 100644
--- a/source/blender/shader_fx/intern/FX_shader_util.c
+++ b/source/blender/shader_fx/intern/FX_shader_util.c
@@ -39,7 +39,6 @@ void shaderfx_type_init(ShaderFxTypeInfo *types[])
INIT_FX_TYPE(Colorize);
INIT_FX_TYPE(Flip);
INIT_FX_TYPE(Glow);
- INIT_FX_TYPE(Light);
INIT_FX_TYPE(Pixel);
INIT_FX_TYPE(Rim);
INIT_FX_TYPE(Shadow);
diff --git a/source/blender/shader_fx/intern/FX_shader_wave.c b/source/blender/shader_fx/intern/FX_shader_wave.c
index 334024bbd3f..35d2e515f76 100644
--- a/source/blender/shader_fx/intern/FX_shader_wave.c
+++ b/source/blender/shader_fx/intern/FX_shader_wave.c
@@ -50,7 +50,7 @@ ShaderFxTypeInfo shaderfx_Type_Wave = {
/* structName */ "WaveShaderFxData",
/* structSize */ sizeof(WaveShaderFxData),
/* type */ eShaderFxType_GpencilType,
- /* flags */ eShaderFxTypeFlag_Single,
+ /* flags */ 0,
/* copyData */ copyData,