diff --git a/scripts/startup/bl_ui/__init__.py b/scripts/startup/bl_ui/__init__.py index 23ccd621c19..40ec518b7ac 100644 --- a/scripts/startup/bl_ui/__init__.py +++ b/scripts/startup/bl_ui/__init__.py @@ -26,7 +26,6 @@ _modules = [ "properties_data_curve", "properties_data_curves", "properties_data_empty", - "properties_data_gpencil", "properties_data_grease_pencil", "properties_data_light", "properties_data_lattice", diff --git a/scripts/startup/bl_ui/properties_data_gpencil.py b/scripts/startup/bl_ui/properties_data_gpencil.py deleted file mode 100644 index d2f1bf24466..00000000000 --- a/scripts/startup/bl_ui/properties_data_gpencil.py +++ /dev/null @@ -1,236 +0,0 @@ -# SPDX-FileCopyrightText: 2018-2023 Blender Authors -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import bpy -from bpy.types import Menu, Panel, UIList -from rna_prop_ui import PropertyPanel -from .space_properties import PropertiesAnimationMixin - -############################### -# Base-Classes (for shared stuff - e.g. poll, attributes, etc.) - - -class DataButtonsPanel: - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = "data" - - @classmethod - def poll(cls, context): - return context.gpencil - - -class ObjectButtonsPanel: - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = "data" - - @classmethod - def poll(cls, context): - ob = context.object - return ob and ob.type == 'GPENCIL' - - -class LayerDataButtonsPanel: - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = "data" - - @classmethod - def poll(cls, context): - gpencil = context.gpencil - return gpencil and gpencil.layers.active - - -############################### -# GP Object Properties Panels and Helper Classes - -class DATA_PT_context_gpencil(DataButtonsPanel, Panel): - bl_label = "" - bl_options = {'HIDE_HEADER'} - - def draw(self, context): - layout = self.layout - - ob = context.object - space = context.space_data - - if ob: - layout.template_ID(ob, "data") - else: - layout.template_ID(space, "pin_id") - - -class DATA_PT_gpencil_onion_skinning(DataButtonsPanel, Panel): - bl_label = "Onion Skinning" - - def draw(self, context): - gpd = context.gpencil - - layout = self.layout - layout.use_property_split = True - - col = layout.column() - col.prop(gpd, "onion_mode") - col.prop(gpd, "onion_factor", text="Opacity", slider=True) - col.prop(gpd, "onion_keyframe_type") - - if gpd.onion_mode == 'ABSOLUTE': - col = layout.column(align=True) - col.prop(gpd, "ghost_before_range", text="Frames Before") - col.prop(gpd, "ghost_after_range", text="Frames After") - elif gpd.onion_mode == 'RELATIVE': - col = layout.column(align=True) - col.prop(gpd, "ghost_before_range", text="Keyframes Before") - col.prop(gpd, "ghost_after_range", text="Keyframes After") - - -class DATA_PT_gpencil_onion_skinning_custom_colors(DataButtonsPanel, Panel): - bl_parent_id = "DATA_PT_gpencil_onion_skinning" - bl_label = "Custom Colors" - bl_options = {'DEFAULT_CLOSED'} - - def draw_header(self, context): - gpd = context.gpencil - - self.layout.prop(gpd, "use_ghost_custom_colors", text="") - - def draw(self, context): - gpd = context.gpencil - - layout = self.layout - layout.use_property_split = True - layout.enabled = gpd.users <= 1 and gpd.use_ghost_custom_colors - - layout.prop(gpd, "before_color", text="Before") - layout.prop(gpd, "after_color", text="After") - - -class DATA_PT_gpencil_onion_skinning_display(DataButtonsPanel, Panel): - bl_parent_id = "DATA_PT_gpencil_onion_skinning" - bl_label = "Display" - bl_options = {'DEFAULT_CLOSED'} - - def draw(self, context): - gpd = context.gpencil - - layout = self.layout - layout.use_property_split = True - layout.enabled = gpd.users <= 1 - - layout.prop(gpd, "use_ghosts_always", text="View in Render") - - col = layout.column(align=True) - col.prop(gpd, "use_onion_fade", text="Fade") - sub = layout.column() - sub.active = gpd.onion_mode in {'RELATIVE', 'SELECTED'} - sub.prop(gpd, "use_onion_loop", text="Show Start Frame") - - -class GPENCIL_UL_vgroups(UIList): - def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): - vgroup = item - if self.layout_type in {'DEFAULT', 'COMPACT'}: - layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon) - icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED' - layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False) - elif self.layout_type == 'GRID': - layout.alignment = 'CENTER' - layout.label(text="", icon_value=icon) - - -class DATA_PT_gpencil_strokes(DataButtonsPanel, Panel): - bl_label = "Strokes" - bl_options = {'DEFAULT_CLOSED'} - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False - - ob = context.object - gpd = context.gpencil - - col = layout.column(align=True) - col.prop(gpd, "stroke_depth_order") - - if ob: - col.enabled = not ob.show_in_front - - col = layout.column(align=True) - col.prop(gpd, "stroke_thickness_space") - sub = col.column() - sub.active = gpd.stroke_thickness_space == 'WORLDSPACE' - sub.prop(gpd, "pixel_factor", text="Thickness Scale") - - col.prop(gpd, "edit_curve_resolution") - - -class DATA_PT_gpencil_display(DataButtonsPanel, Panel): - bl_label = "Viewport Display" - bl_options = {'DEFAULT_CLOSED'} - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False - - gpd = context.gpencil - - layout.prop(gpd, "edit_line_color", text="Edit Line Color") - - -class DATA_PT_gpencil_canvas(DataButtonsPanel, Panel): - bl_label = "Canvas" - bl_parent_id = "DATA_PT_gpencil_display" - bl_options = {'DEFAULT_CLOSED'} - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False - gpd = context.gpencil - grid = gpd.grid - - row = layout.row(align=True) - col = row.column() - col.prop(grid, "color", text="Color") - col.prop(grid, "scale", text="Scale") - col.prop(grid, "offset") - row = layout.row(align=True) - col = row.column() - col.prop(grid, "lines", text="Subdivisions") - - -class DATA_PT_gpencil_animation(DataButtonsPanel, PropertiesAnimationMixin, PropertyPanel, Panel): - _animated_id_context_property = "gpencil" - - -class DATA_PT_custom_props_gpencil(DataButtonsPanel, PropertyPanel, Panel): - _context_path = "object.data" - _property_type = bpy.types.GreasePencil - - -############################### - - -classes = ( - DATA_PT_context_gpencil, - DATA_PT_gpencil_onion_skinning, - DATA_PT_gpencil_onion_skinning_custom_colors, - DATA_PT_gpencil_onion_skinning_display, - DATA_PT_gpencil_strokes, - DATA_PT_gpencil_display, - DATA_PT_gpencil_canvas, - DATA_PT_gpencil_animation, - DATA_PT_custom_props_gpencil, - - GPENCIL_UL_vgroups, -) - -if __name__ == "__main__": # only for live edit. - from bpy.utils import register_class - - for cls in classes: - register_class(cls) diff --git a/source/blender/blenkernel/BKE_gpencil_curve_legacy.h b/source/blender/blenkernel/BKE_gpencil_curve_legacy.h index 2f56b4404d3..2800f9b1d26 100644 --- a/source/blender/blenkernel/BKE_gpencil_curve_legacy.h +++ b/source/blender/blenkernel/BKE_gpencil_curve_legacy.h @@ -20,25 +20,6 @@ struct bGPDlayer; struct bGPDstroke; struct bGPdata; -/** - * Convert a curve object to grease pencil stroke. - * - * \param bmain: Main thread pointer - * \param scene: Original scene. - * \param ob_gp: Grease pencil object to add strokes. - * \param ob_cu: Curve to convert. - * \param use_collections: Create layers using collection names. - * \param scale_thickness: Scale thickness factor. - * \param sample: Sample distance, zero to disable. - */ -void BKE_gpencil_convert_curve(struct Main *bmain, - struct Scene *scene, - struct Object *ob_gp, - struct Object *ob_cu, - bool use_collections, - float scale_thickness, - float sample); - /** * Creates a bGPDcurve by doing a cubic curve fitting on the grease pencil stroke points. */ @@ -46,32 +27,12 @@ struct bGPDcurve *BKE_gpencil_stroke_editcurve_generate(struct bGPDstroke *gps, float error_threshold, float corner_angle, float stroke_radius); -/** - * Updates the edit-curve for a stroke. Frees the old curve if one exists and generates a new one. - */ -void BKE_gpencil_stroke_editcurve_update(struct bGPdata *gpd, - struct bGPDlayer *gpl, - struct bGPDstroke *gps); /** * Sync the selection from stroke to edit-curve. */ void BKE_gpencil_editcurve_stroke_sync_selection(struct bGPdata *gpd, struct bGPDstroke *gps, struct bGPDcurve *gpc); -/** - * Sync the selection from edit-curve to stroke. - */ -void BKE_gpencil_stroke_editcurve_sync_selection(struct bGPdata *gpd, - struct bGPDstroke *gps, - struct bGPDcurve *gpc); -void BKE_gpencil_strokes_selected_update_editcurve(struct bGPdata *gpd); -void BKE_gpencil_strokes_selected_sync_selection_editcurve(struct bGPdata *gpd); -/** - * Recalculate stroke points with the edit-curve of the stroke. - */ -void BKE_gpencil_stroke_update_geometry_from_editcurve(struct bGPDstroke *gps, - uint resolution, - bool is_adaptive); /** * Recalculate the handles of the edit curve of a grease pencil stroke. */ diff --git a/source/blender/blenkernel/BKE_gpencil_geom_legacy.h b/source/blender/blenkernel/BKE_gpencil_geom_legacy.h index dbbad2af4d2..94983fc2a7b 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom_legacy.h +++ b/source/blender/blenkernel/BKE_gpencil_geom_legacy.h @@ -67,57 +67,12 @@ void BKE_gpencil_stroke_boundingbox_calc(struct bGPDstroke *gps); * \param r_normal: Return Normal vector normalized */ void BKE_gpencil_stroke_normal(const struct bGPDstroke *gps, float r_normal[3]); -/** - * Reduce a series of points to a simplified version, - * but maintains the general shape of the series. - * - * Ramer - Douglas - Peucker algorithm - * by http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm - * \param gpd: Grease pencil data-block - * \param gps: Grease pencil stroke - * \param epsilon: Epsilon value to define precision of the algorithm - */ -void BKE_gpencil_stroke_simplify_adaptive(struct bGPdata *gpd, - struct bGPDstroke *gps, - float epsilon); -/** - * Simplify alternate vertex of stroke except extremes. - * \param gpd: Grease pencil data-block - * \param gps: Grease pencil stroke - */ -void BKE_gpencil_stroke_simplify_fixed(struct bGPdata *gpd, struct bGPDstroke *gps); -/** - * Subdivide a stroke - * \param gpd: Grease pencil data-block - * \param gps: Stroke - * \param level: Level of subdivision - * \param type: Type of subdivision - */ -void BKE_gpencil_stroke_subdivide(struct bGPdata *gpd, - struct bGPDstroke *gps, - int level, - int type); + /** * Trim stroke to the first intersection or loop. * \param gps: Stroke data */ bool BKE_gpencil_stroke_trim(struct bGPdata *gpd, struct bGPDstroke *gps); -/** - * Reduce a series of points when the distance is below a threshold. - * Special case for first and last points (both are kept) for other points, - * the merge point always is at first point. - * - * \param gpd: Grease pencil data-block. - * \param gpf: Grease Pencil frame. - * \param gps: Grease Pencil stroke. - * \param threshold: Distance between points. - * \param use_unselected: Set to true to analyze all stroke and not only selected points. - */ -void BKE_gpencil_stroke_merge_distance(struct bGPdata *gpd, - struct bGPDframe *gpf, - struct bGPDstroke *gps, - float threshold, - bool use_unselected); /** * Get points of stroke always flat to view not affected @@ -199,18 +154,6 @@ void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd, const GPencilPointCoordinates *elem_data, const float mat[4][4]); -/** - * Resample a stroke - * \param gpd: Grease pencil data-block - * \param gps: Stroke to sample - * \param dist: Distance of one segment - * \param sharp_threshold: Threshold for preserving sharp corners - */ -bool BKE_gpencil_stroke_sample(struct bGPdata *gpd, - struct bGPDstroke *gps, - const float dist, - const bool select, - const float sharp_threshold); /** * Apply smooth position to stroke point. * \param gps: Stroke to smooth @@ -293,47 +236,7 @@ void BKE_gpencil_stroke_smooth(struct bGPDstroke *gps, * \param gps: Stroke to close */ bool BKE_gpencil_stroke_close(struct bGPDstroke *gps); -/** - * Dissolve points in stroke. - * \param gpd: Grease pencil data-block - * \param gpf: Grease pencil frame - * \param gps: Grease pencil stroke - * \param tag: Type of tag for point - */ -void BKE_gpencil_dissolve_points(struct bGPdata *gpd, - struct bGPDframe *gpf, - struct bGPDstroke *gps, - short tag); -/** - * Backbone stretch similar to Freestyle. - * \param gps: Stroke to sample. - * \param dist: Length of the added section. - * \param overshoot_fac: Relative length of the curve which is used to determine the extension. - * \param mode: Affect to Start, End or Both extremes (0->Both, 1->Start, 2->End). - * \param follow_curvature: True for approximating curvature of given overshoot. - * \param extra_point_count: When follow_curvature is true, use this amount of extra points. - */ -bool BKE_gpencil_stroke_stretch(struct bGPDstroke *gps, - float dist, - float overshoot_fac, - short mode, - bool follow_curvature, - int extra_point_count, - float segment_influence, - float max_angle, - bool invert_curvature); -/** - * Trim stroke to needed segments. - * \param gps: Target stroke. - * \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. - * \param keep_point: Keep strokes with one point. False remove the single points strokes - */ -bool BKE_gpencil_stroke_trim_points(struct bGPDstroke *gps, - int index_from, - int index_to, - const bool keep_point); /** * Split the given stroke into several new strokes, partitioning * it based on whether the stroke points have a particular flag @@ -347,38 +250,11 @@ struct bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(struct bGPdata *gpd, bool select, bool flat_cap, int limit); -void BKE_gpencil_curve_delete_tagged_points(struct bGPdata *gpd, - struct bGPDframe *gpf, - struct bGPDstroke *gps, - struct bGPDstroke *next_stroke, - struct bGPDcurve *gpc, - int tag_flags); /** * Flip stroke. */ void BKE_gpencil_stroke_flip(struct bGPDstroke *gps); -/** - * Split stroke. - * \param gpd: Grease pencil data-block. - * \param gpf: Grease pencil frame. - * \param gps: Grease pencil original stroke. - * \param before_index: Position of the point to split. - * \param remaining_gps: Secondary stroke after split. - * \return True if the split was done - */ -bool BKE_gpencil_stroke_split(struct bGPdata *gpd, - struct bGPDframe *gpf, - struct bGPDstroke *gps, - int before_index, - struct bGPDstroke **remaining_gps); -/** - * Shrink the stroke by length. - * \param gps: Stroke to shrink - * \param dist: delta length - * \param mode: 1->Start, 2->End - */ -bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, float dist, short mode); /** * Calculate grease pencil stroke length. @@ -409,63 +285,6 @@ void BKE_gpencil_stroke_join(struct bGPDstroke *gps_a, bool fit_thickness, bool smooth, bool auto_flip); -/** - * Set stroke start point in the selected index. Only works for Cyclic strokes. - * \param start_idx: Index of the point to be the start point. - */ -void BKE_gpencil_stroke_start_set(struct bGPDstroke *gps, int start_idx); -/** - * Copy the stroke of the frame to all frames selected (except current). - */ -void BKE_gpencil_stroke_copy_to_keyframes(struct bGPdata *gpd, - struct bGPDlayer *gpl, - struct bGPDframe *gpf, - struct bGPDstroke *gps, - bool tail); - -/** - * Convert a mesh object to grease pencil stroke. - * - * \param bmain: Main thread pointer. - * \param depsgraph: Original depsgraph. - * \param scene: Original scene. - * \param ob_gp: Grease pencil object to add strokes. - * \param ob_mesh: Mesh to convert. - * \param angle: Limit angle to consider a edge-loop ends. - * \param thickness: Thickness of the strokes. - * \param offset: Offset along the normals. - * \param matrix: Transformation matrix. - * \param frame_offset: Destination frame number offset. - * \param use_seams: Only export seam edges. - * \param use_faces: Export faces as filled strokes. - */ -bool BKE_gpencil_convert_mesh(struct Main *bmain, - struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob_gp, - struct Object *ob_mesh, - float angle, - int thickness, - float offset, - const float matrix[4][4], - int frame_offset, - bool use_seams, - bool use_faces, - bool use_vgroups); - -/** - * Subdivide the grease pencil stroke so the number of points is target_number. - * Does not change the shape of the stroke. The new points will be distributed as - * uniformly as possible by repeatedly subdividing the current longest edge. - * - * \param gps: The stroke to be up-sampled. - * \param target_number: The number of points the up-sampled stroke should have. - * \param select: Select/Deselect the stroke. - */ -void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd, - struct bGPDstroke *gps, - uint32_t target_number, - bool select); /** * Stroke to view space @@ -485,18 +304,6 @@ void BKE_gpencil_stroke_to_view_space(struct bGPDstroke *gps, void BKE_gpencil_stroke_from_view_space(struct bGPDstroke *gps, float viewinv[4][4], const float diff_mat[4][4]); -/** - * Calculates the perimeter of a stroke projected from the view and returns it as a new stroke. - * \param subdivisions: Number of subdivisions for the start and end caps. - * \return bGPDstroke pointer to stroke perimeter. - */ -struct bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(float viewmat[4][4], - struct bGPdata *gpd, - const struct bGPDlayer *gpl, - struct bGPDstroke *gps, - int subdivisions, - const float diff_mat[4][4], - const float thickness_chg); /** * Get average pressure. */ diff --git a/source/blender/blenkernel/BKE_gpencil_legacy.h b/source/blender/blenkernel/BKE_gpencil_legacy.h index f29cfc44ae6..2b9354bdc58 100644 --- a/source/blender/blenkernel/BKE_gpencil_legacy.h +++ b/source/blender/blenkernel/BKE_gpencil_legacy.h @@ -42,8 +42,6 @@ struct bGPdata; #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) \ - ((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))) @@ -55,20 +53,6 @@ struct bGPdata; /* Vertex Color macros. */ #define GPENCIL_USE_VERTEX_COLOR(toolsettings) \ (((toolsettings)->gp_paint->mode == GPPAINT_FLAG_USE_VERTEXCOLOR)) -#define GPENCIL_USE_VERTEX_COLOR_STROKE(toolsettings, brush) \ - ((GPENCIL_USE_VERTEX_COLOR(toolsettings) && \ - (((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_STROKE) || \ - ((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH)))) -#define GPENCIL_USE_VERTEX_COLOR_FILL(toolsettings, brush) \ - ((GPENCIL_USE_VERTEX_COLOR(toolsettings) && \ - (((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_FILL) || \ - ((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH)))) -#define GPENCIL_TINT_VERTEX_COLOR_STROKE(brush) \ - (((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_STROKE) || \ - ((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH)) -#define GPENCIL_TINT_VERTEX_COLOR_FILL(brush) \ - (((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_FILL) || \ - ((brush)->gpencil_settings->vertex_mode == GPPAINT_MODE_BOTH)) /* ------------ Grease-Pencil API ------------------ */ @@ -88,11 +72,6 @@ void BKE_gpencil_free_layers(struct ListBase *list); void BKE_gpencil_free_legacy_palette_data(struct ListBase *list); /** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */ void BKE_gpencil_free_data(struct bGPdata *gpd, bool free_all); -/** - * Delete grease pencil evaluated data - * \param gpd_eval: Grease pencil data-block - */ -void BKE_gpencil_eval_delete(struct bGPdata *gpd_eval); void BKE_gpencil_free_layer_masks(struct bGPDlayer *gpl); /** * Tag data-block for depsgraph update. @@ -104,17 +83,6 @@ void BKE_gpencil_tag(struct bGPdata *gpd); void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd); void BKE_gpencil_batch_cache_free(struct bGPdata *gpd); -/** - * Ensure selection status of stroke is in sync with its points. - * \param gps: Grease pencil stroke - */ -void BKE_gpencil_stroke_sync_selection(struct bGPdata *gpd, struct bGPDstroke *gps); -void BKE_gpencil_curve_sync_selection(struct bGPdata *gpd, struct bGPDstroke *gps); -/** Assign unique stroke ID for selection. */ -void BKE_gpencil_stroke_select_index_set(struct bGPdata *gpd, struct bGPDstroke *gps); -/** Reset unique stroke ID for selection. */ -void BKE_gpencil_stroke_select_index_reset(struct bGPDstroke *gps); - /** * Add a new gp-frame to the given layer. * \param gpl: Grease pencil layer @@ -164,38 +132,6 @@ struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src, bool dup_frames, bool dup_strokes); -/** - * Make a copy of a given gpencil data settings. - */ -void BKE_gpencil_data_copy_settings(const struct bGPdata *gpd_src, struct bGPdata *gpd_dst); - -/** - * Make a copy of a given gpencil layer settings. - */ -void BKE_gpencil_layer_copy_settings(const struct bGPDlayer *gpl_src, struct bGPDlayer *gpl_dst); - -/** - * Make a copy of a given gpencil frame settings. - */ -void BKE_gpencil_frame_copy_settings(const struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst); - -/** - * Make a copy of a given gpencil stroke settings. - */ -void BKE_gpencil_stroke_copy_settings(const struct bGPDstroke *gps_src, - struct bGPDstroke *gps_dst); - -/** - * Make a copy of strokes between gpencil frames. - * \param gpf_src: Source grease pencil frame - * \param gpf_dst: Destination grease pencil frame - */ -void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst); -/* Create a hash with the list of selected frame number. */ -void BKE_gpencil_frame_selected_hash(struct bGPdata *gpd, struct GHash *r_list); - -/* Make a copy of a given gpencil stroke editcurve */ -struct bGPDcurve *BKE_gpencil_stroke_curve_duplicate(struct bGPDcurve *gpc_src); /** * Make a copy of a given grease-pencil stroke. * \param gps_src: Source grease pencil strokes. @@ -216,73 +152,6 @@ struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy); -/** - * Delete the last stroke of the given frame. - * \param gpl: Grease pencil layer - * \param gpf: Grease pencil frame - */ -void BKE_gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf); - -/* materials */ -/** - * Reassign strokes using a material. - * \param gpd: Grease pencil data-block - * \param totcol: Total materials - * \param index: Index of the material - */ -void BKE_gpencil_material_index_reassign(struct bGPdata *gpd, int totcol, int index); -/** - * Remove strokes using a material. - * \param gpd: Grease pencil data-block - * \param index: Index of the material - * \return True if removed - */ -bool BKE_gpencil_material_index_used(struct bGPdata *gpd, int index); -/** - * Remap material - * \param gpd: Grease pencil data-block - * \param remap: Remap index - * \param remap_len: Remap length - */ -void BKE_gpencil_material_remap(struct bGPdata *gpd, - const unsigned int *remap, - unsigned int remap_len); -/** - * Load a table with material conversion index for merged materials. - * \param ob: Grease pencil object. - * \param hue_threshold: Threshold for Hue. - * \param sat_threshold: Threshold for Saturation. - * \param val_threshold: Threshold for Value. - * \param r_mat_table: return material table. - * \return True if done. - */ -bool BKE_gpencil_merge_materials_table_get(struct Object *ob, - float hue_threshold, - float sat_threshold, - float val_threshold, - struct GHash *r_mat_table); -/** - * Merge similar materials - * \param ob: Grease pencil object - * \param hue_threshold: Threshold for Hue - * \param sat_threshold: Threshold for Saturation - * \param val_threshold: Threshold for Value - * \param r_removed: Number of materials removed - * \return True if done - */ -bool BKE_gpencil_merge_materials(struct Object *ob, - float hue_threshold, - float sat_threshold, - float val_threshold, - int *r_removed); - -/* statistics functions */ -/** - * Calc grease pencil statistics functions. - * \param gpd: Grease pencil data-block - */ -void BKE_gpencil_stats_update(struct bGPdata *gpd); - /** * Create a new stroke, with pre-allocated data buffers. * \param mat_idx: Index of the material @@ -303,22 +172,6 @@ struct bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thic struct bGPDstroke *BKE_gpencil_stroke_add( struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness, bool insert_at_head); -/** - * Add a stroke and copy the temporary drawing color value - * from one of the existing stroke. - * \param gpf: Grease pencil frame - * \param existing: Stroke with the style to copy - * \param mat_idx: Material index - * \param totpoints: Total points - * \param thickness: Stroke thickness - * \return Pointer to new stroke - */ -struct bGPDstroke *BKE_gpencil_stroke_add_existing_style(struct bGPDframe *gpf, - struct bGPDstroke *existing, - int mat_idx, - int totpoints, - short thickness); - struct bGPDcurve *BKE_gpencil_stroke_editcurve_new(int tot_curve_points); /* Stroke and Fill - Alpha Visibility Threshold */ @@ -405,13 +258,6 @@ void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl); */ void BKE_gpencil_layer_autolock_set(struct bGPdata *gpd, bool unlock); -/** - * Add grease pencil mask layer. - * \param gpl: Grease pencil layer - * \param name: Name of the mask - * \return Pointer to new mask layer - */ -struct bGPDlayer_Mask *BKE_gpencil_layer_mask_add(struct bGPDlayer *gpl, const char *name); /** * Remove grease pencil mask layer. * \param gpl: Grease pencil layer @@ -424,13 +270,6 @@ void BKE_gpencil_layer_mask_remove(struct bGPDlayer *gpl, struct bGPDlayer_Mask * \param name: Name of the mask layer */ void BKE_gpencil_layer_mask_remove_ref(struct bGPdata *gpd, const char *name); -/** - * Get mask layer by name. - * \param gpl: Grease pencil layer - * \param name: Mask name - * \return Pointer to mask layer - */ -struct bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(struct bGPDlayer *gpl, const char *name); /** * Sort grease pencil mask layers. * \param gpd: Grease pencil data-block @@ -450,10 +289,6 @@ void BKE_gpencil_layer_mask_copy(const struct bGPDlayer *gpl_src, struct bGPDlay * Clean any invalid mask layer. */ void BKE_gpencil_layer_mask_cleanup(struct bGPdata *gpd, struct bGPDlayer *gpl); -/** - * Clean any invalid mask layer for all layers. - */ -void BKE_gpencil_layer_mask_cleanup_all_layers(struct bGPdata *gpd); /** * Sort grease pencil frames. @@ -462,17 +297,7 @@ void BKE_gpencil_layer_mask_cleanup_all_layers(struct bGPdata *gpd); */ void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames); -struct bGPDlayer *BKE_gpencil_layer_get_by_name(struct bGPdata *gpd, - const char *name, - int first_if_not_found); - /* Brush */ -/** - * Get grease pencil material from brush. - * \param brush: Brush - * \return Pointer to material - */ -struct Material *BKE_gpencil_brush_material_get(struct Brush *brush); /** * Set grease pencil brush material. * \param brush: Brush @@ -480,121 +305,7 @@ struct Material *BKE_gpencil_brush_material_get(struct Brush *brush); */ void BKE_gpencil_brush_material_set(struct Brush *brush, struct Material *material); -/* Object */ -/** - * Get active color, and add all default settings if we don't find anything. - * \param ob: Grease pencil object - * \return Material pointer - */ -struct Material *BKE_gpencil_object_material_ensure_active(struct Object *ob); -/** - * Adds the pinned material to the object if necessary. - * \param bmain: Main pointer - * \param ob: Grease pencil object - * \param brush: Brush - * \return Pointer to material - */ -struct Material *BKE_gpencil_object_material_ensure_from_brush(struct Main *bmain, - struct Object *ob, - struct Brush *brush); -/** - * Assigns the material to object (if not already present) and returns its index (mat_nr). - * \param bmain: Main pointer - * \param ob: Grease pencil object - * \param material: Material - * \return Index of the material - */ -int BKE_gpencil_object_material_ensure(struct Main *bmain, - struct Object *ob, - struct Material *material); -struct Material *BKE_gpencil_object_material_ensure_by_name(struct Main *bmain, - struct Object *ob, - const char *name, - int *r_index); - -/** - * Creates a new grease-pencil material and assigns it to object. - * \param bmain: Main pointer - * \param ob: Grease pencil object - * \param name: Material name - * \param r_index: value is set to zero based index of the new material if \a r_index is not NULL. - * \return Material pointer. - */ -struct Material *BKE_gpencil_object_material_new(struct Main *bmain, - struct Object *ob, - const char *name, - int *r_index); - -/** - * Get material index (0-based like mat_nr not #Object::actcol). - * \param ob: Grease pencil object - * \param ma: Material - * \return Index of the material - */ -int BKE_gpencil_object_material_index_get(struct Object *ob, struct Material *ma); -int BKE_gpencil_object_material_index_get_by_name(struct Object *ob, const char *name); - -/** - * Returns the material for a brush with respect to its pinned state. - * \param ob: Grease pencil object - * \param brush: Brush - * \return Material pointer - */ -struct Material *BKE_gpencil_object_material_from_brush_get(struct Object *ob, - struct Brush *brush); -/** - * Returns the material index for a brush with respect to its pinned state. - * \param ob: Grease pencil object - * \param brush: Brush - * \return Material index. - */ -int BKE_gpencil_object_material_get_index_from_brush(struct Object *ob, struct Brush *brush); - -/** - * Guaranteed to return a material assigned to object. Returns never NULL. - * \param bmain: Main pointer - * \param ob: Grease pencil object - * \return Material pointer. - */ -struct Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings( - struct Main *bmain, struct Object *ob, struct ToolSettings *ts); -/** - * Guaranteed to return a material assigned to object. Returns never NULL. - * \param bmain: Main pointer - * \param ob: Grease pencil object. - * \param brush: Brush - * \return Material pointer - */ -struct Material *BKE_gpencil_object_material_ensure_from_active_input_brush(struct Main *bmain, - struct Object *ob, - struct Brush *brush); -/** - * Guaranteed to return a material assigned to object. Returns never NULL. - * Only use this for materials unrelated to user input. - * \param ob: Grease pencil object - * \return Material pointer - */ -struct Material *BKE_gpencil_object_material_ensure_from_active_input_material(struct Object *ob); - -/** - * Check if stroke has any point selected - * \param gps: Grease pencil stroke - * \return True if selected - */ -bool BKE_gpencil_stroke_select_check(const struct bGPDstroke *gps); - /* vertex groups */ -/** - * Ensure stroke has vertex group. - * \param gps: Grease pencil stroke - */ -void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps); -/** - * Remove a vertex group. - * \param ob: Grease pencil object - * \param defgroup: deform group - */ -void BKE_gpencil_vgroup_remove(struct Object *ob, struct bDeformGroup *defgroup); /** * Make a copy of a given gpencil weights. * \param gps_src: Source grease pencil stroke @@ -602,14 +313,6 @@ void BKE_gpencil_vgroup_remove(struct Object *ob, struct bDeformGroup *defgroup) */ void BKE_gpencil_stroke_weights_duplicate(struct bGPDstroke *gps_src, struct bGPDstroke *gps_dst); -/* Set active frame by layer. */ -/** - * Set current grease pencil active frame. - * \param depsgraph: Current depsgraph - * \param gpd: Grease pencil data-block. - */ -void BKE_gpencil_frame_active_set(struct Depsgraph *depsgraph, struct bGPdata *gpd); - /** * Get range of selected frames in layer. * Always the active frame is considered as selected, so if no more selected the range @@ -636,19 +339,6 @@ float BKE_gpencil_multiframe_falloff_calc( * \param scene: Scene */ void BKE_gpencil_palette_ensure(struct Main *bmain, struct Scene *scene); - -/** - * Create grease pencil strokes from image - * \param sima: Image - * \param gpd: Grease pencil data-block - * \param gpf: Grease pencil frame - * \param size: Size - * \param mask: Mask - * \return True if done - */ -bool BKE_gpencil_from_image( - struct SpaceImage *sima, struct bGPdata *gpd, struct bGPDframe *gpf, float size, bool mask); - /* Iterators */ /** * Frame & stroke are NULL if it is a layer callback. @@ -658,11 +348,6 @@ typedef void (*gpIterCb)(struct bGPDlayer *layer, struct bGPDstroke *stroke, void *thunk); -void BKE_gpencil_visible_stroke_iter(struct bGPdata *gpd, - gpIterCb layer_cb, - gpIterCb stroke_cb, - void *thunk); - void BKE_gpencil_visible_stroke_advanced_iter(struct ViewLayer *view_layer, struct Object *ob, gpIterCb layer_cb, @@ -733,17 +418,6 @@ int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd); -bool BKE_gpencil_can_avoid_full_copy_on_write(const struct Depsgraph *depsgraph, - struct bGPdata *gpd); - -/** - * Update the geometry of the evaluated bGPdata. - * This function will: - * 1) Copy the original data over to the evaluated object. - * 2) Update the original pointers in the runtime structs. - */ -void BKE_gpencil_update_on_write(struct bGPdata *gpd_orig, struct bGPdata *gpd_eval); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_gpencil_modifier_legacy.h b/source/blender/blenkernel/BKE_gpencil_modifier_legacy.h index 2d487d4a56e..e858289d2bc 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier_legacy.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier_legacy.h @@ -26,10 +26,6 @@ typedef void (*GreasePencilIDWalkFunc)(void *user_data, struct Object *ob, struct ID **idpoin, int cb_flag); -typedef void (*GreasePencilTexWalkFunc)(void *user_data, - struct Object *ob, - struct GpencilModifierData *md, - const char *propname); /** * Free grease pencil modifier data diff --git a/source/blender/blenkernel/BKE_gpencil_update_cache_legacy.h b/source/blender/blenkernel/BKE_gpencil_update_cache_legacy.h index 4080c2f2d3e..8f45162f1ca 100644 --- a/source/blender/blenkernel/BKE_gpencil_update_cache_legacy.h +++ b/source/blender/blenkernel/BKE_gpencil_update_cache_legacy.h @@ -102,31 +102,6 @@ void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache, GPencilUpdateCacheTraverseSettings *ts, void *user_data); -/** - * Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) and all of its containing data to - * be updated in the next update-on-write operation. - * - * The function assumes that when a parameter is NULL all of the following parameters are NULL too. - * E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL). - */ -void BKE_gpencil_tag_full_update(struct bGPdata *gpd, - struct bGPDlayer *gpl, - struct bGPDframe *gpf, - struct bGPDstroke *gps); - -/** - * Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) to be updated in the next - * update-on-write operation. This function will not update any of the containing data, only the - * struct itself. - * - * The function assumes that when a parameter is NULL all of the following parameters are NULL too. - * E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL). - */ -void BKE_gpencil_tag_light_update(struct bGPdata *gpd, - struct bGPDlayer *gpl, - struct bGPDframe *gpf, - struct bGPDstroke *gps); - /** * Frees the GPencilUpdateCache on the gpd->runtime. This will not free the data that the cache * node might point to. It assumes that the cache does not own the data. diff --git a/source/blender/blenkernel/BKE_object_types.hh b/source/blender/blenkernel/BKE_object_types.hh index 63d07c92efd..139d434d3d9 100644 --- a/source/blender/blenkernel/BKE_object_types.hh +++ b/source/blender/blenkernel/BKE_object_types.hh @@ -100,18 +100,6 @@ struct ObjectRuntime { */ Mesh *editmesh_eval_cage = nullptr; - /** - * Original grease pencil bGPdata pointer, before object->data was changed to point - * to gpd_eval. - * Is assigned by dependency graph's copy-on-evaluation. - */ - bGPdata *gpd_orig = nullptr; - /** - * bGPdata structure created during object evaluation. - * It has all modifiers applied. - */ - bGPdata *gpd_eval = nullptr; - /** * This is a mesh representation of corresponding object. * It created when Python calls `object.to_mesh()`. diff --git a/source/blender/blenkernel/intern/gpencil_curve_legacy.cc b/source/blender/blenkernel/intern/gpencil_curve_legacy.cc index 73278ce2585..93b981a3d16 100644 --- a/source/blender/blenkernel/intern/gpencil_curve_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_curve_legacy.cc @@ -44,415 +44,6 @@ extern "C" { /** \name Convert to curve object * \{ */ -/* Helper: Check materials with same color. */ -static int gpencil_check_same_material_color(Object *ob_gp, - const float color_stroke[4], - const float color_fill[4], - const bool do_stroke, - const bool do_fill, - Material **r_mat) -{ - int index = -1; - Material *ma = nullptr; - *r_mat = nullptr; - float color_cu[4]; - float hsv_stroke[4], hsv_fill[4]; - - copy_v4_v4(color_cu, color_stroke); - zero_v3(hsv_stroke); - rgb_to_hsv_v(color_cu, hsv_stroke); - hsv_stroke[3] = color_stroke[3]; - - copy_v4_v4(color_cu, color_fill); - zero_v3(hsv_fill); - rgb_to_hsv_v(color_cu, hsv_fill); - hsv_fill[3] = color_fill[3]; - - bool match_stroke = false; - bool match_fill = false; - - for (int i = 1; i <= ob_gp->totcol; i++) { - ma = BKE_object_material_get(ob_gp, i); - MaterialGPencilStyle *gp_style = ma->gp_style; - const bool fill = (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID); - const bool stroke = (gp_style->fill_style == GP_MATERIAL_STROKE_STYLE_SOLID); - - if (do_fill && !fill) { - continue; - } - - if (do_stroke && !stroke) { - continue; - } - - /* Check color with small tolerance (better result in HSV). */ - float hsv2[4]; - if (do_fill) { - zero_v3(hsv2); - rgb_to_hsv_v(gp_style->fill_rgba, hsv2); - hsv2[3] = gp_style->fill_rgba[3]; - if (compare_v4v4(hsv_fill, hsv2, 0.01f)) { - *r_mat = ma; - index = i - 1; - match_fill = true; - } - } - else { - match_fill = true; - } - - if (do_stroke) { - zero_v3(hsv2); - rgb_to_hsv_v(gp_style->stroke_rgba, hsv2); - hsv2[3] = gp_style->stroke_rgba[3]; - if (compare_v4v4(hsv_stroke, hsv2, 0.01f)) { - *r_mat = ma; - index = i - 1; - match_stroke = true; - } - } - else { - match_stroke = true; - } - - /* If match, don't look for more. */ - if (match_stroke || match_fill) { - break; - } - } - - if (!match_stroke || !match_fill) { - *r_mat = nullptr; - index = -1; - } - - return index; -} - -/* Helper: Add gpencil material using curve material as base. */ -static Material *gpencil_add_from_curve_material(Main *bmain, - Object *ob_gp, - const float stroke_color[4], - const float fill_color[4], - const bool stroke, - const bool fill, - int *r_index) -{ - Material *mat_gp = BKE_gpencil_object_material_new(bmain, ob_gp, "Material", r_index); - MaterialGPencilStyle *gp_style = mat_gp->gp_style; - - /* Stroke color. */ - if (stroke) { - copy_v4_v4(mat_gp->gp_style->stroke_rgba, stroke_color); - gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - } - - /* Fill color. */ - if (fill) { - copy_v4_v4(mat_gp->gp_style->fill_rgba, fill_color); - gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - - /* Check at least one is enabled. */ - 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; -} - -/* Helper: Create new stroke section. */ -static void gpencil_add_new_points(bGPDstroke *gps, - const float *coord_array, - const float pressure_start, - const float pressure_end, - const int init, - const int totpoints, - const float init_co[3], - const bool last) -{ - BLI_assert(totpoints > 0); - - const float step = 1.0f / (float(totpoints) - 1.0f); - float factor = 0.0f; - for (int i = 0; i < totpoints; i++) { - bGPDspoint *pt = &gps->points[i + init]; - copy_v3_v3(&pt->x, &coord_array[3 * i]); - /* Be sure the last point is not on top of the first point of the curve or - * the close of the stroke will produce glitches. */ - if ((last) && (i > 0) && (i == totpoints - 1)) { - float dist = len_v3v3(init_co, &pt->x); - if (dist < 0.1f) { - /* Interpolate between previous point and current to back slightly. */ - bGPDspoint *pt_prev = &gps->points[i + init - 1]; - interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); - } - } - - pt->strength = 1.0f; - pt->pressure = interpf(pressure_end, pressure_start, factor); - factor += step; - } -} - -/* Helper: Get the first collection that includes the object. */ -static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) -{ - Collection *mycol = nullptr; - FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - if ((mycol == nullptr) && (cob->ob == ob)) { - mycol = collection; - } - } - } - FOREACH_SCENE_COLLECTION_END; - - return mycol; -} -static int gpencil_get_stroke_material_fromcurve( - Main *bmain, Object *ob_gp, Object *ob_cu, bool *r_do_stroke, bool *r_do_fill) -{ - Curve *cu = (Curve *)ob_cu->data; - - Material *mat_gp = nullptr; - Material *mat_curve_stroke = nullptr; - Material *mat_curve_fill = nullptr; - - float color_stroke[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float color_fill[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - /* If the curve has 2 materials, the first is considered as Fill and the second as Stroke. - * If the has only one material, if the name contains "_stroke", - * it's used as a stroke, otherwise as fill. */ - if (ob_cu->totcol >= 2) { - *r_do_stroke = true; - *r_do_fill = true; - mat_curve_fill = BKE_object_material_get(ob_cu, 1); - mat_curve_stroke = BKE_object_material_get(ob_cu, 2); - } - else if (ob_cu->totcol == 1) { - mat_curve_stroke = BKE_object_material_get(ob_cu, 1); - if ((mat_curve_stroke) && (strstr(mat_curve_stroke->id.name, "_stroke") != nullptr)) { - *r_do_stroke = true; - *r_do_fill = false; - mat_curve_fill = nullptr; - } - else { - *r_do_stroke = false; - *r_do_fill = true; - /* Invert materials. */ - mat_curve_fill = mat_curve_stroke; - mat_curve_stroke = nullptr; - } - } - else { - /* No materials in the curve. */ - *r_do_fill = false; - return -1; - } - - if (mat_curve_stroke) { - copy_v4_v4(color_stroke, &mat_curve_stroke->r); - } - if (mat_curve_fill) { - copy_v4_v4(color_fill, &mat_curve_fill->r); - } - - int index = gpencil_check_same_material_color( - ob_gp, color_stroke, color_fill, *r_do_stroke, *r_do_fill, &mat_gp); - - if ((ob_gp->totcol < index) || (index < 0)) { - mat_gp = gpencil_add_from_curve_material( - bmain, ob_gp, color_stroke, color_fill, *r_do_stroke, *r_do_fill, &index); - } - - /* 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_MATERIAL_STROKE_SHOW; - mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW; - } - else { - mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - - return index; -} - -/* Helper: Convert one spline to grease pencil stroke. */ -static void gpencil_convert_spline(Main *bmain, - Object *ob_gp, - Object *ob_cu, - const float scale_thickness, - const float sample, - bGPDframe *gpf, - Nurb *nu) -{ - bGPdata *gpd = (bGPdata *)ob_gp->data; - bool cyclic = true; - - /* Create Stroke. */ - bGPDstroke *gps = static_cast(MEM_callocN(sizeof(bGPDstroke), "bGPDstroke")); - gps->thickness = 1.0f; - gps->fill_opacity_fac = 1.0f; - gps->hardness = 1.0f; - gps->uv_scale = 1.0f; - - ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f); - ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); - gps->inittime = 0.0f; - - gps->flag &= ~GP_STROKE_SELECT; - gps->flag |= GP_STROKE_3DSPACE; - - gps->mat_nr = 0; - /* Count total points - * The total of points must consider that last point of each segment is equal to the first - * point of next segment. - */ - int totpoints = 0; - int segments = 0; - int resolu = nu->resolu + 1; - segments = nu->pntsu; - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - segments--; - cyclic = false; - } - totpoints = (resolu * segments) - (segments - 1); - - /* Materials - * Notice: The color of the material is the color of viewport and not the final shader color. - */ - bool do_stroke, do_fill; - int index = gpencil_get_stroke_material_fromcurve(bmain, ob_gp, ob_cu, &do_stroke, &do_fill); - CLAMP_MIN(index, 0); - - /* Assign material index to stroke. */ - gps->mat_nr = index; - - /* Add stroke to frame. */ - BLI_addtail(&gpf->strokes, gps); - - float init_co[3]; - - switch (nu->type) { - case CU_POLY: { - /* Allocate memory for storage points. */ - gps->totpoints = nu->pntsu; - gps->points = static_cast( - MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points")); - /* Increase thickness for this type. */ - gps->thickness = 10.0f; - - /* Get all curve points */ - for (int s = 0; s < gps->totpoints; s++) { - BPoint *bp = &nu->bp[s]; - bGPDspoint *pt = &gps->points[s]; - copy_v3_v3(&pt->x, bp->vec); - pt->pressure = bp->radius; - pt->strength = 1.0f; - } - break; - } - case CU_BEZIER: { - /* Allocate memory for storage points. */ - gps->totpoints = totpoints; - gps->points = static_cast( - MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points")); - - int init = 0; - resolu = nu->resolu + 1; - segments = nu->pntsu; - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - segments--; - } - /* Get all interpolated curve points of Bezier. */ - for (int s = 0; s < segments; s++) { - int inext = (s + 1) % nu->pntsu; - BezTriple *prevbezt = &nu->bezt[s]; - BezTriple *bezt = &nu->bezt[inext]; - bool last = bool(s == segments - 1); - - float *coord_array = static_cast( - MEM_callocN(sizeof(float[3]) * resolu, __func__)); - for (int j = 0; j < 3; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], - prevbezt->vec[2][j], - bezt->vec[0][j], - bezt->vec[1][j], - coord_array + j, - resolu - 1, - sizeof(float[3])); - } - /* Save first point coordinates. */ - if (s == 0) { - copy_v3_v3(init_co, &coord_array[0]); - } - /* Add points to the stroke */ - float radius_start = prevbezt->radius * scale_thickness; - float radius_end = bezt->radius * scale_thickness; - - gpencil_add_new_points( - gps, coord_array, radius_start, radius_end, init, resolu, init_co, last); - - /* Free memory. */ - MEM_freeN(coord_array); - - /* As the last point of segment is the first point of next segment, back one array - * element to avoid duplicated points on the same location. - */ - init += resolu - 1; - } - break; - } - case CU_NURBS: { - if (nu->pntsv == 1) { - - int nurb_points; - if (nu->flagu & CU_NURB_CYCLIC) { - resolu++; - nurb_points = nu->pntsu * resolu; - } - else { - nurb_points = (nu->pntsu - 1) * resolu; - } - /* Get all curve points. */ - float *coord_array = static_cast( - MEM_callocN(sizeof(float[3]) * nurb_points, __func__)); - BKE_nurb_makeCurve(nu, coord_array, nullptr, nullptr, nullptr, resolu, sizeof(float[3])); - - /* Allocate memory for storage points. */ - gps->totpoints = nurb_points; - gps->points = static_cast( - MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points")); - - /* Add points. */ - gpencil_add_new_points(gps, coord_array, 1.0f, 1.0f, 0, gps->totpoints, init_co, false); - - MEM_freeN(coord_array); - } - break; - } - default: { - break; - } - } - /* Cyclic curve, close stroke. */ - if (cyclic) { - BKE_gpencil_stroke_close(gps); - } - - if (sample > 0.0f) { - BKE_gpencil_stroke_sample(gpd, gps, sample, false, 0); - } - - /* Recalc fill geometry. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); -} - static void gpencil_editstroke_deselect_all(bGPDcurve *gpc) { for (int i = 0; i < gpc->tot_curve_points; i++) { @@ -464,80 +55,6 @@ static void gpencil_editstroke_deselect_all(bGPDcurve *gpc) gpc->flag &= ~GP_CURVE_SELECT; } -void BKE_gpencil_convert_curve(Main *bmain, - Scene *scene, - Object *ob_gp, - Object *ob_cu, - const bool use_collections, - const float scale_thickness, - const float sample) -{ - if (ELEM(nullptr, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL_LEGACY) || - (ob_gp->data == nullptr)) - { - return; - } - - Curve *cu = (Curve *)ob_cu->data; - bGPdata *gpd = (bGPdata *)ob_gp->data; - bGPDlayer *gpl = nullptr; - - /* If the curve is empty, cancel. */ - if (cu->nurb.first == nullptr) { - return; - } - - /* Check if there is an active layer. */ - if (use_collections) { - Collection *collection = gpencil_get_parent_collection(scene, ob_cu); - if (collection != nullptr) { - gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2); - if (gpl == nullptr) { - gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true, false); - } - } - } - - if (gpl == nullptr) { - gpl = BKE_gpencil_layer_active_get(gpd); - if (gpl == nullptr) { - gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false); - } - } - - /* Check if there is an active frame and add if needed. */ - bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_ADD_COPY); - - /* Read all splines of the curve and create a stroke for each. */ - LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { - gpencil_convert_spline(bmain, ob_gp, ob_cu, scale_thickness, sample, gpf, nu); - } - - /* Merge any similar material. */ - int removed = 0; - BKE_gpencil_merge_materials(ob_gp, 0.001f, 0.001f, 0.001f, &removed); - - /* Remove any unused slot. */ - int actcol = ob_gp->actcol; - - for (int slot = 1; slot <= ob_gp->totcol; slot++) { - while (slot <= ob_gp->totcol && !BKE_object_material_slot_used(ob_gp, slot)) { - ob_gp->actcol = slot; - BKE_object_material_slot_remove(bmain, ob_gp); - - if (actcol >= slot) { - actcol--; - } - } - } - - ob_gp->actcol = actcol; - - /* Tag for recalculation */ - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL); - DEG_id_tag_update(&ob_gp->id, ID_RECALC_GEOMETRY); -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -729,28 +246,6 @@ bGPDcurve *BKE_gpencil_stroke_editcurve_generate(bGPDstroke *gps, return editcurve; } -void BKE_gpencil_stroke_editcurve_update(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps) -{ - if (gps == nullptr || gps->totpoints < 0) { - return; - } - - if (gps->editcurve != nullptr) { - BKE_gpencil_free_stroke_editcurve(gps); - } - - float defaultpixsize = 1000.0f / gpd->pixfactor; - float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f; - - bGPDcurve *editcurve = BKE_gpencil_stroke_editcurve_generate( - gps, gpd->curve_edit_threshold, gpd->curve_edit_corner_angle, stroke_radius); - if (editcurve == nullptr) { - return; - } - - gps->editcurve = editcurve; -} - void BKE_gpencil_editcurve_stroke_sync_selection(bGPdata * /*gpd*/, bGPDstroke *gps, bGPDcurve *gpc) @@ -777,346 +272,6 @@ void BKE_gpencil_editcurve_stroke_sync_selection(bGPdata * /*gpd*/, } } -void BKE_gpencil_stroke_editcurve_sync_selection(bGPdata *gpd, bGPDstroke *gps, bGPDcurve *gpc) -{ - if (gpc->flag & GP_CURVE_SELECT) { - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); - - for (int i = 0; i < gpc->tot_curve_points - 1; i++) { - bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - bGPDspoint *pt = &gps->points[gpc_pt->point_index]; - bGPDcurve_point *gpc_pt_next = &gpc->curve_points[i + 1]; - - if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { - pt->flag |= GP_SPOINT_SELECT; - if (gpc_pt_next->flag & GP_CURVE_POINT_SELECT) { - /* select all the points after */ - for (int j = gpc_pt->point_index + 1; j < gpc_pt_next->point_index; j++) { - bGPDspoint *pt_next = &gps->points[j]; - pt_next->flag |= GP_SPOINT_SELECT; - } - } - } - else { - pt->flag &= ~GP_SPOINT_SELECT; - /* deselect all points after */ - for (int j = gpc_pt->point_index + 1; j < gpc_pt_next->point_index; j++) { - bGPDspoint *pt_next = &gps->points[j]; - pt_next->flag &= ~GP_SPOINT_SELECT; - } - } - } - - bGPDcurve_point *gpc_first = &gpc->curve_points[0]; - bGPDcurve_point *gpc_last = &gpc->curve_points[gpc->tot_curve_points - 1]; - bGPDspoint *last_pt = &gps->points[gpc_last->point_index]; - if (gpc_last->flag & GP_CURVE_POINT_SELECT) { - last_pt->flag |= GP_SPOINT_SELECT; - } - else { - last_pt->flag &= ~GP_SPOINT_SELECT; - } - - if (gps->flag & GP_STROKE_CYCLIC) { - if (gpc_first->flag & GP_CURVE_POINT_SELECT && gpc_last->flag & GP_CURVE_POINT_SELECT) { - for (int i = gpc_last->point_index + 1; i < gps->totpoints; i++) { - bGPDspoint *pt_next = &gps->points[i]; - pt_next->flag |= GP_SPOINT_SELECT; - } - } - else { - for (int i = gpc_last->point_index + 1; i < gps->totpoints; i++) { - bGPDspoint *pt_next = &gps->points[i]; - pt_next->flag &= ~GP_SPOINT_SELECT; - } - } - } - } - else { - gps->flag &= ~GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_reset(gps); - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - pt->flag &= ~GP_SPOINT_SELECT; - } - } -} - -static void gpencil_interpolate_fl_from_to( - float from, float to, float *point_offset, int it, int stride) -{ - /* smooth interpolation */ - float *r = point_offset; - for (int i = 0; i <= it; i++) { - float fac = float(i) / float(it); - fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; /* Smooth. */ - *r = interpf(to, from, fac); - r = static_cast(POINTER_OFFSET(r, stride)); - } -} - -static void gpencil_interpolate_v4_from_to( - float from[4], float to[4], float *point_offset, int it, int stride) -{ - /* smooth interpolation */ - float *r = point_offset; - for (int i = 0; i <= it; i++) { - float fac = float(i) / float(it); - fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; /* Smooth. */ - interp_v4_v4v4(r, from, to, fac); - r = static_cast(POINTER_OFFSET(r, stride)); - } -} - -static float gpencil_approximate_curve_segment_arclength(bGPDcurve_point *cpt_start, - bGPDcurve_point *cpt_end) -{ - BezTriple *bezt_start = &cpt_start->bezt; - BezTriple *bezt_end = &cpt_end->bezt; - - float chord_len = len_v3v3(bezt_start->vec[1], bezt_end->vec[1]); - float net_len = len_v3v3(bezt_start->vec[1], bezt_start->vec[2]); - net_len += len_v3v3(bezt_start->vec[2], bezt_end->vec[0]); - net_len += len_v3v3(bezt_end->vec[0], bezt_end->vec[1]); - - return (chord_len + net_len) / 2.0f; -} - -static void gpencil_calculate_stroke_points_curve_segment( - bGPDcurve_point *cpt, bGPDcurve_point *cpt_next, float *points_offset, int resolu, int stride) -{ - /* sample points on all 3 axis between two curve points */ - for (uint axis = 0; axis < 3; axis++) { - BKE_curve_forward_diff_bezier( - cpt->bezt.vec[1][axis], - cpt->bezt.vec[2][axis], - cpt_next->bezt.vec[0][axis], - cpt_next->bezt.vec[1][axis], - static_cast(POINTER_OFFSET(points_offset, sizeof(float) * axis)), - int(resolu), - stride); - } - - /* interpolate other attributes */ - gpencil_interpolate_fl_from_to( - cpt->pressure, - cpt_next->pressure, - static_cast(POINTER_OFFSET(points_offset, sizeof(float) * 3)), - resolu, - stride); - gpencil_interpolate_fl_from_to( - cpt->strength, - cpt_next->strength, - static_cast(POINTER_OFFSET(points_offset, sizeof(float) * 4)), - resolu, - stride); - gpencil_interpolate_v4_from_to( - cpt->vert_color, - cpt_next->vert_color, - static_cast(POINTER_OFFSET(points_offset, sizeof(float) * 5)), - resolu, - stride); -} - -static float *gpencil_stroke_points_from_editcurve_adaptive_resolu( - bGPDcurve_point *curve_point_array, - int curve_point_array_len, - int resolution, - bool is_cyclic, - int *r_points_len) -{ - /* One stride contains: `x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor`. */ - const uint stride = sizeof(float[9]); - const uint cpt_last = curve_point_array_len - 1; - const uint num_segments = (is_cyclic) ? curve_point_array_len : curve_point_array_len - 1; - int *segment_point_lengths = static_cast( - MEM_callocN(sizeof(int) * num_segments, __func__)); - - uint points_len = 1; - for (int i = 0; i < cpt_last; i++) { - bGPDcurve_point *cpt = &curve_point_array[i]; - bGPDcurve_point *cpt_next = &curve_point_array[i + 1]; - float arclen = gpencil_approximate_curve_segment_arclength(cpt, cpt_next); - int segment_resolu = int(floorf(arclen * resolution)); - CLAMP_MIN(segment_resolu, 1); - - segment_point_lengths[i] = segment_resolu; - points_len += segment_resolu; - } - - if (is_cyclic) { - bGPDcurve_point *cpt = &curve_point_array[cpt_last]; - bGPDcurve_point *cpt_next = &curve_point_array[0]; - float arclen = gpencil_approximate_curve_segment_arclength(cpt, cpt_next); - int segment_resolu = int(floorf(arclen * resolution)); - CLAMP_MIN(segment_resolu, 1); - - segment_point_lengths[cpt_last] = segment_resolu; - points_len += segment_resolu; - } - - float(*r_points)[9] = static_cast( - MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__)); - float *points_offset = &r_points[0][0]; - int point_index = 0; - for (int i = 0; i < cpt_last; i++) { - bGPDcurve_point *cpt_curr = &curve_point_array[i]; - bGPDcurve_point *cpt_next = &curve_point_array[i + 1]; - int segment_resolu = segment_point_lengths[i]; - gpencil_calculate_stroke_points_curve_segment( - cpt_curr, cpt_next, points_offset, segment_resolu, stride); - /* update the index */ - cpt_curr->point_index = point_index; - point_index += segment_resolu; - points_offset = static_cast(POINTER_OFFSET(points_offset, segment_resolu * stride)); - } - - bGPDcurve_point *cpt_curr = &curve_point_array[cpt_last]; - cpt_curr->point_index = point_index; - if (is_cyclic) { - bGPDcurve_point *cpt_next = &curve_point_array[0]; - int segment_resolu = segment_point_lengths[cpt_last]; - gpencil_calculate_stroke_points_curve_segment( - cpt_curr, cpt_next, points_offset, segment_resolu, stride); - } - - MEM_freeN(segment_point_lengths); - - *r_points_len = points_len; - return (float *)r_points; -} - -/** - * Helper: calculate the points on a curve with a fixed resolution. - */ -static float *gpencil_stroke_points_from_editcurve_fixed_resolu(bGPDcurve_point *curve_point_array, - int curve_point_array_len, - int resolution, - bool is_cyclic, - int *r_points_len) -{ - /* One stride contains: `x, y, z, pressure, strength, Vr, Vg, Vb, Vmix_factor`. */ - const uint stride = sizeof(float[9]); - const uint array_last = curve_point_array_len - 1; - const uint resolu_stride = resolution * stride; - const uint points_len = BKE_curve_calc_coords_axis_len( - curve_point_array_len, resolution, is_cyclic, false); - - float(*r_points)[9] = static_cast( - MEM_callocN((stride * points_len * (is_cyclic ? 2 : 1)), __func__)); - float *points_offset = &r_points[0][0]; - for (uint i = 0; i < array_last; i++) { - bGPDcurve_point *cpt_curr = &curve_point_array[i]; - bGPDcurve_point *cpt_next = &curve_point_array[i + 1]; - - gpencil_calculate_stroke_points_curve_segment( - cpt_curr, cpt_next, points_offset, resolution, stride); - /* update the index */ - cpt_curr->point_index = i * resolution; - points_offset = static_cast(POINTER_OFFSET(points_offset, resolu_stride)); - } - - bGPDcurve_point *cpt_curr = &curve_point_array[array_last]; - cpt_curr->point_index = array_last * resolution; - if (is_cyclic) { - bGPDcurve_point *cpt_next = &curve_point_array[0]; - gpencil_calculate_stroke_points_curve_segment( - cpt_curr, cpt_next, points_offset, resolution, stride); - } - - *r_points_len = points_len; - return (float *)r_points; -} - -void BKE_gpencil_stroke_update_geometry_from_editcurve(bGPDstroke *gps, - const uint resolution, - const bool adaptive) -{ - if (gps == nullptr || gps->editcurve == nullptr) { - return; - } - - bGPDcurve *editcurve = gps->editcurve; - bGPDcurve_point *curve_point_array = editcurve->curve_points; - int curve_point_array_len = editcurve->tot_curve_points; - if (curve_point_array_len == 0) { - return; - } - /* Handle case for single curve point. */ - if (curve_point_array_len == 1) { - bGPDcurve_point *cpt = &curve_point_array[0]; - /* resize stroke point array */ - gps->totpoints = 1; - gps->points = static_cast( - MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints)); - if (gps->dvert != nullptr) { - gps->dvert = static_cast( - MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints)); - } - - bGPDspoint *pt = &gps->points[0]; - copy_v3_v3(&pt->x, cpt->bezt.vec[1]); - - pt->pressure = cpt->pressure; - pt->strength = cpt->strength; - - copy_v4_v4(pt->vert_color, cpt->vert_color); - - /* deselect */ - pt->flag &= ~GP_SPOINT_SELECT; - gps->flag &= ~GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_reset(gps); - - return; - } - - bool is_cyclic = gps->flag & GP_STROKE_CYCLIC; - - int points_len = 0; - float(*points)[9] = nullptr; - if (adaptive) { - points = (float(*)[9])gpencil_stroke_points_from_editcurve_adaptive_resolu( - curve_point_array, curve_point_array_len, resolution, is_cyclic, &points_len); - } - else { - points = (float(*)[9])gpencil_stroke_points_from_editcurve_fixed_resolu( - curve_point_array, curve_point_array_len, resolution, is_cyclic, &points_len); - } - - if (points == nullptr || points_len == 0) { - return; - } - - /* resize stroke point array */ - gps->totpoints = points_len; - gps->points = static_cast( - MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints)); - if (gps->dvert != nullptr) { - gps->dvert = static_cast( - MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints)); - } - - /* write new data to stroke point array */ - for (int i = 0; i < points_len; i++) { - bGPDspoint *pt = &gps->points[i]; - copy_v3_v3(&pt->x, &points[i][0]); - - pt->pressure = points[i][3]; - pt->strength = points[i][4]; - - copy_v4_v4(pt->vert_color, &points[i][5]); - - /* deselect points */ - pt->flag &= ~GP_SPOINT_SELECT; - } - gps->flag &= ~GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_reset(gps); - - /* free temp data */ - MEM_freeN(points); -} - void BKE_gpencil_editcurve_recalculate_handles(bGPDstroke *gps) { if (gps == nullptr || gps->editcurve == nullptr) { @@ -1325,68 +480,4 @@ void BKE_gpencil_editcurve_subdivide(bGPDstroke *gps, const int cuts) } } -void BKE_gpencil_strokes_selected_update_editcurve(bGPdata *gpd) -{ - const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)); - /* For all selected strokes, update edit curve. */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (!BKE_gpencil_layer_is_editable(gpl)) { - continue; - } - bGPDframe *init_gpf = static_cast((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)) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* skip deselected stroke */ - if (!(gps->flag & GP_STROKE_SELECT)) { - continue; - } - - /* Generate the curve if there is none or the stroke was changed */ - if (gps->editcurve == nullptr) { - BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps); - /* Continue if curve could not be generated. */ - if (gps->editcurve == nullptr) { - continue; - } - } - else if (gps->editcurve->flag & GP_CURVE_NEEDS_STROKE_UPDATE) { - BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps); - } - /* Update the selection from the stroke to the curve. */ - BKE_gpencil_editcurve_stroke_sync_selection(gpd, gps, gps->editcurve); - - gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - BKE_gpencil_stroke_geometry_update(gpd, gps); - } - } - } - } -} - -void BKE_gpencil_strokes_selected_sync_selection_editcurve(bGPdata *gpd) -{ - const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)); - /* Sync selection for all strokes with editcurve. */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (!BKE_gpencil_layer_is_editable(gpl)) { - continue; - } - bGPDframe *init_gpf = static_cast((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)) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - bGPDcurve *gpc = gps->editcurve; - if (gpc != nullptr) { - /* Update the selection of every stroke that has an editcurve */ - BKE_gpencil_stroke_editcurve_sync_selection(gpd, gps, gpc); - } - } - } - } - } -} - /** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc index 9b5d2023c40..a7fe04b62b2 100644 --- a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc @@ -122,833 +122,6 @@ void BKE_gpencil_stroke_boundingbox_calc(bGPDstroke *gps) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Stroke Sample - * \{ */ - -static int stroke_march_next_point(const bGPDstroke *gps, - const int index_next_pt, - const float *current, - const float dist, - float *result, - float *pressure, - float *strength, - float *vert_color, - float *uv_fac, - float *uv_fill, - float *uv_rot, - float *ratio_result, - int *index_from, - int *index_to) -{ - float remaining_till_next = 0.0f; - float remaining_march = dist; - float step_start[3]; - float point[3]; - int next_point_index = index_next_pt; - bGPDspoint *pt = nullptr; - - if (next_point_index == gps->totpoints) { - next_point_index = 0; - } - - copy_v3_v3(step_start, current); - pt = &gps->points[next_point_index]; - copy_v3_v3(point, &pt->x); - remaining_till_next = len_v3v3(point, step_start); - - while (remaining_till_next < remaining_march && next_point_index) { - remaining_march -= remaining_till_next; - pt = &gps->points[next_point_index]; - if (pt->flag & GP_SPOINT_TEMP_TAG) { - pt = &gps->points[next_point_index]; - copy_v3_v3(result, &pt->x); - *pressure = gps->points[next_point_index].pressure; - *strength = gps->points[next_point_index].strength; - memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float[4])); - - *index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1); - *index_to = next_point_index; - *ratio_result = 1.0f; - next_point_index++; - return next_point_index == 0 ? gps->totpoints : next_point_index; - } - next_point_index++; - copy_v3_v3(point, &pt->x); - copy_v3_v3(step_start, point); - if (!(next_point_index < gps->totpoints)) { - if (gps->flag & GP_STROKE_CYCLIC) { - next_point_index = 0; - } - else { - next_point_index = gps->totpoints - 1; - remaining_till_next = 0; - break; - } - } - pt = &gps->points[next_point_index]; - copy_v3_v3(point, &pt->x); - remaining_till_next = len_v3v3(point, step_start); - } - if (remaining_till_next < remaining_march) { - pt = &gps->points[next_point_index]; - copy_v3_v3(result, &pt->x); - *pressure = gps->points[next_point_index].pressure; - *strength = gps->points[next_point_index].strength; - memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float[4])); - - *index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1); - *index_to = next_point_index; - *ratio_result = 1.0f; - - return 0; - } - - *index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1); - *index_to = next_point_index; - - float ratio = remaining_march / remaining_till_next; - interp_v3_v3v3(result, step_start, point, ratio); - *ratio_result = ratio; - float d1 = len_v3v3(result, &gps->points[*index_from].x); - float d2 = len_v3v3(result, &gps->points[next_point_index].x); - float vratio = d1 / (d1 + d2); - - *pressure = interpf( - gps->points[next_point_index].pressure, gps->points[*index_from].pressure, vratio); - *strength = interpf( - gps->points[next_point_index].strength, gps->points[*index_from].strength, vratio); - *uv_fac = interpf(gps->points[next_point_index].uv_fac, gps->points[*index_from].uv_fac, vratio); - *uv_rot = interpf(gps->points[next_point_index].uv_rot, gps->points[*index_from].uv_rot, vratio); - interp_v2_v2v2( - uv_fill, gps->points[*index_from].uv_fill, gps->points[next_point_index].uv_fill, vratio); - interp_v4_v4v4(vert_color, - gps->points[*index_from].vert_color, - gps->points[next_point_index].vert_color, - vratio); - - return next_point_index == 0 ? gps->totpoints : next_point_index; -} - -static int stroke_march_next_point_no_interp(const bGPDstroke *gps, - const int index_next_pt, - const float *current, - const float dist, - const float sharp_threshold, - float *result) -{ - float remaining_till_next = 0.0f; - float remaining_march = dist; - float step_start[3]; - float point[3]; - int next_point_index = index_next_pt; - bGPDspoint *pt = nullptr; - - if (next_point_index == gps->totpoints) { - next_point_index = 0; - } - - copy_v3_v3(step_start, current); - pt = &gps->points[next_point_index]; - copy_v3_v3(point, &pt->x); - remaining_till_next = len_v3v3(point, step_start); - - while (remaining_till_next < remaining_march && next_point_index) { - remaining_march -= remaining_till_next; - pt = &gps->points[next_point_index]; - if (next_point_index < gps->totpoints - 1 && - angle_v3v3v3(&gps->points[next_point_index - 1].x, - &gps->points[next_point_index].x, - &gps->points[next_point_index + 1].x) < sharp_threshold) - { - copy_v3_v3(result, &pt->x); - pt->flag |= GP_SPOINT_TEMP_TAG; - next_point_index++; - return next_point_index == 0 ? gps->totpoints : next_point_index; - } - next_point_index++; - copy_v3_v3(point, &pt->x); - copy_v3_v3(step_start, point); - if (!(next_point_index < gps->totpoints)) { - if (gps->flag & GP_STROKE_CYCLIC) { - next_point_index = 0; - } - else { - next_point_index = gps->totpoints - 1; - remaining_till_next = 0; - break; - } - } - pt = &gps->points[next_point_index]; - copy_v3_v3(point, &pt->x); - remaining_till_next = len_v3v3(point, step_start); - } - if (remaining_till_next < remaining_march) { - pt = &gps->points[next_point_index]; - copy_v3_v3(result, &pt->x); - /* Stroke marching only terminates here. */ - return 0; - } - - float ratio = remaining_march / remaining_till_next; - interp_v3_v3v3(result, step_start, point, ratio); - return next_point_index == 0 ? gps->totpoints : next_point_index; -} - -static int stroke_march_count(const bGPDstroke *gps, const float dist, const float sharp_threshold) -{ - int point_count = 0; - float point[3]; - int next_point_index = 1; - bGPDspoint *pt = nullptr; - - pt = &gps->points[0]; - copy_v3_v3(point, &pt->x); - point_count++; - - /* Sharp points will be tagged by the stroke_march_next_point_no_interp() call below. */ - for (int i = 0; i < gps->totpoints; i++) { - gps->points[i].flag &= (~GP_SPOINT_TEMP_TAG); - } - - while ((next_point_index = stroke_march_next_point_no_interp( - gps, next_point_index, point, dist, sharp_threshold, point)) > -1) - { - point_count++; - if (next_point_index == 0) { - break; /* last point finished */ - } - } - return point_count; -} - -static void stroke_defvert_create_nr_list(MDeformVert *dv_list, - int count, - ListBase *result, - int *totweight) -{ - LinkData *ld; - MDeformVert *dv; - MDeformWeight *dw; - int i, j; - int tw = 0; - for (i = 0; i < count; i++) { - dv = &dv_list[i]; - - /* find def_nr in list, if not exist, then create one */ - for (j = 0; j < dv->totweight; j++) { - bool found = false; - dw = &dv->dw[j]; - LISTBASE_FOREACH (LinkData *, ld, result) { - if (ld->data == POINTER_FROM_INT(dw->def_nr)) { - found = true; - break; - } - } - if (!found) { - ld = MEM_cnew("def_nr_item"); - ld->data = POINTER_FROM_INT(dw->def_nr); - BLI_addtail(result, ld); - tw++; - } - } - } - - *totweight = tw; -} - -static MDeformVert *stroke_defvert_new_count(int count, int totweight, ListBase *def_nr_list) -{ - int i, j; - MDeformVert *dst = (MDeformVert *)MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert"); - - for (i = 0; i < count; i++) { - dst[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * totweight, - "new_deformWeight"); - dst[i].totweight = totweight; - j = 0; - /* re-assign deform groups */ - LISTBASE_FOREACH (LinkData *, ld, def_nr_list) { - dst[i].dw[j].def_nr = POINTER_AS_INT(ld->data); - j++; - } - } - - return dst; -} - -static void stroke_interpolate_deform_weights( - bGPDstroke *gps, int index_from, int index_to, float ratio, MDeformVert *vert) -{ - const MDeformVert *vl = &gps->dvert[index_from]; - const MDeformVert *vr = &gps->dvert[index_to]; - - for (int i = 0; i < vert->totweight; i++) { - float wl = BKE_defvert_find_weight(vl, vert->dw[i].def_nr); - float wr = BKE_defvert_find_weight(vr, vert->dw[i].def_nr); - vert->dw[i].weight = interpf(wr, wl, ratio); - } -} - -bool BKE_gpencil_stroke_sample(bGPdata *gpd, - bGPDstroke *gps, - const float dist, - const bool select, - const float sharp_threshold) -{ - bGPDspoint *pt = gps->points; - bGPDspoint *pt1 = nullptr; - bGPDspoint *pt2 = nullptr; - ListBase def_nr_list = {nullptr}; - - if (gps->totpoints < 2 || dist < FLT_EPSILON) { - return false; - } - /* TODO: Implement feature point preservation. */ - int count = stroke_march_count(gps, dist, sharp_threshold); - const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0; - if (is_cyclic) { - count--; - } - - bGPDspoint *new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * count, - "gp_stroke_points_sampled"); - MDeformVert *new_dv = nullptr; - - int result_totweight; - - if (gps->dvert != nullptr) { - stroke_defvert_create_nr_list(gps->dvert, gps->totpoints, &def_nr_list, &result_totweight); - new_dv = stroke_defvert_new_count(count, result_totweight, &def_nr_list); - } - - int next_point_index = 1; - int i = 0; - float pressure, strength, ratio_result; - float uv_fac, uv_rot, uv_fill[2]; - float vert_color[4]; - int index_from, index_to; - float last_coord[3]; - - /* 1st point is always at the start */ - pt1 = &gps->points[0]; - copy_v3_v3(last_coord, &pt1->x); - pt2 = &new_pt[i]; - copy_v3_v3(&pt2->x, last_coord); - new_pt[i].pressure = pt[0].pressure; - new_pt[i].strength = pt[0].strength; - copy_v3_v3(&pt2->x, last_coord); - new_pt[i].pressure = pt[0].pressure; - new_pt[i].strength = pt[0].strength; - new_pt[i].uv_fac = pt[0].uv_fac; - new_pt[i].uv_rot = pt[0].uv_rot; - copy_v2_v2(new_pt[i].uv_fill, pt[0].uv_fill); - copy_v4_v4(new_pt[i].vert_color, pt[0].vert_color); - if (select) { - new_pt[i].flag |= GP_SPOINT_SELECT; - } - i++; - - if (new_dv) { - stroke_interpolate_deform_weights(gps, 0, 0, 0, &new_dv[0]); - } - - /* The rest. */ - while ((next_point_index = stroke_march_next_point(gps, - next_point_index, - last_coord, - dist, - last_coord, - &pressure, - &strength, - vert_color, - &uv_fac, - uv_fill, - &uv_rot, - &ratio_result, - &index_from, - &index_to)) > -1) - { - if (is_cyclic && next_point_index == 0) { - break; /* last point finished */ - } - pt2 = &new_pt[i]; - copy_v3_v3(&pt2->x, last_coord); - new_pt[i].pressure = pressure; - new_pt[i].strength = strength; - new_pt[i].uv_fac = uv_fac; - new_pt[i].uv_rot = uv_rot; - copy_v2_v2(new_pt[i].uv_fill, uv_fill); - - memcpy(new_pt[i].vert_color, vert_color, sizeof(float[4])); - if (select) { - new_pt[i].flag |= GP_SPOINT_SELECT; - } - - if (new_dv) { - stroke_interpolate_deform_weights(gps, index_from, index_to, ratio_result, &new_dv[i]); - } - - i++; - if (next_point_index == 0) { - break; /* last point finished */ - } - } - - gps->points = new_pt; - /* Free original vertex list. */ - MEM_freeN(pt); - - if (new_dv) { - /* Free original weight data. */ - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - while (LinkData *ld = (LinkData *)BLI_pophead(&def_nr_list)) { - MEM_freeN(ld); - } - - gps->dvert = new_dv; - } - - BLI_assert(i == count); - gps->totpoints = i; - - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); - - return true; -} - -/** - * Give extra stroke points before and after the original tip points. - * \param gps: Target stroke - * \param count_before: how many extra points to be added before a stroke - * \param count_after: how many extra points to be added after a stroke - */ -static bool BKE_gpencil_stroke_extra_points(bGPDstroke *gps, - const int count_before, - const int count_after) -{ - bGPDspoint *pts = gps->points; - - BLI_assert(count_before >= 0); - BLI_assert(count_after >= 0); - if (!count_before && !count_after) { - return false; - } - - const int new_count = count_before + count_after + gps->totpoints; - - bGPDspoint *new_pts = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, __func__); - - for (int i = 0; i < count_before; i++) { - new_pts[i] = blender::dna::shallow_copy(pts[0]); - } - memcpy(static_cast(&new_pts[count_before]), pts, sizeof(bGPDspoint) * gps->totpoints); - for (int i = new_count - count_after; i < new_count; i++) { - new_pts[i] = blender::dna::shallow_copy(pts[gps->totpoints - 1]); - } - - if (gps->dvert) { - MDeformVert *new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count, __func__); - - for (int i = 0; i < new_count; i++) { - MDeformVert *dv = &gps->dvert[std::clamp(i - count_before, 0, gps->totpoints - 1)]; - int inew = i; - new_dv[inew].flag = dv->flag; - new_dv[inew].totweight = dv->totweight; - new_dv[inew].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, - __func__); - memcpy(new_dv[inew].dw, dv->dw, sizeof(MDeformWeight) * dv->totweight); - } - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - gps->dvert = new_dv; - } - - MEM_freeN(gps->points); - gps->points = new_pts; - gps->totpoints = new_count; - - return true; -} - -bool BKE_gpencil_stroke_stretch(bGPDstroke *gps, - const float dist, - const float overshoot_fac, - const short mode, - const bool follow_curvature, - const int extra_point_count, - const float segment_influence, - const float max_angle, - const bool invert_curvature) -{ -#define BOTH 0 -#define START 1 -#define END 2 - - const bool do_start = ELEM(mode, BOTH, START); - const bool do_end = ELEM(mode, BOTH, END); - float used_percent_length = overshoot_fac; - CLAMP(used_percent_length, 1e-4f, 1.0f); - if (!isfinite(used_percent_length)) { - /* #used_percent_length must always be finite, otherwise a segfault occurs. - * Since this function should never segfault, set #used_percent_length to a safe fallback. */ - /* NOTE: This fallback is used if `gps->totpoints == 2`, see `MOD_gpencil_legacy_length.cc`. */ - used_percent_length = 0.1f; - } - - if (gps->totpoints <= 1 || dist < FLT_EPSILON || extra_point_count <= 0) { - return false; - } - - /* NOTE: When it's just a straight line, we don't need to do the curvature stuff. */ - if (!follow_curvature || gps->totpoints <= 2) { - /* Not following curvature, just straight line. */ - /* NOTE: #overshoot_point_param can not be zero. */ - float overshoot_point_param = used_percent_length * (gps->totpoints - 1); - float result[3]; - - if (do_start) { - int index1 = floor(overshoot_point_param); - int index2 = ceil(overshoot_point_param); - interp_v3_v3v3(result, - &gps->points[index1].x, - &gps->points[index2].x, - fmodf(overshoot_point_param, 1.0f)); - sub_v3_v3(result, &gps->points[0].x); - if (UNLIKELY(is_zero_v3(result))) { - sub_v3_v3v3(result, &gps->points[1].x, &gps->points[0].x); - } - madd_v3_v3fl(&gps->points[0].x, result, -dist / len_v3(result)); - } - - if (do_end) { - int index1 = gps->totpoints - 1 - floor(overshoot_point_param); - int index2 = gps->totpoints - 1 - ceil(overshoot_point_param); - interp_v3_v3v3(result, - &gps->points[index1].x, - &gps->points[index2].x, - fmodf(overshoot_point_param, 1.0f)); - sub_v3_v3(result, &gps->points[gps->totpoints - 1].x); - if (UNLIKELY(is_zero_v3(result))) { - sub_v3_v3v3( - result, &gps->points[gps->totpoints - 2].x, &gps->points[gps->totpoints - 1].x); - } - madd_v3_v3fl(&gps->points[gps->totpoints - 1].x, result, -dist / len_v3(result)); - } - return true; - } - - /* Curvature calculation. */ - - /* First allocate the new stroke size. */ - const int first_old_index = do_start ? extra_point_count : 0; - const int last_old_index = gps->totpoints - 1 + first_old_index; - const int orig_totpoints = gps->totpoints; - BKE_gpencil_stroke_extra_points(gps, first_old_index, do_end ? extra_point_count : 0); - - /* The fractional amount of points to query when calculating the average curvature of the - * strokes. */ - const float overshoot_parameter = used_percent_length * (orig_totpoints - 2); - int overshoot_pointcount = ceil(overshoot_parameter); - CLAMP(overshoot_pointcount, 1, orig_totpoints - 2); - - /* Do for both sides without code duplication. */ - float no[3], vec1[3], vec2[3], total_angle[3]; - for (int k = 0; k < 2; k++) { - if ((k == 0 && !do_start) || (k == 1 && !do_end)) { - continue; - } - - const int start_i = k == 0 ? first_old_index : - last_old_index; // first_old_index, last_old_index - const int dir_i = 1 - k * 2; // 1, -1 - - sub_v3_v3v3(vec1, &gps->points[start_i + dir_i].x, &gps->points[start_i].x); - zero_v3(total_angle); - float segment_length = normalize_v3(vec1); - float overshoot_length = 0.0f; - - /* Accumulate rotation angle and length. */ - int j = 0; - for (int i = start_i; j < overshoot_pointcount; i += dir_i, j++) { - /* Don't fully add last segment to get continuity in overshoot_fac. */ - float fac = fmin(overshoot_parameter - j, 1.0f); - - /* Read segments. */ - copy_v3_v3(vec2, vec1); - sub_v3_v3v3(vec1, &gps->points[i + dir_i * 2].x, &gps->points[i + dir_i].x); - const float len = normalize_v3(vec1); - float angle = angle_normalized_v3v3(vec1, vec2) * fac; - - /* Add half of both adjacent legs of the current angle. */ - const float added_len = (segment_length + len) * 0.5f * fac; - overshoot_length += added_len; - segment_length = len; - - if (angle > max_angle) { - continue; - } - if (angle > M_PI * 0.995f) { - continue; - } - - angle *= powf(added_len, segment_influence); - - cross_v3_v3v3(no, vec1, vec2); - normalize_v3_length(no, angle); - add_v3_v3(total_angle, no); - } - - if (UNLIKELY(overshoot_length == 0.0f)) { - /* Don't do a proper extension if the used points are all in the same position. */ - continue; - } - - sub_v3_v3v3(vec1, &gps->points[start_i].x, &gps->points[start_i + dir_i].x); - /* In general curvature = 1/radius. For the case without the - * weights introduced by #segment_influence, the calculation is: - * `curvature = delta angle/delta arclength = len_v3(total_angle) / overshoot_length` */ - float curvature = normalize_v3(total_angle) / overshoot_length; - /* Compensate for the weights powf(added_len, segment_influence). */ - curvature /= powf(overshoot_length / fminf(overshoot_parameter, float(j)), segment_influence); - if (invert_curvature) { - curvature = -curvature; - } - const float angle_step = curvature * dist / extra_point_count; - float step_length = dist / extra_point_count; - if (fabsf(angle_step) > FLT_EPSILON) { - /* Make a direct step length from the assigned arc step length. */ - step_length *= sin(angle_step * 0.5f) / (angle_step * 0.5f); - } - else { - zero_v3(total_angle); - } - const float prev_length = normalize_v3_length(vec1, step_length); - - /* Build rotation matrix here to get best performance. */ - float rot[3][3]; - float q[4]; - axis_angle_to_quat(q, total_angle, angle_step); - quat_to_mat3(rot, q); - - /* Rotate the starting direction to account for change in edge lengths. */ - axis_angle_to_quat(q, - total_angle, - fmaxf(0.0f, 1.0f - fabs(segment_influence)) * - (curvature * prev_length - angle_step) / 2.0f); - mul_qt_v3(q, vec1); - - /* Now iteratively accumulate the segments with a rotating added direction. */ - for (int i = start_i - dir_i, j = 0; j < extra_point_count; i -= dir_i, j++) { - mul_v3_m3v3(vec1, rot, vec1); - add_v3_v3v3(&gps->points[i].x, vec1, &gps->points[i + dir_i].x); - } - } - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Stroke Trim - * \{ */ - -bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, - const int index_from, - const int index_to, - const bool keep_point) -{ - bGPDspoint *pt = gps->points, *new_pt; - MDeformVert *dv, *new_dv; - - const int new_count = index_to - index_from + 1; - - if (new_count >= gps->totpoints) { - return false; - } - - if ((!keep_point) && (new_count == 1)) { - if (gps->dvert) { - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - } - MEM_freeN(gps->points); - gps->points = nullptr; - gps->dvert = nullptr; - gps->totpoints = 0; - return false; - } - - new_pt = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed"); - memcpy(static_cast(new_pt), &pt[index_from], sizeof(bGPDspoint) * new_count); - - if (gps->dvert) { - new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count, - "gp_stroke_dverts_trimmed"); - for (int i = 0; i < new_count; i++) { - dv = &gps->dvert[i + index_from]; - new_dv[i].flag = dv->flag; - new_dv[i].totweight = dv->totweight; - new_dv[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw_trimmed"); - for (int j = 0; j < dv->totweight; j++) { - new_dv[i].dw[j].weight = dv->dw[j].weight; - new_dv[i].dw[j].def_nr = dv->dw[j].def_nr; - } - } - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - gps->dvert = new_dv; - } - - MEM_freeN(gps->points); - gps->points = new_pt; - gps->totpoints = new_count; - - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Stroke Split - * \{ */ - -bool BKE_gpencil_stroke_split(bGPdata *gpd, - bGPDframe *gpf, - bGPDstroke *gps, - const int before_index, - bGPDstroke **remaining_gps) -{ - bGPDstroke *new_gps; - bGPDspoint *pt = gps->points, *new_pt; - MDeformVert *dv, *new_dv; - - if (before_index >= gps->totpoints || before_index == 0) { - return false; - } - - const int new_count = gps->totpoints - before_index; - const int old_count = before_index; - - /* Handle remaining segments first. */ - - 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. */ - memcpy(static_cast(new_pt), &pt[before_index], sizeof(bGPDspoint) * new_count); - - if (gps->dvert) { - new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count, - "gp_stroke_dverts_remaining(MDeformVert)"); - for (int i = 0; i < new_count; i++) { - dv = &gps->dvert[i + before_index]; - new_dv[i].flag = dv->flag; - new_dv[i].totweight = dv->totweight; - new_dv[i].dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw_remaining(MDeformWeight)"); - for (int j = 0; j < dv->totweight; j++) { - new_dv[i].dw[j].weight = dv->dw[j].weight; - new_dv[i].dw[j].def_nr = dv->dw[j].def_nr; - } - } - new_gps->dvert = new_dv; - } - - (*remaining_gps) = new_gps; - - /* Trim the original stroke into a shorter one. - * Keep the end point. */ - - BKE_gpencil_stroke_trim_points(gps, 0, old_count, false); - BKE_gpencil_stroke_geometry_update(gpd, gps); - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Stroke Shrink - * \{ */ - -bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mode) -{ -#define START 1 -#define END 2 - - bGPDspoint *pt = gps->points, *second_last; - int i; - - if (gps->totpoints < 2) { - if (gps->totpoints == 1) { - second_last = &pt[1]; - if (len_v3v3(&second_last->x, &pt->x) < dist) { - BKE_gpencil_stroke_trim_points(gps, 0, 0, false); - return true; - } - } - - return false; - } - - second_last = &pt[gps->totpoints - 2]; - - float len; - float len1, cut_len1; - float len2, cut_len2; - len1 = len2 = cut_len1 = cut_len2 = 0.0f; - - int index_start = 0; - int index_end = 0; - if (mode == START) { - i = 0; - index_end = gps->totpoints - 1; - while (len1 < dist && gps->totpoints > i + 1) { - len = len_v3v3(&pt[i].x, &pt[i + 1].x); - len1 += len; - cut_len1 = len1 - dist; - i++; - } - index_start = i - 1; - interp_v3_v3v3(&pt[index_start].x, &pt[index_start + 1].x, &pt[index_start].x, cut_len1 / len); - } - - if (mode == END) { - index_start = 0; - i = 2; - while (len2 < dist && gps->totpoints >= i) { - second_last = &pt[gps->totpoints - i]; - len = len_v3v3(&second_last[1].x, &second_last->x); - len2 += len; - cut_len2 = len2 - dist; - i++; - } - index_end = gps->totpoints - i + 2; - interp_v3_v3v3(&pt[index_end].x, &pt[index_end - 1].x, &pt[index_end].x, cut_len2 / len); - } - - if (index_end <= index_start) { - index_start = index_end = 0; /* empty stroke */ - } - - if ((index_end == index_start + 1) && (cut_len1 + cut_len2 < 0)) { - index_start = index_end = 0; /* no length left to cut */ - } - - BKE_gpencil_stroke_trim_points(gps, index_start, index_end, false); - - if (gps->totpoints == 0) { - return false; - } - - return true; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Stroke Smooth Positions * \{ */ @@ -1589,28 +762,12 @@ void BKE_gpencil_stroke_uv_update(bGPDstroke *gps) } } -void BKE_gpencil_stroke_geometry_update(bGPdata *gpd, bGPDstroke *gps) +void BKE_gpencil_stroke_geometry_update(bGPdata * /*gpd*/, bGPDstroke *gps) { if (gps == nullptr) { return; } - if (gps->editcurve != nullptr) { - if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) { - /* curve geometry was updated: stroke needs recalculation */ - if (gps->flag & GP_STROKE_NEEDS_CURVE_UPDATE) { - bool is_adaptive = gpd->flag & GP_DATA_CURVE_ADAPTIVE_RESOLUTION; - BKE_gpencil_stroke_update_geometry_from_editcurve( - gps, gpd->curve_edit_resolution, is_adaptive); - gps->flag &= ~GP_STROKE_NEEDS_CURVE_UPDATE; - } - } - else { - /* stroke geometry was updated: editcurve needs recalculation */ - gps->editcurve->flag |= GP_CURVE_NEEDS_STROKE_UPDATE; - } - } - if (gps->totpoints > 2) { BKE_gpencil_stroke_fill_triangulate(gps); } @@ -1856,94 +1013,6 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Dissolve Points - * \{ */ - -void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps, const short tag) -{ - bGPDspoint *pt; - MDeformVert *dvert = nullptr; - int i; - - int tot = gps->totpoints; /* number of points in new buffer */ - /* first pass: count points to remove */ - /* Count how many points are selected (i.e. how many to remove) */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & tag) { - /* selected point - one of the points to remove */ - tot--; - } - } - - /* if no points are left, we simply delete the entire stroke */ - if (tot <= 0) { - /* remove the entire stroke */ - if (gps->points) { - MEM_freeN(gps->points); - } - if (gps->dvert) { - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - } - if (gps->triangles) { - MEM_freeN(gps->triangles); - } - BLI_freelinkN(&gpf->strokes, gps); - } - else { - /* just copy all points to keep into a smaller buffer */ - bGPDspoint *new_points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * tot, - "new gp stroke points copy"); - bGPDspoint *npt = new_points; - - MDeformVert *new_dvert = nullptr; - MDeformVert *ndvert = nullptr; - - if (gps->dvert != nullptr) { - new_dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * tot, - "new gp stroke weights copy"); - ndvert = new_dvert; - } - - (gps->dvert != nullptr) ? dvert = gps->dvert : nullptr; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((pt->flag & tag) == 0) { - *npt = blender::dna::shallow_copy(*pt); - npt++; - - if (gps->dvert != nullptr) { - *ndvert = *dvert; - ndvert->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); - ndvert++; - } - } - if (gps->dvert != nullptr) { - dvert++; - } - } - - /* free the old buffer */ - if (gps->points) { - MEM_freeN(gps->points); - } - if (gps->dvert) { - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - } - - /* save the new buffer */ - gps->points = new_points; - gps->dvert = new_dvert; - gps->totpoints = tot; - - /* triangles cache needs to be recalculated */ - BKE_gpencil_stroke_geometry_update(gpd, gps); - } -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Normal Calculation * \{ */ @@ -1980,819 +1049,6 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3]) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Stroke Simplify - * \{ */ - -void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float epsilon) -{ - bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); - int totpoints = gps->totpoints; - char *marked = nullptr; - char work; - - int start = 0; - int end = gps->totpoints - 1; - - marked = (char *)MEM_callocN(totpoints, "GP marked array"); - marked[start] = 1; - marked[end] = 1; - - work = 1; - int totmarked = 0; - /* while still reducing */ - while (work) { - int ls, le; - work = 0; - - ls = start; - le = start + 1; - - /* while not over interval */ - while (ls < end) { - int max_i = 0; - /* divided to get more control */ - float max_dist = epsilon / 10.0f; - - /* find the next marked point */ - while (marked[le] == 0) { - le++; - } - - for (int i = ls + 1; i < le; i++) { - float point_on_line[3]; - float dist; - - closest_to_line_segment_v3( - point_on_line, &old_points[i].x, &old_points[ls].x, &old_points[le].x); - - dist = len_v3v3(point_on_line, &old_points[i].x); - - if (dist > max_dist) { - max_dist = dist; - max_i = i; - } - } - - if (max_i != 0) { - work = 1; - marked[max_i] = 1; - totmarked++; - } - - ls = le; - le = ls + 1; - } - } - (void)totmarked; /* Quiet set-but-unused warning (may be removed). */ - - /* adding points marked */ - MDeformVert *old_dvert = nullptr; - MDeformVert *dvert_src = nullptr; - - if (gps->dvert != nullptr) { - old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); - } - /* resize gps */ - int j = 0; - for (int i = 0; i < totpoints; i++) { - bGPDspoint *pt_src = &old_points[i]; - bGPDspoint *pt = &gps->points[j]; - - if ((marked[i]) || (i == 0) || (i == totpoints - 1)) { - *pt = blender::dna::shallow_copy(*pt_src); - if (gps->dvert != nullptr) { - dvert_src = &old_dvert[i]; - MDeformVert *dvert = &gps->dvert[j]; - memcpy(dvert, dvert_src, sizeof(MDeformVert)); - if (dvert_src->dw) { - memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight)); - } - } - j++; - } - else { - if (gps->dvert != nullptr) { - dvert_src = &old_dvert[i]; - BKE_gpencil_free_point_weights(dvert_src); - } - } - } - - gps->totpoints = j; - - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); - - MEM_SAFE_FREE(old_points); - MEM_SAFE_FREE(old_dvert); - MEM_SAFE_FREE(marked); -} - -void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps) -{ - if (gps->totpoints < 4) { - return; - } - - /* save points */ - bGPDspoint *old_points = (bGPDspoint *)MEM_dupallocN(gps->points); - MDeformVert *old_dvert = nullptr; - MDeformVert *dvert_src = nullptr; - - if (gps->dvert != nullptr) { - old_dvert = (MDeformVert *)MEM_dupallocN(gps->dvert); - } - - /* resize gps */ - int newtot = (gps->totpoints - 2) / 2; - if ((gps->totpoints % 2) != 0) { - newtot++; - } - newtot += 2; - - gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(*gps->points) * newtot); - if (gps->dvert != nullptr) { - gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot); - } - - int j = 0; - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt_src = &old_points[i]; - bGPDspoint *pt = &gps->points[j]; - - if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) { - *pt = blender::dna::shallow_copy(*pt_src); - if (gps->dvert != nullptr) { - dvert_src = &old_dvert[i]; - MDeformVert *dvert = &gps->dvert[j]; - memcpy(dvert, dvert_src, sizeof(MDeformVert)); - if (dvert_src->dw) { - memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight)); - } - } - j++; - } - else { - if (gps->dvert != nullptr) { - dvert_src = &old_dvert[i]; - BKE_gpencil_free_point_weights(dvert_src); - } - } - } - - gps->totpoints = j; - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); - - MEM_SAFE_FREE(old_points); - MEM_SAFE_FREE(old_dvert); -} - -void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int type) -{ - bGPDspoint *temp_points; - MDeformVert *temp_dverts = nullptr; - MDeformVert *dvert = nullptr; - MDeformVert *dvert_final = nullptr; - MDeformVert *dvert_next = nullptr; - int totnewpoints, oldtotpoints; - - bool cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0; - - for (int s = 0; s < level; s++) { - totnewpoints = gps->totpoints; - if (!cyclic) { - totnewpoints--; - } - /* duplicate points in a temp area */ - temp_points = gps->points; - oldtotpoints = gps->totpoints; - - /* resize the points arrays */ - gps->totpoints += totnewpoints; - gps->points = (bGPDspoint *)MEM_malloc_arrayN(gps->totpoints, sizeof(*gps->points), __func__); - if (gps->dvert != nullptr) { - temp_dverts = gps->dvert; - gps->dvert = (MDeformVert *)MEM_malloc_arrayN(gps->totpoints, sizeof(*gps->dvert), __func__); - } - - /* move points from last to first to new place */ - for (int i = 0; i < oldtotpoints; i++) { - bGPDspoint *pt = &temp_points[i]; - bGPDspoint *pt_final = &gps->points[i * 2]; - - copy_v3_v3(&pt_final->x, &pt->x); - pt_final->pressure = pt->pressure; - pt_final->strength = pt->strength; - pt_final->uv_rot = pt->uv_rot; - pt_final->uv_fac = pt->uv_fac; - pt_final->time = pt->time; - pt_final->flag = pt->flag; - pt_final->runtime.pt_orig = pt->runtime.pt_orig; - pt_final->runtime.idx_orig = pt->runtime.idx_orig; - copy_v4_v4(pt_final->vert_color, pt->vert_color); - copy_v4_v4(pt_final->uv_fill, pt->uv_fill); - - if (gps->dvert != nullptr) { - dvert = &temp_dverts[i]; - dvert_final = &gps->dvert[i * 2]; - dvert_final->totweight = dvert->totweight; - dvert_final->dw = dvert->dw; - } - } - /* interpolate mid points */ - for (int i = cyclic ? 0 : 1, j = cyclic ? oldtotpoints - 1 : 0; i < oldtotpoints; j = i, i++) { - bGPDspoint *pt = &temp_points[j]; - bGPDspoint *next = &temp_points[i]; - bGPDspoint *pt_final = &gps->points[j * 2 + 1]; - - /* add a half way point */ - interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f); - pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f); - pt_final->strength = interpf(pt->strength, next->strength, 0.5f); - pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f); - pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f); - interp_v4_v4v4(pt_final->uv_fill, pt->uv_fill, next->uv_fill, 0.5f); - CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f); - pt_final->time = 0; - pt_final->runtime.pt_orig = nullptr; - pt_final->flag = 0; - interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f); - - if (gps->dvert != nullptr) { - dvert = &temp_dverts[j]; - dvert_next = &temp_dverts[i]; - dvert_final = &gps->dvert[j * 2 + 1]; - - dvert_final->totweight = dvert->totweight; - dvert_final->dw = (MDeformWeight *)MEM_dupallocN(dvert->dw); - - /* interpolate weight values */ - for (int d = 0; d < dvert->totweight; d++) { - MDeformWeight *dw_a = &dvert->dw[d]; - if (dvert_next->totweight > d) { - MDeformWeight *dw_b = &dvert_next->dw[d]; - MDeformWeight *dw_final = &dvert_final->dw[d]; - dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f); - } - } - } - } - - MEM_SAFE_FREE(temp_points); - MEM_SAFE_FREE(temp_dverts); - - /* Move points to smooth stroke (not simple type). */ - if (type != GP_SUBDIV_SIMPLE) { - float mid[3]; - /* extreme points are not changed */ - for (int i = cyclic ? 0 : 2, j = cyclic ? gps->totpoints - 2 : 0; i < gps->totpoints - 2; - j = i, i += 2) - { - bGPDspoint *prev = &gps->points[j + 1]; - bGPDspoint *pt = &gps->points[i]; - bGPDspoint *next = &gps->points[i + 1]; - - /* move point */ - interp_v3_v3v3(mid, &prev->x, &next->x, 0.5f); - interp_v3_v3v3(&pt->x, mid, &pt->x, 0.5f); - } - } - } - - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Merge by Distance - * \{ */ - -void BKE_gpencil_stroke_merge_distance(bGPdata *gpd, - bGPDframe *gpf, - bGPDstroke *gps, - const float threshold, - const bool use_unselected) -{ - bGPDspoint *pt = nullptr; - bGPDspoint *pt_next = nullptr; - float tagged = false; - /* Use square distance to speed up loop */ - const float th_square = threshold * threshold; - /* Need to have something to merge. */ - if (gps->totpoints < 2) { - return; - } - int i = 0; - int step = 1; - while ((i < gps->totpoints - 1) && (i + step < gps->totpoints)) { - pt = &gps->points[i]; - if (pt->flag & GP_SPOINT_TAG) { - i++; - step = 1; - continue; - } - pt_next = &gps->points[i + step]; - /* Do not recalc tagged points. */ - if (pt_next->flag & GP_SPOINT_TAG) { - step++; - continue; - } - /* Check if contiguous points are selected. */ - if (!use_unselected) { - if (((pt->flag & GP_SPOINT_SELECT) == 0) || ((pt_next->flag & GP_SPOINT_SELECT) == 0)) { - i++; - step = 1; - continue; - } - } - float len_square = len_squared_v3v3(&pt->x, &pt_next->x); - if (len_square <= th_square) { - tagged = true; - if (i != gps->totpoints - 1) { - /* Tag second point for delete. */ - pt_next->flag |= GP_SPOINT_TAG; - } - else { - pt->flag |= GP_SPOINT_TAG; - } - /* Jump to next pair of points, keeping first point segment equals. */ - step++; - } - else { - /* Analyze next point. */ - i++; - step = 1; - } - } - - /* Always untag extremes. */ - pt = &gps->points[0]; - pt->flag &= ~GP_SPOINT_TAG; - pt = &gps->points[gps->totpoints - 1]; - pt->flag &= ~GP_SPOINT_TAG; - - /* Dissolve tagged points */ - if (tagged) { - BKE_gpencil_dissolve_points(gpd, gpf, gps, GP_SPOINT_TAG); - } - - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); -} - -struct GpEdge { - uint v1, v2; - /* Coordinates. */ - float v1_co[3], v2_co[3]; - /* Normals. */ - float n1[3], n2[3]; - /* Direction of the segment. */ - float vec[3]; - int flag; -}; - -static int gpencil_next_edge( - GpEdge *gp_edges, int totedges, GpEdge *gped_init, const float threshold, const bool reverse) -{ - int edge = -1; - float last_angle = 999999.0f; - for (int i = 0; i < totedges; i++) { - GpEdge *gped = &gp_edges[i]; - if (gped->flag != 0) { - continue; - } - if (reverse) { - if (gped_init->v1 != gped->v2) { - continue; - } - } - else { - if (gped_init->v2 != gped->v1) { - continue; - } - } - /* Look for straight lines. */ - float angle = angle_v3v3(gped->vec, gped_init->vec); - if ((angle < threshold) && (angle <= last_angle)) { - edge = i; - last_angle = angle; - } - } - - return edge; -} - -static int gpencil_walk_edge(GHash *v_table, - GpEdge *gp_edges, - int totedges, - uint *stroke_array, - int init_idx, - const float angle, - const bool reverse) -{ - GpEdge *gped_init = &gp_edges[init_idx]; - int idx = 1; - int edge = 0; - while (edge > -1) { - edge = gpencil_next_edge(gp_edges, totedges, gped_init, angle, reverse); - if (edge > -1) { - GpEdge *gped = &gp_edges[edge]; - stroke_array[idx] = edge; - gped->flag = 1; - gped_init = &gp_edges[edge]; - idx++; - - /* Avoid following already visited vertices. */ - if (reverse) { - if (BLI_ghash_haskey(v_table, POINTER_FROM_INT(gped->v1))) { - edge = -1; - } - else { - BLI_ghash_insert(v_table, POINTER_FROM_INT(gped->v1), POINTER_FROM_INT(gped->v1)); - } - } - else { - if (BLI_ghash_haskey(v_table, POINTER_FROM_INT(gped->v2))) { - edge = -1; - } - else { - BLI_ghash_insert(v_table, POINTER_FROM_INT(gped->v2), POINTER_FROM_INT(gped->v2)); - } - } - } - } - - return idx; -} - -static void gpencil_generate_edgeloops(Object *ob, - bGPdata *gpd, - bGPDframe *gpf_stroke, - int stroke_mat_index, - const float angle, - const int thickness, - const float offset, - const float matrix[4][4], - const bool use_seams, - const bool use_vgroups) -{ - using namespace blender; - using namespace blender::bke; - Mesh *mesh = (Mesh *)ob->data; - if (mesh->edges_num == 0) { - return; - } - const Span vert_positions = mesh->vert_positions(); - const Span edges = mesh->edges(); - const Span dverts = mesh->deform_verts(); - const blender::Span vert_normals = mesh->vert_normals(); - const bke::AttributeAccessor attributes = mesh->attributes(); - const VArray uv_seams = *attributes.lookup_or_default( - ".uv_seam", AttrDomain::Edge, false); - - /* Arrays for all edge vertices (forward and backward) that form a edge loop. - * This is reused for each edge-loop to create gpencil stroke. */ - uint *stroke = (uint *)MEM_mallocN(sizeof(uint) * mesh->edges_num * 2, __func__); - uint *stroke_fw = (uint *)MEM_mallocN(sizeof(uint) * mesh->edges_num, __func__); - uint *stroke_bw = (uint *)MEM_mallocN(sizeof(uint) * mesh->edges_num, __func__); - - /* Create array with all edges. */ - GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * mesh->edges_num, __func__); - GpEdge *gped = nullptr; - for (int i = 0; i < mesh->edges_num; i++) { - const blender::int2 &edge = edges[i]; - gped = &gp_edges[i]; - copy_v3_v3(gped->n1, vert_normals[edge[0]]); - - gped->v1 = edge[0]; - copy_v3_v3(gped->v1_co, vert_positions[edge[0]]); - - copy_v3_v3(gped->n2, vert_normals[edge[1]]); - gped->v2 = edge[1]; - copy_v3_v3(gped->v2_co, vert_positions[edge[1]]); - - sub_v3_v3v3(gped->vec, vert_positions[edge[0]], vert_positions[edge[1]]); - - /* If use seams, mark as done if not a seam. */ - if ((use_seams) && !uv_seams[i]) { - gped->flag = 1; - } - } - - /* Loop edges to find edgeloops */ - bool pending = true; - int e = 0; - while (pending) { - gped = &gp_edges[e]; - /* Look first unused edge. */ - if (gped->flag != 0) { - e++; - if (e == mesh->edges_num) { - pending = false; - } - continue; - } - /* Add current edge to arrays. */ - stroke_fw[0] = e; - stroke_bw[0] = e; - gped->flag = 1; - - /* Hash used to avoid loop over same vertices. */ - GHash *v_table = BLI_ghash_int_new(__func__); - /* Look forward edges. */ - int totedges = gpencil_walk_edge( - v_table, gp_edges, mesh->edges_num, stroke_fw, e, angle, false); - /* Look backward edges. */ - int totbw = gpencil_walk_edge(v_table, gp_edges, mesh->edges_num, stroke_bw, e, angle, true); - - BLI_ghash_free(v_table, nullptr, nullptr); - - /* Join both arrays. */ - int array_len = 0; - for (int i = totbw - 1; i > 0; i--) { - stroke[array_len] = stroke_bw[i]; - array_len++; - } - for (int i = 0; i < totedges; i++) { - stroke[array_len] = stroke_fw[i]; - array_len++; - } - - /* Create Stroke. */ - bGPDstroke *gps_stroke = BKE_gpencil_stroke_add( - gpf_stroke, std::max(stroke_mat_index, 0), array_len + 1, thickness * thickness, false); - - /* Create dvert data. */ - if (use_vgroups && !dverts.is_empty()) { - gps_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (array_len + 1), - "gp_stroke_dverts"); - } - - /* Create first segment. */ - float fpt[3]; - for (int i = 0; i < array_len + 1; i++) { - int vertex_index = i == 0 ? gp_edges[stroke[0]].v1 : gp_edges[stroke[i - 1]].v2; - /* Add segment. */ - bGPDspoint *pt = &gps_stroke->points[i]; - copy_v3_v3(fpt, vert_normals[vertex_index]); - mul_v3_v3fl(fpt, fpt, offset); - add_v3_v3v3(&pt->x, vert_positions[vertex_index], fpt); - mul_m4_v3(matrix, &pt->x); - - pt->pressure = 1.0f; - pt->strength = 1.0f; - - /* Copy vertex groups from mesh. Assuming they already exist in the same order. */ - if (use_vgroups && !dverts.is_empty()) { - MDeformVert *dv = &gps_stroke->dvert[i]; - const MDeformVert *src_dv = &dverts[vertex_index]; - dv->totweight = src_dv->totweight; - dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, - "gp_stroke_dverts_dw"); - for (int j = 0; j < dv->totweight; j++) { - dv->dw[j].weight = src_dv->dw[j].weight; - dv->dw[j].def_nr = src_dv->dw[j].def_nr; - } - } - } - - BKE_gpencil_stroke_geometry_update(gpd, gps_stroke); - } - - /* Free memory. */ - MEM_SAFE_FREE(stroke); - MEM_SAFE_FREE(stroke_fw); - MEM_SAFE_FREE(stroke_bw); - MEM_SAFE_FREE(gp_edges); -} - -/* Helper: Add gpencil material using material as base. */ -static Material *gpencil_add_material(Main *bmain, - Object *ob_gp, - const char *name, - const float color[4], - const bool use_stroke, - const bool use_fill, - int *r_idx) -{ - Material *mat_gp = BKE_gpencil_object_material_new(bmain, ob_gp, name, r_idx); - MaterialGPencilStyle *gp_style = mat_gp->gp_style; - - /* Stroke color. */ - if (use_stroke) { - ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); - gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - } - else { - copy_v4_v4(gp_style->stroke_rgba, color); - gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - } - - /* Fill color. */ - copy_v4_v4(gp_style->fill_rgba, color); - if (use_fill) { - gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - - /* Check at least one is enabled. */ - 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; -} - -static int gpencil_material_find_index_by_name(Object *ob, const char *name) -{ - for (int i = 0; i < ob->totcol; i++) { - Material *ma = BKE_object_material_get(ob, i + 1); - if ((ma != nullptr) && (ma->gp_style != nullptr) && STREQ(ma->id.name + 2, name)) { - return i; - } - } - - return -1; -} - -/** - * Create the name with the object name and a suffix. - */ -static void make_element_name(const char *obname, const char *name, const int maxlen, char *r_name) -{ - char str[256]; - SNPRINTF(str, "%s_%s", obname, name); - - /* Replace any point by underscore. */ - BLI_string_replace_char(str, '.', '_'); - - BLI_strncpy_utf8(r_name, str, maxlen); -} - -bool BKE_gpencil_convert_mesh(Main *bmain, - Depsgraph *depsgraph, - Scene *scene, - Object *ob_gp, - Object *ob_mesh, - const float angle, - const int thickness, - const float offset, - const float matrix[4][4], - const int frame_offset, - const bool use_seams, - const bool use_faces, - const bool use_vgroups) -{ - using namespace blender; - using namespace blender::bke; - if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL_LEGACY) || - (ob_gp->data == nullptr)) - { - return false; - } - - bGPdata *gpd = (bGPdata *)ob_gp->data; - - /* Use evaluated data to get mesh with all modifiers on top. */ - Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh); - const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); - const Span positions = mesh_eval->vert_positions(); - const OffsetIndices faces = mesh_eval->faces(); - const Span corner_verts = mesh_eval->corner_verts(); - int faces_len = mesh_eval->faces_num; - char element_name[200]; - - /* Need at least an edge. */ - if (mesh_eval->edges_num < 1) { - return false; - } - - /* Create matching vertex groups. */ - BKE_defgroup_copy_list(&gpd->vertex_group_names, &mesh_eval->vertex_group_names); - gpd->vertex_group_active_index = mesh_eval->vertex_group_active_index; - - const float default_colors[2][4] = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}; - /* Lookup existing stroke material on gp object. */ - make_element_name(ob_mesh->id.name + 2, "Stroke", 64, element_name); - int stroke_mat_index = gpencil_material_find_index_by_name(ob_gp, element_name); - - if (stroke_mat_index == -1) { - /* Create new default stroke material as there is no existing material. */ - gpencil_add_material( - bmain, ob_gp, element_name, default_colors[0], true, false, &stroke_mat_index); - } - - /* Export faces as filled strokes. */ - if (use_faces && faces_len > 0) { - /* Read all polygons and create fill for each. */ - make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name); - /* Create Layer and Frame. */ - bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name); - if (gpl_fill == nullptr) { - gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false); - } - bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get( - gpl_fill, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW); - int i; - - const VArray mesh_material_indices = *mesh_eval->attributes().lookup_or_default( - "material_index", AttrDomain::Face, 0); - for (i = 0; i < faces_len; i++) { - const IndexRange face = faces[i]; - - /* Find material. */ - int mat_idx = 0; - Material *ma = BKE_object_material_get(ob_mesh, mesh_material_indices[i] + 1); - make_element_name( - ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name); - mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name); - if (mat_idx == -1) { - float color[4]; - if (ma != nullptr) { - copy_v3_v3(color, &ma->r); - color[3] = 1.0f; - } - else { - copy_v4_v4(color, default_colors[1]); - } - gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx); - } - - bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, face.size(), 10, false); - gps_fill->flag |= GP_STROKE_CYCLIC; - - /* Create dvert data. */ - const Span dverts = mesh_eval->deform_verts(); - if (use_vgroups && !dverts.is_empty()) { - gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * face.size(), - "gp_fill_dverts"); - } - - /* Add points to strokes. */ - for (int j = 0; j < face.size(); j++) { - const int vert = corner_verts[face[j]]; - - bGPDspoint *pt = &gps_fill->points[j]; - copy_v3_v3(&pt->x, positions[vert]); - mul_m4_v3(matrix, &pt->x); - pt->pressure = 1.0f; - pt->strength = 1.0f; - - /* Copy vertex groups from mesh. Assuming they already exist in the same order. */ - if (use_vgroups && !dverts.is_empty()) { - MDeformVert *dv = &gps_fill->dvert[j]; - const MDeformVert *src_dv = &dverts[vert]; - dv->totweight = src_dv->totweight; - dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight, - "gp_fill_dverts_dw"); - for (int k = 0; k < dv->totweight; k++) { - dv->dw[k].weight = src_dv->dw[k].weight; - dv->dw[k].def_nr = src_dv->dw[k].def_nr; - } - } - } - /* If has only 3 points subdivide. */ - if (face.size() == 3) { - BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE); - } - - BKE_gpencil_stroke_geometry_update(gpd, gps_fill); - } - } - - /* Create stroke from edges. */ - - /* Create Layer and Frame. */ - make_element_name(ob_mesh->id.name + 2, "Lines", 128, element_name); - bGPDlayer *gpl_stroke = BKE_gpencil_layer_named_get(gpd, element_name); - if (gpl_stroke == nullptr) { - gpl_stroke = BKE_gpencil_layer_addnew(gpd, element_name, true, false); - } - bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get( - gpl_stroke, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW); - - gpencil_generate_edgeloops(ob_eval, - gpd, - gpf_stroke, - stroke_mat_index, - angle, - thickness, - offset, - matrix, - use_seams, - use_vgroups); - - /* Tag for recalculation */ - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL); - - return true; -} - void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4]) { if (gpd == nullptr) { @@ -3243,112 +1499,6 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd, return new_stroke; } -void BKE_gpencil_curve_delete_tagged_points(bGPdata *gpd, - bGPDframe *gpf, - bGPDstroke *gps, - bGPDstroke *next_stroke, - bGPDcurve *gpc, - int tag_flags) -{ - if (gpc == nullptr) { - return; - } - const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC; - const int idx_last = gpc->tot_curve_points - 1; - bGPDstroke *gps_first = nullptr; - bGPDstroke *gps_last = nullptr; - - int idx_start = 0; - int idx_end = 0; - bool prev_selected = gpc->curve_points[0].flag & tag_flags; - for (int i = 1; i < gpc->tot_curve_points; i++) { - bool selected = gpc->curve_points[i].flag & tag_flags; - if (prev_selected == true && selected == false) { - idx_start = i; - } - /* Island ends if the current point is selected or if we reached the end of the stroke */ - if ((prev_selected == false && selected == true) || (selected == false && i == idx_last)) { - - idx_end = selected ? i - 1 : i; - int island_length = idx_end - idx_start + 1; - - /* If an island has only a single curve point, there is no curve segment, so skip island */ - if (island_length == 1) { - if (is_cyclic) { - if (idx_start > 0 && idx_end < idx_last) { - prev_selected = selected; - continue; - } - } - else { - prev_selected = selected; - continue; - } - } - - bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false, false); - new_stroke->points = nullptr; - new_stroke->flag &= ~GP_STROKE_CYCLIC; - new_stroke->editcurve = BKE_gpencil_stroke_editcurve_new(island_length); - - if (gps_first == nullptr) { - gps_first = new_stroke; - } - - bGPDcurve *new_gpc = new_stroke->editcurve; - memcpy(new_gpc->curve_points, - gpc->curve_points + idx_start, - sizeof(bGPDcurve_point) * island_length); - - BKE_gpencil_editcurve_recalculate_handles(new_stroke); - new_stroke->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, new_stroke); - - if (next_stroke) { - BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke); - } - else { - BLI_addtail(&gpf->strokes, new_stroke); - } - - gps_last = new_stroke; - } - prev_selected = selected; - } - - /* join first and last stroke if cyclic */ - if (is_cyclic && gps_first != nullptr && gps_last != nullptr && gps_first != gps_last) { - bGPDcurve *gpc_first = gps_first->editcurve; - bGPDcurve *gpc_last = gps_last->editcurve; - int first_tot_points = gpc_first->tot_curve_points; - int old_tot_points = gpc_last->tot_curve_points; - - gpc_last->tot_curve_points = first_tot_points + old_tot_points; - gpc_last->curve_points = (bGPDcurve_point *)MEM_recallocN( - gpc_last->curve_points, sizeof(bGPDcurve_point) * gpc_last->tot_curve_points); - /* copy data from first to last */ - memcpy(gpc_last->curve_points + old_tot_points, - gpc_first->curve_points, - sizeof(bGPDcurve_point) * first_tot_points); - - BKE_gpencil_editcurve_recalculate_handles(gps_last); - gps_last->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(gpd, gps_last); - - /* remove first one */ - BLI_remlink(&gpf->strokes, gps_first); - BKE_gpencil_free_stroke(gps_first); - } - - /* Delete the old stroke */ - BLI_remlink(&gpf->strokes, gps); - BKE_gpencil_free_stroke(gps); -} - /* Helper: copy point between strokes */ static void gpencil_stroke_copy_point(bGPDstroke *gps, MDeformVert *dvert, @@ -3531,254 +1681,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, } } -void BKE_gpencil_stroke_start_set(bGPDstroke *gps, int start_idx) -{ - if ((start_idx < 1) || (start_idx >= gps->totpoints) || (gps->totpoints < 2)) { - return; - } - - /* Only cyclic strokes. */ - if ((gps->flag & GP_STROKE_CYCLIC) == 0) { - return; - } - - bGPDstroke *gps_b = BKE_gpencil_stroke_duplicate(gps, true, false); - BKE_gpencil_stroke_trim_points(gps_b, 0, start_idx - 1, true); - BKE_gpencil_stroke_trim_points(gps, start_idx, gps->totpoints - 1, true); - - /* Join both strokes. */ - BKE_gpencil_stroke_join(gps, gps_b, false, false, false, false); - - BKE_gpencil_free_stroke(gps_b); -} - -void BKE_gpencil_stroke_copy_to_keyframes( - bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const bool tail) -{ - GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); - BKE_gpencil_frame_selected_hash(gpd, frame_list); - - GHashIterator gh_iter; - GHASH_ITER (gh_iter, frame_list) { - int cfra = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter)); - - if (gpf->framenum != cfra) { - bGPDframe *gpf_new = BKE_gpencil_layer_frame_find(gpl, cfra); - if (gpf_new == nullptr) { - gpf_new = BKE_gpencil_frame_addnew(gpl, cfra); - } - - if (gpf_new == nullptr) { - continue; - } - - bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true); - if (gps_new == nullptr) { - continue; - } - - if (tail) { - BLI_addhead(&gpf_new->strokes, gps_new); - } - else { - BLI_addtail(&gpf_new->strokes, gps_new); - } - } - } - - /* Free hash table. */ - BLI_ghash_free(frame_list, nullptr, nullptr); -} - /** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Stroke Uniform Subdivide - * \{ */ - -struct tSamplePoint { - tSamplePoint *next, *prev; - float x, y, z; - float pressure, strength, time; - float vertex_color[4]; - MDeformWeight *dw; - int totweight; -}; - -struct tSampleEdge { - float length_sq; - tSamplePoint *from; - tSamplePoint *to; -}; - -/* Helper: creates a tSamplePoint from a bGPDspoint and (optionally) a MDeformVert. */ -static tSamplePoint *new_sample_point_from_gp_point(const bGPDspoint *pt, const MDeformVert *dvert) -{ - tSamplePoint *new_pt = MEM_cnew(__func__); - copy_v3_v3(&new_pt->x, &pt->x); - new_pt->pressure = pt->pressure; - new_pt->strength = pt->strength; - new_pt->time = pt->time; - copy_v4_v4((float *)&new_pt->vertex_color, (float *)&pt->vert_color); - if (dvert != nullptr) { - new_pt->totweight = dvert->totweight; - new_pt->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_pt->totweight, __func__); - for (uint i = 0; i < new_pt->totweight; ++i) { - MDeformWeight *dw = &new_pt->dw[i]; - MDeformWeight *dw_from = &dvert->dw[i]; - dw->def_nr = dw_from->def_nr; - dw->weight = dw_from->weight; - } - } - return new_pt; -} - -/* Helper: creates a tSampleEdge from two tSamplePoints. Also calculates the length (squared) of - * the edge. */ -static tSampleEdge *new_sample_edge_from_sample_points(tSamplePoint *from, tSamplePoint *to) -{ - tSampleEdge *new_edge = MEM_cnew(__func__); - new_edge->from = from; - new_edge->to = to; - new_edge->length_sq = len_squared_v3v3(&from->x, &to->x); - return new_edge; -} - -void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd, - bGPDstroke *gps, - const uint32_t target_number, - const bool select) -{ - /* Stroke needs at least two points and strictly less points than the target number. */ - if (gps == nullptr || gps->totpoints < 2 || gps->totpoints >= target_number) { - return; - } - - const int totpoints = gps->totpoints; - const bool has_dverts = (gps->dvert != nullptr); - const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC); - - ListBase points = {nullptr, nullptr}; - Heap *edges = BLI_heap_new(); - - /* Add all points into list. */ - for (uint32_t i = 0; i < totpoints; ++i) { - bGPDspoint *pt = &gps->points[i]; - MDeformVert *dvert = has_dverts ? &gps->dvert[i] : nullptr; - tSamplePoint *sp = new_sample_point_from_gp_point(pt, dvert); - BLI_addtail(&points, sp); - } - - /* Iterate over edges and insert them into the heap. */ - for (tSamplePoint *pt = ((tSamplePoint *)points.first)->next; pt != nullptr; pt = pt->next) { - tSampleEdge *se = new_sample_edge_from_sample_points(pt->prev, pt); - /* BLI_heap is a min-heap, but we need the largest key to be at the top, so we take the - * negative of the squared length. */ - BLI_heap_insert(edges, -(se->length_sq), se); - } - - if (is_cyclic) { - tSamplePoint *sp_first = (tSamplePoint *)points.first; - tSamplePoint *sp_last = (tSamplePoint *)points.last; - tSampleEdge *se = new_sample_edge_from_sample_points(sp_last, sp_first); - BLI_heap_insert(edges, -(se->length_sq), se); - } - - int num_points_needed = target_number - totpoints; - BLI_assert(num_points_needed > 0); - - while (num_points_needed > 0) { - tSampleEdge *se = (tSampleEdge *)BLI_heap_pop_min(edges); - tSamplePoint *sp = se->from; - tSamplePoint *sp_next = se->to; - - /* Subdivide the edge. */ - tSamplePoint *new_sp = MEM_cnew(__func__); - interp_v3_v3v3(&new_sp->x, &sp->x, &sp_next->x, 0.5f); - new_sp->pressure = interpf(sp->pressure, sp_next->pressure, 0.5f); - new_sp->strength = interpf(sp->strength, sp_next->strength, 0.5f); - new_sp->time = interpf(sp->time, sp_next->time, 0.5f); - interp_v4_v4v4((float *)&new_sp->vertex_color, - (float *)&sp->vertex_color, - (float *)&sp_next->vertex_color, - 0.5f); - if (sp->dw && sp_next->dw) { - new_sp->totweight = std::min(sp->totweight, sp_next->totweight); - new_sp->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * new_sp->totweight, - __func__); - for (uint32_t i = 0; i < new_sp->totweight; ++i) { - MDeformWeight *dw = &new_sp->dw[i]; - MDeformWeight *dw_from = &sp->dw[i]; - MDeformWeight *dw_to = &sp_next->dw[i]; - dw->def_nr = dw_from->def_nr; - dw->weight = interpf(dw_from->weight, dw_to->weight, 0.5f); - } - } - BLI_insertlinkafter(&points, sp, new_sp); - - tSampleEdge *se_prev = new_sample_edge_from_sample_points(sp, new_sp); - tSampleEdge *se_next = new_sample_edge_from_sample_points(new_sp, sp_next); - BLI_heap_insert(edges, -(se_prev->length_sq), se_prev); - BLI_heap_insert(edges, -(se_next->length_sq), se_next); - - MEM_freeN(se); - num_points_needed--; - } - - /* Edges are no longer needed. Heap is freed. */ - BLI_heap_free(edges, (HeapFreeFP)MEM_freeN); - - gps->totpoints = target_number; - gps->points = (bGPDspoint *)MEM_recallocN(gps->points, sizeof(bGPDspoint) * gps->totpoints); - if (has_dverts) { - gps->dvert = (MDeformVert *)MEM_recallocN(gps->dvert, sizeof(MDeformVert) * gps->totpoints); - } - - /* Convert list back to stroke point array. */ - tSamplePoint *sp = (tSamplePoint *)points.first; - for (uint32_t i = 0; i < gps->totpoints && sp; ++i, sp = sp->next) { - bGPDspoint *pt = &gps->points[i]; - MDeformVert *dvert = &gps->dvert[i]; - - copy_v3_v3(&pt->x, &sp->x); - pt->pressure = sp->pressure; - pt->strength = sp->strength; - pt->time = sp->time; - copy_v4_v4((float *)&pt->vert_color, (float *)&sp->vertex_color); - - if (sp->dw) { - dvert->totweight = sp->totweight; - dvert->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dvert->totweight, __func__); - for (uint32_t j = 0; j < dvert->totweight; ++j) { - MDeformWeight *dw = &dvert->dw[j]; - MDeformWeight *dw_from = &sp->dw[j]; - dw->def_nr = dw_from->def_nr; - dw->weight = dw_from->weight; - } - } - if (select) { - pt->flag |= GP_SPOINT_SELECT; - } - } - - if (select) { - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); - } - - /* Free the sample points. Important to use the mutable loop here because we are erasing the list - * elements. */ - LISTBASE_FOREACH_MUTABLE (tSamplePoint *, temp, &points) { - if (temp->dw != nullptr) { - MEM_freeN(temp->dw); - } - MEM_SAFE_FREE(temp); - } - - /* Update the geometry of the stroke. */ - BKE_gpencil_stroke_geometry_update(gpd, gps); -} - void BKE_gpencil_stroke_to_view_space(bGPDstroke *gps, float viewmat[4][4], const float diff_mat[4][4]) @@ -3808,494 +1711,6 @@ void BKE_gpencil_stroke_from_view_space(bGPDstroke *gps, /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Stroke to Perimeter - * \{ */ - -struct tPerimeterPoint { - tPerimeterPoint *next, *prev; - float x, y, z; -}; - -static tPerimeterPoint *new_perimeter_point(const float pt[3]) -{ - tPerimeterPoint *new_pt = MEM_cnew(__func__); - copy_v3_v3(&new_pt->x, pt); - return new_pt; -} - -static int generate_arc_from_point_to_point(ListBase *list, - tPerimeterPoint *from, - tPerimeterPoint *to, - float center_pt[3], - int subdivisions, - bool clockwise) -{ - float vec_from[2]; - float vec_to[2]; - sub_v2_v2v2(vec_from, &from->x, center_pt); - sub_v2_v2v2(vec_to, &to->x, center_pt); - if (is_zero_v2(vec_from) || is_zero_v2(vec_to)) { - return 0; - } - - float dot = dot_v2v2(vec_from, vec_to); - float det = cross_v2v2(vec_from, vec_to); - float angle = clockwise ? M_PI - atan2f(-det, -dot) : atan2f(-det, -dot) + M_PI; - - /* Number of points is 2^(n+1) + 1 on half a circle (n=subdivisions) - * so we multiply by (angle / pi) to get the right amount of - * points to insert. */ - int num_points = int(((1 << (subdivisions + 1)) - 1) * (angle / M_PI)); - if (num_points > 0) { - float angle_incr = angle / float(num_points); - - float vec_p[3]; - float vec_t[3]; - float tmp_angle; - tPerimeterPoint *last_point; - if (clockwise) { - last_point = to; - copy_v2_v2(vec_t, vec_to); - } - else { - last_point = from; - copy_v2_v2(vec_t, vec_from); - } - - for (int i = 0; i < num_points - 1; i++) { - tmp_angle = (i + 1) * angle_incr; - - rotate_v2_v2fl(vec_p, vec_t, tmp_angle); - add_v2_v2(vec_p, center_pt); - vec_p[2] = center_pt[2]; - - tPerimeterPoint *new_point = new_perimeter_point(vec_p); - if (clockwise) { - BLI_insertlinkbefore(list, last_point, new_point); - } - else { - BLI_insertlinkafter(list, last_point, new_point); - } - - last_point = new_point; - } - - return num_points - 1; - } - - return 0; -} - -static int generate_semi_circle_from_point_to_point(ListBase *list, - tPerimeterPoint *from, - tPerimeterPoint *to, - int subdivisions) -{ - int num_points = (1 << (subdivisions + 1)) + 1; - float center_pt[3]; - interp_v3_v3v3(center_pt, &from->x, &to->x, 0.5f); - - float vec_center[2]; - sub_v2_v2v2(vec_center, &from->x, center_pt); - if (is_zero_v2(vec_center)) { - return 0; - } - - float vec_p[3]; - float angle_incr = M_PI / (float(num_points) - 1); - - tPerimeterPoint *last_point = from; - for (int i = 1; i < num_points; i++) { - float angle = i * angle_incr; - - /* Rotate vector around point to get perimeter points. */ - rotate_v2_v2fl(vec_p, vec_center, angle); - add_v2_v2(vec_p, center_pt); - vec_p[2] = center_pt[2]; - - tPerimeterPoint *new_point = new_perimeter_point(vec_p); - BLI_insertlinkafter(list, last_point, new_point); - - last_point = new_point; - } - - return num_points - 1; -} - -static int generate_perimeter_cap(const float point[4], - const float other_point[4], - float radius, - ListBase *list, - int subdivisions, - short cap_type) -{ - float cap_vec[2]; - sub_v2_v2v2(cap_vec, other_point, point); - normalize_v2(cap_vec); - - float cap_nvec[2]; - if (is_zero_v2(cap_vec)) { - cap_nvec[0] = 0; - cap_nvec[1] = radius; - } - else { - cap_nvec[0] = -cap_vec[1]; - cap_nvec[1] = cap_vec[0]; - mul_v2_fl(cap_nvec, radius); - } - float cap_nvec_inv[2]; - negate_v2_v2(cap_nvec_inv, cap_nvec); - - float vec_perimeter[3]; - copy_v3_v3(vec_perimeter, point); - add_v2_v2(vec_perimeter, cap_nvec); - - float vec_perimeter_inv[3]; - copy_v3_v3(vec_perimeter_inv, point); - add_v2_v2(vec_perimeter_inv, cap_nvec_inv); - - tPerimeterPoint *p_pt = new_perimeter_point(vec_perimeter); - tPerimeterPoint *p_pt_inv = new_perimeter_point(vec_perimeter_inv); - - BLI_addtail(list, p_pt); - BLI_addtail(list, p_pt_inv); - - int num_points = 0; - if (cap_type == GP_STROKE_CAP_ROUND) { - num_points += generate_semi_circle_from_point_to_point(list, p_pt, p_pt_inv, subdivisions); - } - - return num_points + 2; -} - -/** - * Calculate the perimeter (outline) of a stroke as list of tPerimeterPoint. - * \param subdivisions: Number of subdivisions for the start and end caps - * \return list of tPerimeterPoint. - */ -static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd, - const bGPDlayer *gpl, - const bGPDstroke *gps, - int subdivisions, - const float thickness_chg, - int *r_num_perimeter_points) -{ - /* sanity check */ - if (gps->totpoints < 1) { - return nullptr; - } - - float defaultpixsize = 1000.0f / gpd->pixfactor; - float ovr_radius = thickness_chg / defaultpixsize / 2.0f; - float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f; - stroke_radius = max_ff(stroke_radius - ovr_radius, 0.0f); - - ListBase *perimeter_right_side = MEM_cnew(__func__); - ListBase *perimeter_left_side = MEM_cnew(__func__); - int num_perimeter_points = 0; - - bGPDspoint *first = &gps->points[0]; - bGPDspoint *last = &gps->points[gps->totpoints - 1]; - - float first_radius = stroke_radius * first->pressure; - float last_radius = stroke_radius * last->pressure; - - bGPDspoint *first_next; - bGPDspoint *last_prev; - if (gps->totpoints > 1) { - first_next = &gps->points[1]; - last_prev = &gps->points[gps->totpoints - 2]; - } - else { - first_next = first; - last_prev = last; - } - - float first_pt[3]; - float last_pt[3]; - float first_next_pt[3]; - float last_prev_pt[3]; - copy_v3_v3(first_pt, &first->x); - copy_v3_v3(last_pt, &last->x); - copy_v3_v3(first_next_pt, &first_next->x); - copy_v3_v3(last_prev_pt, &last_prev->x); - - /* Edge-case if single point. */ - if (gps->totpoints == 1) { - first_next_pt[0] += 1.0f; - last_prev_pt[0] -= 1.0f; - } - - /* Generate points for start cap. */ - num_perimeter_points += generate_perimeter_cap( - first_pt, first_next_pt, first_radius, perimeter_right_side, subdivisions, gps->caps[0]); - - /* Generate perimeter points. */ - float curr_pt[3], next_pt[3], prev_pt[3]; - float vec_next[2], vec_prev[2]; - float nvec_next[2], nvec_prev[2]; - float nvec_next_pt[3], nvec_prev_pt[3]; - float vec_tangent[2]; - - float vec_miter_left[2], vec_miter_right[2]; - float miter_left_pt[3], miter_right_pt[3]; - - for (int i = 1; i < gps->totpoints - 1; i++) { - bGPDspoint *curr = &gps->points[i]; - bGPDspoint *prev = &gps->points[i - 1]; - bGPDspoint *next = &gps->points[i + 1]; - float radius = stroke_radius * curr->pressure; - - copy_v3_v3(curr_pt, &curr->x); - copy_v3_v3(next_pt, &next->x); - copy_v3_v3(prev_pt, &prev->x); - - sub_v2_v2v2(vec_prev, curr_pt, prev_pt); - sub_v2_v2v2(vec_next, next_pt, curr_pt); - float prev_length = len_v2(vec_prev); - float next_length = len_v2(vec_next); - - if (normalize_v2(vec_prev) == 0.0f) { - vec_prev[0] = 1.0f; - vec_prev[1] = 0.0f; - } - if (normalize_v2(vec_next) == 0.0f) { - vec_next[0] = 1.0f; - vec_next[1] = 0.0f; - } - - nvec_prev[0] = -vec_prev[1]; - nvec_prev[1] = vec_prev[0]; - - nvec_next[0] = -vec_next[1]; - nvec_next[1] = vec_next[0]; - - add_v2_v2v2(vec_tangent, vec_prev, vec_next); - if (normalize_v2(vec_tangent) == 0.0f) { - copy_v2_v2(vec_tangent, nvec_prev); - } - - vec_miter_left[0] = -vec_tangent[1]; - vec_miter_left[1] = vec_tangent[0]; - - /* calculate miter length */ - float an1 = dot_v2v2(vec_miter_left, nvec_prev); - if (an1 == 0.0f) { - an1 = 1.0f; - } - float miter_length = radius / an1; - if (miter_length <= 0.0f) { - miter_length = 0.01f; - } - - normalize_v2_length(vec_miter_left, miter_length); - - copy_v2_v2(vec_miter_right, vec_miter_left); - negate_v2(vec_miter_right); - - float angle = dot_v2v2(vec_next, nvec_prev); - /* Add two points if angle is close to being straight. */ - if (fabsf(angle) < 0.0001f) { - normalize_v2_length(nvec_prev, radius); - normalize_v2_length(nvec_next, radius); - - copy_v3_v3(nvec_prev_pt, curr_pt); - add_v2_v2(nvec_prev_pt, nvec_prev); - - copy_v3_v3(nvec_next_pt, curr_pt); - negate_v2(nvec_next); - add_v2_v2(nvec_next_pt, nvec_next); - - tPerimeterPoint *normal_prev = new_perimeter_point(nvec_prev_pt); - tPerimeterPoint *normal_next = new_perimeter_point(nvec_next_pt); - - BLI_addtail(perimeter_left_side, normal_prev); - BLI_addtail(perimeter_right_side, normal_next); - num_perimeter_points += 2; - } - else { - /* bend to the left */ - if (angle < 0.0f) { - normalize_v2_length(nvec_prev, radius); - normalize_v2_length(nvec_next, radius); - - copy_v3_v3(nvec_prev_pt, curr_pt); - add_v2_v2(nvec_prev_pt, nvec_prev); - - copy_v3_v3(nvec_next_pt, curr_pt); - add_v2_v2(nvec_next_pt, nvec_next); - - tPerimeterPoint *normal_prev = new_perimeter_point(nvec_prev_pt); - tPerimeterPoint *normal_next = new_perimeter_point(nvec_next_pt); - - BLI_addtail(perimeter_left_side, normal_prev); - BLI_addtail(perimeter_left_side, normal_next); - num_perimeter_points += 2; - - num_perimeter_points += generate_arc_from_point_to_point( - perimeter_left_side, normal_prev, normal_next, curr_pt, subdivisions, true); - - if (miter_length < prev_length && miter_length < next_length) { - copy_v3_v3(miter_right_pt, curr_pt); - add_v2_v2(miter_right_pt, vec_miter_right); - } - else { - copy_v3_v3(miter_right_pt, curr_pt); - negate_v2(nvec_next); - add_v2_v2(miter_right_pt, nvec_next); - } - - tPerimeterPoint *miter_right = new_perimeter_point(miter_right_pt); - BLI_addtail(perimeter_right_side, miter_right); - num_perimeter_points++; - } - /* bend to the right */ - else { - normalize_v2_length(nvec_prev, -radius); - normalize_v2_length(nvec_next, -radius); - - copy_v3_v3(nvec_prev_pt, curr_pt); - add_v2_v2(nvec_prev_pt, nvec_prev); - - copy_v3_v3(nvec_next_pt, curr_pt); - add_v2_v2(nvec_next_pt, nvec_next); - - tPerimeterPoint *normal_prev = new_perimeter_point(nvec_prev_pt); - tPerimeterPoint *normal_next = new_perimeter_point(nvec_next_pt); - - BLI_addtail(perimeter_right_side, normal_prev); - BLI_addtail(perimeter_right_side, normal_next); - num_perimeter_points += 2; - - num_perimeter_points += generate_arc_from_point_to_point( - perimeter_right_side, normal_prev, normal_next, curr_pt, subdivisions, false); - - if (miter_length < prev_length && miter_length < next_length) { - copy_v3_v3(miter_left_pt, curr_pt); - add_v2_v2(miter_left_pt, vec_miter_left); - } - else { - copy_v3_v3(miter_left_pt, curr_pt); - negate_v2(nvec_prev); - add_v2_v2(miter_left_pt, nvec_prev); - } - - tPerimeterPoint *miter_left = new_perimeter_point(miter_left_pt); - BLI_addtail(perimeter_left_side, miter_left); - num_perimeter_points++; - } - } - } - - /* generate points for end cap */ - num_perimeter_points += generate_perimeter_cap( - last_pt, last_prev_pt, last_radius, perimeter_right_side, subdivisions, gps->caps[1]); - - /* merge both sides to one list */ - BLI_listbase_reverse(perimeter_right_side); - BLI_movelisttolist(perimeter_left_side, - perimeter_right_side); // perimeter_left_side contains entire list - ListBase *perimeter_list = perimeter_left_side; - - /* close by creating a point close to the first (make a small gap) */ - float close_pt[3]; - tPerimeterPoint *close_first = (tPerimeterPoint *)perimeter_list->first; - tPerimeterPoint *close_last = (tPerimeterPoint *)perimeter_list->last; - interp_v3_v3v3(close_pt, &close_last->x, &close_first->x, 0.99f); - - if (compare_v3v3(close_pt, &close_first->x, FLT_EPSILON) == false) { - tPerimeterPoint *close_p_pt = new_perimeter_point(close_pt); - BLI_addtail(perimeter_list, close_p_pt); - num_perimeter_points++; - } - - /* free temp data */ - BLI_freelistN(perimeter_right_side); - MEM_freeN(perimeter_right_side); - - *r_num_perimeter_points = num_perimeter_points; - return perimeter_list; -} - -bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(float viewmat[4][4], - bGPdata *gpd, - const bGPDlayer *gpl, - bGPDstroke *gps, - const int subdivisions, - const float diff_mat[4][4], - const float thickness_chg) -{ - if (gps->totpoints == 0) { - return nullptr; - } - - float viewinv[4][4]; - invert_m4_m4(viewinv, viewmat); - - /* Duplicate only points and fill data. Weight and Curve are not needed. */ - bGPDstroke *gps_temp = (bGPDstroke *)MEM_dupallocN(gps); - gps_temp->prev = gps_temp->next = nullptr; - gps_temp->triangles = (bGPDtriangle *)MEM_dupallocN(gps->triangles); - gps_temp->points = (bGPDspoint *)MEM_dupallocN(gps->points); - gps_temp->dvert = nullptr; - gps_temp->editcurve = nullptr; - - const bool cyclic = ((gps_temp->flag & GP_STROKE_CYCLIC) != 0); - - /* If Cyclic, add a new point. */ - if (cyclic && (gps_temp->totpoints > 1)) { - gps_temp->totpoints++; - gps_temp->points = (bGPDspoint *)MEM_recallocN( - gps_temp->points, sizeof(*gps_temp->points) * gps_temp->totpoints); - bGPDspoint *pt_src = &gps_temp->points[0]; - bGPDspoint *pt_dst = &gps_temp->points[gps_temp->totpoints - 1]; - copy_v3_v3(&pt_dst->x, &pt_src->x); - pt_dst->pressure = pt_src->pressure; - pt_dst->strength = pt_src->strength; - pt_dst->uv_fac = 1.0f; - pt_dst->uv_rot = 0; - } - - BKE_gpencil_stroke_to_view_space(gps_temp, viewmat, diff_mat); - int num_perimeter_points = 0; - ListBase *perimeter_points = gpencil_stroke_perimeter_ex( - gpd, gpl, gps_temp, subdivisions, thickness_chg, &num_perimeter_points); - - if (num_perimeter_points == 0) { - return nullptr; - } - - /* Create new stroke. */ - bGPDstroke *perimeter_stroke = BKE_gpencil_stroke_new(gps_temp->mat_nr, num_perimeter_points, 1); - - int i = 0; - LISTBASE_FOREACH_INDEX (tPerimeterPoint *, curr, perimeter_points, i) { - bGPDspoint *pt = &perimeter_stroke->points[i]; - - copy_v3_v3(&pt->x, &curr->x); - pt->pressure = 0.0f; - pt->strength = 1.0f; - - pt->flag |= GP_SPOINT_SELECT; - } - - BKE_gpencil_stroke_from_view_space(perimeter_stroke, viewinv, diff_mat); - - /* Free temp data. */ - BLI_freelistN(perimeter_points); - MEM_freeN(perimeter_points); - - /* Triangles cache needs to be recalculated. */ - BKE_gpencil_stroke_geometry_update(gpd, perimeter_stroke); - - perimeter_stroke->flag |= GP_STROKE_SELECT | GP_STROKE_CYCLIC; - - BKE_gpencil_free_stroke(gps_temp); - - return perimeter_stroke; -} - float BKE_gpencil_stroke_average_pressure_get(bGPDstroke *gps) { diff --git a/source/blender/blenkernel/intern/gpencil_legacy.cc b/source/blender/blenkernel/intern/gpencil_legacy.cc index 6fa09c42196..1992bc15b38 100644 --- a/source/blender/blenkernel/intern/gpencil_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_legacy.cc @@ -477,14 +477,6 @@ void BKE_gpencil_free_data(bGPdata *gpd, bool free_all) } } -void BKE_gpencil_eval_delete(bGPdata *gpd_eval) -{ - BKE_gpencil_free_data(gpd_eval, true); - BKE_libblock_free_data(&gpd_eval->id, false); - BLI_assert(!gpd_eval->id.py_instance); /* Or call #BKE_libblock_free_data_py. */ - MEM_freeN(gpd_eval); -} - void BKE_gpencil_tag(bGPdata *gpd) { DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -790,17 +782,6 @@ bGPDstroke *BKE_gpencil_stroke_add( return gps; } -bGPDstroke *BKE_gpencil_stroke_add_existing_style( - bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short 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. */ - gps->runtime = blender::dna::shallow_copy(existing->runtime); - return gps; -} - bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points) { bGPDcurve *new_gp_curve = (bGPDcurve *)MEM_callocN(sizeof(bGPDcurve), __func__); @@ -824,20 +805,9 @@ void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_d BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints); } -bGPDcurve *BKE_gpencil_stroke_curve_duplicate(bGPDcurve *gpc_src) -{ - bGPDcurve *gpc_dst = static_cast(MEM_dupallocN(gpc_src)); - - if (gpc_src->curve_points != nullptr) { - gpc_dst->curve_points = static_cast(MEM_dupallocN(gpc_src->curve_points)); - } - - return gpc_dst; -} - bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points, - const bool dup_curve) + const bool /*dup_curve*/) { bGPDstroke *gps_dst = nullptr; @@ -861,12 +831,7 @@ bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, gps_dst->dvert = nullptr; } - if (dup_curve && gps_src->editcurve != nullptr) { - gps_dst->editcurve = BKE_gpencil_stroke_curve_duplicate(gps_src->editcurve); - } - else { - gps_dst->editcurve = nullptr; - } + gps_dst->editcurve = nullptr; /* return new stroke */ return gps_dst; @@ -900,23 +865,6 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_ return gpf_dst; } -void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, bGPDframe *gpf_dst) -{ - bGPDstroke *gps_dst = nullptr; - /* error checking */ - if ((gpf_src == nullptr) || (gpf_dst == nullptr)) { - return; - } - - /* copy strokes */ - BLI_listbase_clear(&gpf_dst->strokes); - LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { - /* make copy of source stroke */ - gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true); - BLI_addtail(&gpf_dst->strokes, gps_dst); - } -} - bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, const bool dup_frames, const bool dup_strokes) @@ -955,91 +903,6 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, return gpl_dst; } -void BKE_gpencil_data_copy_settings(const bGPdata *gpd_src, bGPdata *gpd_dst) -{ - gpd_dst->flag = gpd_src->flag; - gpd_dst->curve_edit_resolution = gpd_src->curve_edit_resolution; - gpd_dst->curve_edit_threshold = gpd_src->curve_edit_threshold; - gpd_dst->curve_edit_corner_angle = gpd_src->curve_edit_corner_angle; - gpd_dst->pixfactor = gpd_src->pixfactor; - copy_v4_v4(gpd_dst->line_color, gpd_src->line_color); - - gpd_dst->onion_factor = gpd_src->onion_factor; - gpd_dst->onion_mode = gpd_src->onion_mode; - gpd_dst->onion_flag = gpd_src->onion_flag; - gpd_dst->gstep = gpd_src->gstep; - gpd_dst->gstep_next = gpd_src->gstep_next; - - copy_v3_v3(gpd_dst->gcolor_prev, gpd_src->gcolor_prev); - copy_v3_v3(gpd_dst->gcolor_next, gpd_src->gcolor_next); - - gpd_dst->zdepth_offset = gpd_src->zdepth_offset; - - gpd_dst->totlayer = gpd_src->totlayer; - gpd_dst->totframe = gpd_src->totframe; - gpd_dst->totstroke = gpd_src->totstroke; - gpd_dst->totpoint = gpd_src->totpoint; - - gpd_dst->draw_mode = gpd_src->draw_mode; - gpd_dst->onion_keytype = gpd_src->onion_keytype; - - gpd_dst->select_last_index = gpd_src->select_last_index; - gpd_dst->vertex_group_active_index = gpd_src->vertex_group_active_index; - - copy_v3_v3(gpd_dst->grid.color, gpd_src->grid.color); - copy_v2_v2(gpd_dst->grid.scale, gpd_src->grid.scale); - copy_v2_v2(gpd_dst->grid.offset, gpd_src->grid.offset); - gpd_dst->grid.lines = gpd_src->grid.lines; -} - -void BKE_gpencil_layer_copy_settings(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst) -{ - gpl_dst->line_change = gpl_src->line_change; - copy_v4_v4(gpl_dst->tintcolor, gpl_src->tintcolor); - gpl_dst->opacity = gpl_src->opacity; - gpl_dst->vertex_paint_opacity = gpl_src->vertex_paint_opacity; - gpl_dst->pass_index = gpl_src->pass_index; - gpl_dst->parent = gpl_src->parent; - copy_m4_m4(gpl_dst->inverse, gpl_src->inverse); - STRNCPY(gpl_dst->parsubstr, gpl_src->parsubstr); - gpl_dst->partype = gpl_src->partype; - STRNCPY(gpl_dst->viewlayername, gpl_src->viewlayername); - copy_v3_v3(gpl_dst->location, gpl_src->location); - copy_v3_v3(gpl_dst->rotation, gpl_src->rotation); - copy_v3_v3(gpl_dst->scale, gpl_src->scale); - copy_m4_m4(gpl_dst->layer_mat, gpl_src->layer_mat); - copy_m4_m4(gpl_dst->layer_invmat, gpl_src->layer_invmat); - gpl_dst->blend_mode = gpl_src->blend_mode; - gpl_dst->flag = gpl_src->flag; - gpl_dst->onion_flag = gpl_src->onion_flag; -} - -void BKE_gpencil_frame_copy_settings(const bGPDframe *gpf_src, bGPDframe *gpf_dst) -{ - gpf_dst->flag = gpf_src->flag; - gpf_dst->key_type = gpf_src->key_type; - gpf_dst->framenum = gpf_src->framenum; -} - -void BKE_gpencil_stroke_copy_settings(const bGPDstroke *gps_src, bGPDstroke *gps_dst) -{ - gps_dst->thickness = gps_src->thickness; - gps_dst->flag = gps_src->flag; - gps_dst->inittime = gps_src->inittime; - gps_dst->mat_nr = gps_src->mat_nr; - copy_v2_v2_short(gps_dst->caps, gps_src->caps); - gps_dst->hardness = gps_src->hardness; - copy_v2_v2(gps_dst->aspect_ratio, gps_src->aspect_ratio); - gps_dst->fill_opacity_fac = gps_src->fill_opacity_fac; - copy_v3_v3(gps_dst->boundbox_min, gps_src->boundbox_min); - copy_v3_v3(gps_dst->boundbox_max, gps_src->boundbox_max); - gps_dst->uv_rotation = gps_src->uv_rotation; - copy_v2_v2(gps_dst->uv_translation, gps_src->uv_translation); - gps_dst->uv_scale = gps_src->uv_scale; - gps_dst->select_index = gps_src->select_index; - copy_v4_v4(gps_dst->vert_color_fill, gps_src->vert_color_fill); -} - bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy) { bGPdata *gpd_dst; @@ -1069,114 +932,6 @@ bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool in return gpd_dst; } -/* ************************************************** */ -/* GP Stroke API */ - -void BKE_gpencil_stroke_sync_selection(bGPdata *gpd, bGPDstroke *gps) -{ - bGPDspoint *pt; - int i; - - /* error checking */ - if (gps == nullptr) { - return; - } - - /* we'll stop when we find the first selected point, - * so initially, we must deselect - */ - gps->flag &= ~GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_reset(gps); - - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) { - gps->flag |= GP_STROKE_SELECT; - break; - } - } - - if (gps->flag & GP_STROKE_SELECT) { - BKE_gpencil_stroke_select_index_set(gpd, gps); - } -} - -void BKE_gpencil_curve_sync_selection(bGPdata *gpd, bGPDstroke *gps) -{ - bGPDcurve *gpc = gps->editcurve; - if (gpc == nullptr) { - return; - } - - gps->flag &= ~GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_reset(gps); - gpc->flag &= ~GP_CURVE_SELECT; - - bool is_selected = false; - for (int i = 0; i < gpc->tot_curve_points; i++) { - bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; - - if (BEZT_ISSEL_ANY(bezt)) { - gpc_pt->flag |= GP_SPOINT_SELECT; - } - else { - gpc_pt->flag &= ~GP_SPOINT_SELECT; - } - - if (gpc_pt->flag & GP_SPOINT_SELECT) { - is_selected = true; - } - } - - if (is_selected) { - gpc->flag |= GP_CURVE_SELECT; - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); - } -} - -void BKE_gpencil_stroke_select_index_set(bGPdata *gpd, bGPDstroke *gps) -{ - gpd->select_last_index++; - gps->select_index = gpd->select_last_index; -} - -void BKE_gpencil_stroke_select_index_reset(bGPDstroke *gps) -{ - gps->select_index = 0; -} - -/* ************************************************** */ -/* GP Frame API */ - -void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf) -{ - bGPDstroke *gps = static_cast((gpf) ? gpf->strokes.last : nullptr); - int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */ - - /* error checking */ - if (ELEM(nullptr, gpf, gps)) { - return; - } - - /* free the stroke and its data */ - if (gps->points) { - MEM_freeN(gps->points); - } - if (gps->dvert) { - BKE_gpencil_free_stroke_weights(gps); - MEM_freeN(gps->dvert); - } - MEM_freeN(gps->triangles); - BLI_freelinkN(&gpf->strokes, gps); - - /* if frame has no strokes after this, delete it */ - if (BLI_listbase_is_empty(&gpf->strokes)) { - BKE_gpencil_layer_frame_delete(gpl, gpf); - BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_USE_PREV); - } -} - /* ************************************************** */ /* GP Layer API */ @@ -1404,27 +1159,6 @@ bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name) return static_cast(BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info))); } -bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(bGPDlayer *gpl, const char *name) -{ - if (name[0] == '\0') { - return nullptr; - } - return static_cast( - BLI_findstring(&gpl->mask_layers, name, offsetof(bGPDlayer_Mask, name))); -} - -bGPDlayer_Mask *BKE_gpencil_layer_mask_add(bGPDlayer *gpl, const char *name) -{ - - bGPDlayer_Mask *mask = static_cast( - MEM_callocN(sizeof(bGPDlayer_Mask), "bGPDlayer_Mask")); - BLI_addtail(&gpl->mask_layers, mask); - STRNCPY(mask->name, name); - gpl->act_mask++; - - return mask; -} - void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask) { BLI_freelinkN(&gpl->mask_layers, mask); @@ -1506,13 +1240,6 @@ void BKE_gpencil_layer_mask_cleanup(bGPdata *gpd, bGPDlayer *gpl) } } -void BKE_gpencil_layer_mask_cleanup_all_layers(bGPdata *gpd) -{ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - BKE_gpencil_layer_mask_cleanup(gpd, gpl); - } -} - static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b) { const bGPDframe *frame_a = static_cast(a); @@ -1557,27 +1284,6 @@ bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd) return nullptr; } -bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, const char *name, int first_if_not_found) -{ - /* error checking */ - if (ELEM(nullptr, gpd, gpd->layers.first)) { - return nullptr; - } - - /* loop over layers until found (assume only one active) */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (STREQ(name, gpl->info)) { - return gpl; - } - } - - /* no such layer */ - if (first_if_not_found) { - return static_cast(gpd->layers.first); - } - return nullptr; -} - void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active) { /* error checking */ @@ -1652,19 +1358,6 @@ void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl) BLI_freelinkN(&gpd->layers, gpl); } -Material *BKE_gpencil_brush_material_get(Brush *brush) -{ - Material *ma = nullptr; - - if ((brush != nullptr) && (brush->gpencil_settings != nullptr) && - (brush->gpencil_settings->material != nullptr)) - { - ma = brush->gpencil_settings->material; - } - - return ma; -} - void BKE_gpencil_brush_material_set(Brush *brush, Material *ma) { BLI_assert(brush); @@ -1680,208 +1373,6 @@ void BKE_gpencil_brush_material_set(Brush *brush, Material *ma) } } -Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob, Brush *brush) -{ - if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { - 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_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); - } - - return ma; - } - - /* using active material instead */ - return BKE_object_material_get(ob, ob->actcol); -} - -int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *material) -{ - if (!material) { - return -1; - } - 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); - return ob->totcol - 1; - } - return index; -} - -Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index) -{ - Material *ma = BKE_gpencil_material_add(bmain, name); - id_us_min(&ma->id); /* no users yet */ - - BKE_object_material_slot_add(bmain, ob); - BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); - - if (r_index) { - *r_index = ob->actcol - 1; - } - return ma; -} - -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)) - { - Material *ma = BKE_gpencil_brush_material_get(brush); - return ma; - } - - return BKE_object_material_get(ob, ob->actcol); -} - -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_index_get(ob, brush->gpencil_settings->material); - } - - return ob->actcol - 1; -} - -Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main *bmain, - Object *ob, - ToolSettings *ts) -{ - if (ts && ts->gp_paint && BKE_paint_brush(&ts->gp_paint->paint)) { - return BKE_gpencil_object_material_ensure_from_active_input_brush( - bmain, ob, BKE_paint_brush(&ts->gp_paint->paint)); - } - - return BKE_gpencil_object_material_ensure_from_active_input_brush(bmain, ob, nullptr); -} - -Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain, - Object *ob, - Brush *brush) -{ - if (brush) { - Material *ma = BKE_gpencil_object_material_ensure_from_brush(bmain, ob, brush); - if (ma) { - return ma; - } - if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { - /* it is easier to just unpin a nullptr material, instead of setting a new one */ - brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED; - } - } - return BKE_gpencil_object_material_ensure_from_active_input_material(ob); -} - -Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob) -{ - Material *ma = BKE_object_material_get(ob, ob->actcol); - if (ma) { - return ma; - } - - return BKE_material_default_gpencil(); -} - -Material *BKE_gpencil_object_material_ensure_active(Object *ob) -{ - Material *ma = nullptr; - - /* sanity checks */ - if (ob == nullptr) { - return nullptr; - } - - ma = BKE_gpencil_object_material_ensure_from_active_input_material(ob); - if (ma->gp_style == nullptr) { - BKE_gpencil_material_attr_init(ma); - } - - return ma; -} - -/* ************************************************** */ - -bool BKE_gpencil_stroke_select_check(const bGPDstroke *gps) -{ - const bGPDspoint *pt; - int i; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) { - return true; - } - } - return false; -} - -/* ************************************************** */ -/* GP Object - Vertex Groups */ - -void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup) -{ - bGPdata *gpd = static_cast(ob->data); - MDeformVert *dvert = nullptr; - - const int def_nr = BLI_findindex(&gpd->vertex_group_names, defgroup); - const int totgrp = BLI_listbase_count(&gpd->vertex_group_names); - - /* Remove points data */ - if (gpd) { - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - if (gps->dvert != nullptr) { - for (int i = 0; i < gps->totpoints; i++) { - dvert = &gps->dvert[i]; - MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr); - if (dw != nullptr) { - BKE_defvert_remove_group(dvert, dw); - } - /* Reorganize weights for other groups after deleted one. */ - for (int g = 0; g < totgrp; g++) { - dw = BKE_defvert_find_index(dvert, g); - if ((dw != nullptr) && (dw->def_nr > def_nr)) { - dw->def_nr--; - } - } - } - } - } - } - } - } - - /* Remove the group */ - BLI_freelinkN(&gpd->vertex_group_names, defgroup); - - /* Update the active deform index if necessary. */ - const int active_index = BKE_object_defgroup_active_index_get(ob); - if (active_index > def_nr) { - BKE_object_defgroup_active_index_set(ob, active_index - 1); - } - /* Keep a valid active index if we still have some vertex groups. */ - if (!BLI_listbase_is_empty(&gpd->vertex_group_names) && - BKE_object_defgroup_active_index_get(ob) < 1) - { - BKE_object_defgroup_active_index_set(ob, 1); - } - - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); -} - -void BKE_gpencil_dvert_ensure(bGPDstroke *gps) -{ - if (gps->dvert == nullptr) { - gps->dvert = static_cast( - MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights")); - } -} - -/* ************************************************** */ - void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe) { *r_initframe = gpl->actframe->framenum; @@ -1930,305 +1421,6 @@ float BKE_gpencil_multiframe_falloff_calc( return value; } -void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index) -{ - 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--; - CLAMP_MIN(gps->mat_nr, 0); - } - } - } - } -} - -bool BKE_gpencil_material_index_used(bGPdata *gpd, int index) -{ - 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; - } - } - } - } - - return false; -} - -void BKE_gpencil_material_remap(bGPdata *gpd, const uint *remap, uint remap_len) -{ - const short remap_len_short = short(remap_len); - -#define MAT_NR_REMAP(n) \ - if (n < remap_len_short) { \ - BLI_assert(n >= 0 && remap[n] < remap_len_short); \ - n = remap[n]; \ - } \ - ((void)0) - - 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); - } - } - } - -#undef MAT_NR_REMAP -} - -bool BKE_gpencil_merge_materials_table_get(Object *ob, - const float hue_threshold, - const float sat_threshold, - const float val_threshold, - GHash *r_mat_table) -{ - bool changed = false; - - Material *ma_primary = nullptr; - Material *ma_secondary = nullptr; - MaterialGPencilStyle *gp_style_primary = nullptr; - MaterialGPencilStyle *gp_style_secondary = nullptr; - GHash *mat_used = BLI_ghash_int_new(__func__); - - short *totcol = BKE_object_material_len_p(ob); - if (totcol == nullptr) { - return changed; - } - - for (int idx_primary = 0; idx_primary < *totcol; idx_primary++) { - /* Read primary material to compare. */ - ma_primary = BKE_gpencil_material(ob, idx_primary + 1); - if (ma_primary == nullptr) { - continue; - } - for (int idx_secondary = 0; idx_secondary < *totcol; idx_secondary++) { - if ((idx_secondary == idx_primary) || - BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) - { - continue; - } - if (BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_secondary))) { - continue; - } - - /* Read secondary material to compare with primary material. */ - ma_secondary = BKE_gpencil_material(ob, idx_secondary + 1); - if ((ma_secondary == nullptr) || - BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) - { - continue; - } - gp_style_primary = ma_primary->gp_style; - gp_style_secondary = ma_secondary->gp_style; - - if ((gp_style_primary == nullptr) || (gp_style_secondary == nullptr) || - (gp_style_secondary->flag & GP_MATERIAL_LOCKED)) - { - continue; - } - - /* Check materials have the same mode. */ - if (gp_style_primary->mode != gp_style_secondary->mode) { - continue; - } - - /* Check materials have same stroke and fill attributes. */ - if ((gp_style_primary->flag & GP_MATERIAL_STROKE_SHOW) != - (gp_style_secondary->flag & GP_MATERIAL_STROKE_SHOW)) - { - continue; - } - - if ((gp_style_primary->flag & GP_MATERIAL_FILL_SHOW) != - (gp_style_secondary->flag & GP_MATERIAL_FILL_SHOW)) - { - continue; - } - - /* Check materials have the same type. */ - if ((gp_style_primary->stroke_style != gp_style_secondary->stroke_style) || - (gp_style_primary->fill_style != gp_style_secondary->fill_style)) - { - continue; - } - - float s_hsv_a[3], s_hsv_b[3], f_hsv_a[3], f_hsv_b[3], col[3]; - zero_v3(s_hsv_a); - zero_v3(s_hsv_b); - zero_v3(f_hsv_a); - zero_v3(f_hsv_b); - - copy_v3_v3(col, gp_style_primary->stroke_rgba); - rgb_to_hsv_compat_v(col, s_hsv_a); - copy_v3_v3(col, gp_style_secondary->stroke_rgba); - rgb_to_hsv_compat_v(col, s_hsv_b); - - copy_v3_v3(col, gp_style_primary->fill_rgba); - rgb_to_hsv_compat_v(col, f_hsv_a); - copy_v3_v3(col, gp_style_secondary->fill_rgba); - rgb_to_hsv_compat_v(col, f_hsv_b); - - /* Check stroke and fill color. */ - if (!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold) || - !compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold) || - !compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold) || - !compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold) || - !compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold) || - !compare_ff(f_hsv_a[2], f_hsv_b[2], val_threshold) || - !compare_ff(gp_style_primary->stroke_rgba[3], - gp_style_secondary->stroke_rgba[3], - val_threshold) || - !compare_ff( - gp_style_primary->fill_rgba[3], gp_style_secondary->fill_rgba[3], val_threshold)) - { - continue; - } - - /* Save conversion indexes. */ - if (!BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) { - BLI_ghash_insert( - r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary)); - changed = true; - - if (!BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_primary))) { - BLI_ghash_insert(mat_used, POINTER_FROM_INT(idx_primary), POINTER_FROM_INT(idx_primary)); - } - } - } - } - /* Free hash memory. */ - BLI_ghash_free(mat_used, nullptr, nullptr); - - return changed; -} - -bool BKE_gpencil_merge_materials(Object *ob, - const float hue_threshold, - const float sat_threshold, - const float val_threshold, - int *r_removed) -{ - bGPdata *gpd = static_cast(ob->data); - - short *totcol = BKE_object_material_len_p(ob); - if (totcol == nullptr) { - *r_removed = 0; - return false; - } - - /* Review materials. */ - GHash *mat_table = BLI_ghash_int_new(__func__); - - bool changed = BKE_gpencil_merge_materials_table_get( - ob, hue_threshold, sat_threshold, val_threshold, mat_table); - - *r_removed = BLI_ghash_len(mat_table); - - /* Update stroke material index. */ - if (changed) { - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* Check if the color is editable. */ - MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); - if (gp_style != nullptr) { - if (gp_style->flag & GP_MATERIAL_HIDE) { - continue; - } - if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && - (gp_style->flag & GP_MATERIAL_LOCKED)) - { - continue; - } - } - - if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) { - int *idx = static_cast( - BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr))); - gps->mat_nr = POINTER_AS_INT(idx); - } - } - } - } - } - - /* Free hash memory. */ - BLI_ghash_free(mat_table, nullptr, nullptr); - - return changed; -} - -void BKE_gpencil_stats_update(bGPdata *gpd) -{ - gpd->totlayer = 0; - gpd->totframe = 0; - gpd->totstroke = 0; - gpd->totpoint = 0; - - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - gpd->totlayer++; - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - gpd->totframe++; - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - gpd->totstroke++; - gpd->totpoint += gps->totpoints; - } - } - } -} - -int BKE_gpencil_object_material_index_get(Object *ob, Material *ma) -{ - short *totcol = BKE_object_material_len_p(ob); - Material *read_ma = nullptr; - for (short i = 0; i < *totcol; i++) { - read_ma = BKE_object_material_get(ob, i + 1); - if (ma == read_ma) { - return i; - } - } - - return -1; -} - -int BKE_gpencil_object_material_index_get_by_name(Object *ob, const char *name) -{ - short *totcol = BKE_object_material_len_p(ob); - Material *read_ma = nullptr; - for (short i = 0; i < *totcol; i++) { - read_ma = BKE_object_material_get(ob, i + 1); - if (STREQ(name, read_ma->id.name + 2)) { - return i; - } - } - - return -1; -} - -Material *BKE_gpencil_object_material_ensure_by_name(Main *bmain, - Object *ob, - const char *name, - int *r_index) -{ - int index = BKE_gpencil_object_material_index_get_by_name(ob, name); - if (index != -1) { - *r_index = index; - return BKE_object_material_get(ob, index + 1); - } - return BKE_gpencil_object_material_new(bmain, ob, name, r_index); -} - void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene) { const char *hexcol[] = { @@ -2278,71 +1470,6 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene) BKE_paint_palette_set(&ts->gp_paint->paint, palette); BKE_paint_palette_set(&ts->gp_vertexpaint->paint, palette); } - -bool BKE_gpencil_from_image( - SpaceImage *sima, bGPdata *gpd, bGPDframe *gpf, const float size, const bool mask) -{ - Image *image = sima->image; - bool done = false; - - if (image == nullptr) { - return false; - } - - ImageUser iuser = sima->iuser; - void *lock; - ImBuf *ibuf; - - ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); - - if (ibuf && ibuf->byte_buffer.data) { - int img_x = ibuf->x; - int img_y = ibuf->y; - - float color[4]; - bGPDspoint *pt; - for (int row = 0; row < img_y; row++) { - /* Create new stroke */ - 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, true, color); - pt = &gps->points[col]; - pt->pressure = 1.0f; - pt->x = col * size; - pt->z = row * size; - if (!mask) { - copy_v3_v3(pt->vert_color, color); - pt->vert_color[3] = 1.0f; - pt->strength = color[3]; - } - else { - zero_v3(pt->vert_color); - pt->vert_color[3] = 1.0f; - pt->strength = 1.0f - color[3]; - } - - /* Select Alpha points. */ - if (pt->strength < 0.03f) { - gps->flag |= GP_STROKE_SELECT; - pt->flag |= GP_SPOINT_SELECT; - } - } - - if (gps->flag & GP_STROKE_SELECT) { - BKE_gpencil_stroke_select_index_set(gpd, gps); - } - - BKE_gpencil_stroke_geometry_update(gpd, gps); - } - } - - /* Free memory. */ - BKE_image_release_ibuf(image, ibuf, lock); - - return done; -} - /** * Helper to check if a layers is used as mask * \param view_layer: Actual view layer. @@ -2372,46 +1499,6 @@ static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer return false; } -/* -------------------------------------------------------------------- */ -/** \name Iterator - * - * Iterate over all visible stroke of all visible layers inside a grease pencil datablock. - * \{ */ - -void BKE_gpencil_visible_stroke_iter(bGPdata *gpd, - gpIterCb layer_cb, - gpIterCb stroke_cb, - void *thunk) -{ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - - /* If scale to 0 the layer must be invisible. */ - if (is_zero_v3(gpl->scale)) { - continue; - } - - bGPDframe *act_gpf = gpl->actframe; - if (layer_cb) { - layer_cb(gpl, act_gpf, nullptr, thunk); - } - - if (act_gpf) { - LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) { - if (gps->totpoints == 0) { - continue; - } - stroke_cb(gpl, act_gpf, gps, thunk); - } - } - } -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Advanced Iterator * @@ -2856,198 +1943,4 @@ int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_ return -1; } -void BKE_gpencil_frame_selected_hash(bGPdata *gpd, GHash *r_list) -{ - const bool is_multiedit = bool(GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)); - bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); - - LISTBASE_FOREACH (bGPDlayer *, gpl_iter, &gpd->layers) { - if ((gpl != nullptr) && (!is_multiedit) && (gpl != gpl_iter)) { - continue; - } - - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_iter->frames) { - if (((gpf == gpl->actframe) && (!is_multiedit)) || - ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) - { - if (!BLI_ghash_lookup(r_list, POINTER_FROM_INT(gpf->framenum))) { - BLI_ghash_insert(r_list, POINTER_FROM_INT(gpf->framenum), gpf); - } - } - } - } -} - -bool BKE_gpencil_can_avoid_full_copy_on_write(const Depsgraph *depsgraph, bGPdata *gpd) -{ - /* For now, we only use the update cache in the active depsgraph. Otherwise we might access the - * cache while another depsgraph frees it. */ - if (!DEG_is_active(depsgraph)) { - return false; - } - - GPencilUpdateCache *update_cache = gpd->runtime.update_cache; - return update_cache != nullptr && update_cache->flag != GP_UPDATE_NODE_FULL_COPY; -} - -struct tGPencilUpdateOnWriteTraverseData { - bGPdata *gpd_eval; - bGPDlayer *gpl_eval; - bGPDframe *gpf_eval; - bGPDstroke *gps_eval; - int gpl_index; - int gpf_index; - int gps_index; -}; - -static bool gpencil_update_on_write_layer_cb(GPencilUpdateCache *gpl_cache, void *user_data) -{ - tGPencilUpdateOnWriteTraverseData *td = (tGPencilUpdateOnWriteTraverseData *)user_data; - td->gpl_eval = static_cast( - BLI_findlinkfrom((Link *)td->gpl_eval, gpl_cache->index - td->gpl_index)); - td->gpl_index = gpl_cache->index; - bGPDlayer *gpl = (bGPDlayer *)gpl_cache->data; - - if (gpl_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - bGPDlayer *gpl_eval_next = td->gpl_eval->next; - BLI_assert(gpl != nullptr); - - BKE_gpencil_layer_delete(td->gpd_eval, td->gpl_eval); - - td->gpl_eval = BKE_gpencil_layer_duplicate(gpl, true, true); - BLI_insertlinkbefore(&td->gpd_eval->layers, gpl_eval_next, td->gpl_eval); - - BKE_gpencil_layer_original_pointers_update(gpl, td->gpl_eval); - td->gpl_eval->runtime.gpl_orig = gpl; - return true; - } - if (gpl_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - BLI_assert(gpl != nullptr); - BKE_gpencil_layer_copy_settings(gpl, td->gpl_eval); - td->gpl_eval->runtime.gpl_orig = gpl; - } - - td->gpf_eval = static_cast(td->gpl_eval->frames.first); - td->gpf_index = 0; - return false; -} - -static bool gpencil_update_on_write_frame_cb(GPencilUpdateCache *gpf_cache, void *user_data) -{ - tGPencilUpdateOnWriteTraverseData *td = (tGPencilUpdateOnWriteTraverseData *)user_data; - td->gpf_eval = static_cast( - BLI_findlinkfrom((Link *)td->gpf_eval, gpf_cache->index - td->gpf_index)); - td->gpf_index = gpf_cache->index; - - bGPDframe *gpf = (bGPDframe *)gpf_cache->data; - - if (gpf_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - /* Do a full copy of the frame. */ - bGPDframe *gpf_eval_next = td->gpf_eval->next; - BLI_assert(gpf != nullptr); - - bool update_actframe = (td->gpl_eval->actframe == td->gpf_eval) ? true : false; - BKE_gpencil_free_strokes(td->gpf_eval); - BLI_freelinkN(&td->gpl_eval->frames, td->gpf_eval); - - td->gpf_eval = BKE_gpencil_frame_duplicate(gpf, true); - BLI_insertlinkbefore(&td->gpl_eval->frames, gpf_eval_next, td->gpf_eval); - - BKE_gpencil_frame_original_pointers_update(gpf, td->gpf_eval); - td->gpf_eval->runtime.gpf_orig = gpf; - - if (update_actframe) { - td->gpl_eval->actframe = td->gpf_eval; - } - - return true; - } - if (gpf_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - BLI_assert(gpf != nullptr); - BKE_gpencil_frame_copy_settings(gpf, td->gpf_eval); - td->gpf_eval->runtime.gpf_orig = gpf; - } - - td->gps_eval = static_cast(td->gpf_eval->strokes.first); - td->gps_index = 0; - return false; -} - -static bool gpencil_update_on_write_stroke_cb(GPencilUpdateCache *gps_cache, void *user_data) -{ - tGPencilUpdateOnWriteTraverseData *td = (tGPencilUpdateOnWriteTraverseData *)user_data; - td->gps_eval = static_cast( - BLI_findlinkfrom((Link *)td->gps_eval, gps_cache->index - td->gps_index)); - td->gps_index = gps_cache->index; - - bGPDstroke *gps = (bGPDstroke *)gps_cache->data; - - if (gps_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - /* Do a full copy of the stroke. */ - bGPDstroke *gps_eval_next = td->gps_eval->next; - BLI_assert(gps != nullptr); - - BLI_remlink(&td->gpf_eval->strokes, td->gps_eval); - BKE_gpencil_free_stroke(td->gps_eval); - - td->gps_eval = BKE_gpencil_stroke_duplicate(gps, true, true); - BLI_insertlinkbefore(&td->gpf_eval->strokes, gps_eval_next, td->gps_eval); - - td->gps_eval->runtime.gps_orig = gps; - - /* Assign original pt pointers. */ - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt_orig = &gps->points[i]; - bGPDspoint *pt_eval = &td->gps_eval->points[i]; - pt_orig->runtime.pt_orig = nullptr; - pt_orig->runtime.idx_orig = i; - pt_eval->runtime.pt_orig = pt_orig; - pt_eval->runtime.idx_orig = i; - } - } - else if (gps_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - BLI_assert(gps != nullptr); - BKE_gpencil_stroke_copy_settings(gps, td->gps_eval); - td->gps_eval->runtime.gps_orig = gps; - } - - return false; -} - -void BKE_gpencil_update_on_write(bGPdata *gpd_orig, bGPdata *gpd_eval) -{ - GPencilUpdateCache *update_cache = gpd_orig->runtime.update_cache; - - /* We assume that a full copy is not needed and the update cache is populated. */ - if (update_cache == nullptr || update_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - return; - } - - if (update_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) { - BKE_gpencil_data_copy_settings(gpd_orig, gpd_eval); - } - - GPencilUpdateCacheTraverseSettings ts = {{ - gpencil_update_on_write_layer_cb, - gpencil_update_on_write_frame_cb, - gpencil_update_on_write_stroke_cb, - }}; - - tGPencilUpdateOnWriteTraverseData data{}; - data.gpd_eval = gpd_eval; - data.gpl_eval = static_cast(gpd_eval->layers.first); - data.gpf_eval = nullptr; - data.gps_eval = nullptr; - data.gpl_index = 0; - data.gpf_index = 0; - data.gps_index = 0; - - BKE_gpencil_traverse_update_cache(update_cache, &ts, &data); - - gpd_eval->flag |= GP_DATA_CACHE_IS_DIRTY; - - /* TODO: This might cause issues when we have multiple depsgraphs? */ - BKE_gpencil_free_update_cache(gpd_orig); -} - /** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier_legacy.cc b/source/blender/blenkernel/intern/gpencil_modifier_legacy.cc index e2e14ad32ea..2a96929a26d 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_modifier_legacy.cc @@ -419,29 +419,6 @@ static void gpencil_modifier_foreach_ID_link(GpencilModifierData *md, /* *************************************************** */ /* Modifier Methods - Evaluation Loops, etc. */ -void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd) -{ - DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd); - int ctime = int(DEG_get_ctime(depsgraph)); - - /* update active frame */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - gpl->actframe = BKE_gpencil_layer_frame_get(gpl, ctime, GP_GETFRAME_USE_PREV); - } - - if (DEG_is_active(depsgraph)) { - bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id); - - /* sync "actframe" changes back to main-db too, - * so that editing tools work with copy-on-evaluation - * when the current frame changes - */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) { - gpl->actframe = BKE_gpencil_layer_frame_get(gpl, ctime, GP_GETFRAME_USE_PREV); - } - } -} - static void modifier_free_data_id_us_cb(void * /*user_data*/, Object * /*ob*/, ID **idpoin, diff --git a/source/blender/blenkernel/intern/gpencil_update_cache_legacy.cc b/source/blender/blenkernel/intern/gpencil_update_cache_legacy.cc index 2a5a81909a9..ff94add1e79 100644 --- a/source/blender/blenkernel/intern/gpencil_update_cache_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_update_cache_legacy.cc @@ -29,24 +29,6 @@ static GPencilUpdateCache *update_cache_alloc(int index, int flag, void *data) return new_cache; } -static short cache_node_compare(void *node, void *data) -{ - int index_a = ((GPencilUpdateCacheNode *)node)->cache->index; - int index_b = ((GPencilUpdateCache *)data)->index; - if (index_a == index_b) { - return 0; - } - return index_a < index_b ? 1 : -1; -} - -static DLRBT_Node *cache_node_alloc(void *data) -{ - GPencilUpdateCacheNode *new_node = static_cast( - MEM_callocN(sizeof(GPencilUpdateCacheNode), __func__)); - new_node->cache = ((GPencilUpdateCache *)data); - return (DLRBT_Node *)new_node; -} - static void cache_node_free(void *node); static void update_cache_free(GPencilUpdateCache *cache) @@ -65,136 +47,6 @@ static void cache_node_free(void *node) MEM_freeN(node); } -static void cache_node_update(void *node, void *data) -{ - GPencilUpdateCache *update_cache = ((GPencilUpdateCacheNode *)node)->cache; - GPencilUpdateCache *new_update_cache = (GPencilUpdateCache *)data; - - /* If the new cache is already "covered" by the current cache, just free it and return. */ - if (new_update_cache->flag <= update_cache->flag) { - update_cache_free(new_update_cache); - return; - } - - update_cache->data = new_update_cache->data; - update_cache->flag = new_update_cache->flag; - - /* In case the new cache does a full update, remove its children since they will be all - * updated by this cache. */ - if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - BLI_dlrbTree_free(update_cache->children, cache_node_free); - } - - update_cache_free(new_update_cache); -} - -static void update_cache_node_create_ex(GPencilUpdateCache *root_cache, - void *data, - int gpl_index, - int gpf_index, - int gps_index, - bool full_copy) -{ - if (root_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - /* Entire data-block has to be recalculated, e.g. nothing else needs to be added to the cache. - */ - return; - } - - const int node_flag = full_copy ? GP_UPDATE_NODE_FULL_COPY : GP_UPDATE_NODE_LIGHT_COPY; - - if (gpl_index == -1) { - root_cache->data = (bGPdata *)data; - root_cache->flag = node_flag; - if (full_copy) { - /* Entire data-block has to be recalculated, remove all caches of "lower" elements. */ - BLI_dlrbTree_free(root_cache->children, cache_node_free); - } - return; - } - - const bool is_layer_update_node = (gpf_index == -1); - /* If the data pointer in #GPencilUpdateCache is nullptr, this element is not actually cached - * and does not need to be updated, but we do need the index to find elements that are in - * levels below. E.g. if a stroke needs to be updated, the frame it is in would not hold a - * pointer to it's data. */ - GPencilUpdateCache *gpl_cache = update_cache_alloc( - gpl_index, - is_layer_update_node ? node_flag : GP_UPDATE_NODE_NO_COPY, - is_layer_update_node ? (bGPDlayer *)data : nullptr); - GPencilUpdateCacheNode *gpl_node = (GPencilUpdateCacheNode *)BLI_dlrbTree_add( - root_cache->children, cache_node_compare, cache_node_alloc, cache_node_update, gpl_cache); - - BLI_dlrbTree_linkedlist_sync(root_cache->children); - if (gpl_node->cache->flag == GP_UPDATE_NODE_FULL_COPY || is_layer_update_node) { - return; - } - - const bool is_frame_update_node = (gps_index == -1); - GPencilUpdateCache *gpf_cache = update_cache_alloc( - gpf_index, - is_frame_update_node ? node_flag : GP_UPDATE_NODE_NO_COPY, - is_frame_update_node ? (bGPDframe *)data : nullptr); - GPencilUpdateCacheNode *gpf_node = (GPencilUpdateCacheNode *)BLI_dlrbTree_add( - gpl_node->cache->children, - cache_node_compare, - cache_node_alloc, - cache_node_update, - gpf_cache); - - BLI_dlrbTree_linkedlist_sync(gpl_node->cache->children); - if (gpf_node->cache->flag == GP_UPDATE_NODE_FULL_COPY || is_frame_update_node) { - return; - } - - GPencilUpdateCache *gps_cache = update_cache_alloc(gps_index, node_flag, (bGPDstroke *)data); - BLI_dlrbTree_add(gpf_node->cache->children, - cache_node_compare, - cache_node_alloc, - cache_node_update, - gps_cache); - - BLI_dlrbTree_linkedlist_sync(gpf_node->cache->children); -} - -static void update_cache_node_create( - bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, bool full_copy) -{ - if (gpd == nullptr) { - return; - } - - GPencilUpdateCache *root_cache = gpd->runtime.update_cache; - if (root_cache == nullptr) { - gpd->runtime.update_cache = update_cache_alloc(0, GP_UPDATE_NODE_NO_COPY, nullptr); - root_cache = gpd->runtime.update_cache; - } - - if (root_cache->flag == GP_UPDATE_NODE_FULL_COPY) { - /* Entire data-block has to be recalculated, e.g. nothing else needs to be added to the cache. - */ - return; - } - - const int gpl_index = (gpl != nullptr) ? BLI_findindex(&gpd->layers, gpl) : -1; - const int gpf_index = (gpl != nullptr && gpf != nullptr) ? BLI_findindex(&gpl->frames, gpf) : -1; - const int gps_index = (gpf != nullptr && gps != nullptr) ? BLI_findindex(&gpf->strokes, gps) : - -1; - - void *data = gps; - if (!data) { - data = gpf; - } - if (!data) { - data = gpl; - } - if (!data) { - data = gpd; - } - - update_cache_node_create_ex(root_cache, data, gpl_index, gpf_index, gps_index, full_copy); -} - static void gpencil_traverse_update_cache_ex(GPencilUpdateCache *parent_cache, GPencilUpdateCacheTraverseSettings *ts, int depth, @@ -237,16 +89,6 @@ void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache, gpencil_traverse_update_cache_ex(cache, ts, 0, user_data); } -void BKE_gpencil_tag_full_update(bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps) -{ - update_cache_node_create(gpd, gpl, gpf, gps, true); -} - -void BKE_gpencil_tag_light_update(bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps) -{ - update_cache_node_create(gpd, gpl, gpf, gps, false); -} - void BKE_gpencil_free_update_cache(bGPdata *gpd) { GPencilUpdateCache *gpd_cache = gpd->runtime.update_cache; diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc index 63d7f6fe7c2..afa5e23c160 100644 --- a/source/blender/blenkernel/intern/material.cc +++ b/source/blender/blenkernel/intern/material.cc @@ -511,8 +511,6 @@ bool BKE_object_material_slot_used(Object *object, short actcol) case ID_MB: /* Meta-elements don't support materials at the moment. */ return false; - case ID_GD_LEGACY: - return BKE_gpencil_material_index_used((bGPdata *)ob_data, actcol - 1); case ID_GP: return BKE_grease_pencil_material_index_used(reinterpret_cast(ob_data), actcol - 1); @@ -1172,9 +1170,6 @@ void BKE_object_material_remap(Object *ob, const uint *remap) else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { BKE_curve_material_remap(static_cast(ob->data), remap, ob->totcol); } - else if (ob->type == OB_GPENCIL_LEGACY) { - BKE_gpencil_material_remap(static_cast(ob->data), remap, ob->totcol); - } else if (ob->type == OB_GREASE_PENCIL) { BKE_grease_pencil_material_remap(static_cast(ob->data), remap, ob->totcol); } @@ -1427,10 +1422,6 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob) BKE_displist_free(&ob->runtime->curve_cache->disp); } } - /* check indices from gpencil legacy. */ - else if (ob->type == OB_GPENCIL_LEGACY) { - BKE_gpencil_material_index_reassign((bGPdata *)ob->data, ob->totcol, actcol - 1); - } return true; } diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 97f00ccb23d..1ab39770dd7 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -1667,12 +1667,6 @@ void BKE_object_free_derived_caches(Object *ob) BKE_crazyspace_api_eval_clear(ob); - /* Clear grease pencil data. */ - if (ob->runtime->gpd_eval != nullptr) { - BKE_gpencil_eval_delete(ob->runtime->gpd_eval); - ob->runtime->gpd_eval = nullptr; - } - if (ob->runtime->geometry_set_eval != nullptr) { delete ob->runtime->geometry_set_eval; ob->runtime->geometry_set_eval = nullptr; @@ -3865,30 +3859,6 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph, return ok; } -struct GPencilStrokePointIterData { - const float (*obmat)[4]; - - void (*point_func_cb)(const float co[3], void *user_data); - void *user_data; -}; - -static void foreach_display_point_gpencil_stroke_fn(bGPDlayer * /*layer*/, - bGPDframe * /*frame*/, - bGPDstroke *stroke, - void *thunk) -{ - GPencilStrokePointIterData *iter_data = (GPencilStrokePointIterData *)thunk; - { - bGPDspoint *pt; - int i; - for (i = 0, pt = stroke->points; i < stroke->totpoints; i++, pt++) { - float3 co; - mul_v3_m4v3(co, iter_data->obmat, &pt->x); - iter_data->point_func_cb(co, iter_data->user_data); - } - } -} - void BKE_object_foreach_display_point(Object *ob, const float obmat[4][4], void (*func_cb)(const float[3], void *), @@ -3905,15 +3875,6 @@ void BKE_object_foreach_display_point(Object *ob, func_cb(co, user_data); } } - else if (ob->type == OB_GPENCIL_LEGACY) { - GPencilStrokePointIterData iter_data{}; - iter_data.obmat = obmat; - iter_data.point_func_cb = func_cb; - iter_data.user_data = user_data; - - BKE_gpencil_visible_stroke_iter( - (bGPdata *)ob->data, nullptr, foreach_display_point_gpencil_stroke_fn, &iter_data); - } else if (ob->runtime->curve_cache && ob->runtime->curve_cache->disp.first) { LISTBASE_FOREACH (DispList *, dl, &ob->runtime->curve_cache->disp) { const float *v3 = dl->verts; @@ -4880,7 +4841,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int /*flag*/) { blender::bke::ObjectRuntime *runtime = object->runtime; runtime->data_eval = nullptr; - runtime->gpd_eval = nullptr; runtime->mesh_deform_eval = nullptr; runtime->curve_cache = nullptr; runtime->object_as_temp_mesh = nullptr; diff --git a/source/blender/blenkernel/intern/object_deform.cc b/source/blender/blenkernel/intern/object_deform.cc index 27de2477276..83c0c49245b 100644 --- a/source/blender/blenkernel/intern/object_deform.cc +++ b/source/blender/blenkernel/intern/object_deform.cc @@ -390,24 +390,19 @@ static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg) void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup) { - if (ob->type == OB_GPENCIL_LEGACY) { - BKE_gpencil_vgroup_remove(ob, defgroup); + if (BKE_object_is_in_editmode_vgroup(ob)) { + object_defgroup_remove_edit_mode(ob, defgroup); } else { - if (BKE_object_is_in_editmode_vgroup(ob)) { - object_defgroup_remove_edit_mode(ob, defgroup); - } - else { - object_defgroup_remove_object_mode(ob, defgroup); - } - - if (ob->type == OB_GREASE_PENCIL) { - blender::bke::greasepencil::validate_drawing_vertex_groups( - *static_cast(ob->data)); - } - - BKE_object_batch_cache_dirty_tag(ob); + object_defgroup_remove_object_mode(ob, defgroup); } + + if (ob->type == OB_GREASE_PENCIL) { + blender::bke::greasepencil::validate_drawing_vertex_groups( + *static_cast(ob->data)); + } + + BKE_object_batch_cache_dirty_tag(ob); } void BKE_object_defgroup_remove_all_ex(Object *ob, bool only_unlocked) diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc index fac447fb18b..e88e83121f1 100644 --- a/source/blender/blenkernel/intern/object_update.cc +++ b/source/blender/blenkernel/intern/object_update.cc @@ -282,9 +282,6 @@ void BKE_object_batch_cache_dirty_tag(Object *ob) } break; } - case OB_GPENCIL_LEGACY: - BKE_gpencil_batch_cache_dirty_tag((bGPdata *)ob->data); - break; case OB_CURVES: BKE_curves_batch_cache_dirty_tag((Curves *)ob->data, BKE_CURVES_BATCH_DIRTY_ALL); break; diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index a3cff95122e..49dbf167a15 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -56,7 +56,6 @@ set(SRC intern/eval/deg_eval_flush.cc intern/eval/deg_eval_runtime_backup.cc intern/eval/deg_eval_runtime_backup_animation.cc - intern/eval/deg_eval_runtime_backup_gpencil.cc intern/eval/deg_eval_runtime_backup_modifier.cc intern/eval/deg_eval_runtime_backup_movieclip.cc intern/eval/deg_eval_runtime_backup_object.cc @@ -126,7 +125,6 @@ set(SRC intern/eval/deg_eval_flush.h intern/eval/deg_eval_runtime_backup.h intern/eval/deg_eval_runtime_backup_animation.h - intern/eval/deg_eval_runtime_backup_gpencil.h intern/eval/deg_eval_runtime_backup_modifier.h intern/eval/deg_eval_runtime_backup_movieclip.h intern/eval/deg_eval_runtime_backup_object.h diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index da60d4b3e7f..2593a5d3f8e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1783,18 +1783,6 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata) break; } - case ID_GD_LEGACY: { - /* GPencil evaluation operations. */ - op_node = add_operation_node(obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - [obdata_cow](::Depsgraph *depsgraph) { - BKE_gpencil_frame_active_set(depsgraph, - (bGPdata *)obdata_cow); - }); - op_node->set_as_entry(); - break; - } case ID_CV: { Curves *curves_id = reinterpret_cast(obdata); 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 458e562e807..4dcaaf9f8ab 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 @@ -888,14 +888,6 @@ ID *deg_update_eval_copy_datablock(const Depsgraph *depsgraph, const IDNode *id_ update_edit_mode_pointers(depsgraph, id_orig, id_cow); return id_cow; } - /* In case we don't need to do a copy-on-evaluation, we can use the update cache of the grease - * pencil data to do an update-on-write. */ - if (id_type == ID_GD_LEGACY && BKE_gpencil_can_avoid_full_copy_on_write( - (const ::Depsgraph *)depsgraph, (bGPdata *)id_orig)) - { - BKE_gpencil_update_on_write((bGPdata *)id_orig, (bGPdata *)id_cow); - return id_cow; - } } RuntimeBackup backup(depsgraph); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc index e7fe01f650b..79fcf5e4040 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -25,8 +25,7 @@ RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) object_backup(depsgraph), drawdata_ptr(nullptr), movieclip_backup(depsgraph), - volume_backup(depsgraph), - gpencil_backup(depsgraph) + volume_backup(depsgraph) { drawdata_backup.first = drawdata_backup.last = nullptr; } @@ -61,9 +60,6 @@ void RuntimeBackup::init_from_id(ID *id) case ID_VO: volume_backup.init_from_volume(reinterpret_cast(id)); break; - case ID_GD_LEGACY: - gpencil_backup.init_from_gpencil(reinterpret_cast(id)); - break; default: break; } @@ -104,9 +100,6 @@ void RuntimeBackup::restore_to_id(ID *id) case ID_VO: volume_backup.restore_to_volume(reinterpret_cast(id)); break; - case ID_GD_LEGACY: - gpencil_backup.restore_to_gpencil(reinterpret_cast(id)); - break; default: break; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h index 364787a6a05..789121ab7e0 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -11,7 +11,6 @@ #include "DNA_ID.h" #include "intern/eval/deg_eval_runtime_backup_animation.h" -#include "intern/eval/deg_eval_runtime_backup_gpencil.h" #include "intern/eval/deg_eval_runtime_backup_movieclip.h" #include "intern/eval/deg_eval_runtime_backup_object.h" #include "intern/eval/deg_eval_runtime_backup_scene.h" @@ -56,7 +55,6 @@ class RuntimeBackup { DrawDataList *drawdata_ptr; MovieClipBackup movieclip_backup; VolumeBackup volume_backup; - GPencilBackup gpencil_backup; }; } // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc deleted file mode 100644 index a06179a884a..00000000000 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-FileCopyrightText: 2022 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup depsgraph - */ - -#include "intern/eval/deg_eval_runtime_backup_gpencil.h" -#include "intern/depsgraph.hh" - -#include "BKE_gpencil_legacy.h" -#include "BKE_gpencil_update_cache_legacy.h" - -#include "DNA_gpencil_legacy_types.h" - -namespace blender::deg { - -GPencilBackup::GPencilBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph) {} - -void GPencilBackup::init_from_gpencil(bGPdata * /*gpd*/) {} - -void GPencilBackup::restore_to_gpencil(bGPdata *gpd) -{ - bGPdata *gpd_orig = reinterpret_cast(gpd->id.orig_id); - - /* We check for the active depsgraph here to avoid freeing the cache on the original object - * multiple times. This free is only needed for the case where we tagged a full update in the - * update cache and did not do an update-on-write. */ - if (depsgraph->is_active) { - BKE_gpencil_free_update_cache(gpd_orig); - } - /* Doing a copy-on-evaluation copies the update cache pointer. Make sure to reset it - * to null as we should never use the update cache from eval data. */ - gpd->runtime.update_cache = nullptr; - /* Make sure to update the original runtime pointers in the eval data. */ - BKE_gpencil_data_update_orig_pointers(gpd_orig, gpd); -} - -} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h deleted file mode 100644 index 28220707b32..00000000000 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-FileCopyrightText: 2022 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup depsgraph - */ - -#pragma once - -struct bGPdata; - -namespace blender::deg { - -struct Depsgraph; - -/* Backup of volume datablocks runtime data. */ -class GPencilBackup { - public: - GPencilBackup(const Depsgraph *depsgraph); - - void init_from_gpencil(bGPdata *gpd); - void restore_to_gpencil(bGPdata *gpd); - - const Depsgraph *depsgraph; -}; - -} // namespace blender::deg diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 6da761ceab4..1999230b3a8 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -294,9 +294,6 @@ void Instance::object_sync(Object *ob) case OB_CURVES: sync.sync_curves(ob, ob_handle, res_handle, ob_ref); break; - case OB_GREASE_PENCIL: - sync.sync_gpencil(ob, ob_handle, res_handle); - break; case OB_LIGHTPROBE: light_probes.sync_probe(ob, ob_handle); break; diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc index 3ad4ef9beec..54f4717eccb 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc @@ -393,149 +393,6 @@ void SyncModule::sync_volume(Object *ob, /** \} */ -/* -------------------------------------------------------------------- */ -/** \name GPencil - * \{ */ - -#define DO_BATCHING true - -struct gpIterData { - Instance &inst; - Object *ob; - MaterialArray &material_array; - int cfra; - - /* Drawcall batching. */ - gpu::Batch *geom = nullptr; - Material *material = nullptr; - int vfirst = 0; - int vcount = 0; - bool instancing = false; - - gpIterData(Instance &inst_, Object *ob_, ObjectHandle &ob_handle, ResourceHandle resource_handle) - : inst(inst_), - ob(ob_), - material_array(inst_.materials.material_array_get( - ob_, - inst_.velocity.step_object_sync( - ob, ob_handle.object_key, resource_handle, ob_handle.recalc))) - { - cfra = DEG_get_ctime(inst.depsgraph); - }; -}; - -static void gpencil_drawcall_flush(gpIterData &iter) -{ -#if 0 /* Incompatible with new draw manager. */ - if (iter.geom != nullptr) { - geometry_call(iter.material->shading.sub_pass, - iter.ob, - iter.geom, - iter.vfirst, - iter.vcount, - iter.instancing); - geometry_call(iter.material->prepass.sub_pass, - iter.ob, - iter.geom, - iter.vfirst, - iter.vcount, - iter.instancing); - geometry_call(iter.material->shadow.sub_pass, - iter.ob, - iter.geom, - iter.vfirst, - iter.vcount, - iter.instancing); - } -#endif - iter.geom = nullptr; - iter.vfirst = -1; - iter.vcount = 0; -} - -/* Group draw-calls that are consecutive and with the same type. Reduces GPU driver overhead. */ -static void gpencil_drawcall_add(gpIterData &iter, - gpu::Batch *geom, - Material *material, - int v_first, - int v_count, - bool instancing) -{ - int last = iter.vfirst + iter.vcount; - /* Interrupt draw-call grouping if the sequence is not consecutive. */ - if (!DO_BATCHING || (geom != iter.geom) || (material != iter.material) || (v_first - last > 3)) { - gpencil_drawcall_flush(iter); - } - iter.geom = geom; - iter.material = material; - iter.instancing = instancing; - if (iter.vfirst == -1) { - iter.vfirst = v_first; - } - iter.vcount = v_first + v_count - iter.vfirst; -} - -static void gpencil_stroke_sync(bGPDlayer * /*gpl*/, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - gpIterData &iter = *(gpIterData *)thunk; - - Material *material = &iter.material_array.materials[gps->mat_nr]; - 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) || - (!DRW_state_is_image_render() && ((gps->flag & GP_STROKE_NOFILL) != 0)); - bool show_fill = (gps->tot_triangles > 0) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0); - - if (hide_material) { - return; - } - - gpu::Batch *geom = DRW_cache_gpencil_get(iter.ob, iter.cfra); - - if (show_fill) { - int vfirst = gps->runtime.fill_start * 3; - int vcount = gps->tot_triangles * 3; - gpencil_drawcall_add(iter, geom, material, vfirst, vcount, false); - } - - if (show_stroke) { - /* Start one vert before to have gl_InstanceID > 0 (see shader). */ - int vfirst = gps->runtime.stroke_start * 3; - /* Include "potential" cyclic vertex and start adj vertex (see shader). */ - int vcount = gps->totpoints + 1 + 1; - gpencil_drawcall_add(iter, geom, material, vfirst, vcount, true); - } -} - -void SyncModule::sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle) -{ - /* TODO(fclem): Waiting for a user option to use the render engine instead of gpencil engine. */ - return; - - /* Is this a surface or curves? */ - if (!inst_.use_surfaces) { - return; - } - - UNUSED_VARS(res_handle); - - gpIterData iter(inst_, ob, ob_handle, res_handle); - - BKE_gpencil_visible_stroke_iter((bGPdata *)ob->data, nullptr, gpencil_stroke_sync, &iter); - - gpencil_drawcall_flush(iter); - - bool is_alpha_blend = true; /* TODO material.is_alpha_blend. */ - bool has_transparent_shadows = true; /* TODO material.has_transparent_shadows. */ - inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend, has_transparent_shadows); -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Hair * \{ */ diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.hh b/source/blender/draw/engines/eevee_next/eevee_sync.hh index 4b925dad894..a053bd4b0ce 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.hh +++ b/source/blender/draw/engines/eevee_next/eevee_sync.hh @@ -178,7 +178,6 @@ class SyncModule { ObjectHandle &ob_handle, ResourceHandle res_handle, const ObjectRef &ob_ref); - void sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle); void sync_curves(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle, diff --git a/source/blender/draw/engines/gpencil/gpencil_engine_c.cc b/source/blender/draw/engines/gpencil/gpencil_engine_c.cc index c66be1ec5ad..f1d2bc96d76 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine_c.cc +++ b/source/blender/draw/engines/gpencil/gpencil_engine_c.cc @@ -244,16 +244,6 @@ void GPENCIL_cache_init(void *ved) pd->do_fast_drawing = false; pd->obact = draw_ctx->obact; - if (pd->obact && pd->obact->type == OB_GPENCIL_LEGACY && !(pd->draw_depth_only)) { - /* 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. */ - } - } } if (pd->do_fast_drawing) { @@ -332,273 +322,8 @@ void GPENCIL_cache_init(void *ved) } } -#define DRAW_NOW 2 - -struct gpIterPopulateData { - Object *ob; - GPENCIL_tObject *tgp_ob; - GPENCIL_PrivateData *pd; - GPENCIL_MaterialPool *matpool; - DRWShadingGroup *grp; - /* Last material UBO bound. Used to avoid unneeded buffer binding. */ - GPUUniformBuf *ubo_mat; - GPUUniformBuf *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. */ - blender::gpu::Batch *geom; - int vfirst, vcount; -}; - #define DISABLE_BATCHING 0 -static void gpencil_drawcall_flush(gpIterPopulateData *iter) -{ -#if !DISABLE_BATCHING - if (iter->geom != nullptr) { - DRW_shgroup_call_range(iter->grp, iter->ob, iter->geom, iter->vfirst, iter->vcount); - } -#endif - - iter->geom = nullptr; - iter->vfirst = -1; - iter->vcount = 0; -} - -/* Group draw-calls that are consecutive and with the same type. Reduces GPU driver overhead. */ -static void gpencil_drawcall_add(gpIterPopulateData *iter, - blender::gpu::Batch *geom, - int v_first, - int v_count) -{ -#if DISABLE_BATCHING - DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count); - return; -#endif - - int last = iter->vfirst + iter->vcount; - /* Interrupt draw-call grouping if the sequence is not consecutive. */ - if ((geom != iter->geom) || (v_first - last > 0)) { - gpencil_drawcall_flush(iter); - } - iter->geom = geom; - if (iter->vfirst == -1) { - iter->vfirst = v_first; - } - iter->vcount = v_first + v_count - iter->vfirst; -} - -static void gpencil_stroke_cache_populate(bGPDlayer *gpl, - bGPDframe *gpf, - bGPDstroke *gps, - void *thunk); - -static void gpencil_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, "gp_materials", iter->ubo_mat); - DRW_shgroup_uniform_float_copy(iter->grp, "gpStrokeIndexOffset", 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); - } - - gpencil_stroke_cache_populate(nullptr, nullptr, iter->pd->sbuffer_stroke, iter); - gpencil_drawcall_flush(iter); - - iter->stroke_index_offset = iter->pd->sbuffer_stroke->totpoints + 1; - iter->do_sbuffer_call = 0; -} - -static void gpencil_layer_cache_populate(bGPDlayer *gpl, - bGPDframe *gpf, - bGPDstroke * /*gps*/, - void *thunk) -{ - gpIterPopulateData *iter = (gpIterPopulateData *)thunk; - GPENCIL_PrivateData *pd = iter->pd; - bGPdata *gpd = (bGPdata *)iter->ob->data; - - gpencil_drawcall_flush(iter); - - if (iter->do_sbuffer_call) { - gpencil_sbuffer_cache_populate(iter); - } - else { - iter->do_sbuffer_call = !pd->do_fast_drawing && (gpd == pd->sbuffer_gpd) && - (gpl == pd->sbuffer_layer) && - (gpf == nullptr || gpf->runtime.onion_id == 0.0f); - } - - GPENCIL_tLayer *tgp_layer = gpencil_layer_cache_add(pd, iter->ob, gpl, gpf, iter->tgp_ob); - - const bool use_lights = pd->use_lighting && ((gpl->flag & GP_LAYER_USE_LIGHTS) != 0) && - (iter->ob->dtx & OB_USE_GPENCIL_LIGHTS); - - iter->ubo_lights = (use_lights) ? pd->global_light_pool->ubo : pd->shadeless_light_pool->ubo; - - gpencil_material_resources_get(iter->matpool, 0, nullptr, nullptr, &iter->ubo_mat); - - /* Iterator dependent uniforms. */ - DRWShadingGroup *grp = iter->grp = tgp_layer->base_shgrp; - DRW_shgroup_uniform_block(grp, "gp_lights", iter->ubo_lights); - DRW_shgroup_uniform_block(grp, "gp_materials", iter->ubo_mat); - DRW_shgroup_uniform_texture(grp, "gpFillTexture", iter->tex_fill); - DRW_shgroup_uniform_texture(grp, "gpStrokeTexture", iter->tex_stroke); - DRW_shgroup_uniform_int_copy(grp, "gpMaterialOffset", iter->mat_ofs); - DRW_shgroup_uniform_float_copy(grp, "gpStrokeIndexOffset", iter->stroke_index_offset); - DRW_shgroup_uniform_vec2_copy(grp, "viewportSize", DRW_viewport_size_get()); -} - -static void gpencil_stroke_cache_populate(bGPDlayer *gpl, - bGPDframe *gpf, - bGPDstroke *gps, - void *thunk) -{ - using namespace blender::draw; - gpIterPopulateData *iter = (gpIterPopulateData *)thunk; - - bGPdata *gpd = static_cast(iter->ob->data); - MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(iter->ob, gps->mat_nr + 1); - - const bool is_render = iter->pd->is_render; - bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0; - bool show_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0) || - (!is_render && ((gps->flag & GP_STROKE_NOFILL) != 0)); - bool show_fill = (gps->tot_triangles > 0) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0) && - (!iter->pd->simplify_fill) && ((gps->flag & GP_STROKE_NOFILL) == 0); - bool only_lines = !GPENCIL_PAINT_MODE(gpd) && gpl && gpf && gpl->actframe != gpf && - iter->pd->use_multiedit_lines_only; - bool is_onion = gpl && gpf && gpf->runtime.onion_id != 0; - bool hide_onion = is_onion && ((gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN) != 0); - if ((hide_material) || (!show_stroke && !show_fill) || (only_lines && !is_onion) || (hide_onion)) - { - return; - } - - GPUUniformBuf *ubo_mat; - GPUTexture *tex_stroke, *tex_fill; - gpencil_material_resources_get( - iter->matpool, iter->mat_ofs + gps->mat_nr, &tex_stroke, &tex_fill, &ubo_mat); - - bool resource_changed = (iter->ubo_mat != ubo_mat) || - (tex_fill && (iter->tex_fill != tex_fill)) || - (tex_stroke && (iter->tex_stroke != tex_stroke)); - - if (resource_changed) { - gpencil_drawcall_flush(iter); - - iter->grp = DRW_shgroup_create_sub(iter->grp); - if (iter->ubo_mat != ubo_mat) { - DRW_shgroup_uniform_block(iter->grp, "gp_materials", ubo_mat); - iter->ubo_mat = ubo_mat; - } - if (tex_fill) { - DRW_shgroup_uniform_texture(iter->grp, "gpFillTexture", tex_fill); - iter->tex_fill = tex_fill; - } - if (tex_stroke) { - DRW_shgroup_uniform_texture(iter->grp, "gpStrokeTexture", tex_stroke); - iter->tex_stroke = tex_stroke; - } - } - - bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW); - - blender::gpu::Batch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_get(iter->ob, show_fill) : - DRW_cache_gpencil_get(iter->ob, iter->pd->cfra); - if (geom != iter->geom) { - gpencil_drawcall_flush(iter); - - blender::gpu::VertBuf *position_tx = - do_sbuffer ? DRW_cache_gpencil_sbuffer_position_buffer_get(iter->ob, show_fill) : - DRW_cache_gpencil_position_buffer_get(iter->ob, iter->pd->cfra); - blender::gpu::VertBuf *color_tx = do_sbuffer ? - DRW_cache_gpencil_sbuffer_color_buffer_get(iter->ob, - show_fill) : - DRW_cache_gpencil_color_buffer_get(iter->ob, - iter->pd->cfra); - DRW_shgroup_buffer_texture(iter->grp, "gp_pos_tx", position_tx); - DRW_shgroup_buffer_texture(iter->grp, "gp_col_tx", color_tx); - } - - if (show_fill) { - int vfirst = gps->runtime.fill_start * 3; - int vcount = gps->tot_triangles * 3; - gpencil_drawcall_add(iter, geom, vfirst, vcount); - } - - if (show_stroke) { - int vfirst = gps->runtime.stroke_start * 3; - bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); - int vcount = (gps->totpoints + int(is_cyclic)) * 2 * 3; - gpencil_drawcall_add(iter, geom, vfirst, vcount); - } - - iter->stroke_index_last = gps->runtime.vertex_start + gps->totpoints + 1; -} - -static void gpencil_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopulateData *iter) -{ - bGPdata *gpd = (bGPdata *)iter->ob->data; - if (gpd != iter->pd->sbuffer_gpd) { - return; - } - - 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. */ - const blender::Bounds bounds = BKE_gpencil_data_minmax(gpd).value_or( - blender::Bounds(float3(0))); - iter->tgp_ob = gpencil_object_cache_add( - iter->pd, iter->ob, (gpd->draw_mode == GP_DRAWMODE_3D), bounds); - /* Remove from the main list. */ - iter->pd->tobjects.last = last_tgp_ob; - last_tgp_ob->next = nullptr; - /* 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; - - gpencil_layer_cache_populate( - iter->pd->sbuffer_layer, iter->pd->sbuffer_layer->actframe, nullptr, iter); - - 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; - gpencil_stroke_cache_populate(nullptr, nullptr, iter->pd->sbuffer_stroke, iter); - gpencil_drawcall_flush(iter); - - gpencil_vfx_cache_populate( - vedata, iter->ob, iter->tgp_ob, (gpd != nullptr && GPENCIL_ANY_EDIT_MODE(gpd))); - - /* Restore state. */ - iter->do_sbuffer_call = 0; - iter->pd->scene_depth_tx = depth_texture; -} - /* Check if the passed in layer is used by any other layer as a mask (in the viewlayer). */ static bool is_used_as_layer_mask_in_viewlayer(const GreasePencil &grease_pencil, const blender::bke::greasepencil::Layer &mask_layer, @@ -877,59 +602,13 @@ 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; - const bool is_final_render = DRW_state_is_image_render(); /* object must be visible */ if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { return; } - if (ob->data && (ob->type == OB_GPENCIL_LEGACY) && (ob->dt >= OB_SOLID)) { - bGPdata *gpd = (bGPdata *)ob->data; - const blender::Bounds bounds = BKE_gpencil_data_minmax(gpd).value_or( - blender::Bounds(float3(0))); - gpIterPopulateData iter = {nullptr}; - iter.ob = ob; - iter.pd = pd; - iter.tgp_ob = gpencil_object_cache_add(pd, ob, (gpd->draw_mode == GP_DRAWMODE_3D), bounds); - iter.matpool = gpencil_material_pool_create(pd, ob, &iter.mat_ofs, GPENCIL_VERTEX_MODE(gpd)); - iter.tex_fill = txl->dummy_texture; - iter.tex_stroke = txl->dummy_texture; - - /* Special case for rendering onion skin. */ - bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS); - gpd->runtime.playing = short(pd->playing); - - /* When render in background the active frame could not be properly set due thread priority, - * better set again. This is not required in viewport. */ - if (txl->render_depth_tx) { - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - gpl->actframe = BKE_gpencil_layer_frame_get(gpl, pd->cfra, GP_GETFRAME_USE_PREV); - } - } - - BKE_gpencil_visible_stroke_advanced_iter(is_final_render ? pd->view_layer : nullptr, - ob, - gpencil_layer_cache_populate, - gpencil_stroke_cache_populate, - &iter, - do_onion, - pd->cfra); - - gpencil_drawcall_flush(&iter); - - if (iter.do_sbuffer_call) { - gpencil_sbuffer_cache_populate(&iter); - } - - gpencil_vfx_cache_populate( - vedata, ob, iter.tgp_ob, (gpd != nullptr && GPENCIL_ANY_EDIT_MODE(gpd))); - - if (pd->do_fast_drawing) { - gpencil_sbuffer_cache_populate_fast(vedata, &iter); - } - } - else if (ob->data && (ob->type == OB_GREASE_PENCIL) && (ob->dt >= OB_SOLID)) { + if (ob->data && (ob->type == OB_GREASE_PENCIL) && (ob->dt >= OB_SOLID)) { GPENCIL_tObject *tgp_ob = grease_pencil_object_cache_populate(pd, txl, ob); gpencil_vfx_cache_populate( vedata, ob, tgp_ob, ELEM(ob->mode, OB_MODE_EDIT, OB_MODE_SCULPT, OB_MODE_WEIGHT_PAINT)); diff --git a/source/blender/draw/engines/overlay/overlay_engine.cc b/source/blender/draw/engines/overlay/overlay_engine.cc index fe90aa50e1c..5385a8a3e44 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.cc +++ b/source/blender/draw/engines/overlay/overlay_engine.cc @@ -518,9 +518,6 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) OVERLAY_metaball_cache_populate(data, ob); } break; - case OB_GPENCIL_LEGACY: - OVERLAY_gpencil_legacy_cache_populate(data, ob); - break; } } /* Non-Meshes */ diff --git a/source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc b/source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc index d4ce478d51a..b490c73c60b 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc +++ b/source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc @@ -322,52 +322,6 @@ void OVERLAY_gpencil_legacy_cache_init(OVERLAY_Data *vedata) } } -static void OVERLAY_edit_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob) -{ - using namespace blender::draw; - OVERLAY_PrivateData *pd = vedata->stl->pd; - bGPdata *gpd = (bGPdata *)ob->data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - /* Overlay is only for active object. */ - if (ob != draw_ctx->obact) { - return; - } - - 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); - - blender::gpu::Batch *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); - - blender::gpu::Batch *geom = DRW_cache_gpencil_edit_points_get(ob, pd->cfra); - DRW_shgroup_call_no_cull(grp, geom, ob); - } - - if (pd->edit_gpencil_curve_handle_grp) { - blender::gpu::Batch *geom = DRW_cache_gpencil_edit_curve_handles_get(ob, pd->cfra); - if (geom) { - DRW_shgroup_call_no_cull(pd->edit_gpencil_curve_handle_grp, geom, ob); - } - } - - if (pd->edit_gpencil_curve_points_grp) { - blender::gpu::Batch *geom = DRW_cache_gpencil_edit_curve_points_get(ob, pd->cfra); - if (geom) { - DRW_shgroup_call_no_cull(pd->edit_gpencil_curve_points_grp, geom, ob); - } - } -} - static void overlay_gpencil_draw_stroke_color_name(bGPDlayer * /*gpl*/, bGPDframe * /*gpf*/, bGPDstroke *gps, @@ -427,30 +381,6 @@ static void OVERLAY_gpencil_color_names(Object *ob) nullptr, ob, nullptr, overlay_gpencil_draw_stroke_color_name, ob, false, cfra); } -void OVERLAY_gpencil_legacy_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 == nullptr) { - 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_LEGACY) && - DRW_state_show_text()) - { - OVERLAY_gpencil_color_names(ob); - } - } -} - void OVERLAY_gpencil_legacy_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc index 3c7a0d8f755..b50ba933ccf 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.cc +++ b/source/blender/draw/engines/overlay/overlay_outline.cc @@ -186,97 +186,6 @@ struct iterData { float plane[4]; }; -static void gpencil_layer_cache_populate(bGPDlayer *gpl, - bGPDframe * /*gpf*/, - bGPDstroke * /*gps*/, - void *thunk) -{ - using namespace blender::draw; - 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->object_to_world().ptr()); - /* Negate thickness sign to tag that strokes are in screen space. - * Convert to world units (by default, 1 meter = 2000 pixels). */ - float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f); - - blender::gpu::VertBuf *position_tx = DRW_cache_gpencil_position_buffer_get(iter->ob, iter->cfra); - blender::gpu::VertBuf *color_tx = DRW_cache_gpencil_color_buffer_get(iter->ob, iter->cfra); - - DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp); - DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", is_stroke_order_3d); - DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", object_scale); - DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", float(gpl->line_change)); - DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", thickness_scale); - DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane); - DRW_shgroup_buffer_texture(grp, "gp_pos_tx", position_tx); - DRW_shgroup_buffer_texture(grp, "gp_col_tx", color_tx); -} - -static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - using namespace blender::draw; - 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; - } - - blender::gpu::Batch *geom = DRW_cache_gpencil_get(iter->ob, iter->cfra); - - if (show_fill) { - int vfirst = gps->runtime.fill_start * 3; - int vcount = gps->tot_triangles * 3; - DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount); - } - - if (show_stroke) { - int vfirst = gps->runtime.stroke_start * 3; - bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2); - int vcount = (gps->totpoints + int(is_cyclic)) * 2 * 3; - DRW_shgroup_call_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{}; - iter.ob = ob; - iter.stroke_grp = pd->outlines_gpencil_grp; - iter.cfra = pd->cfra; - - if (gpd->draw_mode == GP_DRAWMODE_2D) { - gpencil_depth_plane(ob, iter.plane); - } - - BKE_gpencil_visible_stroke_advanced_iter(nullptr, - ob, - gpencil_layer_cache_populate, - gpencil_stroke_cache_populate, - &iter, - false, - pd->cfra); -} - static void OVERLAY_outline_grease_pencil(OVERLAY_PrivateData *pd, Scene *scene, Object *ob) { using namespace blender; @@ -413,11 +322,6 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, return; } - if (ob->type == OB_GPENCIL_LEGACY) { - OVERLAY_outline_gpencil(pd, ob); - return; - } - if (ob->type == OB_GREASE_PENCIL) { OVERLAY_outline_grease_pencil(pd, draw_ctx->scene, ob); return; diff --git a/source/blender/draw/engines/overlay/overlay_private.hh b/source/blender/draw/engines/overlay/overlay_private.hh index 9a992045124..f367d778125 100644 --- a/source/blender/draw/engines/overlay/overlay_private.hh +++ b/source/blender/draw/engines/overlay/overlay_private.hh @@ -607,7 +607,6 @@ void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata); void OVERLAY_edit_gpencil_legacy_cache_init(OVERLAY_Data *vedata); void OVERLAY_gpencil_legacy_cache_init(OVERLAY_Data *vedata); -void OVERLAY_gpencil_legacy_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_gpencil_legacy_draw(OVERLAY_Data *vedata); void OVERLAY_edit_gpencil_legacy_draw(OVERLAY_Data *vedata); diff --git a/source/blender/draw/intern/draw_cache.cc b/source/blender/draw/intern/draw_cache.cc index d70ac77f617..c2b8577bb5a 100644 --- a/source/blender/draw/intern/draw_cache.cc +++ b/source/blender/draw/intern/draw_cache.cc @@ -890,8 +890,6 @@ blender::gpu::Batch *DRW_cache_object_face_wireframe_get(const Scene *scene, Obj return DRW_pointcloud_batch_cache_get_dots(ob); case OB_VOLUME: return DRW_cache_volume_face_wireframe_get(ob); - case OB_GPENCIL_LEGACY: - return DRW_cache_gpencil_face_wireframe_get(ob); case OB_GREASE_PENCIL: return DRW_cache_grease_pencil_face_wireframe_get(scene, ob); default: @@ -961,8 +959,6 @@ int DRW_cache_object_material_count_get(const Object *ob) return DRW_pointcloud_material_count_get(static_cast(ob->data)); case OB_VOLUME: return DRW_volume_material_count_get(static_cast(ob->data)); - case OB_GPENCIL_LEGACY: - return DRW_gpencil_material_count_get(static_cast(ob->data)); default: BLI_assert(0); return 0; diff --git a/source/blender/draw/intern/draw_cache.hh b/source/blender/draw/intern/draw_cache.hh index b15f9b7b3fe..01ce6ae25dd 100644 --- a/source/blender/draw/intern/draw_cache.hh +++ b/source/blender/draw/intern/draw_cache.hh @@ -258,23 +258,6 @@ DRWVolumeGrid *DRW_volume_batch_cache_get_grid(Volume *volume, blender::gpu::Batch *DRW_cache_volume_face_wireframe_get(Object *ob); blender::gpu::Batch *DRW_cache_volume_selection_surface_get(Object *ob); -/* GPencil (legacy) */ - -blender::gpu::Batch *DRW_cache_gpencil_get(Object *ob, int cfra); -gpu::VertBuf *DRW_cache_gpencil_position_buffer_get(Object *ob, int cfra); -gpu::VertBuf *DRW_cache_gpencil_color_buffer_get(Object *ob, int cfra); -blender::gpu::Batch *DRW_cache_gpencil_edit_lines_get(Object *ob, int cfra); -blender::gpu::Batch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra); -blender::gpu::Batch *DRW_cache_gpencil_edit_curve_handles_get(Object *ob, int cfra); -blender::gpu::Batch *DRW_cache_gpencil_edit_curve_points_get(Object *ob, int cfra); -blender::gpu::Batch *DRW_cache_gpencil_sbuffer_get(Object *ob, bool show_fill); -gpu::VertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob, bool show_fill); -gpu::VertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob, bool show_fill); -int DRW_gpencil_material_count_get(const bGPdata *gpd); - -blender::gpu::Batch *DRW_cache_gpencil_face_wireframe_get(Object *ob); - -bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob); /** * Sbuffer batches are temporary. We need to clear it after drawing. */ diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil_legacy.cc b/source/blender/draw/intern/draw_cache_impl_gpencil_legacy.cc index 56476e93879..1a8e4671ff6 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil_legacy.cc +++ b/source/blender/draw/intern/draw_cache_impl_gpencil_legacy.cc @@ -66,57 +66,10 @@ struct GpencilBatchCache { namespace blender::draw { -/* -------------------------------------------------------------------- */ -/** \name Internal Types - * \{ */ - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Internal Utilities * \{ */ -static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra) -{ - bool valid = true; - - if (cache == nullptr) { - return false; - } - - if (cfra != cache->cache_frame) { - valid = false; - } - else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) { - valid = false; - } - else if (cache->is_dirty) { - 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 = (GpencilBatchCache *)MEM_callocN(sizeof(*cache), - __func__); - } - else { - memset(cache, 0, sizeof(*cache)); - } - - cache->is_dirty = true; - cache->cache_frame = cfra; - - return cache; -} - static void gpencil_batch_cache_clear(GpencilBatchCache *cache) { if (!cache) { @@ -140,19 +93,6 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache) 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); - } - - return cache; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -173,539 +113,10 @@ void DRW_gpencil_batch_cache_free(bGPdata *gpd) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Vertex Formats - * \{ */ - -/* MUST match the format below. */ -struct gpStrokeVert { - /** Position and thickness packed in the same attribute. */ - float pos[3], thickness; - /** Material Index, Stroke Index, Point Index, Packed aspect + hardness + rotation. */ - int32_t mat, stroke_id, point_id, packed_asp_hard_rot; - /** UV and strength packed in the same attribute. */ - float uv_fill[2], u_stroke, strength; -}; - -static GPUVertFormat *gpencil_stroke_format() -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - return &format; -} - -/* MUST match the format below. */ -struct gpEditVert { - uint vflag; - float weight; -}; - -static GPUVertFormat *gpencil_edit_stroke_format() -{ - 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. */ -struct gpEditCurveVert { - float pos[3]; - uint32_t data; -}; - -static GPUVertFormat *gpencil_edit_curve_format() -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - /* initialize vertex formats */ - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - GPU_vertformat_attr_add(&format, "data", GPU_COMP_U32, 1, GPU_FETCH_INT); - } - return &format; -} - -/* MUST match the format below. */ -struct gpColorVert { - float vcol[4]; /* Vertex color */ - float fcol[4]; /* Fill color */ -}; - -static GPUVertFormat *gpencil_color_format() -{ - 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); - } - return &format; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Buffers - * \{ */ - -struct gpIterData { - bGPdata *gpd; - gpStrokeVert *verts; - gpColorVert *cols; - GPUIndexBufBuilder ibo; - int vert_len; - int tri_len; - int curve_len; -}; - -static gpu::VertBuf *gpencil_dummy_buffer_get() -{ - blender::gpu::Batch *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); -} - -BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float hard) -{ - int32_t packed = 0; - /* Aspect uses 9 bits */ - float asp_normalized = (asp > 1.0f) ? (1.0f / asp) : asp; - packed |= int32_t(unit_float_to_uchar_clamp(asp_normalized)); - /* Store if inversed in the 9th bit. */ - if (asp > 1.0f) { - packed |= 1 << 8; - } - /* Rotation uses 9 bits */ - /* Rotation are in [-90..90 degree] range, so we can encode the sign of the angle + the cosine - * because the cosine will always be positive. */ - packed |= int32_t(unit_float_to_uchar_clamp(cosf(rot))) << 9; - /* Store sine sign in 9th bit. */ - if (rot < 0.0f) { - packed |= 1 << 17; - } - /* Hardness uses 8 bits */ - packed |= int32_t(unit_float_to_uchar_clamp(hard)) << 18; - return packed; -} - -static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo, - gpStrokeVert *verts, - gpColorVert *cols, - const bGPDstroke *gps, - const bGPDspoint *pt, - int v, - bool is_endpoint) -{ - /* NOTE: we use the sign of strength 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.vertex_start; - vert->point_id = v; - vert->thickness = max_ff(0.0f, gps->thickness * pt->pressure) * (round_cap1 ? 1.0f : -1.0f); - /* Tag endpoint material to -1 so they get discarded by vertex shader. */ - vert->mat = (is_endpoint) ? -1 : (gps->mat_nr % GPENCIL_MATERIAL_BUFFER_LEN); - - float aspect_ratio = gps->aspect_ratio[0] / max_ff(gps->aspect_ratio[1], 1e-8); - - vert->packed_asp_hard_rot = pack_rotation_aspect_hardness( - pt->uv_rot, aspect_ratio, gps->hardness); - - if (!is_endpoint) { - /* Issue a Quad per point. */ - /* The attribute loading uses a different shader and will undo this bit packing. */ - int v_mat = (v << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT; - GPU_indexbuf_add_tri_verts(ibo, v_mat + 0, v_mat + 1, v_mat + 2); - GPU_indexbuf_add_tri_verts(ibo, v_mat + 2, v_mat + 1, v_mat + 3); - } -} - -static void gpencil_buffer_add_stroke(GPUIndexBufBuilder *ibo, - 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.vertex_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(ibo, verts, cols, gps, &pts[adj_idx], v++, true); - - for (int i = 0; i < pts_len; i++) { - gpencil_buffer_add_point(ibo, 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(ibo, verts, cols, gps, &pts[0], v, false); - /* UV factor needs to be adjusted for the last point to not be equal to the UV factor of the - * first point. It should be the factor of the last point plus the distance from the last point - * to the first. - */ - gpStrokeVert *vert = &verts[v]; - vert->u_stroke = verts[v - 1].u_stroke + len_v3v3(&pts[pts_len - 1].x, &pts[0].x); - v++; - } - /* Last adjacency point (not drawn). */ - adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2); - gpencil_buffer_add_point(ibo, 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.vertex_start + 1; - for (int i = 0; i < tri_len; i++) { - uint *tri = gps->triangles[i].verts; - /* The attribute loading uses a different shader and will undo this bit packing. */ - GPU_indexbuf_add_tri_verts(ibo, - (v + tri[0]) << GP_VERTEX_ID_SHIFT, - (v + tri[1]) << GP_VERTEX_ID_SHIFT, - (v + tri[2]) << GP_VERTEX_ID_SHIFT); - } -} - -static void gpencil_stroke_iter_cb(bGPDlayer * /*gpl*/, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - gpIterData *iter = (gpIterData *)thunk; - if (gps->tot_triangles > 0) { - gpencil_buffer_add_fill(&iter->ibo, gps); - } - gpencil_buffer_add_stroke(&iter->ibo, iter->verts, iter->cols, gps); -} - -static void gpencil_object_verts_count_cb(bGPDlayer * /*gpl*/, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - gpIterData *iter = (gpIterData *)thunk; - int stroke_vert_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); - gps->runtime.vertex_start = iter->vert_len; - /* Add additional padding at the start and end. */ - iter->vert_len += 1 + stroke_vert_len + 1; - /* Store first index offset. */ - gps->runtime.fill_start = iter->tri_len; - iter->tri_len += gps->tot_triangles; - gps->runtime.stroke_start = iter->tri_len; - iter->tri_len += stroke_vert_len * 2; -} - -static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) -{ - bGPdata *gpd = (bGPdata *)ob->data; - - if (cache->vbo == nullptr) { - /* Should be discarded together. */ - BLI_assert(cache->vbo == nullptr && cache->ibo == nullptr); - BLI_assert(cache->geom_batch == nullptr); - /* 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 = {}; - iter.gpd = gpd; - iter.verts = nullptr; - iter.ibo = {0}; - iter.vert_len = 0; - iter.tri_len = 0; - iter.curve_len = 0; - BKE_gpencil_visible_stroke_advanced_iter( - nullptr, ob, nullptr, gpencil_object_verts_count_cb, &iter, do_onion, cfra); - - GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; - /* Create VBOs. */ - GPUVertFormat *format = gpencil_stroke_format(); - GPUVertFormat *format_col = gpencil_color_format(); - cache->vbo = GPU_vertbuf_create_with_format_ex(*format, vbo_flag); - cache->vbo_col = GPU_vertbuf_create_with_format_ex(*format_col, vbo_flag); - /* 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 = cache->vbo->data().data(); - iter.cols = cache->vbo_col->data().data(); - /* Create IBO. */ - GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, 0xFFFFFFFFu); - - /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_advanced_iter( - nullptr, ob, nullptr, 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; - } - /* Also mark first vert as invalid. */ - iter.verts[0].mat = -1; - - /* Finish the IBO. */ - cache->ibo = GPU_indexbuf_build(&iter.ibo); - /* Create the batches */ - cache->geom_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo); - /* Allow creation of buffer texture. */ - GPU_vertbuf_use(cache->vbo); - GPU_vertbuf_use(cache->vbo_col); - - gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; - cache->is_dirty = false; - } -} - -blender::gpu::Batch *DRW_cache_gpencil_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - - return cache->geom_batch; -} - -gpu::VertBuf *DRW_cache_gpencil_position_buffer_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - - return cache->vbo; -} - -gpu::VertBuf *DRW_cache_gpencil_color_buffer_get(Object *ob, int cfra) -{ - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra); - gpencil_batches_ensure(ob, cache, cfra); - - return cache->vbo_col; -} - -static void gpencil_lines_indices_cb(bGPDlayer * /*gpl*/, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - gpIterData *iter = (gpIterData *)thunk; - int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); - - int start = gps->runtime.vertex_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); -} - -blender::gpu::Batch *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 == nullptr) { - gpu::VertBuf *vbo = cache->vbo; - - gpIterData iter = {}; - iter.gpd = (bGPdata *)ob->data; - iter.ibo = {0}; - - uint vert_len = GPU_vertbuf_get_vertex_len(vbo); - GPU_indexbuf_init_ex(&iter.ibo, GPU_PRIM_LINE_STRIP, vert_len, vert_len); - - /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ - bool do_onion = true; - BKE_gpencil_visible_stroke_advanced_iter( - nullptr, ob, nullptr, gpencil_lines_indices_cb, &iter, do_onion, cfra); - - blender::gpu::IndexBuf *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; - Brush *brush = gpd->runtime.sbuffer_brush; - /* Convert the sbuffer to a bGPDstroke. */ - if (gpd->runtime.sbuffer_gps == nullptr) { - bGPDstroke *gps = (bGPDstroke *)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 = brush->size; - gps->hardness = brush->gpencil_settings->hardness; - copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio); - - gps->fill_opacity_fac = gpd->runtime.fill_opacity_fac; - - gps->tot_triangles = max_ii(0, gpd->runtime.sbuffer_used - 2); - gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND; - gps->runtime.vertex_start = 0; - gps->runtime.fill_start = 0; - gps->runtime.stroke_start = 0; - copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill); - /* Caps. */ - gps->caps[0] = gps->caps[1] = short(brush->gpencil_settings->caps_type); - - gpd->runtime.sbuffer_gps = gps; - } - return gpd->runtime.sbuffer_gps; -} - -static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill) -{ - tGPspoint *tpoints = (tGPspoint *)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 != nullptr); - - if (gpd->runtime.sbuffer_batch == nullptr) { - gps->points = (bGPDspoint *)MEM_mallocN(vert_len * sizeof(*gps->points), __func__); - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ARegion *region = draw_ctx->region; - Object *ob = draw_ctx->obact; - - BLI_assert(ob && (ob->type == OB_GPENCIL_LEGACY)); - - /* Get origin to reproject points. */ - float origin[3]; - ToolSettings *ts = scene->toolsettings; - ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin); - - for (int i = 0; i < vert_len; i++) { - ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); - mul_m4_v3(ob->world_to_object().ptr(), &gps->points[i].x); - bGPDspoint *pt = &gps->points[i]; - copy_v4_v4(pt->vert_color, tpoints[i].vert_color); - } - /* Calc uv data along the stroke. */ - BKE_gpencil_stroke_uv_update(gps); - - int tri_len = gps->tot_triangles + (gps->totpoints + gpencil_stroke_is_cyclic(gps)) * 2; - /* Create IBO. */ - GPUIndexBufBuilder ibo_builder; - GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, tri_len, 0xFFFFFFFFu); - /* Create VBO. */ - GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; - GPUVertFormat *format = gpencil_stroke_format(); - GPUVertFormat *format_color = gpencil_color_format(); - gpu::VertBuf *vbo = GPU_vertbuf_create_with_format_ex(*format, vbo_flag); - gpu::VertBuf *vbo_col = GPU_vertbuf_create_with_format_ex(*format_color, vbo_flag); - /* Add extra space at the start and end 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 = vbo->data().data(); - gpColorVert *cols = vbo_col->data().data(); - - /* Create fill indices. */ - if (do_fill && gps->tot_triangles > 0) { - float(*tpoints2d)[2] = (float(*)[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].m_xy); - } - /* 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 and shift. */ - for (int i = 0; i < gps->tot_triangles * 3; i++) { - ibo_builder.data[i] = (ibo_builder.data[i] + 1) << GP_VERTEX_ID_SHIFT; - } - /* 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; - ibo_builder.index_min = 0; - /* For this case, do not allow index compaction to avoid yet another preprocessing step. */ - ibo_builder.index_max = 0xFFFFFFFFu - 1u; - - gps->runtime.stroke_start = gps->tot_triangles; - - MEM_freeN(tpoints2d); - } - - /* Fill buffers with data. */ - gpencil_buffer_add_stroke(&ibo_builder, verts, cols, gps); - - blender::gpu::Batch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, - gpencil_dummy_buffer_get(), - GPU_indexbuf_build(&ibo_builder), - GPU_BATCH_OWNS_INDEX); - - gpd->runtime.sbuffer_position_buf = vbo; - gpd->runtime.sbuffer_color_buf = vbo_col; - gpd->runtime.sbuffer_batch = batch; - - MEM_freeN(gps->points); - } -} - -blender::gpu::Batch *DRW_cache_gpencil_sbuffer_get(Object *ob, bool show_fill) -{ - bGPdata *gpd = (bGPdata *)ob->data; - /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, show_fill); - - return gpd->runtime.sbuffer_batch; -} - -gpu::VertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob, bool show_fill) -{ - bGPdata *gpd = (bGPdata *)ob->data; - /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, show_fill); - - return gpd->runtime.sbuffer_position_buf; -} - -gpu::VertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob, bool show_fill) -{ - bGPdata *gpd = (bGPdata *)ob->data; - /* Fill batch also need stroke batch to be created (vbo is shared). */ - gpencil_sbuffer_stroke_ensure(gpd, show_fill); - - return gpd->runtime.sbuffer_color_buf; -} - void DRW_cache_gpencil_sbuffer_clear(Object *ob) { bGPdata *gpd = (bGPdata *)ob->data; @@ -717,285 +128,4 @@ void DRW_cache_gpencil_sbuffer_clear(Object *ob) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name 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) -#define GP_EDIT_POINT_DIMMED (1 << 5) - -struct gpEditIterData { - gpEditVert *verts; - int vgindex; -}; - -struct gpEditCurveIterData { - gpEditCurveVert *verts; - int vgindex; -}; - -static uint32_t gpencil_point_edit_flag(const bool layer_lock, - const bGPDspoint *pt, - int v, - int v_len) -{ - uint32_t sflag = 0; - SET_FLAG_FROM_TEST(sflag, (!layer_lock) && 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); - SET_FLAG_FROM_TEST(sflag, pt->runtime.pt_orig == nullptr, GP_EDIT_POINT_DIMMED); - return sflag; -} - -static float gpencil_point_edit_weight(const MDeformVert *dvert, int v, int vgindex) -{ - return (dvert && dvert[v].dw) ? BKE_defvert_find_weight(&dvert[v], vgindex) : -1.0f; -} - -static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl, - bGPDframe *gpf, - bGPDstroke *gps, - void *thunk) -{ - gpEditIterData *iter = (gpEditIterData *)thunk; - const int v_len = gps->totpoints; - const int v = gps->runtime.vertex_start + 1; - MDeformVert *dvert = ((iter->vgindex > -1) && gps->dvert) ? gps->dvert : nullptr; - gpEditVert *vert_ptr = iter->verts + v; - - const bool layer_lock = (gpl->flag & GP_LAYER_LOCKED); - uint32_t sflag = 0; - SET_FLAG_FROM_TEST( - sflag, (!layer_lock) && 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(layer_lock, &gps->points[i], i, v_len); - vert_ptr->weight = gpencil_point_edit_weight(dvert, i, iter->vgindex); - vert_ptr++; - } - - if (gpencil_stroke_is_cyclic(gps)) { - /* Draw line to first point to complete the loop for cyclic strokes. */ - vert_ptr->vflag = sflag | gpencil_point_edit_flag(layer_lock, &gps->points[0], 0, v_len); - vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex); - } -} - -static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - if (gpl->flag & GP_LAYER_LOCKED) { - return; - } - - gpIterData *iter = (gpIterData *)thunk; - - if (gps->editcurve == nullptr) { - return; - } - - /* Store first index offset */ - gps->runtime.curve_start = iter->curve_len; - iter->curve_len += gps->editcurve->tot_curve_points * 4; -} - -static uint32_t gpencil_beztriple_vflag_get(char flag, - char col_id, - bool handle_point, - const bool handle_selected) -{ - uint32_t vflag = 0; - SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); - SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); - SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE); - vflag |= VFLAG_VERT_GPENCIL_BEZT_HANDLE; - - /* Handle color id. */ - vflag |= col_id << COLOR_SHIFT; - return vflag; -} - -static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl, - bGPDframe * /*gpf*/, - bGPDstroke *gps, - void *thunk) -{ - if (gpl->flag & GP_LAYER_LOCKED) { - return; - } - - if (gps->editcurve == nullptr) { - return; - } - bGPDcurve *editcurve = gps->editcurve; - gpEditCurveIterData *iter = (gpEditCurveIterData *)thunk; - const int v = gps->runtime.curve_start; - gpEditCurveVert *vert_ptr = iter->verts + v; - /* Hide points when the curve is unselected. Passing the control point - * as handle produces the point shader skip it if you are not in ALL mode. */ - const bool hide = !(editcurve->flag & GP_CURVE_SELECT); - - for (int i = 0; i < editcurve->tot_curve_points; i++) { - BezTriple *bezt = &editcurve->curve_points[i].bezt; - const bool handle_selected = BEZT_ISSEL_ANY(bezt); - const uint32_t vflag[3] = { - gpencil_beztriple_vflag_get(bezt->f1, bezt->h1, true, handle_selected), - gpencil_beztriple_vflag_get(bezt->f2, bezt->h1, hide, handle_selected), - gpencil_beztriple_vflag_get(bezt->f3, bezt->h2, true, handle_selected), - }; - - /* First segment. */ - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[0]); - vert_ptr->data = vflag[0]; - vert_ptr++; - - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); - vert_ptr->data = vflag[1]; - vert_ptr++; - - /* Second segment. */ - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); - vert_ptr->data = vflag[1]; - vert_ptr++; - - mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[2]); - vert_ptr->data = vflag[2]; - vert_ptr++; - } -} - -static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra) -{ - bGPdata *gpd = (bGPdata *)ob->data; - - if (cache->edit_vbo == nullptr) { - /* 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 = GPU_vertbuf_get_vertex_len(cache->vbo); - - gpEditIterData iter; - iter.vgindex = gpd->vertex_group_active_index - 1; - if (!BLI_findlink(&gpd->vertex_group_names, 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 = cache->edit_vbo->data().data(); - - /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_advanced_iter( - nullptr, ob, nullptr, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra); - - /* Create the batches */ - cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, nullptr); - GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo, false); - - cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, nullptr); - GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo, false); - } - - /* Curve Handles and Points for Editing. */ - if (cache->edit_curve_vbo == nullptr) { - gpIterData iterdata = {}; - iterdata.gpd = gpd; - iterdata.verts = nullptr; - iterdata.ibo = {0}; - iterdata.vert_len = 0; - iterdata.tri_len = 0; - iterdata.curve_len = 0; - - /* Create VBO. */ - GPUVertFormat *format = gpencil_edit_curve_format(); - cache->edit_curve_vbo = GPU_vertbuf_create_with_format(*format); - - /* Count data. */ - BKE_gpencil_visible_stroke_advanced_iter( - nullptr, ob, nullptr, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra); - - gpEditCurveIterData iter; - int vert_len = iterdata.curve_len; - if (vert_len > 0) { - - GPU_vertbuf_data_alloc(*cache->edit_curve_vbo, vert_len); - iter.verts = cache->edit_curve_vbo->data().data(); - - /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_advanced_iter( - nullptr, ob, nullptr, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra); - - cache->edit_curve_handles_batch = GPU_batch_create( - GPU_PRIM_LINES, cache->edit_curve_vbo, nullptr); - GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo, false); - - cache->edit_curve_points_batch = GPU_batch_create( - GPU_PRIM_POINTS, cache->edit_curve_vbo, nullptr); - GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo, false); - } - - gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; - cache->is_dirty = false; - } -} - -blender::gpu::Batch *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; -} - -blender::gpu::Batch *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; -} - -blender::gpu::Batch *DRW_cache_gpencil_edit_curve_handles_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_curve_handles_batch; -} - -blender::gpu::Batch *DRW_cache_gpencil_edit_curve_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_curve_points_batch; -} - -int DRW_gpencil_material_count_get(const bGPdata *gpd) -{ - return max_ii(1, gpd->totcol); -} - -/** \} */ - } // namespace blender::draw diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index c93ffdc7039..b9bfc0e2377 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -35,7 +35,6 @@ set(SRC eyedroppers/eyedropper_datablock.cc eyedroppers/eyedropper_depth.cc eyedroppers/eyedropper_driver.cc - eyedroppers/eyedropper_gpencil_color.cc eyedroppers/eyedropper_grease_pencil_color.cc eyedroppers/interface_eyedropper.cc interface.cc diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc deleted file mode 100644 index a34515b7465..00000000000 --- a/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-FileCopyrightText: 2009 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup edinterface - * - * Eyedropper (RGB Color) - * - * Defines: - * - #UI_OT_eyedropper_gpencil_color - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_listbase.h" -#include "BLI_string.h" - -#include "BLT_translation.hh" - -#include "DNA_gpencil_legacy_types.h" -#include "DNA_material_types.h" -#include "DNA_space_types.h" - -#include "BKE_context.hh" -#include "BKE_gpencil_legacy.h" -#include "BKE_lib_id.hh" -#include "BKE_material.h" -#include "BKE_paint.hh" - -#include "UI_interface.hh" - -#include "IMB_colormanagement.hh" - -#include "WM_api.hh" -#include "WM_types.hh" - -#include "RNA_access.hh" -#include "RNA_define.hh" - -#include "ED_screen.hh" -#include "ED_undo.hh" - -#include "DEG_depsgraph_build.hh" - -#include "eyedropper_intern.hh" -#include "interface_intern.hh" - -enum eGP_EyeMode { - GP_EYE_MATERIAL = 0, - GP_EYE_PALETTE = 1, -}; - -struct EyedropperGPencil { - ColorManagedDisplay *display; - /** color under cursor RGB */ - float color[3]; - /** Mode */ - eGP_EyeMode mode; -}; - -/* Helper: Draw status message while the user is running the operator */ -static void eyedropper_gpencil_status_indicators(bContext *C) -{ - char msg_str[UI_MAX_DRAW_STR]; - STRNCPY(msg_str, IFACE_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill")); - - ED_workspace_status_text(C, msg_str); -} - -/* Initialize. */ -static bool eyedropper_gpencil_init(bContext *C, wmOperator *op) -{ - EyedropperGPencil *eye = MEM_cnew(__func__); - - op->customdata = eye; - Scene *scene = CTX_data_scene(C); - - const char *display_device; - display_device = scene->display_settings.display_device; - eye->display = IMB_colormanagement_display_get_named(display_device); - - eye->mode = (eGP_EyeMode)RNA_enum_get(op->ptr, "mode"); - return true; -} - -/* Exit and free memory. */ -static void eyedropper_gpencil_exit(bContext *C, wmOperator *op) -{ - /* Clear status message area. */ - ED_workspace_status_text(C, nullptr); - - MEM_SAFE_FREE(op->customdata); -} - -static void eyedropper_add_material(bContext *C, - const float col_conv[4], - const bool only_stroke, - const bool only_fill, - const bool both) -{ - Main *bmain = CTX_data_main(C); - Object *ob = CTX_data_active_object(C); - Material *ma = nullptr; - - bool found = false; - - /* Look for a similar material in grease pencil slots. */ - short *totcol = BKE_object_material_len_p(ob); - for (short i = 0; i < *totcol; i++) { - ma = BKE_object_material_get(ob, i + 1); - if (ma == nullptr) { - continue; - } - - MaterialGPencilStyle *gp_style = ma->gp_style; - if (gp_style != nullptr) { - /* Check stroke color. */ - bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) && - (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_MATERIAL_FILL_SHOW); - - 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_MATERIAL_STROKE_SHOW) == 0)) { - found = true; - } - else if ((both) && (found_stroke) && (found_fill)) { - found = true; - } - - /* Found existing material. */ - if (found) { - ob->actcol = i + 1; - WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, nullptr); - WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, nullptr); - return; - } - } - } - - /* If material was not found add a new material with stroke and/or fill color - * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill) - */ - int idx; - Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx); - WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, &ob->id); - WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, nullptr); - DEG_relations_tag_update(bmain); - - BLI_assert(ma_new != nullptr); - - MaterialGPencilStyle *gp_style_new = ma_new->gp_style; - BLI_assert(gp_style_new != nullptr); - - /* Only create Stroke (default option). */ - if (only_stroke) { - /* Stroke color. */ - 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_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_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); - } - /* Push undo for new created material. */ - ED_undo_push(C, "Add Grease Pencil Material"); -} - -/* Create a new palette color and palette if needed. */ -static void eyedropper_add_palette_color(bContext *C, const float col_conv[4]) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ToolSettings *ts = scene->toolsettings; - GpPaint *gp_paint = ts->gp_paint; - GpVertexPaint *gp_vertexpaint = ts->gp_vertexpaint; - Paint *paint = &gp_paint->paint; - Paint *vertexpaint = &gp_vertexpaint->paint; - - /* Check for Palette in Draw and Vertex Paint Mode. */ - if (paint->palette == nullptr) { - Palette *palette = BKE_palette_add(bmain, "Grease Pencil"); - id_us_min(&palette->id); - - BKE_paint_palette_set(paint, palette); - - if (vertexpaint->palette == nullptr) { - BKE_paint_palette_set(vertexpaint, palette); - } - } - /* Check if the color exist already. */ - Palette *palette = paint->palette; - LISTBASE_FOREACH (PaletteColor *, palcolor, &palette->colors) { - if (compare_v3v3(palcolor->rgb, col_conv, 0.01f)) { - return; - } - } - - /* Create Colors. */ - PaletteColor *palcol = BKE_palette_color_add(palette); - if (palcol) { - copy_v3_v3(palcol->rgb, col_conv); - } -} - -/* Set the material or the palette color. */ -static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye) -{ - - const bool only_stroke = (event->modifier & (KM_CTRL | KM_SHIFT)) == 0; - const bool only_fill = ((event->modifier & KM_CTRL) == 0 && (event->modifier & KM_SHIFT)); - const bool both = ((event->modifier & KM_CTRL) && (event->modifier & KM_SHIFT)); - - float col_conv[4]; - - /* Convert from linear rgb space to display space because palette 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) && (eye->mode == GP_EYE_PALETTE)) { - 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); - } - - /* Add material or Palette color. */ - if (eye->mode == GP_EYE_MATERIAL) { - eyedropper_add_material(C, col_conv, only_stroke, only_fill, both); - } - else { - eyedropper_add_palette_color(C, col_conv); - } -} - -/* Sample the color below cursor. */ -static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, const int m_xy[2]) -{ - eyedropper_color_sample_fl(C, nullptr, m_xy, eye->color); -} - -/* Cancel operator. */ -static void eyedropper_gpencil_cancel(bContext *C, wmOperator *op) -{ - eyedropper_gpencil_exit(C, op); -} - -/* Main modal status check. */ -static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - EyedropperGPencil *eye = (EyedropperGPencil *)op->customdata; - /* Handle modal keymap */ - switch (event->type) { - case EVT_MODAL_MAP: { - switch (event->val) { - case EYE_MODAL_SAMPLE_BEGIN: { - return OPERATOR_RUNNING_MODAL; - } - case EYE_MODAL_CANCEL: { - eyedropper_gpencil_cancel(C, op); - return OPERATOR_CANCELLED; - } - case EYE_MODAL_SAMPLE_CONFIRM: { - eyedropper_gpencil_color_sample(C, eye, event->xy); - - /* Create material. */ - eyedropper_gpencil_color_set(C, event, eye); - WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, nullptr); - - eyedropper_gpencil_exit(C, op); - return OPERATOR_FINISHED; - } - default: { - break; - } - } - break; - } - case MOUSEMOVE: - case INBETWEEN_MOUSEMOVE: { - eyedropper_gpencil_color_sample(C, eye, event->xy); - break; - } - default: { - break; - } - } - - return OPERATOR_RUNNING_MODAL; -} - -/* Modal Operator init */ -static int eyedropper_gpencil_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) -{ - /* Init. */ - if (eyedropper_gpencil_init(C, op)) { - /* Add modal temp handler. */ - WM_event_add_modal_handler(C, op); - /* Status message. */ - eyedropper_gpencil_status_indicators(C); - - return OPERATOR_RUNNING_MODAL; - } - return OPERATOR_PASS_THROUGH; -} - -/* Repeat operator */ -static int eyedropper_gpencil_exec(bContext *C, wmOperator *op) -{ - /* init */ - if (eyedropper_gpencil_init(C, op)) { - - /* cleanup */ - eyedropper_gpencil_exit(C, op); - - return OPERATOR_FINISHED; - } - return OPERATOR_PASS_THROUGH; -} - -static bool eyedropper_gpencil_poll(bContext *C) -{ - /* Only valid if the current active object is grease pencil. */ - Object *obact = CTX_data_active_object(C); - if ((obact == nullptr) || (obact->type != OB_GPENCIL_LEGACY)) { - return false; - } - - /* Test we have a window below. */ - return (CTX_wm_window(C) != nullptr); -} - -void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot) -{ - static const EnumPropertyItem items_mode[] = { - {GP_EYE_MATERIAL, "MATERIAL", 0, "Material", ""}, - {GP_EYE_PALETTE, "PALETTE", 0, "Palette", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - /* identifiers */ - ot->name = "Grease Pencil Eyedropper"; - ot->idname = "UI_OT_eyedropper_gpencil_color"; - ot->description = "Sample a color from the Blender Window and create Grease Pencil material"; - - /* api callbacks */ - ot->invoke = eyedropper_gpencil_invoke; - ot->modal = eyedropper_gpencil_modal; - ot->cancel = eyedropper_gpencil_cancel; - ot->exec = eyedropper_gpencil_exec; - ot->poll = eyedropper_gpencil_poll; - - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, GP_EYE_MATERIAL, "Mode", ""); -} diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc index 1809c713ffd..7e4967e2a67 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_grease_pencil_color.cc @@ -24,7 +24,7 @@ #include "DNA_space_types.h" #include "BKE_context.hh" -#include "BKE_gpencil_legacy.h" +#include "BKE_grease_pencil.hh" #include "BKE_lib_id.hh" #include "BKE_material.h" #include "BKE_paint.hh" @@ -203,7 +203,7 @@ static void eyedropper_add_material(bContext *C, * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill) */ int idx; - Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx); + Material *ma_new = BKE_grease_pencil_object_material_new(bmain, ob, "Material", &idx); WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, &ob->id); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, nullptr); DEG_relations_tag_update(bmain); @@ -295,9 +295,9 @@ static void eyedropper_set_brush_color(bContext *C, const float3 &col_conv) } /* Set the material or the palette color. */ -static void eyedropper_gpencil_color_set(bContext *C, - const wmEvent *event, - EyedropperGreasePencil *eye) +static void eyedropper_grease_pencil_color_set(bContext *C, + const wmEvent *event, + EyedropperGreasePencil *eye) { const bool is_ctrl = (event->modifier & KM_CTRL) != 0; const bool is_shift = (event->modifier & KM_SHIFT) != 0; @@ -386,7 +386,7 @@ static int eyedropper_grease_pencil_modal(bContext *C, wmOperator *op, const wmE eyedropper_grease_pencil_color_sample(C, eye, event->xy); /* Create material. */ - eyedropper_gpencil_color_set(C, event, eye); + eyedropper_grease_pencil_color_set(C, event, eye); WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, nullptr); eyedropper_grease_pencil_exit(C, op); diff --git a/source/blender/editors/interface/eyedroppers/interface_eyedropper.cc b/source/blender/editors/interface/eyedroppers/interface_eyedropper.cc index 30e17bb98d5..9e43c223881 100644 --- a/source/blender/editors/interface/eyedroppers/interface_eyedropper.cc +++ b/source/blender/editors/interface/eyedroppers/interface_eyedropper.cc @@ -56,7 +56,6 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_bone"); WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth"); WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_driver"); - WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_gpencil_color"); WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_grease_pencil_color"); return keymap; diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 2b704ca5a6b..9b14eb60785 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -1570,10 +1570,6 @@ void UI_OT_eyedropper_depth(wmOperatorType *ot); void UI_OT_eyedropper_driver(wmOperatorType *ot); -/* interface_eyedropper_gpencil_color.c */ - -void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot); - /* eyedropper_grease_pencil_color.cc */ void UI_OT_eyedropper_grease_pencil_color(wmOperatorType *ot); diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index 431a83d6cd8..c4e2e20b13c 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -2845,7 +2845,6 @@ void ED_operatortypes_ui() WM_operatortype_append(UI_OT_eyedropper_id); WM_operatortype_append(UI_OT_eyedropper_depth); WM_operatortype_append(UI_OT_eyedropper_driver); - WM_operatortype_append(UI_OT_eyedropper_gpencil_color); WM_operatortype_append(UI_OT_eyedropper_bone); WM_operatortype_append(UI_OT_eyedropper_grease_pencil_color); } diff --git a/source/blender/editors/space_info/info_stats.cc b/source/blender/editors/space_info/info_stats.cc index 1e2fa8fb5d1..3c66b3969fd 100644 --- a/source/blender/editors/space_info/info_stats.cc +++ b/source/blender/editors/space_info/info_stats.cc @@ -171,24 +171,6 @@ static void stats_object(Object *ob, stats->totlampsel++; } break; - case OB_GPENCIL_LEGACY: { - if (is_selected) { - bGPdata *gpd = (bGPdata *)ob->data; - if (!BLI_gset_add(objects_gset, gpd)) { - break; - } - /* GPXX Review if we can move to other place when object change - * maybe to depsgraph evaluation - */ - BKE_gpencil_stats_update(gpd); - - stats->totgplayer += gpd->totlayer; - stats->totgpframe += gpd->totframe; - stats->totgpstroke += gpd->totstroke; - stats->totgppoint += gpd->totpoint; - } - break; - } case OB_GREASE_PENCIL: { if (!is_selected) { break; diff --git a/source/blender/io/grease_pencil/intern/grease_pencil_io.cc b/source/blender/io/grease_pencil/intern/grease_pencil_io.cc index 9da2b4b8a45..bb35737dbfa 100644 --- a/source/blender/io/grease_pencil/intern/grease_pencil_io.cc +++ b/source/blender/io/grease_pencil/intern/grease_pencil_io.cc @@ -5,19 +5,18 @@ #include "BLI_color.hh" #include "BLI_math_matrix.hh" #include "BLI_math_vector.h" +#include "BLI_math_vector.hh" #include "BKE_attribute.hh" #include "BKE_camera.h" #include "BKE_context.hh" #include "BKE_crazyspace.hh" #include "BKE_curves.hh" -#include "BKE_gpencil_legacy.h" #include "BKE_grease_pencil.hh" #include "BKE_layer.hh" #include "BKE_material.h" #include "BKE_scene.hh" -#include "BLI_math_vector.hh" #include "DNA_grease_pencil_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" @@ -126,12 +125,13 @@ int GreasePencilImporter::create_material(const StringRefNull name, { const ColorGeometry4f default_stroke_color = {0.0f, 0.0f, 0.0f, 1.0f}; const ColorGeometry4f default_fill_color = {0.5f, 0.5f, 0.5f, 1.0f}; - int mat_index = BKE_gpencil_object_material_index_get_by_name(object_, name.c_str()); + int mat_index = BKE_grease_pencil_object_material_index_get_by_name(object_, name.c_str()); /* Stroke and Fill material. */ if (mat_index == -1) { Main *bmain = CTX_data_main(&context_.C); int new_idx; - Material *mat_gp = BKE_gpencil_object_material_new(bmain, object_, name.c_str(), &new_idx); + Material *mat_gp = BKE_grease_pencil_object_material_new( + bmain, object_, name.c_str(), &new_idx); MaterialGPencilStyle *gp_style = mat_gp->gp_style; gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; gp_style->flag &= ~GP_MATERIAL_FILL_SHOW; diff --git a/source/blender/makesdna/DNA_gpencil_legacy_types.h b/source/blender/makesdna/DNA_gpencil_legacy_types.h index 69c8ebd4019..c6d0337d13d 100644 --- a/source/blender/makesdna/DNA_gpencil_legacy_types.h +++ b/source/blender/makesdna/DNA_gpencil_legacy_types.h @@ -333,9 +333,6 @@ typedef struct bGPDstroke { /** Curve used to edit the stroke using Bezier handlers. */ struct bGPDcurve *editcurve; - /* NOTE: When adding new members, make sure to add them to BKE_gpencil_stroke_copy_settings as - * well! */ - bGPDstroke_Runtime runtime; void *_pad5; } bGPDstroke; @@ -429,9 +426,6 @@ typedef struct bGPDframe { /** Keyframe type (eBezTriple_KeyframeType). */ short key_type; - /* NOTE: When adding new members, make sure to add them to BKE_gpencil_frame_copy_settings as - * well! */ - bGPDframe_Runtime runtime; } bGPDframe; @@ -561,9 +555,6 @@ typedef struct bGPDlayer { float layer_mat[4][4], layer_invmat[4][4]; char _pad3[4]; - /* NOTE: When adding new members, make sure to add them to BKE_gpencil_layer_copy_settings as - * well! */ - bGPDlayer_Runtime runtime; } bGPDlayer; @@ -769,9 +760,6 @@ typedef struct bGPdata { bGPgrid grid; - /* NOTE: When adding new members, make sure to add them to BKE_gpencil_data_copy_settings as - * well! */ - bGPdata_Runtime runtime; } bGPdata; diff --git a/source/blender/makesrna/intern/rna_object_api.cc b/source/blender/makesrna/intern/rna_object_api.cc index 8a261c9f452..620a6e59dc7 100644 --- a/source/blender/makesrna/intern/rna_object_api.cc +++ b/source/blender/makesrna/intern/rna_object_api.cc @@ -800,31 +800,6 @@ static bool rna_Object_update_from_editmode(Object *ob, Main *bmain) return result; } -bool rna_Object_generate_gpencil_strokes(Object *ob, - bContext *C, - ReportList *reports, - Object *ob_gpencil, - bool use_collections, - float scale_thickness, - float sample) -{ - if (ob->type != OB_CURVES_LEGACY) { - BKE_reportf(reports, - RPT_ERROR, - "Object '%s' is not valid for this operation! Only curves are supported", - ob->id.name + 2); - return false; - } - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - - BKE_gpencil_convert_curve( - bmain, scene, ob_gpencil, ob, use_collections, scale_thickness, sample); - - WM_main_add_notifier(NC_GPENCIL | ND_DATA, nullptr); - - return true; -} #else /* RNA_RUNTIME */ void RNA_api_object(StructRNA *srna) @@ -1356,25 +1331,6 @@ void RNA_api_object(StructRNA *srna) RNA_def_function_ui_description(func, "Release memory used by caches associated with this object. " "Intended to be used by render engines only."); - - /* Convert curve object to gpencil strokes. */ - func = RNA_def_function(srna, "generate_gpencil_strokes", "rna_Object_generate_gpencil_strokes"); - RNA_def_function_ui_description(func, "Convert a curve object to grease pencil strokes."); - RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); - - parm = RNA_def_pointer(func, - "grease_pencil_object", - "Object", - "", - "Grease Pencil object used to create new strokes"); - RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - parm = RNA_def_boolean(func, "use_collections", true, "", "Use Collections"); - parm = RNA_def_float( - func, "scale_thickness", 1.0f, 0.0f, FLT_MAX, "", "Thickness scaling factor", 0.0f, 100.0f); - parm = RNA_def_float( - func, "sample", 0.0f, 0.0f, FLT_MAX, "", "Sample distance, zero to disable", 0.0f, 100.0f); - parm = RNA_def_boolean(func, "result", false, "", "Result"); - RNA_def_function_return(func, parm); } #endif /* RNA_RUNTIME */ diff --git a/source/blender/modifiers/intern/lineart/MOD_lineart.h b/source/blender/modifiers/intern/lineart/MOD_lineart.h index 6145e171a93..c4af5ee495c 100644 --- a/source/blender/modifiers/intern/lineart/MOD_lineart.h +++ b/source/blender/modifiers/intern/lineart/MOD_lineart.h @@ -871,7 +871,6 @@ struct GreasePencilLineartModifierData; struct LineartData; struct Scene; -void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd_legacy); void MOD_lineart_destroy_render_data_v3(struct GreasePencilLineartModifierData *lmd); void MOD_lineart_chain_feature_lines(LineartData *ld); @@ -902,10 +901,6 @@ void MOD_lineart_finalize_chains(LineartData *ld); * * \return True when a change is made. */ -bool MOD_lineart_compute_feature_lines(struct Depsgraph *depsgraph, - struct LineartGpencilModifierData *lmd_legacy, - struct LineartCache **cached_result, - bool enable_stroke_depth_offset); bool MOD_lineart_compute_feature_lines_v3(struct Depsgraph *depsgraph, struct GreasePencilLineartModifierData &lmd, struct LineartCache **cached_result, @@ -921,32 +916,6 @@ LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartData *ld, doubl */ LineartBoundingArea *MOD_lineart_get_bounding_area(LineartData *ld, double x, double y); -/** - * Wrapper for external calls. - */ -void MOD_lineart_gpencil_generate(LineartCache *cache, - struct Depsgraph *depsgraph, - struct Object *ob, - struct bGPDlayer *gpl, - struct bGPDframe *gpf, - int8_t source_type, - void *source_reference, - int level_start, - int level_end, - int mat_nr, - int16_t edge_types, - uint8_t mask_switches, - uint8_t material_mask_bits, - uint8_t intersection_mask, - int16_t thickness, - float opacity, - uint8_t shadow_selection, - uint8_t silhouette_mode, - const char *source_vgname, - const char *vgname, - int modifier_flags, - int modifier_calculation_flags); - namespace blender::bke::greasepencil { class Drawing; } diff --git a/source/blender/modifiers/intern/lineart/lineart_cpu.cc b/source/blender/modifiers/intern/lineart/lineart_cpu.cc index 842f65bfc57..9703087ee91 100644 --- a/source/blender/modifiers/intern/lineart/lineart_cpu.cc +++ b/source/blender/modifiers/intern/lineart/lineart_cpu.cc @@ -3576,14 +3576,6 @@ void MOD_lineart_destroy_render_data_v3(GreasePencilLineartModifierData *lmd) } } -void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd_legacy) -{ - GreasePencilLineartModifierData lmd; - greasepencil::convert::lineart_wrap_v3(lmd_legacy, &lmd); - MOD_lineart_destroy_render_data_v3(&lmd); - greasepencil::convert::lineart_unwrap_v3(lmd_legacy, &lmd); -} - LineartCache *MOD_lineart_init_cache() { LineartCache *lc = static_cast( @@ -5229,327 +5221,11 @@ bool MOD_lineart_compute_feature_lines_v3(Depsgraph *depsgraph, return true; } -bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, - LineartGpencilModifierData *lmd_legacy, - LineartCache **cached_result, - bool enable_stroke_depth_offset) -{ - bool ret = false; - GreasePencilLineartModifierData lmd; - greasepencil::convert::lineart_wrap_v3(lmd_legacy, &lmd); - ret = MOD_lineart_compute_feature_lines_v3( - depsgraph, lmd, cached_result, enable_stroke_depth_offset); - greasepencil::convert::lineart_unwrap_v3(lmd_legacy, &lmd); - return ret; -} - -static void lineart_gpencil_generate(LineartCache *cache, - Depsgraph *depsgraph, - Object *gpencil_object, - float (*gp_obmat_inverse)[4], - bGPDlayer * /*gpl*/, - bGPDframe *gpf, - int level_start, - int level_end, - int material_nr, - Object *source_object, - Collection *source_collection, - int types, - uchar mask_switches, - uchar material_mask_bits, - uchar intersection_mask, - int16_t thickness, - float opacity, - uchar shaodow_selection, - uchar silhouette_mode, - const char *source_vgname, - const char *vgname, - int modifier_flags, - int modifier_calculation_flags) -{ - if (cache == nullptr) { - if (G.debug_value == 4000) { - printf("nullptr Lineart cache!\n"); - } - return; - } - - int stroke_count = 0; - int color_idx = 0; - - Object *orig_ob = nullptr; - if (source_object) { - orig_ob = source_object->id.orig_id ? (Object *)source_object->id.orig_id : source_object; - } - - Collection *orig_col = nullptr; - if (source_collection) { - orig_col = source_collection->id.orig_id ? (Collection *)source_collection->id.orig_id : - source_collection; - } - - /* (!orig_col && !orig_ob) means the whole scene is selected. */ - - int enabled_types = cache->all_enabled_edge_types; - bool invert_input = modifier_calculation_flags & MOD_LINEART_INVERT_SOURCE_VGROUP; - bool match_output = modifier_calculation_flags & MOD_LINEART_MATCH_OUTPUT_VGROUP; - bool inverse_silhouette = modifier_flags & MOD_LINEART_INVERT_SILHOUETTE_FILTER; - - LISTBASE_FOREACH (LineartEdgeChain *, ec, &cache->chains) { - - if (ec->picked) { - continue; - } - if (!(ec->type & (types & enabled_types))) { - continue; - } - if (ec->level > level_end || ec->level < level_start) { - continue; - } - if (orig_ob && orig_ob != ec->object_ref) { - continue; - } - if (orig_col && ec->object_ref) { - if (BKE_collection_has_object_recursive_instanced(orig_col, (Object *)ec->object_ref)) { - if (modifier_flags & MOD_LINEART_INVERT_COLLECTION) { - continue; - } - } - else { - if (!(modifier_flags & MOD_LINEART_INVERT_COLLECTION)) { - continue; - } - } - } - if (mask_switches & MOD_LINEART_MATERIAL_MASK_ENABLE) { - if (mask_switches & MOD_LINEART_MATERIAL_MASK_MATCH) { - if (ec->material_mask_bits != material_mask_bits) { - continue; - } - } - else { - if (!(ec->material_mask_bits & material_mask_bits)) { - continue; - } - } - } - if (ec->type & MOD_LINEART_EDGE_FLAG_INTERSECTION) { - if (mask_switches & MOD_LINEART_INTERSECTION_MATCH) { - if (ec->intersection_mask != intersection_mask) { - continue; - } - } - else { - if ((intersection_mask) && !(ec->intersection_mask & intersection_mask)) { - continue; - } - } - } - if (shaodow_selection) { - if (ec->shadow_mask_bits != LRT_SHADOW_MASK_UNDEFINED) { - /* TODO(@Yiming): Give a behavior option for how to display undefined shadow info. */ - if (shaodow_selection == LINEART_SHADOW_FILTER_ILLUMINATED && - !(ec->shadow_mask_bits & LRT_SHADOW_MASK_ILLUMINATED)) - { - continue; - } - if (shaodow_selection == LINEART_SHADOW_FILTER_SHADED && - !(ec->shadow_mask_bits & LRT_SHADOW_MASK_SHADED)) - { - continue; - } - if (shaodow_selection == LINEART_SHADOW_FILTER_ILLUMINATED_ENCLOSED_SHAPES) { - uint32_t test_bits = ec->shadow_mask_bits & LRT_SHADOW_TEST_SHAPE_BITS; - if ((test_bits != LRT_SHADOW_MASK_ILLUMINATED) && - (test_bits != (LRT_SHADOW_MASK_SHADED | LRT_SHADOW_MASK_ILLUMINATED_SHAPE))) - { - continue; - } - } - } - } - if (silhouette_mode && (ec->type & (MOD_LINEART_EDGE_FLAG_CONTOUR))) { - bool is_silhouette = false; - if (orig_col) { - if (!ec->silhouette_backdrop) { - is_silhouette = true; - } - else if (!BKE_collection_has_object_recursive_instanced(orig_col, ec->silhouette_backdrop)) - { - is_silhouette = true; - } - } - else { - if ((!orig_ob) && (!ec->silhouette_backdrop)) { - is_silhouette = true; - } - } - - if ((silhouette_mode == LINEART_SILHOUETTE_FILTER_INDIVIDUAL || orig_ob) && - ec->silhouette_backdrop != ec->object_ref) - { - is_silhouette = true; - } - - if (inverse_silhouette) { - is_silhouette = !is_silhouette; - } - if (!is_silhouette) { - continue; - } - } - - /* Preserved: If we ever do asynchronous generation, this picked flag should be set here. */ - // ec->picked = 1; - - const int count = MOD_lineart_chain_count(ec); - if (count < 2) { - continue; - } - - bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, color_idx, count, thickness, false); - - int i; - LISTBASE_FOREACH_INDEX (LineartEdgeChainItem *, eci, &ec->chain, i) { - bGPDspoint *point = &gps->points[i]; - mul_v3_m4v3(&point->x, gp_obmat_inverse, eci->gpos); - point->pressure = 1.0f; - point->strength = opacity; - } - - BKE_gpencil_dvert_ensure(gps); - gps->mat_nr = max_ii(material_nr, 0); - - if (source_vgname && vgname) { - Object *eval_ob = DEG_get_evaluated_object(depsgraph, ec->object_ref); - int gpdg = -1; - if (match_output || (gpdg = BKE_object_defgroup_name_index(gpencil_object, vgname)) >= 0) { - if (eval_ob && eval_ob->type == OB_MESH) { - int dindex = 0; - Mesh *mesh = BKE_object_get_evaluated_mesh(eval_ob); - MDeformVert *dvert = mesh->deform_verts_for_write().data(); - if (dvert) { - LISTBASE_FOREACH (bDeformGroup *, db, &mesh->vertex_group_names) { - if ((!source_vgname) || strstr(db->name, source_vgname) == db->name) { - if (match_output) { - gpdg = BKE_object_defgroup_name_index(gpencil_object, db->name); - if (gpdg < 0) { - continue; - } - } - int sindex = 0, vindex; - LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) { - vindex = eci->index; - if (vindex >= mesh->verts_num) { - break; - } - MDeformWeight *mdw = BKE_defvert_ensure_index(&dvert[vindex], dindex); - MDeformWeight *gdw = BKE_defvert_ensure_index(&gps->dvert[sindex], gpdg); - - float use_weight = mdw->weight; - if (invert_input) { - use_weight = 1 - use_weight; - } - gdw->weight = std::max(use_weight, gdw->weight); - - sindex++; - } - } - dindex++; - } - } - } - } - } - - if (G.debug_value == 4000) { - BKE_gpencil_stroke_set_random_color(gps); - } - BKE_gpencil_stroke_geometry_update(static_cast(gpencil_object->data), gps); - stroke_count++; - } - - if (G.debug_value == 4000) { - printf("LRT: Generated %d strokes.\n", stroke_count); - } -} - typedef struct LineartChainWriteInfo { LineartEdgeChain *chain; int point_count; } LineartChainWriteInfo; -void MOD_lineart_gpencil_generate(LineartCache *cache, - Depsgraph *depsgraph, - Object *ob, - bGPDlayer *gpl, - bGPDframe *gpf, - int8_t source_type, - void *source_reference, - int level_start, - int level_end, - int mat_nr, - int16_t edge_types, - uchar mask_switches, - uchar material_mask_bits, - uchar intersection_mask, - int16_t thickness, - float opacity, - uchar shadow_selection, - uchar silhouette_mode, - const char *source_vgname, - const char *vgname, - int modifier_flags, - int modifier_calculation_flags) -{ - - if (!gpl || !gpf || !ob) { - return; - } - - Object *source_object = nullptr; - Collection *source_collection = nullptr; - int16_t use_types = edge_types; - if (source_type == LINEART_SOURCE_OBJECT) { - if (!source_reference) { - return; - } - source_object = (Object *)source_reference; - } - else if (source_type == LINEART_SOURCE_COLLECTION) { - if (!source_reference) { - return; - } - source_collection = (Collection *)source_reference; - } - - float gp_obmat_inverse[4][4]; - invert_m4_m4(gp_obmat_inverse, ob->object_to_world().ptr()); - lineart_gpencil_generate(cache, - depsgraph, - ob, - gp_obmat_inverse, - gpl, - gpf, - level_start, - level_end, - mat_nr, - source_object, - source_collection, - use_types, - mask_switches, - material_mask_bits, - intersection_mask, - thickness, - opacity, - shadow_selection, - silhouette_mode, - source_vgname, - vgname, - modifier_flags, - modifier_calculation_flags); -} - void MOD_lineart_gpencil_generate_v3(const LineartCache *cache, const blender::float4x4 &inverse_mat, Depsgraph *depsgraph,