diff options
Diffstat (limited to 'source/blender/editors')
201 files changed, 8756 insertions, 5373 deletions
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index bd83bdae31b..9564b662b12 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -3414,12 +3414,13 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data) /* ----------- Public API --------------- */ -/* This function filters the active data source to leave only animation channels suitable for +/** + * This function filters the active data source to leave only animation channels suitable for * usage by the caller. It will return the length of the list * - * *anim_data: is a pointer to a ListBase, to which the filtered animation channels - * will be placed for use. - * filter_mode: how should the data be filtered - bitmapping accessed flags + * \param anim_data: Is a pointer to a #ListBase, + * to which the filtered animation channels will be placed for use. + * \param filter_mode: how should the data be filtered - bit-mapping accessed flags. */ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 863f433c778..edc36326c57 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -92,7 +92,9 @@ static void draw_current_frame(const Scene *scene, bool display_seconds, const View2D *v2d, const rcti *scrub_region_rect, - int current_frame) + int current_frame, + float sub_frame, + bool draw_line) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; int frame_x = UI_view2d_view_to_region_x(v2d, current_frame); @@ -106,6 +108,22 @@ static void draw_current_frame(const Scene *scene, float bg_color[4]; UI_GetThemeColorShade4fv(TH_CFRAME, -5, bg_color); + if (draw_line) { + /* Draw vertical line to from the bottom of the current frame box to the bottom of the screen. + */ + const float subframe_x = UI_view2d_view_to_region_x(v2d, current_frame + sub_frame); + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_CFRAME); + immRectf(pos, + subframe_x - U.pixelsize, + scrub_region_rect->ymax - box_padding, + subframe_x + U.pixelsize, + 0.0f); + immUnbindProgram(); + } + UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_3fv_alpha(true, @@ -135,6 +153,28 @@ static void draw_current_frame(const Scene *scene, text_color); } +void ED_time_scrub_draw_current_frame(const ARegion *region, + const Scene *scene, + bool display_seconds, + bool draw_line) +{ + const View2D *v2d = ®ion->v2d; + GPU_matrix_push_projection(); + wmOrtho2_region_pixelspace(region); + + rcti scrub_region_rect; + get_time_scrub_region_rect(region, &scrub_region_rect); + + draw_current_frame(scene, + display_seconds, + v2d, + &scrub_region_rect, + scene->r.cfra, + scene->r.subframe, + draw_line); + GPU_matrix_pop_projection(); +} + void ED_time_scrub_draw(const ARegion *region, const Scene *scene, bool display_seconds, @@ -161,8 +201,6 @@ void ED_time_scrub_draw(const ARegion *region, region, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); } - draw_current_frame(scene, display_seconds, v2d, &scrub_region_rect, scene->r.cfra); - GPU_matrix_pop_projection(); } diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index a7a705a6202..a010fbd5e81 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -140,7 +140,16 @@ void ED_armature_origin_set( mul_m4_v3(ob->imat, cent); } else { - if (around == V3D_AROUND_CENTER_MEDIAN) { + if (around == V3D_AROUND_CENTER_BOUNDS) { + float min[3], max[3]; + INIT_MINMAX(min, max); + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + minmax_v3v3_v3(min, max, ebone->head); + minmax_v3v3_v3(min, max, ebone->tail); + } + mid_v3_v3v3(cent, min, max); + } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ int total = 0; zero_v3(cent); for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { @@ -152,15 +161,6 @@ void ED_armature_origin_set( mul_v3_fl(cent, 1.0f / (float)total); } } - else { - float min[3], max[3]; - INIT_MINMAX(min, max); - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - minmax_v3v3_v3(min, max, ebone->head); - minmax_v3v3_v3(min, max, ebone->tail); - } - mid_v3_v3v3(cent, min, max); - } } /* Do the adjustments */ diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index d3d00fc44f2..f90d781baca 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -270,7 +270,7 @@ static void joined_armature_fix_links( } /* join armature exec is exported for use in object->join objects operator... */ -int join_armature_exec(bContext *C, wmOperator *op) +int ED_armature_join_objects_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -304,10 +304,10 @@ int join_armature_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* Get editbones of active armature to add editbones to */ + /* Get edit-bones of active armature to add edit-bones to */ ED_armature_to_edit(arm); - /* get pose of active object and move it out of posemode */ + /* Get pose of active object and move it out of pose-mode */ pose = ob_active->pose; ob_active->mode &= ~OB_MODE_POSE; @@ -325,7 +325,7 @@ int join_armature_exec(bContext *C, wmOperator *op) afd.tarArm = ob_active; afd.names_map = BLI_ghash_str_new("join_armature_adt_fix"); - /* Make a list of editbones in current armature */ + /* Make a list of edit-bones in current armature */ ED_armature_to_edit(ob_iter->data); /* Get Pose of current armature */ @@ -549,7 +549,7 @@ static void separated_armature_fix_links(Main *bmain, Object *origArm, Object *n /* Helper function for armature separating - remove certain bones from the given armature * sel: remove selected bones from the armature, otherwise the unselected bones are removed - * (ob is not in editmode) + * (ob is not in edit-mode) */ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_select) { @@ -557,7 +557,7 @@ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_selec bPoseChannel *pchan, *pchann; EditBone *curbone; - /* make local set of editbones to manipulate here */ + /* make local set of edit-bones to manipulate here */ ED_armature_to_edit(arm); /* go through pose-channels, checking if a bone should be removed */ @@ -591,7 +591,7 @@ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_selec } } - /* free any of the extra-data this pchan might have */ + /* Free any of the extra-data this pchan might have. */ BKE_pose_channel_free(pchan); BKE_pose_channels_hash_free(ob->pose); @@ -601,7 +601,7 @@ static void separate_armature_bones(Main *bmain, Object *ob, const bool is_selec } } - /* exit editmode (recalculates pchans too) */ + /* Exit edit-mode (recalculates pose-channels too). */ ED_armature_edit_deselect_all(ob); ED_armature_from_edit(bmain, ob->data); ED_armature_edit_free(ob->data); @@ -652,15 +652,15 @@ static int separate_armature_exec(bContext *C, wmOperator *op) } /* We are going to do this as follows (unlike every other instance of separate): - * 1. Exit editmode +posemode for active armature/base. Take note of what this is. + * 1. Exit edit-mode & pose-mode for active armature/base. Take note of what this is. * 2. Duplicate base - BASACT is the new one now * 3. For each of the two armatures, - * enter editmode -> remove appropriate bones -> exit editmode + recalc. + * enter edit-mode -> remove appropriate bones -> exit edit-mode + recalculate. * 4. Fix constraint links - * 5. Make original armature active and enter editmode + * 5. Make original armature active and enter edit-mode */ - /* 1) store starting settings and exit editmode */ + /* 1) store starting settings and exit edit-mode */ ob_old->mode &= ~OB_MODE_POSE; ED_armature_from_edit(bmain, ob_old->data); @@ -700,7 +700,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op) } MEM_freeN(bases); - /* recalc/redraw + cleanup */ + /* Recalculate/redraw + cleanup */ WM_cursor_wait(0); if (ok) { @@ -754,7 +754,7 @@ static void bone_connect_to_new_parent(ListBase *edbo, float offset[3]; if ((selbone->parent) && (selbone->flag & BONE_CONNECTED)) { - selbone->parent->flag &= ~(BONE_TIPSEL); + selbone->parent->flag &= ~BONE_TIPSEL; } /* make actbone the parent of selbone */ @@ -956,7 +956,7 @@ static void editbone_clear_parent(EditBone *ebone, int mode) { if (ebone->parent) { /* for nice selection */ - ebone->parent->flag &= ~(BONE_TIPSEL); + ebone->parent->flag &= ~BONE_TIPSEL; } if (mode == 1) { diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index eb7c1bc74ea..ccd39429704 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -188,7 +188,7 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode Base *base = NULL; bool sel; - hitresult &= ~(BONESEL_ANY); + hitresult &= ~BONESEL_ANY; /* Determine what the current bone is */ if (is_editmode == false) { base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hitresult, &pchan); @@ -1302,7 +1302,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) if ((ebone->flag & BONE_UNSELECTABLE) == 0) { ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); if (ebone->parent) { - ebone->parent->flag |= (BONE_TIPSEL); + ebone->parent->flag |= BONE_TIPSEL; } } break; @@ -1317,7 +1317,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) if ((ebone->flag & BONE_UNSELECTABLE) == 0) { ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); if (ebone->parent) { - ebone->parent->flag |= (BONE_TIPSEL); + ebone->parent->flag |= BONE_TIPSEL; } } } diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 61d8856afbc..b3c58f2575b 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -283,11 +283,11 @@ static void add_verts_to_dgroups(ReportList *reports, * weights, either through envelopes or using a heat equilibrium. * * This function can be called both when parenting a mesh to an armature, - * or in weightpaint + posemode. In the latter case selection is taken + * or in weight-paint + pose-mode. In the latter case selection is taken * into account and vertex weights can be mirrored. * * The mesh vertex positions used are either the final deformed coords - * from the evaluated mesh in weightpaint mode, the final subsurf coords + * from the evaluated mesh in weight-paint mode, the final sub-surface coords * when parenting, or simply the original mesh coords. */ diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index d8a6a22a7df..145071522ed 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -94,9 +94,8 @@ struct LaplacianSystem { float (*verts)[3]; /* vertex coordinates */ float (*vnors)[3]; /* vertex normals */ - float (*root)[3]; /* bone root */ - float (*tip)[3]; /* bone tip */ - float (*source)[3]; /* vertex source */ + float (*root)[3]; /* bone root */ + float (*tip)[3]; /* bone tip */ int numsource; float *H; /* diagonal H matrix */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 4e1c07af001..a39c8261b32 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1432,7 +1432,7 @@ static int separate_exec(bContext *C, wmOperator *op) /* 2. Duplicate the object and data. */ /* Take into account user preferences for duplicating actions. */ - short dupflag = (U.dupflag & USER_DUP_ACT); + const eDupli_ID_Flags dupflag = (U.dupflag & USER_DUP_ACT); newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, dupflag); DEG_relations_tag_update(bmain); @@ -6895,7 +6895,7 @@ void CURVE_OT_shade_flat(wmOperatorType *ot) * This is used externally, by #OBJECT_OT_join. * TODO: shape keys - as with meshes. */ -int join_curve_exec(bContext *C, wmOperator *op) +int ED_curve_join_objects_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 9294bc6e91b..73f970876b1 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -988,7 +988,7 @@ void CURVE_OT_select_more(wmOperatorType *ot) /* identifiers */ ot->name = "Select More"; ot->idname = "CURVE_OT_select_more"; - ot->description = "Select control points directly linked to already selected ones"; + ot->description = "Select control points at the boundary of each selection region"; /* api callbacks */ ot->exec = curve_select_more_exec; @@ -1203,7 +1203,7 @@ void CURVE_OT_select_less(wmOperatorType *ot) /* identifiers */ ot->name = "Select Less"; ot->idname = "CURVE_OT_select_less"; - ot->description = "Reduce current selection by deselecting boundary elements"; + ot->description = "Deselect control points at the boundary of each selection region"; /* api callbacks */ ot->exec = curve_select_less_exec; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index dc5dc71106f..1bbd4b4a5bc 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1635,7 +1635,7 @@ static int insert_text_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); char *inserted_utf8; - wchar_t *inserted_text; + char32_t *inserted_text; int a, len; if (!RNA_struct_property_is_set(op->ptr, "text")) { @@ -1645,8 +1645,8 @@ static int insert_text_exec(bContext *C, wmOperator *op) inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0); len = BLI_strlen_utf8(inserted_utf8); - inserted_text = MEM_callocN(sizeof(wchar_t) * (len + 1), "FONT_insert_text"); - BLI_strncpy_wchar_from_utf8(inserted_text, inserted_utf8, len + 1); + inserted_text = MEM_callocN(sizeof(char32_t) * (len + 1), "FONT_insert_text"); + len = BLI_str_utf8_as_utf32(inserted_text, inserted_utf8, MAXTEXT); for (a = 0; a < len; a++) { insert_into_textbuf(obedit, inserted_text[a]); @@ -2133,7 +2133,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event) vfont = (VFont *)idptr.owner_id; } - path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir; + path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->filepath : U.fontdir; if (RNA_struct_property_is_set(op->ptr, "filepath")) { return font_open_exec(C, op); diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 1a5b3d6ac45..0dcb8de37f1 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -713,6 +713,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES ops.mesh.bisect ops.mesh.dupli_extrude_cursor ops.mesh.extrude_faces_move + ops.mesh.extrude_manifold ops.mesh.extrude_region_move ops.mesh.extrude_region_shrink_fatten ops.mesh.inset diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index 4083169d65c..735ad8bc039 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -49,6 +49,7 @@ set(SRC gpencil_fill.c gpencil_interpolate.c gpencil_merge.c + gpencil_mesh.c gpencil_ops.c gpencil_ops_versioning.c gpencil_paint.c diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index 22df7bbbf31..20307e7f809 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -172,9 +172,14 @@ static void annotation_draw_stroke_buffer(bGPdata *gps, float oldpressure = points[0].pressure; /* draw stroke curve */ - GPU_line_width(max_ff(oldpressure * thickness, 1.0)); + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + + float viewport[4]; + GPU_viewport_size_get_f(viewport); + immUniform2fv("viewportSize", &viewport[2]); + + immUniform1f("lineWidth", max_ff(oldpressure * thickness, 1.0) * U.pixelsize); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); immUniformColor3fvAlpha(ink, ink[3]); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints); @@ -193,7 +198,7 @@ static void annotation_draw_stroke_buffer(bGPdata *gps, immEnd(); draw_points = 0; - GPU_line_width(max_ff(pt->pressure * thickness, 1.0f)); + immUniform1f("lineWidth", max_ff(pt->pressure * thickness, 1.0) * U.pixelsize); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1); /* need to roll-back one point to ensure that there are no gaps in the stroke */ @@ -327,11 +332,17 @@ static void annotation_draw_stroke_3d( GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + + float viewport[4]; + GPU_viewport_size_get_f(viewport); + immUniform2fv("viewportSize", &viewport[2]); + + immUniform1f("lineWidth", max_ff(curpressure * thickness, 1.0) * U.pixelsize); + immUniformColor3fvAlpha(ink, ink[3]); /* draw stroke curve */ - GPU_line_width(max_ff(curpressure * thickness, 1.0f)); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add); const bGPDspoint *pt = points; for (int i = 0; i < totpoints; i++, pt++) { @@ -351,7 +362,7 @@ static void annotation_draw_stroke_3d( draw_points = 0; curpressure = pt->pressure; - GPU_line_width(max_ff(curpressure * thickness, 1.0f)); + immUniform1f("lineWidth", max_ff(curpressure * thickness, 1.0) * U.pixelsize); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add); /* need to roll-back one point to ensure that there are no gaps in the stroke */ @@ -424,11 +435,15 @@ static void annotation_draw_stroke_2d(const bGPDspoint *points, } else { /* draw stroke curve */ - GPU_line_width(max_ff(oldpressure * thickness, 1.0)); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); immUniformColor3fvAlpha(ink, ink[3]); + float viewport[4]; + GPU_viewport_size_get_f(viewport); + immUniform2fv("viewportSize", &viewport[2]); + + immUniform1f("lineWidth", max_ff(oldpressure * thickness, 1.0) * U.pixelsize); + immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints); for (int i = 0; i < totpoints; i++) { @@ -448,7 +463,8 @@ static void annotation_draw_stroke_2d(const bGPDspoint *points, immEnd(); draw_points = 0; - GPU_line_width(max_ff(pt->pressure * thickness, 1.0f)); + immUniform1f("lineWidth", max_ff(pt->pressure * thickness, 1.0) * U.pixelsize); + immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1); /* need to roll-back one point to ensure that there are no gaps in the stroke */ @@ -683,9 +699,6 @@ static void annotation_draw_data_layers( continue; } - /* set basic stroke thickness */ - GPU_line_width(lthick); - /* Add layer drawing settings to the set of "draw flags" * NOTE: If the setting doesn't apply, it *must* be cleared, * as dflag's carry over from the previous layer @@ -774,13 +787,7 @@ static void annotation_draw_data_all(Scene *scene, } } -/* ----- Grease Pencil Sketches Drawing API ------ */ - -/* ............................ - * XXX - * We need to review the calls below, since they may be/are not that suitable for - * the new ways that we intend to be drawing data... - * ............................ */ +/* ----- Annotation Sketches Drawing API ------ */ /* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */ void ED_annotation_draw_2dimage(const bContext *C) diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 5c5adb32a97..9d80a75b959 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -204,12 +204,12 @@ typedef struct tGPsdata { /* minimum length of new segment before new point can be added */ #define MIN_EUCLIDEAN_PX (U.gp_euclideandist) -static bool gp_stroke_added_check(tGPsdata *p) +static bool annotation_stroke_added_check(tGPsdata *p) { return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED); } -static void gp_stroke_added_enable(tGPsdata *p) +static void annotation_stroke_added_enable(tGPsdata *p) { BLI_assert(p->gpf->strokes.last != NULL); p->flags |= GP_PAINTFLAG_STROKEADDED; @@ -218,13 +218,13 @@ static void gp_stroke_added_enable(tGPsdata *p) /* ------ */ /* Forward defines for some functions... */ -static void gp_session_validatebuffer(tGPsdata *p); +static void annotation_session_validatebuffer(tGPsdata *p); /* ******************************************* */ /* Context Wrangling... */ /* check if context is suitable for drawing */ -static bool gpencil_draw_poll(bContext *C) +static bool annotation_draw_poll(bContext *C) { if (ED_operator_regionactive(C)) { /* check if current context can support GPencil data */ @@ -249,7 +249,7 @@ static bool gpencil_draw_poll(bContext *C) } /* check if projecting strokes into 3d-geometry in the 3D-View */ -static bool gpencil_project_check(tGPsdata *p) +static bool annotation_project_check(tGPsdata *p) { bGPdata *gpd = p->gpd; return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) && @@ -262,7 +262,7 @@ static bool gpencil_project_check(tGPsdata *p) /* Utilities --------------------------------- */ /* get the reference point for stroke-point conversions */ -static void gp_get_3d_reference(tGPsdata *p, float vec[3]) +static void annotation_get_3d_reference(tGPsdata *p, float vec[3]) { const float *fp = p->scene->cursor.location; @@ -273,7 +273,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) /* Stroke Editing ---------------------------- */ /* check if the current mouse position is suitable for adding a new point */ -static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2]) +static bool annotation_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2]) { int dx = (int)fabsf(mval[0] - pmval[0]); int dy = (int)fabsf(mval[1] - pmval[1]); @@ -318,7 +318,10 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2 } /* convert screen-coordinates to buffer-coordinates */ -static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[3], float *depth) +static void annotation_stroke_convertcoords(tGPsdata *p, + const float mval[2], + float out[3], + float *depth) { bGPdata *gpd = p->gpd; @@ -326,7 +329,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) { int mval_i[2]; round_v2i_v2fl(mval_i, mval); - if (gpencil_project_check(p) && + if (annotation_project_check(p) && (ED_view3d_autodist_simple(p->region, mval_i, out, 0, depth))) { /* projecting onto 3D-Geometry * - nothing more needs to be done here, since view_autodist_simple() has already done it @@ -346,7 +349,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ * reference point instead or as offset, for easier stroke matching */ - gp_get_3d_reference(p, rvec); + annotation_get_3d_reference(p, rvec); zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec, NULL); if (ED_view3d_project_float_global(p->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == @@ -381,16 +384,17 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ } } -/* Apply smooth to buffer while drawing +/** + * Apply smooth to buffer while drawing * to smooth point C, use 2 before (A, B) and current point (D): * - * A----B-----C------D + * `A----B-----C------D` * * \param p: Temp data * \param inf: Influence factor * \param idx: Index of the last point (need minimum 3 points in the array) */ -static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) +static void annotation_smooth_buffer(tGPsdata *p, float inf, int idx) { bGPdata *gpd = p->gpd; short num_points = gpd->runtime.sbuffer_used; @@ -438,12 +442,12 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) copy_v2_v2(&ptc->x, c); } -static void gp_stroke_arrow_calc_points_segment(float stroke_points[8], - const float ref_point[2], - const float dir_cw[2], - const float dir_ccw[2], - const float lenght, - const float sign) +static void annotation_stroke_arrow_calc_points_segment(float stroke_points[8], + const float ref_point[2], + const float dir_cw[2], + const float dir_ccw[2], + const float lenght, + const float sign) { stroke_points[0] = ref_point[0] + dir_cw[0] * lenght * sign; stroke_points[1] = ref_point[1] + dir_cw[1] * lenght * sign; @@ -451,11 +455,11 @@ static void gp_stroke_arrow_calc_points_segment(float stroke_points[8], stroke_points[3] = ref_point[1] + dir_ccw[1] * lenght * sign; } -static void gp_stroke_arrow_calc_points(tGPspoint *point, - const float stroke_dir[2], - float corner[2], - float stroke_points[8], - const int arrow_style) +static void annotation_stroke_arrow_calc_points(tGPspoint *point, + const float stroke_dir[2], + float corner[2], + float stroke_points[8], + const int arrow_style) { const int arrow_lenght = 8; float norm_dir[2]; @@ -473,12 +477,12 @@ static void gp_stroke_arrow_calc_points(tGPspoint *point, stroke_points[3] = corner[1] + inv_norm_dir_counterclockwise[1] * arrow_lenght + norm_dir[1]; break; case GP_STROKE_ARROWSTYLE_SEGMENT: - gp_stroke_arrow_calc_points_segment(stroke_points, - corner, - inv_norm_dir_clockwise, - inv_norm_dir_counterclockwise, - arrow_lenght, - 1.0f); + annotation_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght, + 1.0f); break; case GP_STROKE_ARROWSTYLE_CLOSED: mul_v2_fl(norm_dir, arrow_lenght); @@ -486,12 +490,12 @@ static void gp_stroke_arrow_calc_points(tGPspoint *point, add_v2_v2(&point->x, norm_dir); copy_v2_v2(corner, &point->x); } - gp_stroke_arrow_calc_points_segment(stroke_points, - corner, - inv_norm_dir_clockwise, - inv_norm_dir_counterclockwise, - arrow_lenght, - -1.0f); + annotation_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght, + -1.0f); stroke_points[4] = corner[0] - norm_dir[0]; stroke_points[5] = corner[1] - norm_dir[1]; break; @@ -501,12 +505,12 @@ static void gp_stroke_arrow_calc_points(tGPspoint *point, add_v2_v2(&point->x, norm_dir); copy_v2_v2(corner, &point->x); } - gp_stroke_arrow_calc_points_segment(stroke_points, - corner, - inv_norm_dir_clockwise, - inv_norm_dir_counterclockwise, - arrow_lenght * 0.75f, - -1.0f); + annotation_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght * 0.75f, + -1.0f); stroke_points[4] = stroke_points[0] - norm_dir[0]; stroke_points[5] = stroke_points[1] - norm_dir[1]; stroke_points[6] = stroke_points[2] - norm_dir[0]; @@ -518,7 +522,10 @@ static void gp_stroke_arrow_calc_points(tGPspoint *point, } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime) +static short annotation_stroke_addpoint(tGPsdata *p, + const float mval[2], + float pressure, + double curtime) { bGPdata *gpd = p->gpd; tGPspoint *pt; @@ -571,14 +578,14 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt++; float e_heading[2] = {start[0] - end[0], start[1] - end[1]}; /* Calculate points for ending arrow. */ - gp_stroke_arrow_calc_points( + annotation_stroke_arrow_calc_points( pt, e_heading, end, gpd->runtime.arrow_end, gpd->runtime.arrow_end_style); } /* Arrow start corner. */ if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) { float s_heading[2] = {end[0] - start[0], end[1] - start[1]}; /* Calculate points for starting arrow. */ - gp_stroke_arrow_calc_points( + annotation_stroke_arrow_calc_points( NULL, s_heading, start, gpd->runtime.arrow_start, gpd->runtime.arrow_start_style); } } @@ -611,7 +618,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { /* smooth while drawing previous points with a reduction factor for previous */ for (int s = 0; s < 3; s++) { - gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); + annotation_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); } } @@ -632,7 +639,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure * to stroke. This allows to draw lines more interactively (see new segment * during mouse slide, e.g.) */ - if (gp_stroke_added_check(p)) { + if (annotation_stroke_added_check(p)) { bGPDstroke *gps = p->gpf->strokes.last; bGPDspoint *pts; @@ -649,7 +656,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure * but poly lines are converting to stroke instantly, * so initialize depth buffer before converting coordinates */ - if (gpencil_project_check(p)) { + if (annotation_project_check(p)) { View3D *v3d = p->area->spacedata.first; view3d_region_operator_needs_opengl(p->win, p->region); @@ -660,7 +667,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure } /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); + annotation_stroke_convertcoords(p, &pt->x, &pts->x, NULL); /* copy pressure and time */ pts->pressure = pt->pressure; @@ -681,115 +688,115 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure return GP_STROKEADD_INVALID; } -static void gp_stroke_arrow_init_point_default(bGPDspoint *pt) +static void annotation_stroke_arrow_init_point_default(bGPDspoint *pt) { pt->pressure = 1.0f; pt->strength = 1.0f; pt->time = 1.0f; } -static void gp_stroke_arrow_init_conv_point(bGPDspoint *pt, const float point[3]) +static void annotation_stroke_arrow_init_conv_point(bGPDspoint *pt, const float point[3]) { copy_v3_v3(&pt->x, point); - gp_stroke_arrow_init_point_default(pt); + annotation_stroke_arrow_init_point_default(pt); } -static void gp_stroke_arrow_init_point( +static void annotation_stroke_arrow_init_point( tGPsdata *p, tGPspoint *ptc, bGPDspoint *pt, const float co[8], const int co_idx) { /* Note: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */ float real_co[2] = {co[co_idx], co[co_idx + 1]}; copy_v2_v2(&ptc->x, real_co); - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - gp_stroke_arrow_init_point_default(pt); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + annotation_stroke_arrow_init_point_default(pt); } -static void gp_stroke_arrow_allocate(bGPDstroke *gps, const int totpoints) +static void annotation_stroke_arrow_allocate(bGPDstroke *gps, const int totpoints) { /* Copy appropriate settings for stroke. */ gps->totpoints = totpoints; /* Allocate enough memory for a continuous array for storage points. */ - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "annotation_stroke_points"); } -static void gp_arrow_create_open(tGPsdata *p, - tGPspoint *ptc, - bGPDspoint *pt, - const float corner_point[3], - const float arrow_points[8]) +static void annotation_arrow_create_open(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float corner_point[3], + const float arrow_points[8]) { - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); pt++; - gp_stroke_arrow_init_conv_point(pt, corner_point); + annotation_stroke_arrow_init_conv_point(pt, corner_point); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); } -static void gp_arrow_create_segm(tGPsdata *p, - tGPspoint *ptc, - bGPDspoint *pt, - const float arrow_points[8]) +static void annotation_arrow_create_segm(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float arrow_points[8]) { - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); } -static void gp_arrow_create_closed(tGPsdata *p, - tGPspoint *ptc, - bGPDspoint *pt, - const float arrow_points[8]) +static void annotation_arrow_create_closed(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float arrow_points[8]) { - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); } -static void gp_arrow_create_square(tGPsdata *p, - tGPspoint *ptc, - bGPDspoint *pt, - const float corner_point[3], - const float arrow_points[8]) +static void annotation_arrow_create_square(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float corner_point[3], + const float arrow_points[8]) { - gp_stroke_arrow_init_conv_point(pt, corner_point); + annotation_stroke_arrow_init_conv_point(pt, corner_point); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 6); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 6); pt++; - gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + annotation_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); pt++; - gp_stroke_arrow_init_conv_point(pt, corner_point); + annotation_stroke_arrow_init_conv_point(pt, corner_point); } -static void gp_arrow_create(tGPsdata *p, - tGPspoint *ptc, - bGPDspoint *pt, - bGPDstroke *arrow_stroke, - const float arrow_points[8], - const int style) +static void annotation_arrow_create(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + bGPDstroke *arrow_stroke, + const float arrow_points[8], + const int style) { float corner_conv[3]; copy_v3_v3(corner_conv, &pt->x); switch (style) { case GP_STROKE_ARROWSTYLE_SEGMENT: - gp_arrow_create_segm(p, ptc, pt, arrow_points); + annotation_arrow_create_segm(p, ptc, pt, arrow_points); break; case GP_STROKE_ARROWSTYLE_CLOSED: - gp_arrow_create_closed(p, ptc, pt, arrow_points); + annotation_arrow_create_closed(p, ptc, pt, arrow_points); break; case GP_STROKE_ARROWSTYLE_OPEN: - gp_arrow_create_open(p, ptc, pt, corner_conv, arrow_points); + annotation_arrow_create_open(p, ptc, pt, corner_conv, arrow_points); break; case GP_STROKE_ARROWSTYLE_SQUARE: - gp_arrow_create_square(p, ptc, pt, corner_conv, arrow_points); + annotation_arrow_create_square(p, ptc, pt, corner_conv, arrow_points); break; default: break; @@ -799,7 +806,7 @@ static void gp_arrow_create(tGPsdata *p, } /* make a new stroke from the buffer data */ -static void gp_stroke_newfrombuffer(tGPsdata *p) +static void annotation_stroke_newfrombuffer(tGPsdata *p) { bGPdata *gpd = p->gpd; bGPDlayer *gpl = p->gpl; @@ -837,13 +844,13 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) * interactive behavior */ if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { - if (gp_stroke_added_check(p)) { + if (annotation_stroke_added_check(p)) { return; } } /* allocate memory for a new stroke */ - gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + gps = MEM_callocN(sizeof(bGPDstroke), "annotation_stroke"); /* copy appropriate settings for stroke */ gps->totpoints = totelem; @@ -857,7 +864,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->tot_triangles = 0; /* allocate enough memory for a continuous array for storage points */ - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "annotation_stroke_points"); gps->tot_triangles = 0; /* set pointer to first non-initialized point */ @@ -871,7 +878,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) ptc = gpd->runtime.sbuffer; /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure and time */ pt->pressure = ptc->pressure; @@ -889,7 +896,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1); /* Convert screen-coordinates to appropriate coordinates (and store them). */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* Copy pressure and time. */ pt->pressure = ptc->pressure; @@ -905,18 +912,19 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* Setting up arrow stroke. */ bGPDstroke *e_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false); - gp_stroke_arrow_allocate(e_arrow_gps, totarrowpoints); + annotation_stroke_arrow_allocate(e_arrow_gps, totarrowpoints); /* Set pointer to first non-initialized point. */ pt = e_arrow_gps->points + (e_arrow_gps->totpoints - totarrowpoints); /* End point. */ ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1); - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - gp_stroke_arrow_init_point_default(pt); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + annotation_stroke_arrow_init_point_default(pt); /* Fill and convert arrow points to create arrow shape. */ - gp_arrow_create(p, ptc, pt, e_arrow_gps, runtime.arrow_end, runtime.arrow_end_style); + annotation_arrow_create( + p, ptc, pt, e_arrow_gps, runtime.arrow_end, runtime.arrow_end_style); } /* Start arrow stroke. */ if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) && @@ -925,18 +933,19 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* Setting up arrow stroke. */ bGPDstroke *s_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false); - gp_stroke_arrow_allocate(s_arrow_gps, totarrowpoints); + annotation_stroke_arrow_allocate(s_arrow_gps, totarrowpoints); /* Set pointer to first non-initialized point. */ pt = s_arrow_gps->points + (s_arrow_gps->totpoints - totarrowpoints); /* Start point. */ ptc = runtime.sbuffer; - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - gp_stroke_arrow_init_point_default(pt); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + annotation_stroke_arrow_init_point_default(pt); /* Fill and convert arrow points to create arrow shape. */ - gp_arrow_create(p, ptc, pt, s_arrow_gps, runtime.arrow_start, runtime.arrow_start_style); + annotation_arrow_create( + p, ptc, pt, s_arrow_gps, runtime.arrow_start, runtime.arrow_start_style); } } } @@ -945,7 +954,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) ptc = gpd->runtime.sbuffer; /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure and time */ pt->pressure = ptc->pressure; @@ -956,7 +965,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) float *depth_arr = NULL; /* get an array of depths, far depths are blended */ - if (gpencil_project_check(p)) { + if (annotation_project_check(p)) { int mval_i[2], mval_prev[2] = {0}; int interp_depth = 0; int found_depth = 0; @@ -1024,7 +1033,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used && ptc; i++, ptc++, pt++) { /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); + annotation_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); /* copy pressure and time */ pt->pressure = ptc->pressure; @@ -1040,7 +1049,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); - gp_stroke_added_enable(p); + annotation_stroke_added_enable(p); } /* --- 'Eraser' for 'Paint' Tool ------ */ @@ -1048,7 +1057,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* helper to free a stroke * NOTE: gps->dvert and gps->triangles should be NULL, but check anyway for good measure */ -static void gp_free_stroke(bGPDframe *gpf, bGPDstroke *gps) +static void annotation_free_stroke(bGPDframe *gpf, bGPDstroke *gps) { if (gps->points) { MEM_freeN(gps->points); @@ -1066,7 +1075,9 @@ static void gp_free_stroke(bGPDframe *gpf, bGPDstroke *gps) BLI_freelinkN(&gpf->strokes, gps); } -/* which which point is infront (result should only be used for comparison) */ +/** + * Which which point is in front (result should only be used for comparison). + */ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) { if (rv3d->is_persp) { @@ -1078,10 +1089,10 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) } /* only erase stroke points that are visible (3d view) */ -static bool gp_stroke_eraser_is_occluded(tGPsdata *p, - const bGPDspoint *pt, - const int x, - const int y) +static bool annotation_stroke_eraser_is_occluded(tGPsdata *p, + const bGPDspoint *pt, + const int x, + const int y) { if ((p->area->spacetype == SPACE_VIEW3D) && (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) { RegionView3D *rv3d = p->region->regiondata; @@ -1100,14 +1111,13 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p, return false; } -/* eraser tool - evaluation per stroke */ -/* TODO: this could really do with some optimization (KD-Tree/BVH?) */ -static void gp_stroke_eraser_dostroke(tGPsdata *p, - bGPDframe *gpf, - bGPDstroke *gps, - const float mval[2], - const int radius, - const rcti *rect) +/* Eraser tool - evaluation per stroke. */ +static void annotation_stroke_eraser_dostroke(tGPsdata *p, + bGPDframe *gpf, + bGPDstroke *gps, + const float mval[2], + const int radius, + const rcti *rect) { bGPDspoint *pt1, *pt2; int pc1[2] = {0}; @@ -1118,19 +1128,19 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, if (gps->totpoints == 0) { /* just free stroke */ - gp_free_stroke(gpf, gps); + annotation_free_stroke(gpf, gps); } else if (gps->totpoints == 1) { /* only process if it hasn't been masked out... */ if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) { - gp_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]); + gpencil_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]); /* do boundbox check first */ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { /* only check if point is inside */ if (len_v2v2_int(mval_i, pc1) <= radius) { /* free stroke */ - gp_free_stroke(gpf, gps); + annotation_free_stroke(gpf, gps); } } } @@ -1164,8 +1174,8 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, continue; } - gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]); - gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]); + gpencil_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]); + gpencil_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]); /* Check that point segment of the boundbox of the eraser stroke */ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) || @@ -1174,9 +1184,9 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { - if ((gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || - (gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { + if (gpencil_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if ((annotation_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || + (annotation_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { /* Edge is affected - Check individual points now */ if (len_v2v2_int(mval_i, pc1) <= radius) { pt1->flag |= GP_SPOINT_TAG; @@ -1192,13 +1202,13 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* Second Pass: Remove any points that are tagged */ if (do_cull) { - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0); + gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0); } } } /* erase strokes which fall under the eraser strokes */ -static void gp_stroke_doeraser(tGPsdata *p) +static void annotation_stroke_doeraser(tGPsdata *p) { bGPDframe *gpf = p->gpf; bGPDstroke *gps, *gpn; @@ -1227,7 +1237,7 @@ static void gp_stroke_doeraser(tGPsdata *p) * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) */ if (ED_gpencil_stroke_can_use_direct(p->area, gps)) { - gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->radius, &rect); + annotation_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->radius, &rect); } } } @@ -1236,7 +1246,7 @@ static void gp_stroke_doeraser(tGPsdata *p) /* Sketching Operator */ /* clear the session buffers (call this before AND after a paint operation) */ -static void gp_session_validatebuffer(tGPsdata *p) +static void annotation_session_validatebuffer(tGPsdata *p) { bGPdata *gpd = p->gpd; @@ -1251,7 +1261,7 @@ static void gp_session_validatebuffer(tGPsdata *p) } /* (re)init new painting data */ -static bool gp_session_initdata(bContext *C, tGPsdata *p) +static bool annotation_session_initdata(bContext *C, tGPsdata *p) { Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = NULL; @@ -1422,13 +1432,13 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) } /* clear out buffer (stored in gp-data), in case something contaminated it */ - gp_session_validatebuffer(p); + annotation_session_validatebuffer(p); return 1; } /* init new painting session */ -static tGPsdata *gp_session_initpaint(bContext *C) +static tGPsdata *annotation_session_initpaint(bContext *C) { tGPsdata *p = NULL; @@ -1438,7 +1448,7 @@ static tGPsdata *gp_session_initpaint(bContext *C) /* Try to initialize context data * WARNING: This may not always succeed (e.g. using GP in an annotation-only context) */ - if (gp_session_initdata(C, p) == 0) { + if (annotation_session_initdata(C, p) == 0) { /* Invalid state - Exit * NOTE: It should be safe to just free the data, since failing context checks should * only happen when no data has been allocated. @@ -1458,7 +1468,7 @@ static tGPsdata *gp_session_initpaint(bContext *C) } /* cleanup after a painting session */ -static void gp_session_cleanup(tGPsdata *p) +static void annotation_session_cleanup(tGPsdata *p) { bGPdata *gpd = (p) ? p->gpd : NULL; @@ -1481,13 +1491,15 @@ static void gp_session_cleanup(tGPsdata *p) p->inittime = 0.0; } -static void gp_session_free(tGPsdata *p) +static void annotation_session_free(tGPsdata *p) { MEM_freeN(p); } /* init new stroke */ -static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph) +static void annotation_paint_initstroke(tGPsdata *p, + eGPencil_PaintModes paintmode, + Depsgraph *depsgraph) { Scene *scene = p->scene; ToolSettings *ts = scene->toolsettings; @@ -1638,13 +1650,13 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps } /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */ -static void gp_paint_strokeend(tGPsdata *p) +static void annotation_paint_strokeend(tGPsdata *p) { ToolSettings *ts = p->scene->toolsettings; /* for surface sketching, need to set the right OpenGL context stuff so that * the conversions will project the values correctly... */ - if (gpencil_project_check(p)) { + if (annotation_project_check(p)) { View3D *v3d = p->area->spacedata.first; /* need to restore the original projection settings before packing up */ @@ -1656,22 +1668,22 @@ static void gp_paint_strokeend(tGPsdata *p) /* check if doing eraser or not */ if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* transfer stroke to frame */ - gp_stroke_newfrombuffer(p); + annotation_stroke_newfrombuffer(p); } /* clean up buffer now */ - gp_session_validatebuffer(p); + annotation_session_validatebuffer(p); } /* finish off stroke painting operation */ -static void gp_paint_cleanup(tGPsdata *p) +static void annotation_paint_cleanup(tGPsdata *p) { /* p->gpd==NULL happens when stroke failed to initialize, * for example when GP is hidden in current space (sergey) */ if (p->gpd) { /* finish off a stroke */ - gp_paint_strokeend(p); + annotation_paint_strokeend(p); } /* "unlock" frame */ @@ -1683,7 +1695,7 @@ static void gp_paint_cleanup(tGPsdata *p) /* ------------------------------- */ /* Helper callback for drawing the cursor itself */ -static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) +static void annotation_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) { tGPsdata *p = (tGPsdata *)p_ptr; @@ -1729,7 +1741,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) } /* Turn brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable) +static void annotation_draw_toggle_eraser_cursor(tGPsdata *p, short enable) { if (p->erasercursor && !enable) { /* clear cursor */ @@ -1741,11 +1753,11 @@ static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable) p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, /* XXX */ - gpencil_draw_eraser, + annotation_draw_eraser, p); } } -static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) +static void annotation_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) { ARegion *region = CTX_wm_region(C); tGPsdata *p = (tGPsdata *)p_ptr; @@ -1793,7 +1805,7 @@ static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) } /* Turn *stabilizer* brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable) +static void annotation_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable) { if (p->stabilizer_cursor && !enable) { /* clear cursor */ @@ -1803,19 +1815,19 @@ static void gpencil_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable) else if (enable && !p->stabilizer_cursor) { /* enable cursor */ p->stabilizer_cursor = WM_paint_cursor_activate( - SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); + SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, annotation_draw_stabilizer, p); } } /* Check if tablet eraser is being used (when processing events) */ -static bool gpencil_is_tablet_eraser_active(const wmEvent *event) +static bool annotation_is_tablet_eraser_active(const wmEvent *event) { return (event->tablet.active == EVT_TABLET_ERASER); } /* ------------------------------- */ -static void gpencil_draw_exit(bContext *C, wmOperator *op) +static void annotation_draw_exit(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; @@ -1827,10 +1839,10 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* check size of buffer before cleanup, to determine if anything happened here */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* turn off radial brush cursor */ - gpencil_draw_toggle_eraser_cursor(p, false); + annotation_draw_toggle_eraser_cursor(p, false); } else if (p->paintmode == GP_PAINTMODE_DRAW) { - gpencil_draw_toggle_stabilizer_cursor(p, false); + annotation_draw_toggle_stabilizer_cursor(p, false); } /* always store the new eraser size to be used again next time @@ -1843,40 +1855,40 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) gpencil_undo_finish(); /* cleanup */ - gp_paint_cleanup(p); - gp_session_cleanup(p); - gp_session_free(p); + annotation_paint_cleanup(p); + annotation_session_cleanup(p); + annotation_session_free(p); p = NULL; } op->customdata = NULL; } -static void gpencil_draw_cancel(bContext *C, wmOperator *op) +static void annotation_draw_cancel(bContext *C, wmOperator *op) { /* this is just a wrapper around exit() */ - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); } /* ------------------------------- */ -static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) +static int annotation_draw_init(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p; eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode"); /* check context */ - p = op->customdata = gp_session_initpaint(C); + p = op->customdata = annotation_session_initpaint(C); if ((p == NULL) || (p->status == GP_STATUS_ERROR)) { /* something wasn't set correctly in context */ - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); return 0; } /* init painting data */ - gp_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C)); + annotation_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C)); if (p->status == GP_STATUS_ERROR) { - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); return 0; } @@ -1894,7 +1906,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) /* ------------------------------- */ /* ensure that the correct cursor icon is set */ -static void gpencil_draw_cursor_set(tGPsdata *p) +static void annotation_draw_cursor_set(tGPsdata *p) { if (p->paintmode == GP_PAINTMODE_ERASER) { WM_cursor_modal_set(p->win, WM_CURSOR_ERASER); @@ -1905,7 +1917,7 @@ static void gpencil_draw_cursor_set(tGPsdata *p) } /* update UI indicators of status, including cursor and header prints */ -static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p) +static void annotation_draw_status_indicators(bContext *C, tGPsdata *p) { /* header prints */ switch (p->status) { @@ -1970,12 +1982,12 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p) /* ------------------------------- */ /* create a new stroke point at the point indicated by the painting context */ -static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph) +static void annotation_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph) { /* handle drawing/erasing -> test for erasing first */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* do 'live' erasing now */ - gp_stroke_doeraser(p); + annotation_stroke_doeraser(p); /* store used values */ p->mvalo[0] = p->mval[0]; @@ -1984,7 +1996,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph } /* Only add current point to buffer if mouse moved * (even though we got an event, it might be just noise). */ - else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { + else if (annotation_stroke_filtermval(p, p->mval, p->mvalo)) { /* If lazy mouse, interpolate the last and current mouse positions. */ if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { float now_mouse[2]; @@ -1996,26 +2008,24 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph } /* try to add point */ - short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); + short ok = annotation_stroke_addpoint(p, p->mval, p->pressure, p->curtime); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ - gp_paint_strokeend(p); + annotation_paint_strokeend(p); /* And start a new one!!! Else, projection errors! */ - gp_paint_initstroke(p, p->paintmode, depsgraph); + annotation_paint_initstroke(p, p->paintmode, depsgraph); /* start a new stroke, starting from previous point */ - /* XXX Must manually reset inittime... */ - /* XXX We only need to reuse previous point if overflow! */ if (ok == GP_STROKEADD_OVERFLOW) { p->inittime = p->ocurtime; - gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); + annotation_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); } else { p->inittime = p->curtime; } - gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); + annotation_stroke_addpoint(p, p->mval, p->pressure, p->curtime); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -2053,16 +2063,16 @@ static void annotation_draw_apply_event( /* Key to toggle stabilization. */ if (event->shift > 0 && p->paintmode == GP_PAINTMODE_DRAW) { /* Using permanent stabilization, shift will deactivate the flag. */ - if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) { + if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { - gpencil_draw_toggle_stabilizer_cursor(p, false); + annotation_draw_toggle_stabilizer_cursor(p, false); p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; } } /* Not using any stabilization flag. Activate temporal one. */ else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(p, true); + annotation_draw_toggle_stabilizer_cursor(p, true); } } /* verify key status for straight lines */ @@ -2091,7 +2101,7 @@ static void annotation_draw_apply_event( so activate the temp flag back again. */ if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { - gpencil_draw_toggle_stabilizer_cursor(p, true); + annotation_draw_toggle_stabilizer_cursor(p, true); p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; } } @@ -2101,7 +2111,7 @@ static void annotation_draw_apply_event( else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { /* Reset temporal stabilizer flag and remove cursor. */ p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(p, false); + annotation_draw_toggle_stabilizer_cursor(p, false); } } @@ -2165,7 +2175,7 @@ static void annotation_draw_apply_event( RNA_float_set(&itemptr, "time", p->curtime - p->inittime); /* apply the current latest drawing point */ - gpencil_draw_apply(op, p, depsgraph); + annotation_draw_apply(op, p, depsgraph); /* force refresh */ /* just active area for now, since doing whole screen is too slow */ @@ -2175,7 +2185,7 @@ static void annotation_draw_apply_event( /* ------------------------------- */ /* operator 'redo' (i.e. after changing some properties, but also for repeat last) */ -static int gpencil_draw_exec(bContext *C, wmOperator *op) +static int annotation_draw_exec(bContext *C, wmOperator *op) { tGPsdata *p = NULL; Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -2183,7 +2193,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) /* printf("GPencil - Starting Re-Drawing\n"); */ /* try to initialize context data needed while drawing */ - if (!gpencil_draw_init(C, op, NULL)) { + if (!annotation_draw_init(C, op, NULL)) { if (op->customdata) { MEM_freeN(op->customdata); } @@ -2217,8 +2227,8 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) */ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) { /* TODO: both of these ops can set error-status, but we probably don't need to worry */ - gp_paint_strokeend(p); - gp_paint_initstroke(p, p->paintmode, depsgraph); + annotation_paint_strokeend(p); + annotation_paint_initstroke(p, p->paintmode, depsgraph); } } @@ -2233,14 +2243,14 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) } /* apply this data as necessary now (as per usual) */ - gpencil_draw_apply(op, p, depsgraph); + annotation_draw_apply(op, p, depsgraph); } RNA_END; /* printf("\tGP - done\n"); */ /* cleanup */ - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); /* refreshes */ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -2252,12 +2262,12 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) /* ------------------------------- */ /* start of interactive drawing part of operator */ -static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int annotation_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = NULL; /* support for tablets eraser pen */ - if (gpencil_is_tablet_eraser_active(event)) { + if (annotation_is_tablet_eraser_active(event)) { RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER); } @@ -2266,7 +2276,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event } /* try to initialize context data needed while drawing */ - if (!gpencil_draw_init(C, op, event)) { + if (!annotation_draw_init(C, op, event)) { if (op->customdata) { MEM_freeN(op->customdata); } @@ -2281,21 +2291,15 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* if empty erase capture and finish */ if (p->status == GP_STATUS_CAPTURE) { - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); BKE_report(op->reports, RPT_ERROR, "Nothing to erase"); return OPERATOR_FINISHED; } - /* TODO: set any additional settings that we can take from the events? - * TODO? if tablet is erasing, force eraser to be on? */ - - /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... - */ - /* if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { - gpencil_draw_toggle_eraser_cursor(p, true); + annotation_draw_toggle_eraser_cursor(p, true); } else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) { @@ -2312,18 +2316,18 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius"); if (RNA_boolean_get(op->ptr, "use_stabilizer")) { p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(p, true); + annotation_draw_toggle_stabilizer_cursor(p, true); } else if (event->shift > 0) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(p, true); + annotation_draw_toggle_stabilizer_cursor(p, true); } } /* set cursor * NOTE: This may change later (i.e. intentionally via brush toggle, * or unintentionally if the user scrolls outside the area)... */ - gpencil_draw_cursor_set(p); + annotation_draw_cursor_set(p); /* only start drawing immediately if we're allowed to do so... */ if (RNA_boolean_get(op->ptr, "wait_for_input") == false) { @@ -2348,13 +2352,13 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event } /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ -static bool gpencil_area_exists(bContext *C, ScrArea *area_test) +static bool annotation_area_exists(bContext *C, ScrArea *area_test) { bScreen *screen = CTX_wm_screen(C); return (BLI_findindex(&screen->areabase, area_test) != -1); } -static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) +static tGPsdata *annotation_stroke_begin(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; @@ -2372,8 +2376,8 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) /* XXX: watch it with the paintmode! in future, * it'd be nice to allow changing paint-mode when in sketching-sessions */ - if (gp_session_initdata(C, p)) { - gp_paint_initstroke(p, p->paintmode, CTX_data_ensure_evaluated_depsgraph(C)); + if (annotation_session_initdata(C, p)) { + annotation_paint_initstroke(p, p->paintmode, CTX_data_ensure_evaluated_depsgraph(C)); } if (p->status != GP_STATUS_ERROR) { @@ -2384,15 +2388,15 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) return op->customdata; } -static void gpencil_stroke_end(wmOperator *op) +static void annotation_stroke_end(wmOperator *op) { tGPsdata *p = op->customdata; - gp_paint_cleanup(p); + annotation_paint_cleanup(p); gpencil_undo_push(p->gpd); - gp_session_cleanup(p); + annotation_session_cleanup(p); p->status = GP_STATUS_IDLING; op->flag |= OP_IS_MODAL_CURSOR_REGION; @@ -2439,7 +2443,7 @@ static void annotation_add_missing_events(bContext *C, } /* events handling during interactive drawing part of operator */ -static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) +static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = op->customdata; /* default exit state - pass through to support MMB view nav, etc. */ @@ -2542,7 +2546,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) if (sketch) { /* end stroke only, and then wait to resume painting soon */ /* printf("\t\tGP - end stroke only\n"); */ - gpencil_stroke_end(op); + annotation_stroke_end(op); /* If eraser mode is on, turn it off after the stroke finishes * NOTE: This just makes it nicer to work with drawing sessions @@ -2561,7 +2565,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * Just hiding this makes it seem like * you can paint again... */ - gpencil_draw_toggle_eraser_cursor(p, false); + annotation_draw_toggle_eraser_cursor(p, false); } } @@ -2637,7 +2641,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Switch paintmode (temporarily if need be) based on which button was used * NOTE: This is to make it more convenient to erase strokes when using drawing sessions */ - if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) { + if ((event->type == RIGHTMOUSE) || annotation_is_tablet_eraser_active(event)) { /* turn on eraser */ p->paintmode = GP_PAINTMODE_ERASER; } @@ -2646,10 +2650,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p->paintmode = RNA_enum_get(op->ptr, "mode"); } - gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER); + annotation_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER); /* not painting, so start stroke (this should be mouse-button down) */ - p = gpencil_stroke_begin(C, op); + p = annotation_stroke_begin(C, op); if (p->status == GP_STATUS_ERROR) { estate = OPERATOR_CANCELLED; @@ -2733,26 +2737,26 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ - if (0 == gpencil_area_exists(C, p->area)) { + if (0 == annotation_area_exists(C, p->area)) { estate = OPERATOR_CANCELLED; } else { /* update status indicators - cursor, header, etc. */ - gpencil_draw_status_indicators(C, p); + annotation_draw_status_indicators(C, p); /* cursor may have changed outside our control - T44084 */ - gpencil_draw_cursor_set(p); + annotation_draw_cursor_set(p); } /* process last operations before exiting */ switch (estate) { case OPERATOR_FINISHED: /* one last flush before we're done */ - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); break; case OPERATOR_CANCELLED: - gpencil_draw_exit(C, op); + annotation_draw_exit(C, op); break; case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH: @@ -2811,11 +2815,11 @@ void GPENCIL_OT_annotate(wmOperatorType *ot) ot->description = "Make annotations on the active data"; /* api callbacks */ - ot->exec = gpencil_draw_exec; - ot->invoke = gpencil_draw_invoke; - ot->modal = gpencil_draw_modal; - ot->cancel = gpencil_draw_cancel; - ot->poll = gpencil_draw_poll; + ot->exec = annotation_draw_exec; + ot->invoke = annotation_draw_invoke; + ot->modal = annotation_draw_modal; + ot->cancel = annotation_draw_cancel; + ot->poll = annotation_draw_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 6d41e9bddbe..60fd52db707 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -114,10 +114,10 @@ typedef enum eDrawStrokeFlags { /* ----- Tool Buffer Drawing ------ */ /* helper functions to set color of buffer point */ -static void gp_set_point_varying_color(const bGPDspoint *pt, - const float ink[4], - uint attr_id, - bool fix_strength) +static void gpencil_set_point_varying_color(const bGPDspoint *pt, + const float ink[4], + uint attr_id, + bool fix_strength) { float alpha = ink[3] * pt->strength; if ((fix_strength) && (alpha >= 0.1f)) { @@ -130,10 +130,10 @@ static void gp_set_point_varying_color(const bGPDspoint *pt, /* ----------- Volumetric Strokes --------------- */ /* draw a 3D stroke in "volumetric" style */ -static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points, - int totpoints, - short thickness, - const float ink[4]) +static void gpencil_draw_stroke_volumetric_3d(const bGPDspoint *points, + int totpoints, + short thickness, + const float ink[4]) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); @@ -147,7 +147,7 @@ static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points, const bGPDspoint *pt = points; for (int i = 0; i < totpoints && pt; i++, pt++) { - gp_set_point_varying_color(pt, ink, color, false); + gpencil_set_point_varying_color(pt, ink, color, false); /* TODO: scale based on view transform */ immAttr1f(size, pt->pressure * thickness); /* we can adjust size in vertex shader based on view/projection! */ @@ -162,7 +162,10 @@ static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points, /* ----- Existing Strokes Drawing (3D and Point) ------ */ /* draw a given stroke in 3d (i.e. in 3d-space) */ -static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4], bool cyclic) +static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, + short thickness, + const float ink[4], + bool cyclic) { bGPDspoint *points = tgpw->gps->points; int totpoints = tgpw->gps->totpoints; @@ -209,7 +212,7 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4 for (int i = 0; i < totpoints; i++, pt++) { /* first point for adjacency (not drawn) */ if (i == 0) { - gp_set_point_varying_color(points, ink, attr_id.color, (bool)tgpw->is_fill_stroke); + gpencil_set_point_varying_color(points, ink, attr_id.color, (bool)tgpw->is_fill_stroke); if ((cyclic) && (totpoints > 2)) { immAttr1f(attr_id.thickness, max_ff((points + totpoints - 1)->pressure * thickness, 1.0f)); @@ -222,7 +225,7 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4 immVertex3fv(attr_id.pos, fpt); } /* set point */ - gp_set_point_varying_color(pt, ink, attr_id.color, (bool)tgpw->is_fill_stroke); + gpencil_set_point_varying_color(pt, ink, attr_id.color, (bool)tgpw->is_fill_stroke); immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, 1.0f)); mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x); immVertex3fv(attr_id.pos, fpt); @@ -241,7 +244,7 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4 } /* last adjacency point (not drawn) */ else { - gp_set_point_varying_color( + gpencil_set_point_varying_color( points + totpoints - 2, ink, attr_id.color, (bool)tgpw->is_fill_stroke); immAttr1f(attr_id.thickness, max_ff((points + totpoints - 2)->pressure * thickness, 1.0f)); @@ -256,7 +259,7 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4 /* ----- Strokes Drawing ------ */ /* Helper for doing all the checks on whether a stroke can be drawn */ -static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag) +static bool gpencil_can_draw_stroke(const bGPDstroke *gps, const int dflag) { /* skip stroke if it isn't in the right display space for this drawing context */ /* 1) 3D Strokes */ @@ -293,7 +296,7 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag) } /* draw a set of strokes */ -static void gp_draw_strokes(tGPDdraw *tgpw) +static void gpencil_draw_strokes(tGPDdraw *tgpw) { float tcolor[4]; short sthickness; @@ -307,7 +310,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) for (bGPDstroke *gps = gps_init; gps; gps = gps->next) { /* check if stroke can be drawn */ - if (gp_can_draw_stroke(gps, tgpw->dflag) == false) { + if (gpencil_can_draw_stroke(gps, tgpw->dflag) == false) { continue; } /* check if the color is visible */ @@ -316,7 +319,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE) || /* if onion and ghost flag do not draw*/ - (tgpw->onion && (gp_style->flag & GP_MATERIAL_ONIONSKIN))) { + (tgpw->onion && (gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN))) { continue; } @@ -379,14 +382,14 @@ static void gp_draw_strokes(tGPDdraw *tgpw) if (gp_style->mode == GP_MATERIAL_MODE_DOT) { /* volumetric stroke drawing */ if (tgpw->disable_fill != 1) { - gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink); + gpencil_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink); } } else { /* 3D Lines - OpenGL primitives-based */ if (gps->totpoints > 1) { tgpw->gps = gps; - gp_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC); + gpencil_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC); } } if (no_xray) { @@ -408,7 +411,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) /* ----- General Drawing ------ */ /* wrapper to draw strokes for filling operator */ -void ED_gp_draw_fill(tGPDdraw *tgpw) +void ED_gpencil_draw_fill(tGPDdraw *tgpw) { - gp_draw_strokes(tgpw); + gpencil_draw_strokes(tgpw); } diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index d2b1eba7d86..752b8a74f4f 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -56,7 +56,9 @@ /* Generics - Loopers */ /* Loops over the gp-frames for a gp-layer, and applies the given callback */ -bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *)) +bool ED_gpencil_layer_frames_looper(bGPDlayer *gpl, + Scene *scene, + short (*gpf_cb)(bGPDframe *, Scene *)) { /* error checker */ if (gpl == NULL) { @@ -79,7 +81,7 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPD /* Data Conversion Tools */ /* make a listing all the gp-frames in a layer as cfraelems */ -void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) +void ED_gpencil_layer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) { CfraElem *ce; @@ -105,7 +107,7 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) /* Selection Tools */ /* check if one of the frames in this layer is selected */ -bool ED_gplayer_frame_select_check(bGPDlayer *gpl) +bool ED_gpencil_layer_frame_select_check(bGPDlayer *gpl) { /* error checking */ if (gpl == NULL) { @@ -124,7 +126,7 @@ bool ED_gplayer_frame_select_check(bGPDlayer *gpl) } /* helper function - select gp-frame based on SELECT_* mode */ -static void gpframe_select(bGPDframe *gpf, short select_mode) +static void gpencil_frame_select(bGPDframe *gpf, short select_mode) { if (gpf == NULL) { return; @@ -153,12 +155,12 @@ void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode) /* handle according to mode */ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - gpframe_select(gpf, select_mode); + gpencil_frame_select(gpf, select_mode); } } /* set all/none/invert select */ -void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode) +void ED_gpencil_layer_frame_select_set(bGPDlayer *gpl, short mode) { /* error checking */ if (gpl == NULL) { @@ -181,12 +183,12 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode) gpf = BKE_gpencil_layer_frame_find(gpl, selx); if (gpf) { - gpframe_select(gpf, select_mode); + gpencil_frame_select(gpf, select_mode); } } /* select the frames in this layer that occur within the bounds specified */ -void ED_gplayer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode) +void ED_gpencil_layer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode) { if (gpl == NULL) { return; @@ -195,16 +197,16 @@ void ED_gplayer_frames_select_box(bGPDlayer *gpl, float min, float max, short se /* only select those frames which are in bounds */ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { if (IN_RANGE(gpf->framenum, min, max)) { - gpframe_select(gpf, select_mode); + gpencil_frame_select(gpf, select_mode); } } } /* select the frames in this layer that occur within the lasso/circle region specified */ -void ED_gplayer_frames_select_region(KeyframeEditData *ked, - bGPDlayer *gpl, - short tool, - short select_mode) +void ED_gpencil_layer_frames_select_region(KeyframeEditData *ked, + bGPDlayer *gpl, + short tool, + short select_mode) { if (gpl == NULL) { return; @@ -222,13 +224,13 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked, if (tool == BEZT_OK_CHANNEL_LASSO) { /* Lasso */ if (keyframe_region_lasso_test(ked->data, pt)) { - gpframe_select(gpf, select_mode); + gpencil_frame_select(gpf, select_mode); } } else if (tool == BEZT_OK_CHANNEL_CIRCLE) { /* Circle */ if (keyframe_region_circle_test(ked->data, pt)) { - gpframe_select(gpf, select_mode); + gpencil_frame_select(gpf, select_mode); } } } @@ -238,7 +240,7 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked, /* Frame Editing Tools */ /* Delete selected frames */ -bool ED_gplayer_frames_delete(bGPDlayer *gpl) +bool ED_gpencil_layer_frames_delete(bGPDlayer *gpl) { bool changed = false; @@ -259,7 +261,7 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl) } /* Duplicate selected frames from given gp-layer */ -void ED_gplayer_frames_duplicate(bGPDlayer *gpl) +void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl) { /* error checking */ if (gpl == NULL) { @@ -282,10 +284,12 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl) } } -/* Set keyframe type for selected frames from given gp-layer - * \param type: The type of keyframe (eBezTriple_KeyframeType) to set selected frames to +/** + * Set keyframe type for selected frames from given gp-layer + * + * \param type: The type of keyframe (#eBezTriple_KeyframeType) to set selected frames to. */ -void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type) +void ED_gpencil_layer_frames_keytype_set(bGPDlayer *gpl, short type) { if (gpl == NULL) { return; @@ -311,20 +315,20 @@ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type) */ /* globals for copy/paste data (like for other copy/paste buffers) */ -static ListBase gp_anim_copybuf = {NULL, NULL}; -static int gp_anim_copy_firstframe = 999999999; -static int gp_anim_copy_lastframe = -999999999; -static int gp_anim_copy_cfra = 0; +static ListBase gpencil_anim_copybuf = {NULL, NULL}; +static int gpencil_anim_copy_firstframe = 999999999; +static int gpencil_anim_copy_lastframe = -999999999; +static int gpencil_anim_copy_cfra = 0; /* This function frees any MEM_calloc'ed copy/paste buffer data */ void ED_gpencil_anim_copybuf_free(void) { - BKE_gpencil_free_layers(&gp_anim_copybuf); - BLI_listbase_clear(&gp_anim_copybuf); + BKE_gpencil_free_layers(&gpencil_anim_copybuf); + BLI_listbase_clear(&gpencil_anim_copybuf); - gp_anim_copy_firstframe = 999999999; - gp_anim_copy_lastframe = -999999999; - gp_anim_copy_cfra = 0; + gpencil_anim_copy_firstframe = 999999999; + gpencil_anim_copy_lastframe = -999999999; + gpencil_anim_copy_cfra = 0; } /* This function adds data to the copy/paste buffer, freeing existing data first @@ -361,11 +365,11 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) BLI_addtail(&copied_frames, new_frame); /* extend extents for keyframes encountered */ - if (gpf->framenum < gp_anim_copy_firstframe) { - gp_anim_copy_firstframe = gpf->framenum; + if (gpf->framenum < gpencil_anim_copy_firstframe) { + gpencil_anim_copy_firstframe = gpf->framenum; } - if (gpf->framenum > gp_anim_copy_lastframe) { - gp_anim_copy_lastframe = gpf->framenum; + if (gpf->framenum > gpencil_anim_copy_lastframe) { + gpencil_anim_copy_lastframe = gpf->framenum; } } } @@ -373,7 +377,7 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) /* create a new layer in buffer if there were keyframes here */ if (BLI_listbase_is_empty(&copied_frames) == false) { bGPDlayer *new_layer = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer"); - BLI_addtail(&gp_anim_copybuf, new_layer); + BLI_addtail(&gpencil_anim_copybuf, new_layer); /* move over copied frames */ BLI_movelisttolist(&new_layer->frames, &copied_frames); @@ -385,13 +389,13 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) } /* in case 'relative' paste method is used */ - gp_anim_copy_cfra = CFRA; + gpencil_anim_copy_cfra = CFRA; /* clean up */ ANIM_animdata_freelist(&anim_data); /* check if anything ended up in the buffer */ - if (ELEM(NULL, gp_anim_copybuf.first, gp_anim_copybuf.last)) { + if (ELEM(NULL, gpencil_anim_copybuf.first, gpencil_anim_copybuf.last)) { BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); return false; } @@ -412,26 +416,26 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) int offset = 0; /* check if buffer is empty */ - if (BLI_listbase_is_empty(&gp_anim_copybuf)) { + if (BLI_listbase_is_empty(&gpencil_anim_copybuf)) { BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste"); return false; } /* check if single channel in buffer (disregard names if so) */ - if (gp_anim_copybuf.first == gp_anim_copybuf.last) { + if (gpencil_anim_copybuf.first == gpencil_anim_copybuf.last) { no_name = true; } /* methods of offset (eKeyPasteOffset) */ switch (offset_mode) { case KEYFRAME_PASTE_OFFSET_CFRA_START: - offset = (CFRA - gp_anim_copy_firstframe); + offset = (CFRA - gpencil_anim_copy_firstframe); break; case KEYFRAME_PASTE_OFFSET_CFRA_END: - offset = (CFRA - gp_anim_copy_lastframe); + offset = (CFRA - gpencil_anim_copy_lastframe); break; case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE: - offset = (CFRA - gp_anim_copy_cfra); + offset = (CFRA - gpencil_anim_copy_cfra); break; case KEYFRAME_PASTE_OFFSET_NONE: offset = 0; @@ -451,7 +455,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) bGPDframe *gpfs, *gpf; /* find suitable layer from buffer to use to paste from */ - for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) { + for (gpls = gpencil_anim_copybuf.first; gpls; gpls = gpls->next) { /* check if layer name matches */ if ((no_name) || STREQ(gpls->info, gpld->info)) { break; @@ -507,7 +511,7 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) /* -------------------------------------- */ /* Snap Tools */ -static short snap_gpf_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene)) +static short gpencil_frame_snap_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene)) { #if 0 /* note: gpf->framenum is already an int! */ if (gpf->flag & GP_FRAME_SELECT) { @@ -517,7 +521,7 @@ static short snap_gpf_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene)) return 0; } -static short snap_gpf_nearestsec(bGPDframe *gpf, Scene *scene) +static short gpencil_frame_snap_nearestsec(bGPDframe *gpf, Scene *scene) { float secf = (float)FPS; if (gpf->flag & GP_FRAME_SELECT) { @@ -526,7 +530,7 @@ static short snap_gpf_nearestsec(bGPDframe *gpf, Scene *scene) return 0; } -static short snap_gpf_cframe(bGPDframe *gpf, Scene *scene) +static short gpencil_frame_snap_cframe(bGPDframe *gpf, Scene *scene) { if (gpf->flag & GP_FRAME_SELECT) { gpf->framenum = (int)CFRA; @@ -534,7 +538,7 @@ static short snap_gpf_cframe(bGPDframe *gpf, Scene *scene) return 0; } -static short snap_gpf_nearmarker(bGPDframe *gpf, Scene *scene) +static short gpencil_frame_snap_nearmarker(bGPDframe *gpf, Scene *scene) { if (gpf->flag & GP_FRAME_SELECT) { gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers, @@ -544,20 +548,20 @@ static short snap_gpf_nearmarker(bGPDframe *gpf, Scene *scene) } /* snap selected frames to ... */ -void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) +void ED_gpencil_layer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) { switch (mode) { case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_snap_nearest); break; case SNAP_KEYS_CURFRAME: /* snap to current frame */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_snap_cframe); break; case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_snap_nearmarker); break; case SNAP_KEYS_NEARSEC: /* snap to nearest second */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_snap_nearestsec); break; default: /* just in case */ break; @@ -567,7 +571,7 @@ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) /* -------------------------------------- */ /* Mirror Tools */ -static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene) +static short gpencil_frame_mirror_cframe(bGPDframe *gpf, Scene *scene) { int diff; @@ -579,7 +583,7 @@ static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene) return 0; } -static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene)) +static short gpencil_frame_mirror_yaxis(bGPDframe *gpf, Scene *UNUSED(scene)) { int diff; @@ -591,7 +595,7 @@ static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene)) return 0; } -static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene)) +static short gpencil_frame_mirror_xaxis(bGPDframe *gpf, Scene *UNUSED(scene)) { int diff; @@ -604,7 +608,7 @@ static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene)) return 0; } -static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene) +static short gpencil_frame_mirror_marker(bGPDframe *gpf, Scene *scene) { static TimeMarker *marker; static short initialized = 0; @@ -646,25 +650,25 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene) /* mirror selected gp-frames on... */ // TODO: mirror over a specific time -void ED_gplayer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode) +void ED_gpencil_layer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode) { switch (mode) { case MIRROR_KEYS_CURFRAME: /* mirror over current frame */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_mirror_cframe); break; case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_mirror_yaxis); break; case MIRROR_KEYS_XAXIS: /* mirror over value 0 */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_mirror_xaxis); break; case MIRROR_KEYS_MARKER: /* mirror over marker */ - mirror_gpf_marker(NULL, scene); - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker); - mirror_gpf_marker(NULL, scene); + gpencil_frame_mirror_marker(NULL, scene); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_mirror_marker); + gpencil_frame_mirror_marker(NULL, scene); break; default: /* just in case */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); + ED_gpencil_layer_frames_looper(gpl, scene, gpencil_frame_mirror_yaxis); break; } } diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index 60a4404beaf..39a2d594c13 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -49,7 +49,10 @@ typedef struct ColorTemplate { } ColorTemplate; /* Add color an ensure duplications (matched by name) */ -static int gp_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct, const bool fill) +static int gpencil_stroke_material(Main *bmain, + Object *ob, + const ColorTemplate *pct, + const bool fill) { short *totcol = BKE_object_material_len_p(ob); Material *ma = NULL; @@ -224,12 +227,12 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) bGPDstroke *gps; /* create colors */ - int color_black = gp_stroke_material(bmain, ob, &gp_stroke_material_black, false); - gp_stroke_material(bmain, ob, &gp_stroke_material_white, false); - gp_stroke_material(bmain, ob, &gp_stroke_material_red, false); - gp_stroke_material(bmain, ob, &gp_stroke_material_green, false); - gp_stroke_material(bmain, ob, &gp_stroke_material_blue, false); - gp_stroke_material(bmain, ob, &gp_stroke_material_grey, true); + int color_black = gpencil_stroke_material(bmain, ob, &gp_stroke_material_black, false); + gpencil_stroke_material(bmain, ob, &gp_stroke_material_white, false); + gpencil_stroke_material(bmain, ob, &gp_stroke_material_red, false); + gpencil_stroke_material(bmain, ob, &gp_stroke_material_green, false); + gpencil_stroke_material(bmain, ob, &gp_stroke_material_blue, false); + gpencil_stroke_material(bmain, ob, &gp_stroke_material_grey, true); /* set first color as active and in brushes */ ob->actcol = color_black + 1; diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 78a34cda2f5..e111ce44bc4 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -54,8 +54,11 @@ #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" +#include "BKE_image.h" #include "BKE_layer.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -151,12 +154,12 @@ static const EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), /* convert the coordinates from the given stroke point into 3d-coordinates * - assumes that the active space is the 3D-View */ -static void gp_strokepoint_convertcoords(bContext *C, - bGPDlayer *gpl, - bGPDstroke *gps, - bGPDspoint *source_pt, - float p3d[3], - const rctf *subrect) +static void gpencil_strokepoint_convertcoords(bContext *C, + bGPDlayer *gpl, + bGPDstroke *gps, + bGPDspoint *source_pt, + float p3d[3], + const rctf *subrect) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -240,7 +243,7 @@ typedef struct tGpTimingData { /* Init point buffers for timing data. * Note this assumes we only grow those arrays! */ -static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) +static void gpencil_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) { float *tmp; @@ -266,10 +269,10 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) } /* add stroke point to timing buffers */ -static void gp_timing_data_add_point(tGpTimingData *gtd, - const double stroke_inittime, - const float time, - const float delta_dist) +static void gpencil_timing_data_add_point(tGpTimingData *gtd, + const double stroke_inittime, + const float time, + const float delta_dist) { float delta_time = 0.0f; const int cur_point = gtd->cur_point; @@ -305,14 +308,14 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, #define MIN_TIME_DELTA 0.02f /* Loop over next points to find the end of the stroke, and compute */ -static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, - RNG *rng, - const int idx, - const int nbr_gaps, - int *nbr_done_gaps, - const float tot_gaps_time, - const float delta_time, - float *next_delta_time) +static int gpencil_find_end_of_stroke_idx(tGpTimingData *gtd, + RNG *rng, + const int idx, + const int nbr_gaps, + int *nbr_done_gaps, + const float tot_gaps_time, + const float delta_time, + float *next_delta_time) { int j; @@ -362,10 +365,10 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, return j - 1; } -static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, - RNG *rng, - int *nbr_gaps, - float *tot_gaps_time) +static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, + RNG *rng, + int *nbr_gaps, + float *tot_gaps_time) { int i; float delta_time = 0.0f; @@ -393,16 +396,16 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, } } -static void gp_stroke_path_animation_add_keyframes(ReportList *reports, - PointerRNA ptr, - PropertyRNA *prop, - FCurve *fcu, - Curve *cu, - tGpTimingData *gtd, - RNG *rng, - const float time_range, - const int nbr_gaps, - const float tot_gaps_time) +static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports, + PointerRNA ptr, + PropertyRNA *prop, + FCurve *fcu, + Curve *cu, + tGpTimingData *gtd, + RNG *rng, + const float time_range, + const int nbr_gaps, + const float tot_gaps_time) { /* Use actual recorded timing! */ const float time_start = (float)gtd->start_frame; @@ -428,7 +431,7 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, start_stroke_idx = i; delta_time = next_delta_time; /* find end of that new stroke */ - end_stroke_idx = gp_find_end_of_stroke_idx( + end_stroke_idx = gpencil_find_end_of_stroke_idx( gtd, rng, i, nbr_gaps, &nbr_done_gaps, tot_gaps_time, delta_time, &next_delta_time); /* This one should *never* be negative! */ end_stroke_time = time_start + @@ -486,10 +489,10 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, } } -static void gp_stroke_path_animation(bContext *C, - ReportList *reports, - Curve *cu, - tGpTimingData *gtd) +static void gpencil_stroke_path_animation(bContext *C, + ReportList *reports, + Curve *cu, + tGpTimingData *gtd) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -557,7 +560,7 @@ static void gp_stroke_path_animation(bContext *C, /* Pre-process gaps, in case we don't want to keep their original timing */ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { - gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time); + gpencil_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time); } if (gtd->realtime) { @@ -571,7 +574,7 @@ static void gp_stroke_path_animation(bContext *C, printf("GP Stroke Path Conversion: Starting keying!\n"); } - gp_stroke_path_animation_add_keyframes( + gpencil_stroke_path_animation_add_keyframes( reports, ptr, prop, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time); BLI_rng_free(rng); @@ -603,16 +606,16 @@ static void gp_stroke_path_animation(bContext *C, /* convert stroke to 3d path */ /* helper */ -static void gp_stroke_to_path_add_point(tGpTimingData *gtd, - BPoint *bp, - const float p[3], - const float prev_p[3], - const bool do_gtd, - const double inittime, - const float time, - const float width, - const float rad_fac, - float minmax_weights[2]) +static void gpencil_stroke_to_path_add_point(tGpTimingData *gtd, + BPoint *bp, + const float p[3], + const float prev_p[3], + const bool do_gtd, + const double inittime, + const float time, + const float width, + const float rad_fac, + float minmax_weights[2]) { copy_v3_v3(bp->vec, p); bp->vec[3] = 1.0f; @@ -631,22 +634,22 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, /* Update timing data */ if (do_gtd) { - gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); + gpencil_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); } } -static void gp_stroke_to_path(bContext *C, - bGPDlayer *gpl, - bGPDstroke *gps, - Curve *cu, - rctf *subrect, - Nurb **curnu, - float minmax_weights[2], - const float rad_fac, - bool stitch, - const bool add_start_point, - const bool add_end_point, - tGpTimingData *gtd) +static void gpencil_stroke_to_path(bContext *C, + bGPDlayer *gpl, + bGPDstroke *gps, + Curve *cu, + rctf *subrect, + Nurb **curnu, + float minmax_weights[2], + const float rad_fac, + bool stitch, + const bool add_start_point, + const bool add_end_point, + tGpTimingData *gtd) { bGPDspoint *pt; Nurb *nu = (curnu) ? *curnu : NULL; @@ -682,7 +685,7 @@ static void gp_stroke_to_path(bContext *C, } if (do_gtd) { - gp_timing_data_set_nbr(gtd, nu->pntsu); + gpencil_timing_data_set_nbr(gtd, nu->pntsu); } /* If needed, make the link between both strokes with two zero-radius additional points */ @@ -710,7 +713,7 @@ static void gp_stroke_to_path(bContext *C, bp = &nu->bp[old_nbp - 1]; /* First point */ - gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); if (prev_bp) { interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC); if (do_gtd) { @@ -725,21 +728,21 @@ static void gp_stroke_to_path(bContext *C, } } bp++; - gp_stroke_to_path_add_point(gtd, - bp, - p1, - (bp - 1)->vec, - do_gtd, - gps->prev->inittime, - dt1, - 0.0f, - rad_fac, - minmax_weights); + gpencil_stroke_to_path_add_point(gtd, + bp, + p1, + (bp - 1)->vec, + do_gtd, + gps->prev->inittime, + dt1, + 0.0f, + rad_fac, + minmax_weights); /* Second point */ /* Note dt2 is always negative, which marks the gap. */ if (gps->totpoints > 1) { - gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); if (do_gtd) { dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); @@ -752,7 +755,7 @@ static void gp_stroke_to_path(bContext *C, } } bp++; - gp_stroke_to_path_add_point( + gpencil_stroke_to_path_add_point( gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights); old_nbp += 2; @@ -761,9 +764,9 @@ static void gp_stroke_to_path(bContext *C, float p[3], next_p[3]; float dt = 0.0f; - gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); if (gps->totpoints > 1) { - gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); interp_v3_v3v3(p, p, next_p, -GAP_DFAC); if (do_gtd) { dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); @@ -778,7 +781,7 @@ static void gp_stroke_to_path(bContext *C, * (which would be expected value) would not work * (it would be *before* gtd->inittime, which is not supported currently). */ - gp_stroke_to_path_add_point( + gpencil_stroke_to_path_add_point( gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); old_nbp++; @@ -796,18 +799,18 @@ static void gp_stroke_to_path(bContext *C, float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC; /* get coordinates to add at */ - gp_strokepoint_convertcoords(C, gpl, gps, pt, p, subrect); - - gp_stroke_to_path_add_point(gtd, - bp, - p, - (prev_bp) ? prev_bp->vec : p, - do_gtd, - gps->inittime, - pt->time, - width, - rad_fac, - minmax_weights); + gpencil_strokepoint_convertcoords(C, gpl, gps, pt, p, subrect); + + gpencil_stroke_to_path_add_point(gtd, + bp, + p, + (prev_bp) ? prev_bp->vec : p, + do_gtd, + gps->inittime, + pt->time, + width, + rad_fac, + minmax_weights); prev_bp = bp; } @@ -829,7 +832,7 @@ static void gp_stroke_to_path(bContext *C, dt = GAP_DFAC; /* Rather arbitrary too! */ } /* Note bp has already been incremented in main loop above, so it points to the right place. */ - gp_stroke_to_path_add_point( + gpencil_stroke_to_path_add_point( gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); } @@ -847,18 +850,18 @@ static void gp_stroke_to_path(bContext *C, /* convert stroke to 3d bezier */ /* helper */ -static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, - BezTriple *bezt, - const float p[3], - const float h1[3], - const float h2[3], - const float prev_p[3], - const bool do_gtd, - const double inittime, - const float time, - const float width, - const float rad_fac, - float minmax_weights[2]) +static void gpencil_stroke_to_bezier_add_point(tGpTimingData *gtd, + BezTriple *bezt, + const float p[3], + const float h1[3], + const float h2[3], + const float prev_p[3], + const bool do_gtd, + const double inittime, + const float time, + const float width, + const float rad_fac, + float minmax_weights[2]) { copy_v3_v3(bezt->vec[0], h1); copy_v3_v3(bezt->vec[1], p); @@ -879,22 +882,22 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, /* Update timing data */ if (do_gtd) { - gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); + gpencil_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); } } -static void gp_stroke_to_bezier(bContext *C, - bGPDlayer *gpl, - bGPDstroke *gps, - Curve *cu, - rctf *subrect, - Nurb **curnu, - float minmax_weights[2], - const float rad_fac, - bool stitch, - const bool add_start_point, - const bool add_end_point, - tGpTimingData *gtd) +static void gpencil_stroke_to_bezier(bContext *C, + bGPDlayer *gpl, + bGPDstroke *gps, + Curve *cu, + rctf *subrect, + Nurb **curnu, + float minmax_weights[2], + const float rad_fac, + bool stitch, + const bool add_start_point, + const bool add_end_point, + tGpTimingData *gtd) { bGPDspoint *pt; Nurb *nu = (curnu) ? *curnu : NULL; @@ -927,7 +930,7 @@ static void gp_stroke_to_bezier(bContext *C, } if (do_gtd) { - gp_timing_data_set_nbr(gtd, nu->pntsu); + gpencil_timing_data_set_nbr(gtd, nu->pntsu); } tot = gps->totpoints; @@ -935,12 +938,13 @@ static void gp_stroke_to_bezier(bContext *C, /* get initial coordinates */ pt = gps->points; if (tot) { - gp_strokepoint_convertcoords(C, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); if (tot > 1) { - gp_strokepoint_convertcoords(C, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); + gpencil_strokepoint_convertcoords( + C, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); } if (stitch && tot > 2) { - gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); } } @@ -1017,24 +1021,24 @@ static void gp_stroke_to_bezier(bContext *C, interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); bezt++; - gp_stroke_to_bezier_add_point(gtd, - bezt, - p1, - h1, - h2, - (bezt - 1)->vec[1], - do_gtd, - gps->prev->inittime, - dt1, - 0.0f, - rad_fac, - minmax_weights); + gpencil_stroke_to_bezier_add_point(gtd, + bezt, + p1, + h1, + h2, + (bezt - 1)->vec[1], + do_gtd, + gps->prev->inittime, + dt1, + 0.0f, + rad_fac, + minmax_weights); /* Second point */ interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); bezt++; - gp_stroke_to_bezier_add_point( + gpencil_stroke_to_bezier_add_point( gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights); old_nbezt += 2; @@ -1059,7 +1063,7 @@ static void gp_stroke_to_bezier(bContext *C, interp_v3_v3v3(h1, p, p3d_cur, -BEZT_HANDLE_FAC); interp_v3_v3v3(h2, p, p3d_cur, BEZT_HANDLE_FAC); bezt = &nu->bezt[old_nbezt]; - gp_stroke_to_bezier_add_point( + gpencil_stroke_to_bezier_add_point( gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); old_nbezt++; @@ -1088,25 +1092,25 @@ static void gp_stroke_to_bezier(bContext *C, interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); } - gp_stroke_to_bezier_add_point(gtd, - bezt, - p3d_cur, - h1, - h2, - prev_bezt ? prev_bezt->vec[1] : p3d_cur, - do_gtd, - gps->inittime, - pt->time, - width, - rad_fac, - minmax_weights); + gpencil_stroke_to_bezier_add_point(gtd, + bezt, + p3d_cur, + h1, + h2, + prev_bezt ? prev_bezt->vec[1] : p3d_cur, + do_gtd, + gps->inittime, + pt->time, + width, + rad_fac, + minmax_weights); /* shift coord vects */ copy_v3_v3(p3d_prev, p3d_cur); copy_v3_v3(p3d_cur, p3d_next); if (i + 2 < tot) { - gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); + gpencil_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); } prev_bezt = bezt; @@ -1138,18 +1142,18 @@ static void gp_stroke_to_bezier(bContext *C, interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC); /* Note bezt has already been incremented in main loop above, * so it points to the right place. */ - gp_stroke_to_bezier_add_point(gtd, - bezt, - p, - h1, - h2, - prev_bezt->vec[1], - do_gtd, - gps->inittime, - dt, - 0.0f, - rad_fac, - minmax_weights); + gpencil_stroke_to_bezier_add_point(gtd, + bezt, + p, + h1, + h2, + prev_bezt->vec[1], + do_gtd, + gps->inittime, + dt, + 0.0f, + rad_fac, + minmax_weights); } /* must calculate handles or else we crash */ @@ -1167,7 +1171,7 @@ static void gp_stroke_to_bezier(bContext *C, #undef WIDTH_CORR_FAC #undef BEZT_HANDLE_FAC -static void gp_stroke_finalize_curve_endpoints(Curve *cu) +static void gpencil_stroke_finalize_curve_endpoints(Curve *cu) { /* start */ Nurb *nu = cu->nurb.first; @@ -1202,7 +1206,7 @@ static void gp_stroke_finalize_curve_endpoints(Curve *cu) } } -static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2]) +static void gpencil_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2]) { Nurb *nu; const float delta = minmax_weights[0]; @@ -1233,7 +1237,7 @@ static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2 } } -static int gp_camera_view_subrect(bContext *C, rctf *subrect) +static int gpencil_camera_view_subrect(bContext *C, rctf *subrect) { View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); @@ -1255,15 +1259,15 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) /* convert a given grease-pencil layer to a 3d-curve representation * (using current view if appropriate) */ -static void gp_layer_to_curve(bContext *C, - ReportList *reports, - bGPdata *gpd, - bGPDlayer *gpl, - const int mode, - const bool norm_weights, - const float rad_fac, - const bool link_strokes, - tGpTimingData *gtd) +static void gpencil_layer_to_curve(bContext *C, + ReportList *reports, + bGPdata *gpd, + bGPDlayer *gpl, + const int mode, + const bool norm_weights, + const float rad_fac, + const bool link_strokes, + tGpTimingData *gtd) { struct Main *bmain = CTX_data_main(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -1292,7 +1296,7 @@ static void gp_layer_to_curve(bContext *C, } /* initialize camera framing */ - if (gp_camera_view_subrect(C, &subrect)) { + if (gpencil_camera_view_subrect(C, &subrect)) { subrect_ptr = &subrect; } @@ -1335,33 +1339,33 @@ static void gp_layer_to_curve(bContext *C, switch (mode) { case GP_STROKECONVERT_PATH: - gp_stroke_to_path(C, - gpl, - gps, - cu, - subrect_ptr, - &nu, - minmax_weights, - rad_fac, - stitch, - add_start_point, - add_end_point, - gtd); + gpencil_stroke_to_path(C, + gpl, + gps, + cu, + subrect_ptr, + &nu, + minmax_weights, + rad_fac, + stitch, + add_start_point, + add_end_point, + gtd); break; case GP_STROKECONVERT_CURVE: case GP_STROKECONVERT_POLY: /* convert after */ - gp_stroke_to_bezier(C, - gpl, - gps, - cu, - subrect_ptr, - &nu, - minmax_weights, - rad_fac, - stitch, - add_start_point, - add_end_point, - gtd); + gpencil_stroke_to_bezier(C, + gpl, + gps, + cu, + subrect_ptr, + &nu, + minmax_weights, + rad_fac, + stitch, + add_start_point, + add_end_point, + gtd); break; default: BLI_assert(!"invalid mode"); @@ -1372,16 +1376,16 @@ static void gp_layer_to_curve(bContext *C, /* If link_strokes, be sure first and last points have a zero weight/size! */ if (link_strokes) { - gp_stroke_finalize_curve_endpoints(cu); + gpencil_stroke_finalize_curve_endpoints(cu); } /* Update curve's weights, if needed */ if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) { - gp_stroke_norm_curve_weights(cu, minmax_weights); + gpencil_stroke_norm_curve_weights(cu, minmax_weights); } /* Create the path animation, if needed */ - gp_stroke_path_animation(C, reports, cu, gtd); + gpencil_stroke_path_animation(C, reports, cu, gtd); if (mode == GP_STROKECONVERT_POLY) { for (nu = cu->nurb.first; nu; nu = nu->next) { @@ -1399,7 +1403,7 @@ static void gp_layer_to_curve(bContext *C, /* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. * op may be NULL. */ -static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) +static bool gpencil_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) { Scene *scene = CTX_data_scene(C); @@ -1447,9 +1451,9 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe } /* Check end_frame is always > start frame! */ -static void gp_convert_set_end_frame(struct Main *UNUSED(main), - struct Scene *UNUSED(scene), - struct PointerRNA *ptr) +static void gpencil_convert_set_end_frame(struct Main *UNUSED(main), + struct Scene *UNUSED(scene), + struct PointerRNA *ptr) { int start_frame = RNA_int_get(ptr, "start_frame"); int end_frame = RNA_int_get(ptr, "end_frame"); @@ -1459,7 +1463,7 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), } } -static bool gp_convert_poll(bContext *C) +static bool gpencil_convert_poll(bContext *C) { Object *ob = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); @@ -1481,7 +1485,7 @@ static bool gp_convert_poll(bContext *C) (gpf->strokes.first) && (!GPENCIL_ANY_EDIT_MODE(gpd))); } -static int gp_convert_layer_exec(bContext *C, wmOperator *op) +static int gpencil_convert_layer_exec(bContext *C, wmOperator *op) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); Object *ob = CTX_data_active_object(C); @@ -1502,7 +1506,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { + if (!RNA_property_is_set(op->ptr, prop) && !gpencil_convert_check_has_valid_timing(C, gpl, op)) { BKE_report(op->reports, RPT_WARNING, "Current Grease Pencil strokes have no valid timing data, most timing options will " @@ -1539,7 +1543,8 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) gtd.offset_time = 0.0f; /* perform conversion */ - gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); + gpencil_layer_to_curve( + C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); /* free temp memory */ if (gtd.dists) { @@ -1560,9 +1565,9 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static bool gp_convert_poll_property(const bContext *UNUSED(C), - wmOperator *op, - const PropertyRNA *prop) +static bool gpencil_convert_poll_property(const bContext *UNUSED(C), + wmOperator *op, + const PropertyRNA *prop) { PointerRNA *ptr = op->ptr; const char *prop_id = RNA_property_identifier(prop); @@ -1641,9 +1646,9 @@ void GPENCIL_OT_convert(wmOperatorType *ot) /* callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = gp_convert_layer_exec; - ot->poll = gp_convert_poll; - ot->poll_property = gp_convert_poll_property; + ot->exec = gpencil_convert_layer_exec; + ot->poll = gpencil_convert_poll; + ot->poll_property = gpencil_convert_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1725,7 +1730,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) "The end frame of the path control curve (if Realtime is not set)", 1, 100000); - RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); + RNA_def_property_update_runtime(prop, gpencil_convert_set_end_frame); RNA_def_float(ot->srna, "gap_duration", @@ -1771,7 +1776,10 @@ static bool image_to_gpencil_poll(bContext *C) { SpaceLink *sl = CTX_wm_space_data(C); if ((sl != NULL) && (sl->spacetype == SPACE_IMAGE)) { - return true; + SpaceImage *sima = CTX_wm_space_image(C); + Image *image = sima->image; + ImageUser iuser = sima->iuser; + return BKE_image_has_ibuf(image, &iuser); } return false; @@ -1811,7 +1819,7 @@ static int image_to_gpencil_exec(bContext *C, wmOperator *op) if (done) { /* Delete any selected point. */ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); + gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); } BKE_reportf(op->reports, RPT_INFO, "Object created"); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 8c80334bf8a..44b866d81d7 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -90,7 +90,7 @@ /* Datablock Operators */ /* ******************* Add New Data ************************ */ -static bool gp_data_add_poll(bContext *C) +static bool gpencil_data_add_poll(bContext *C) { /* the base line we have is that we have somewhere to add Grease Pencil data */ @@ -98,7 +98,7 @@ static bool gp_data_add_poll(bContext *C) } /* add new datablock - wrapper around API */ -static int gp_data_add_exec(bContext *C, wmOperator *op) +static int gpencil_data_add_exec(bContext *C, wmOperator *op) { PointerRNA gpd_owner = {NULL}; bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner); @@ -145,14 +145,14 @@ void GPENCIL_OT_annotation_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_data_add_exec; - ot->poll = gp_data_add_poll; + ot->exec = gpencil_data_add_exec; + ot->poll = gpencil_data_add_poll; } /* ******************* Unlink Data ************************ */ /* poll callback for adding data/layers - special */ -static bool gp_data_unlink_poll(bContext *C) +static bool gpencil_data_unlink_poll(bContext *C) { bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, NULL); @@ -168,7 +168,7 @@ static bool gp_data_unlink_poll(bContext *C) } /* unlink datablock - wrapper around API */ -static int gp_data_unlink_exec(bContext *C, wmOperator *op) +static int gpencil_data_unlink_exec(bContext *C, wmOperator *op) { bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, NULL); @@ -199,8 +199,8 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_data_unlink_exec; - ot->poll = gp_data_unlink_poll; + ot->exec = gpencil_data_unlink_exec; + ot->poll = gpencil_data_unlink_poll; } /* ************************************************ */ @@ -209,7 +209,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot) /* ******************* Add New Layer ************************ */ /* add new layer - wrapper around API */ -static int gp_layer_add_exec(bContext *C, wmOperator *op) +static int gpencil_layer_add_exec(bContext *C, wmOperator *op) { const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_layer_annotation_add"); @@ -268,11 +268,11 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_layer_add_exec; - ot->poll = gp_add_poll; + ot->exec = gpencil_layer_add_exec; + ot->poll = gpencil_add_poll; } -static bool gp_add_annotation_poll(bContext *C) +static bool gpencil_add_annotation_poll(bContext *C) { return ED_annotation_data_get_pointers(C, NULL) != NULL; } @@ -287,12 +287,12 @@ void GPENCIL_OT_layer_annotation_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_layer_add_exec; - ot->poll = gp_add_annotation_poll; + ot->exec = gpencil_layer_add_exec; + ot->poll = gpencil_add_annotation_poll; } /* ******************* Remove Active Layer ************************* */ -static int gp_layer_remove_exec(bContext *C, wmOperator *op) +static int gpencil_layer_remove_exec(bContext *C, wmOperator *op) { const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_layer_annotation_remove"); @@ -345,11 +345,11 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_layer_remove_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_layer_remove_exec; + ot->poll = gpencil_active_layer_poll; } -static bool gp_active_layer_annotation_poll(bContext *C) +static bool gpencil_active_layer_annotation_poll(bContext *C) { bGPdata *gpd = ED_annotation_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -367,8 +367,8 @@ void GPENCIL_OT_layer_annotation_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_layer_remove_exec; - ot->poll = gp_active_layer_annotation_poll; + ot->exec = gpencil_layer_remove_exec; + ot->poll = gpencil_active_layer_annotation_poll; } /* ******************* Move Layer Up/Down ************************** */ @@ -377,7 +377,7 @@ enum { GP_LAYER_MOVE_DOWN = 1, }; -static int gp_layer_move_exec(bContext *C, wmOperator *op) +static int gpencil_layer_move_exec(bContext *C, wmOperator *op) { const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_layer_annotation_move"); @@ -418,8 +418,8 @@ void GPENCIL_OT_layer_move(wmOperatorType *ot) ot->description = "Move the active Grease Pencil layer up/down in the list"; /* api callbacks */ - ot->exec = gp_layer_move_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_layer_move_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -441,8 +441,8 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot) ot->description = "Move the active Annotation layer up/down in the list"; /* api callbacks */ - ot->exec = gp_layer_move_exec; - ot->poll = gp_active_layer_annotation_poll; + ot->exec = gpencil_layer_move_exec; + ot->poll = gpencil_active_layer_annotation_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -451,7 +451,7 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot) } /* ********************* Duplicate Layer ************************** */ -static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -491,8 +491,8 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) ot->description = "Make a copy of the active Grease Pencil layer"; /* callbacks */ - ot->exec = gp_layer_copy_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_layer_copy_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -504,7 +504,7 @@ enum { GP_LAYER_COPY_OBJECT_ACT_FRAME = 1, }; -static bool gp_layer_duplicate_object_poll(bContext *C) +static bool gpencil_layer_duplicate_object_poll(bContext *C) { ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = CTX_data_active_object(C); @@ -529,7 +529,7 @@ static bool gp_layer_duplicate_object_poll(bContext *C) return false; } -static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op) +static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -622,8 +622,8 @@ void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot) ot->description = "Make a copy of the active Grease Pencil layer to new object"; /* callbacks */ - ot->exec = gp_layer_duplicate_object_exec; - ot->poll = gp_layer_duplicate_object_poll; + ot->exec = gpencil_layer_duplicate_object_exec; + ot->poll = gpencil_layer_duplicate_object_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -641,7 +641,7 @@ enum { GP_FRAME_DUP_ALL = 1, }; -static int gp_frame_duplicate_exec(bContext *C, wmOperator *op) +static int gpencil_frame_duplicate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd); @@ -685,8 +685,8 @@ void GPENCIL_OT_frame_duplicate(wmOperatorType *ot) ot->description = "Make a copy of the active Grease Pencil Frame"; /* callbacks */ - ot->exec = gp_frame_duplicate_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_frame_duplicate_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -700,7 +700,7 @@ enum { GP_FRAME_CLEAN_FILL_ALL = 1, }; -static int gp_frame_clean_fill_exec(bContext *C, wmOperator *op) +static int gpencil_frame_clean_fill_exec(bContext *C, wmOperator *op) { bool changed = false; bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -770,8 +770,8 @@ void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot) ot->description = "Remove 'no fill' boundary strokes"; /* callbacks */ - ot->exec = gp_frame_clean_fill_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_frame_clean_fill_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -780,7 +780,7 @@ void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot) } /* ********************* Clean Loose Boundaries on Frame ************************** */ -static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op) +static int gpencil_frame_clean_loose_exec(bContext *C, wmOperator *op) { bool changed = false; bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -846,8 +846,8 @@ void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot) ot->description = "Remove loose points"; /* callbacks */ - ot->exec = gp_frame_clean_loose_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_frame_clean_loose_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -865,7 +865,7 @@ void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot) /* *********************** Hide Layers ******************************** */ -static int gp_hide_exec(bContext *C, wmOperator *op) +static int gpencil_hide_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd); @@ -908,8 +908,8 @@ void GPENCIL_OT_hide(wmOperatorType *ot) ot->description = "Hide selected/unselected Grease Pencil layers"; /* callbacks */ - ot->exec = gp_hide_exec; - ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */ + ot->exec = gpencil_hide_exec; + ot->poll = gpencil_active_layer_poll; /* NOTE: we need an active layer to play with */ /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -922,12 +922,12 @@ void GPENCIL_OT_hide(wmOperatorType *ot) /* ********************** Show All Layers ***************************** */ /* poll callback for showing layers */ -static bool gp_reveal_poll(bContext *C) +static bool gpencil_reveal_poll(bContext *C) { return ED_gpencil_data_get_active(C) != NULL; } -static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select) +static void gpencil_reveal_select_frame(bContext *C, bGPDframe *frame, bool select) { bGPDstroke *gps; for (gps = frame->strokes.first; gps; gps = gps->next) { @@ -948,7 +948,7 @@ static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select) } } -static int gp_reveal_exec(bContext *C, wmOperator *op) +static int gpencil_reveal_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); const bool select = RNA_boolean_get(op->ptr, "select"); @@ -967,14 +967,14 @@ static int gp_reveal_exec(bContext *C, wmOperator *op) if (select) { /* select all strokes on active frame only (same as select all operator) */ if (gpl->actframe) { - gp_reveal_select_frame(C, gpl->actframe, true); + gpencil_reveal_select_frame(C, gpl->actframe, true); } } else { /* deselect strokes on all frames (same as deselect all operator) */ bGPDframe *gpf; for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - gp_reveal_select_frame(C, gpf, false); + gpencil_reveal_select_frame(C, gpf, false); } } } @@ -996,8 +996,8 @@ void GPENCIL_OT_reveal(wmOperatorType *ot) ot->description = "Show all Grease Pencil layers"; /* callbacks */ - ot->exec = gp_reveal_exec; - ot->poll = gp_reveal_poll; + ot->exec = gpencil_reveal_exec; + ot->poll = gpencil_reveal_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1008,7 +1008,7 @@ void GPENCIL_OT_reveal(wmOperatorType *ot) /* ***************** Lock/Unlock All Layers ************************ */ -static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_lock_all_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1038,8 +1038,8 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot) "Lock all Grease Pencil layers to prevent them from being accidentally modified"; /* callbacks */ - ot->exec = gp_lock_all_exec; - ot->poll = gp_reveal_poll; + ot->exec = gpencil_lock_all_exec; + ot->poll = gpencil_reveal_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1047,7 +1047,7 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot) /* -------------------------- */ -static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1076,8 +1076,8 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot) ot->description = "Unlock all Grease Pencil layers so that they can be edited"; /* callbacks */ - ot->exec = gp_unlock_all_exec; - ot->poll = gp_reveal_poll; + ot->exec = gpencil_unlock_all_exec; + ot->poll = gpencil_reveal_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1085,7 +1085,7 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot) /* ********************** Isolate Layer **************************** */ -static int gp_isolate_layer_exec(bContext *C, wmOperator *op) +static int gpencil_isolate_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd); @@ -1153,8 +1153,8 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot) "Toggle whether the active layer is the only one that can be edited and/or visible"; /* callbacks */ - ot->exec = gp_isolate_layer_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_isolate_layer_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1169,7 +1169,7 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot) /* ********************** Merge Layer with the next layer **************************** */ -static int gp_merge_layer_exec(bContext *C, wmOperator *op) +static int gpencil_merge_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl_next = BKE_gpencil_layer_active_get(gpd); @@ -1242,8 +1242,8 @@ void GPENCIL_OT_layer_merge(wmOperatorType *ot) ot->description = "Merge the current layer with the layer below"; /* callbacks */ - ot->exec = gp_merge_layer_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_merge_layer_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1251,7 +1251,7 @@ void GPENCIL_OT_layer_merge(wmOperatorType *ot) /* ********************** Change Layer ***************************** */ -static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt)) +static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt)) { uiPopupMenu *pup; uiLayout *layout; @@ -1265,7 +1265,7 @@ static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UN return OPERATOR_INTERFACE; } -static int gp_layer_change_exec(bContext *C, wmOperator *op) +static int gpencil_layer_change_exec(bContext *C, wmOperator *op) { bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *gpl = NULL; @@ -1306,9 +1306,9 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot) ot->description = "Change active Grease Pencil layer"; /* callbacks */ - ot->invoke = gp_layer_change_invoke; - ot->exec = gp_layer_change_exec; - ot->poll = gp_active_layer_poll; + ot->invoke = gpencil_layer_change_invoke; + ot->exec = gpencil_layer_change_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1318,7 +1318,7 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot) RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf); } -static int gp_layer_active_exec(bContext *C, wmOperator *op) +static int gpencil_layer_active_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -1352,8 +1352,8 @@ void GPENCIL_OT_layer_active(wmOperatorType *ot) ot->description = "Active Grease Pencil layer"; /* callbacks */ - ot->exec = gp_layer_active_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_layer_active_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1373,7 +1373,7 @@ enum { GP_STROKE_MOVE_BOTTOM = 3, }; -static int gp_stroke_arrange_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1503,8 +1503,8 @@ void GPENCIL_OT_stroke_arrange(wmOperatorType *ot) ot->description = "Arrange selected strokes up/down in the drawing order of the active layer"; /* callbacks */ - ot->exec = gp_stroke_arrange_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_arrange_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1515,7 +1515,7 @@ void GPENCIL_OT_stroke_arrange(wmOperatorType *ot) /* ******************* Move Stroke to new color ************************** */ -static int gp_stroke_change_color_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Material *ma = NULL; @@ -1599,8 +1599,8 @@ void GPENCIL_OT_stroke_change_color(wmOperatorType *ot) ot->description = "Move selected strokes to active material"; /* callbacks */ - ot->exec = gp_stroke_change_color_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_change_color_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1610,7 +1610,7 @@ void GPENCIL_OT_stroke_change_color(wmOperatorType *ot) /* ******************* Lock color of non selected Strokes colors ************************** */ -static int gp_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1674,8 +1674,8 @@ void GPENCIL_OT_material_lock_unused(wmOperatorType *ot) ot->description = "Lock any material not used in any selected stroke"; /* api callbacks */ - ot->exec = gp_material_lock_unsused_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_material_lock_unsused_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1685,7 +1685,7 @@ void GPENCIL_OT_material_lock_unused(wmOperatorType *ot) /* Drawing Brushes Operators */ /* ******************* Brush resets ************************** */ -static int gp_brush_reset_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_brush_reset_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -1743,16 +1743,16 @@ void GPENCIL_OT_brush_reset(wmOperatorType *ot) ot->description = "Reset Brush to default parameters"; /* api callbacks */ - ot->exec = gp_brush_reset_exec; + ot->exec = gpencil_brush_reset_exec; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static Brush *gp_brush_get_first_by_mode(Main *bmain, - Paint *UNUSED(paint), - const enum eContextObjectMode mode, - char tool) +static Brush *gpencil_brush_get_first_by_mode(Main *bmain, + Paint *UNUSED(paint), + const enum eContextObjectMode mode, + char tool) { Brush *brush_next = NULL; for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) { @@ -1782,9 +1782,9 @@ static Brush *gp_brush_get_first_by_mode(Main *bmain, return NULL; } -static void gp_brush_delete_mode_brushes(Main *bmain, - Paint *paint, - const enum eContextObjectMode mode) +static void gpencil_brush_delete_mode_brushes(Main *bmain, + Paint *paint, + const enum eContextObjectMode mode) { Brush *brush_active = paint->brush; Brush *brush_next = NULL; @@ -1847,7 +1847,7 @@ static void gp_brush_delete_mode_brushes(Main *bmain, } } -static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -1903,7 +1903,7 @@ static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op)) } } - gp_brush_delete_mode_brushes(bmain, paint, mode); + gpencil_brush_delete_mode_brushes(bmain, paint, mode); switch (mode) { case CTX_MODE_PAINT_GPENCIL: { @@ -1930,7 +1930,7 @@ static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op)) BKE_paint_toolslots_brush_validate(bmain, paint); /* Set Again the first brush of the mode. */ - Brush *deft_brush = gp_brush_get_first_by_mode(bmain, paint, mode, tool); + Brush *deft_brush = gpencil_brush_get_first_by_mode(bmain, paint, mode, tool); if (deft_brush) { BKE_paint_brush_set(paint, deft_brush); } @@ -1950,7 +1950,7 @@ void GPENCIL_OT_brush_reset_all(wmOperatorType *ot) ot->description = "Delete all mode brushes and recreate a default set"; /* api callbacks */ - ot->exec = gp_brush_reset_all_exec; + ot->exec = gpencil_brush_reset_all_exec; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2496,7 +2496,7 @@ typedef struct tJoinGPencil_AdtFixData { * Callback to pass to #BKE_fcurves_main_cb() * for RNA Paths attached to each F-Curve used in the #AnimData. */ -static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data) +static void gpencil_joined_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data) { tJoinGPencil_AdtFixData *afd = (tJoinGPencil_AdtFixData *)user_data; ID *src_id = &afd->src_gpd->id; @@ -2534,8 +2534,8 @@ static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data) if (dtar->id == src_id) { dtar->id = dst_id; - /* Also check on the subtarget... - * We duplicate the logic from drivers_path_rename_fix() here, with our own + /* Also check on the sub-target. + * We duplicate the logic from #drivers_path_rename_fix() here, with our own * little twists so that we know that it isn't going to clobber the wrong data */ if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) { @@ -2721,7 +2721,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) } /* Fix all the animation data */ - BKE_fcurves_main_cb(bmain, joined_gpencil_fix_animdata_cb, &afd); + BKE_fcurves_main_cb(bmain, gpencil_joined_fix_animdata_cb, &afd); BLI_ghash_free(afd.names_map, MEM_freeN, NULL); /* Only copy over animdata now, after all the remapping has been done, @@ -2856,7 +2856,7 @@ void GPENCIL_OT_lock_layer(wmOperatorType *ot) /* api callbacks */ ot->exec = gpencil_lock_layer_exec; - ot->poll = gp_active_layer_poll; + ot->poll = gpencil_active_layer_poll; } /* ********************** Isolate gpencil_ color **************************** */ @@ -3415,7 +3415,7 @@ bool ED_gpencil_add_lattice_modifier(const bContext *C, } /* Masking operators */ -static int gp_layer_mask_add_exec(bContext *C, wmOperator *op) +static int gpencil_layer_mask_add_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { @@ -3476,14 +3476,14 @@ void GPENCIL_OT_layer_mask_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_layer_mask_add_exec; - ot->poll = gp_add_poll; + ot->exec = gpencil_layer_mask_add_exec; + ot->poll = gpencil_add_poll; /* properties */ RNA_def_string(ot->srna, "name", NULL, 128, "Layer", "Name of the layer"); } -static int gp_layer_mask_remove_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_layer_mask_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_active_object(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { @@ -3525,6 +3525,6 @@ void GPENCIL_OT_layer_mask_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_layer_mask_remove_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_layer_mask_remove_exec; + ot->poll = gpencil_active_layer_poll; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 76776b5c23c..78e2812fdef 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -95,7 +95,7 @@ * \{ */ /* poll callback for all stroke editing operators */ -static bool gp_stroke_edit_poll(bContext *C) +static bool gpencil_stroke_edit_poll(bContext *C) { /* edit only supported with grease pencil objects */ Object *ob = CTX_data_active_object(C); @@ -108,7 +108,7 @@ static bool gp_stroke_edit_poll(bContext *C) } /* poll callback to verify edit mode in 3D view only */ -static bool gp_strokes_edit3d_poll(bContext *C) +static bool gpencil_strokes_edit3d_poll(bContext *C) { /* edit only supported with grease pencil objects */ Object *ob = CTX_data_active_object(C); @@ -120,7 +120,7 @@ static bool gp_strokes_edit3d_poll(bContext *C) * - 1) Editable GP data * - 2) 3D View only */ - return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C)); + return (gpencil_stroke_edit_poll(C) && ED_operator_view3d_active(C)); } static bool gpencil_editmode_toggle_poll(bContext *C) @@ -789,7 +789,7 @@ void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot) /* callbacks */ ot->exec = gpencil_hideselect_toggle_exec; - ot->poll = gp_stroke_edit_poll; + ot->poll = gpencil_stroke_edit_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; @@ -802,9 +802,9 @@ void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot) * \{ */ /* Make copies of selected point segments in a selected stroke */ -static void gp_duplicate_points(const bGPDstroke *gps, - ListBase *new_strokes, - const char *layername) +static void gpencil_duplicate_points(const bGPDstroke *gps, + ListBase *new_strokes, + const char *layername) { bGPDspoint *pt; int i; @@ -880,7 +880,7 @@ static void gp_duplicate_points(const bGPDstroke *gps, } } -static int gp_duplicate_exec(bContext *C, wmOperator *op) +static int gpencil_duplicate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -933,7 +933,7 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) } else { /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */ - gp_duplicate_points(gps, &new_strokes, gpl->info); + gpencil_duplicate_points(gps, &new_strokes, gpl->info); } /* deselect original stroke, or else the originals get moved too @@ -969,8 +969,8 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) ot->description = "Duplicate the selected Grease Pencil strokes"; /* callbacks */ - ot->exec = gp_duplicate_exec; - ot->poll = gp_stroke_edit_poll; + ot->exec = gpencil_duplicate_exec; + ot->poll = gpencil_stroke_edit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -983,12 +983,12 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) * \{ */ /* helper to copy a point to temp area */ -static void copy_move_point(bGPDstroke *gps, - bGPDspoint *temp_points, - MDeformVert *temp_dverts, - int from_idx, - int to_idx, - const bool copy) +static void gpencil_copy_move_point(bGPDstroke *gps, + bGPDspoint *temp_points, + MDeformVert *temp_dverts, + int from_idx, + int to_idx, + const bool copy) { bGPDspoint *pt = &temp_points[from_idx]; bGPDspoint *pt_final = &gps->points[to_idx]; @@ -1053,7 +1053,7 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps) BLI_insertlinkafter(&gpf->strokes, gps, gps_new); /* copy selected point data to new stroke */ - copy_move_point(gps_new, gps->points, gps->dvert, i, 0, true); + gpencil_copy_move_point(gps_new, gps->points, gps->dvert, i, 0, true); /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gps); @@ -1098,13 +1098,13 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps) /* move points to new position */ for (int i = 0; i < oldtotpoints; i++) { - copy_move_point(gps, temp_points, temp_dverts, i, i2, false); + gpencil_copy_move_point(gps, temp_points, temp_dverts, i, i2, false); i2++; } /* If first point, add new point at the beginning. */ if (do_first) { - copy_move_point(gps, temp_points, temp_dverts, 0, 0, true); + gpencil_copy_move_point(gps, temp_points, temp_dverts, 0, 0, true); /* deselect old */ pt = &gps->points[1]; pt->flag &= ~GP_SPOINT_SELECT; @@ -1115,7 +1115,8 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps) /* if last point, add new point at the end */ if (do_last) { - copy_move_point(gps, temp_points, temp_dverts, oldtotpoints - 1, gps->totpoints - 1, true); + gpencil_copy_move_point( + gps, temp_points, temp_dverts, oldtotpoints - 1, gps->totpoints - 1, true); /* deselect old */ pt = &gps->points[gps->totpoints - 2]; @@ -1138,7 +1139,7 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps) } } -static int gp_extrude_exec(bContext *C, wmOperator *op) +static int gpencil_extrude_exec(bContext *C, wmOperator *op) { Object *obact = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)obact->data; @@ -1194,8 +1195,8 @@ void GPENCIL_OT_extrude(wmOperatorType *ot) ot->description = "Extrude the selected Grease Pencil points"; /* callbacks */ - ot->exec = gp_extrude_exec; - ot->poll = gp_stroke_edit_poll; + ot->exec = gpencil_extrude_exec; + ot->poll = gpencil_stroke_edit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1216,16 +1217,16 @@ void GPENCIL_OT_extrude(wmOperatorType *ot) /* list of bGPDstroke instances */ /* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */ -ListBase gp_strokes_copypastebuf = {NULL, NULL}; +ListBase gpencil_strokes_copypastebuf = {NULL, NULL}; /* Hash for hanging on to all the colors used by strokes in the buffer * * This is needed to prevent dangling and unsafe pointers when pasting across data-blocks, * or after a color used by a stroke in the buffer gets deleted (via user action or undo). */ -static GHash *gp_strokes_copypastebuf_colors = NULL; +static GHash *gpencil_strokes_copypastebuf_colors = NULL; -static GHash *gp_strokes_copypastebuf_colors_material_to_name_create(Main *bmain) +static GHash *gpencil_strokes_copypastebuf_colors_material_to_name_create(Main *bmain) { GHash *ma_to_name = BLI_ghash_ptr_new(__func__); @@ -1237,12 +1238,12 @@ static GHash *gp_strokes_copypastebuf_colors_material_to_name_create(Main *bmain return ma_to_name; } -static void gp_strokes_copypastebuf_colors_material_to_name_free(GHash *ma_to_name) +static void gpencil_strokes_copypastebuf_colors_material_to_name_free(GHash *ma_to_name) { BLI_ghash_free(ma_to_name, NULL, MEM_freeN); } -static GHash *gp_strokes_copypastebuf_colors_name_to_material_create(Main *bmain) +static GHash *gpencil_strokes_copypastebuf_colors_name_to_material_create(Main *bmain) { GHash *name_to_ma = BLI_ghash_str_new(__func__); @@ -1254,7 +1255,7 @@ static GHash *gp_strokes_copypastebuf_colors_name_to_material_create(Main *bmain return name_to_ma; } -static void gp_strokes_copypastebuf_colors_name_to_material_free(GHash *name_to_ma) +static void gpencil_strokes_copypastebuf_colors_name_to_material_free(GHash *name_to_ma) { BLI_ghash_free(name_to_ma, MEM_freeN, NULL); } @@ -1267,13 +1268,13 @@ void ED_gpencil_strokes_copybuf_free(void) /* Free the colors buffer * NOTE: This is done before the strokes so that the ptrs are still safe */ - if (gp_strokes_copypastebuf_colors) { - BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN); - gp_strokes_copypastebuf_colors = NULL; + if (gpencil_strokes_copypastebuf_colors) { + BLI_ghash_free(gpencil_strokes_copypastebuf_colors, NULL, MEM_freeN); + gpencil_strokes_copypastebuf_colors = NULL; } /* Free the stroke buffer */ - for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) { + for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gpsn) { gpsn = gps->next; if (gps->points) { @@ -1286,17 +1287,17 @@ void ED_gpencil_strokes_copybuf_free(void) MEM_SAFE_FREE(gps->triangles); - BLI_freelinkN(&gp_strokes_copypastebuf, gps); + BLI_freelinkN(&gpencil_strokes_copypastebuf, gps); } - gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL; + gpencil_strokes_copypastebuf.first = gpencil_strokes_copypastebuf.last = NULL; } /** * Ensure that destination datablock has all the colors the pasted strokes need. * Helper function for copy-pasting strokes */ -GHash *gp_copybuf_validate_colormap(bContext *C) +GHash *gpencil_copybuf_validate_colormap(bContext *C) { Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); @@ -1304,9 +1305,9 @@ GHash *gp_copybuf_validate_colormap(bContext *C) GHashIterator gh_iter; /* For each color, check if exist and add if not */ - GHash *name_to_ma = gp_strokes_copypastebuf_colors_name_to_material_create(bmain); + GHash *name_to_ma = gpencil_strokes_copypastebuf_colors_name_to_material_create(bmain); - GHASH_ITER (gh_iter, gp_strokes_copypastebuf_colors) { + GHASH_ITER (gh_iter, gpencil_strokes_copypastebuf_colors) { int *key = BLI_ghashIterator_getKey(&gh_iter); char *ma_name = BLI_ghashIterator_getValue(&gh_iter); Material *ma = BLI_ghash_lookup(name_to_ma, ma_name); @@ -1319,7 +1320,7 @@ GHash *gp_copybuf_validate_colormap(bContext *C) } } - gp_strokes_copypastebuf_colors_name_to_material_free(name_to_ma); + gpencil_strokes_copypastebuf_colors_name_to_material_free(name_to_ma); return new_colors; } @@ -1330,7 +1331,7 @@ GHash *gp_copybuf_validate_colormap(bContext *C) /** \name Copy Selected Strokes Operator * \{ */ -static int gp_strokes_copy_exec(bContext *C, wmOperator *op) +static int gpencil_strokes_copy_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); @@ -1389,11 +1390,11 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) /* add to temp buffer */ gpsd->next = gpsd->prev = NULL; - BLI_addtail(&gp_strokes_copypastebuf, gpsd); + BLI_addtail(&gpencil_strokes_copypastebuf, gpsd); } else { /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */ - gp_duplicate_points(gps, &gp_strokes_copypastebuf, gpl->info); + gpencil_duplicate_points(gps, &gpencil_strokes_copypastebuf, gpl->info); } } } @@ -1401,10 +1402,10 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* Build up hash of material colors used in these strokes */ - if (gp_strokes_copypastebuf.first) { - gp_strokes_copypastebuf_colors = BLI_ghash_int_new("GPencil CopyBuf Colors"); - GHash *ma_to_name = gp_strokes_copypastebuf_colors_material_to_name_create(bmain); - LISTBASE_FOREACH (bGPDstroke *, gps, &gp_strokes_copypastebuf) { + if (gpencil_strokes_copypastebuf.first) { + gpencil_strokes_copypastebuf_colors = BLI_ghash_int_new("GPencil CopyBuf Colors"); + GHash *ma_to_name = gpencil_strokes_copypastebuf_colors_material_to_name_create(bmain); + LISTBASE_FOREACH (bGPDstroke *, gps, &gpencil_strokes_copypastebuf) { if (ED_gpencil_stroke_can_use(C, gps)) { Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1); /* Avoid default material. */ @@ -1414,13 +1415,13 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) char **ma_name_val; if (!BLI_ghash_ensure_p( - gp_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) { + gpencil_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) { char *ma_name = BLI_ghash_lookup(ma_to_name, ma); *ma_name_val = MEM_dupallocN(ma_name); } } } - gp_strokes_copypastebuf_colors_material_to_name_free(ma_to_name); + gpencil_strokes_copypastebuf_colors_material_to_name_free(ma_to_name); } /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */ @@ -1438,8 +1439,8 @@ void GPENCIL_OT_copy(wmOperatorType *ot) ot->description = "Copy selected Grease Pencil points and strokes"; /* callbacks */ - ot->exec = gp_strokes_copy_exec; - ot->poll = gp_stroke_edit_poll; + ot->exec = gpencil_strokes_copy_exec; + ot->poll = gpencil_stroke_edit_poll; /* flags */ // ot->flag = OPTYPE_REGISTER; @@ -1451,7 +1452,7 @@ void GPENCIL_OT_copy(wmOperatorType *ot) /** \name Paste Selected Strokes Operator * \{ */ -static bool gp_strokes_paste_poll(bContext *C) +static bool gpencil_strokes_paste_poll(bContext *C) { ScrArea *area = CTX_wm_area(C); if (!((area != NULL) && (area->spacetype == SPACE_VIEW3D))) { @@ -1464,7 +1465,7 @@ static bool gp_strokes_paste_poll(bContext *C) * 2) Copy buffer must at least have something (though it may be the wrong sort...). */ return (ED_gpencil_data_get_active(C) != NULL) && - (!BLI_listbase_is_empty(&gp_strokes_copypastebuf)); + (!BLI_listbase_is_empty(&gpencil_strokes_copypastebuf)); } typedef enum eGP_PasteMode { @@ -1472,7 +1473,7 @@ typedef enum eGP_PasteMode { GP_COPY_TO_ACTIVE = 1, } eGP_PasteMode; -static int gp_strokes_paste_exec(bContext *C, wmOperator *op) +static int gpencil_strokes_paste_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -1489,7 +1490,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition"); return OPERATOR_CANCELLED; } - else if (BLI_listbase_is_empty(&gp_strokes_copypastebuf)) { + else if (BLI_listbase_is_empty(&gpencil_strokes_copypastebuf)) { BKE_report(op->reports, RPT_ERROR, "No strokes to paste, select and copy some points before trying again"); @@ -1509,7 +1510,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) bGPDstroke *gps; bool ok = false; - for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { + for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { ok = true; break; @@ -1535,10 +1536,11 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* Ensure that all the necessary colors exist */ - new_colors = gp_copybuf_validate_colormap(C); + new_colors = gpencil_copybuf_validate_colormap(C); /* Copy over the strokes from the buffer (and adjust the colors) */ - bGPDstroke *gps_init = (!on_back) ? gp_strokes_copypastebuf.first : gp_strokes_copypastebuf.last; + bGPDstroke *gps_init = (!on_back) ? gpencil_strokes_copypastebuf.first : + gpencil_strokes_copypastebuf.last; for (bGPDstroke *gps = gps_init; gps; gps = (!on_back) ? gps->next : gps->prev) { if (ED_gpencil_stroke_can_use(C, gps)) { /* Need to verify if layer exists */ @@ -1606,8 +1608,8 @@ void GPENCIL_OT_paste(wmOperatorType *ot) ot->description = "Paste previously copied strokes to active layer or to original layer"; /* callbacks */ - ot->exec = gp_strokes_paste_exec; - ot->poll = gp_strokes_paste_poll; + ot->exec = gpencil_strokes_paste_exec; + ot->poll = gpencil_strokes_paste_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1626,7 +1628,7 @@ void GPENCIL_OT_paste(wmOperatorType *ot) /** \name Move To Layer Operator * \{ */ -static int gp_move_to_layer_exec(bContext *C, wmOperator *op) +static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -1732,8 +1734,8 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) "Move selected strokes to another layer"; // XXX: allow moving individual points too? /* callbacks */ - ot->exec = gp_move_to_layer_exec; - ot->poll = gp_stroke_edit_poll; // XXX? + ot->exec = gpencil_move_to_layer_exec; + ot->poll = gpencil_stroke_edit_poll; // XXX? /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1750,7 +1752,7 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) /** \name Add Blank Frame Operator * \{ */ -static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) +static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Scene *scene = CTX_data_scene(C); @@ -1808,8 +1810,8 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) "(all subsequently existing frames, if any, are shifted right by one frame)"; /* callbacks */ - ot->exec = gp_blank_frame_add_exec; - ot->poll = gp_add_poll; + ot->exec = gpencil_blank_frame_add_exec; + ot->poll = gpencil_add_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1828,7 +1830,7 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) /** \name Delete Active Frame Operator * \{ */ -static bool gp_actframe_delete_poll(bContext *C) +static bool gpencil_actframe_delete_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -1837,7 +1839,7 @@ static bool gp_actframe_delete_poll(bContext *C) return (gpl && gpl->actframe); } -static bool gp_annotation_actframe_delete_poll(bContext *C) +static bool annotation_actframe_delete_poll(bContext *C) { bGPdata *gpd = ED_annotation_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -1847,7 +1849,7 @@ static bool gp_annotation_actframe_delete_poll(bContext *C) } /* delete active frame - wrapper around API calls */ -static int gp_actframe_delete_exec(bContext *C, wmOperator *op) +static int gpencil_actframe_delete_exec(bContext *C, wmOperator *op) { const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_annotation_active_frame_delete"); @@ -1890,8 +1892,8 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_actframe_delete_exec; - ot->poll = gp_actframe_delete_poll; + ot->exec = gpencil_actframe_delete_exec; + ot->poll = gpencil_actframe_delete_poll; } void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot) @@ -1904,8 +1906,8 @@ void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_actframe_delete_exec; - ot->poll = gp_annotation_actframe_delete_poll; + ot->exec = gpencil_actframe_delete_exec; + ot->poll = annotation_actframe_delete_poll; } /** \} */ @@ -1914,7 +1916,7 @@ void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot) /** \name Delete All Active Frames * \{ */ -static bool gp_actframe_delete_all_poll(bContext *C) +static bool gpencil_actframe_delete_all_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1924,7 +1926,7 @@ static bool gp_actframe_delete_all_poll(bContext *C) return (gpd && gpd->layers.first); } -static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op) +static int gpencil_actframe_delete_all_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Scene *scene = CTX_data_scene(C); @@ -1969,8 +1971,8 @@ void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* callbacks */ - ot->exec = gp_actframe_delete_all_exec; - ot->poll = gp_actframe_delete_all_poll; + ot->exec = gpencil_actframe_delete_all_exec; + ot->poll = gpencil_actframe_delete_all_poll; } /** \} */ @@ -1998,7 +2000,7 @@ typedef enum eGP_DissolveMode { } eGP_DissolveMode; /* Delete selected strokes */ -static int gp_delete_selected_strokes(bContext *C) +static int gpencil_delete_selected_strokes(bContext *C) { bool changed = false; bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -2056,7 +2058,7 @@ static int gp_delete_selected_strokes(bContext *C) /* ----------------------------------- */ /* Delete selected points but keep the stroke */ -static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode) +static int gpencil_dissolve_selected_points(bContext *C, eGP_DissolveMode mode) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -2282,7 +2284,9 @@ typedef struct tGPDeleteIsland { int end_idx; } tGPDeleteIsland; -static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDstroke *gps_last) +static void gpencil_stroke_join_islands(bGPDframe *gpf, + bGPDstroke *gps_first, + bGPDstroke *gps_last) { bGPDspoint *pt = NULL; bGPDspoint *pt_final = NULL; @@ -2382,12 +2386,12 @@ static void gp_stroke_join_islands(bGPDframe *gpf, bGPDstroke *gps_first, bGPDst * 2) Each island gets converted to a new stroke * If the number of points is <= limit, the stroke is deleted */ -void gp_stroke_delete_tagged_points(bGPDframe *gpf, - bGPDstroke *gps, - bGPDstroke *next_stroke, - int tag_flags, - bool select, - int limit) +void gpencil_stroke_delete_tagged_points(bGPDframe *gpf, + bGPDstroke *gps, + bGPDstroke *next_stroke, + int tag_flags, + bool select, + int limit) { tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands"); @@ -2517,7 +2521,7 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, } /* if cyclic, need to join last stroke with first stroke */ if ((is_cyclic) && (gps_first != NULL) && (gps_first != new_stroke)) { - gp_stroke_join_islands(gpf, gps_first, new_stroke); + gpencil_stroke_join_islands(gpf, gps_first, new_stroke); } } @@ -2530,7 +2534,7 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, } /* Split selected strokes into segments, splitting on selected points */ -static int gp_delete_selected_points(bContext *C) +static int gpencil_delete_selected_points(bContext *C) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -2564,7 +2568,7 @@ static int gp_delete_selected_points(bContext *C) gps->flag &= ~GP_STROKE_SELECT; /* delete unwanted points by splitting stroke into several smaller ones */ - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); + gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); changed = true; } @@ -2585,9 +2589,9 @@ static int gp_delete_selected_points(bContext *C) } /* simple wrapper to external call */ -int gp_delete_selected_point_wrap(bContext *C) +int gpencil_delete_selected_point_wrap(bContext *C) { - return gp_delete_selected_points(C); + return gpencil_delete_selected_points(C); } /** \} */ @@ -2596,22 +2600,22 @@ int gp_delete_selected_point_wrap(bContext *C) /** \name Delete Operator * \{ */ -static int gp_delete_exec(bContext *C, wmOperator *op) +static int gpencil_delete_exec(bContext *C, wmOperator *op) { eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type"); int result = OPERATOR_CANCELLED; switch (mode) { case GP_DELETEOP_STROKES: /* selected strokes */ - result = gp_delete_selected_strokes(C); + result = gpencil_delete_selected_strokes(C); break; case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */ - result = gp_delete_selected_points(C); + result = gpencil_delete_selected_points(C); break; case GP_DELETEOP_FRAME: /* active frame */ - result = gp_actframe_delete_exec(C, op); + result = gpencil_actframe_delete_exec(C, op); break; } @@ -2638,8 +2642,8 @@ void GPENCIL_OT_delete(wmOperatorType *ot) /* callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = gp_delete_exec; - ot->poll = gp_stroke_edit_poll; + ot->exec = gpencil_delete_exec; + ot->poll = gpencil_stroke_edit_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; @@ -2659,11 +2663,11 @@ void GPENCIL_OT_delete(wmOperatorType *ot) /** \name Dissolve Operator * \{ */ -static int gp_dissolve_exec(bContext *C, wmOperator *op) +static int gpencil_dissolve_exec(bContext *C, wmOperator *op) { eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type"); - return gp_dissolve_selected_points(C, mode); + return gpencil_dissolve_selected_points(C, mode); } void GPENCIL_OT_dissolve(wmOperatorType *ot) @@ -2686,8 +2690,8 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot) /* callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = gp_dissolve_exec; - ot->poll = gp_stroke_edit_poll; + ot->exec = gpencil_dissolve_exec; + ot->poll = gpencil_stroke_edit_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; @@ -2711,7 +2715,7 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot) /* NOTE: For now, we only allow these in the 3D view, as other editors do not * define a cursor or gridstep which can be used */ -static bool gp_snap_poll(bContext *C) +static bool gpencil_snap_poll(bContext *C) { ScrArea *area = CTX_wm_area(C); Object *ob = CTX_data_active_object(C); @@ -2720,7 +2724,7 @@ static bool gp_snap_poll(bContext *C) ((area != NULL) && (area->spacetype == SPACE_VIEW3D)); } -static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); RegionView3D *rv3d = CTX_wm_region_data(C); @@ -2766,7 +2770,7 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) /* return data */ copy_v3_v3(&pt->x, fpt); - gp_apply_parent_point(depsgraph, obact, gpl, pt); + gpencil_apply_parent_point(depsgraph, obact, gpl, pt); } } } @@ -2787,8 +2791,8 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) ot->description = "Snap selected points to the nearest grid points"; /* callbacks */ - ot->exec = gp_snap_to_grid; - ot->poll = gp_snap_poll; + ot->exec = gpencil_snap_to_grid; + ot->poll = gpencil_snap_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2800,7 +2804,7 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) /** \name Snapping Selection to Cursor Operator * \{ */ -static int gp_snap_to_cursor(bContext *C, wmOperator *op) +static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -2854,7 +2858,7 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op) for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { copy_v3_v3(&pt->x, cursor_global); - gp_apply_parent_point(depsgraph, obact, gpl, pt); + gpencil_apply_parent_point(depsgraph, obact, gpl, pt); } } } @@ -2876,8 +2880,8 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) ot->description = "Snap selected points/strokes to the cursor"; /* callbacks */ - ot->exec = gp_snap_to_cursor; - ot->poll = gp_snap_poll; + ot->exec = gpencil_snap_to_cursor; + ot->poll = gpencil_snap_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2896,7 +2900,7 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) /** \name Snapping Cursor to Selection Operator * \{ */ -static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *obact = CTX_data_active_object(C); @@ -2956,13 +2960,16 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) } } - if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN && count) { - mul_v3_fl(centroid, 1.0f / (float)count); - copy_v3_v3(cursor, centroid); - } - else { + if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) { mid_v3_v3v3(cursor, min, max); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + zero_v3(cursor); + if (count) { + mul_v3_fl(centroid, 1.0f / (float)count); + copy_v3_v3(cursor, centroid); + } + } DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); @@ -2978,8 +2985,8 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot) ot->description = "Snap cursor to center of selected points"; /* callbacks */ - ot->exec = gp_snap_cursor_to_sel; - ot->poll = gp_snap_poll; + ot->exec = gpencil_snap_cursor_to_sel; + ot->poll = gpencil_snap_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2991,7 +2998,7 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot) /** \name Apply Layer Thickness Change to Strokes Operator * \{ */ -static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); @@ -3032,8 +3039,8 @@ void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot) ot->description = "Apply the thickness change of the layer to its strokes"; /* api callbacks */ - ot->exec = gp_stroke_apply_thickness_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_apply_thickness_exec; + ot->poll = gpencil_active_layer_poll; } /** \} */ @@ -3048,7 +3055,7 @@ enum { GP_STROKE_CYCLIC_TOGGLE = 3, }; -static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_cyclical_set_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); @@ -3147,8 +3154,8 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) ot->description = "Close or open the selected stroke adding an edge from last to first point"; /* api callbacks */ - ot->exec = gp_stroke_cyclical_set_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_cyclical_set_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3173,7 +3180,7 @@ enum { GP_STROKE_CAPS_TOGGLE_DEFAULT = 3, }; -static int gp_stroke_caps_set_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_caps_set_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); @@ -3250,8 +3257,8 @@ void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot) ot->description = "Change Stroke caps mode (rounded or flat)"; /* api callbacks */ - ot->exec = gp_stroke_caps_set_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_caps_set_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3422,7 +3429,7 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, } } -static int gp_stroke_join_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd); @@ -3549,8 +3556,8 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot) ot->description = "Join selected strokes (optionally as new stroke)"; /* api callbacks */ - ot->exec = gp_stroke_join_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_join_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3570,7 +3577,7 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot) /** \name Stroke Flip Operator * \{ */ -static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); @@ -3620,8 +3627,8 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot) ot->description = "Change direction of the points of the selected strokes"; /* api callbacks */ - ot->exec = gp_stroke_flip_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_flip_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3633,7 +3640,7 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot) /** \name Stroke Re-project Operator * \{ */ -static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) +static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Scene *scene = CTX_data_scene(C); @@ -3647,7 +3654,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) /* Init space conversion stuff. */ GP_SpaceConversion gsc = {NULL}; SnapObjectContext *sctx = NULL; - gp_point_conversion_init(C, &gsc); + gpencil_point_conversion_init(C, &gsc); /* Init snap context for geometry projection. */ sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C)); @@ -3718,8 +3725,8 @@ void GPENCIL_OT_reproject(wmOperatorType *ot) /* callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = gp_strokes_reproject_exec; - ot->poll = gp_strokes_edit3d_poll; + ot->exec = gpencil_strokes_reproject_exec; + ot->poll = gpencil_strokes_edit3d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3736,7 +3743,7 @@ void GPENCIL_OT_reproject(wmOperatorType *ot) "Keep original strokes and create a copy before reprojecting instead of reproject them"); } -static int gp_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_active_object(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { @@ -3765,8 +3772,8 @@ void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) ot->description = "Update all internal geometry data"; /* callbacks */ - ot->exec = gp_recalc_geometry_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_recalc_geometry_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3779,7 +3786,7 @@ void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) * \{ */ /* helper to smooth */ -static void gp_smooth_stroke(bContext *C, wmOperator *op) +static void gpencil_smooth_stroke(bContext *C, wmOperator *op) { const int repeat = RNA_int_get(op->ptr, "repeat"); float factor = RNA_float_get(op->ptr, "factor"); @@ -3826,7 +3833,7 @@ static void gp_smooth_stroke(bContext *C, wmOperator *op) } /* helper: Count how many points need to be inserted */ -static int gp_count_subdivision_cuts(bGPDstroke *gps) +static int gpencil_count_subdivision_cuts(bGPDstroke *gps) { bGPDspoint *pt; int i; @@ -3844,7 +3851,7 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps) return totnewpoints; } -static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_subdivide_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDspoint *temp_points; @@ -3863,7 +3870,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op) if (gps->flag & GP_STROKE_SELECT) { /* loop as many times as cuts */ for (int s = 0; s < cuts; s++) { - totnewpoints = gp_count_subdivision_cuts(gps); + totnewpoints = gpencil_count_subdivision_cuts(gps); if (totnewpoints == 0) { continue; } @@ -3963,7 +3970,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op) GP_EDITABLE_STROKES_END(gpstroke_iter); /* smooth stroke */ - gp_smooth_stroke(C, op); + gpencil_smooth_stroke(C, op); /* notifiers */ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -3984,8 +3991,8 @@ void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot) "them"; /* api callbacks */ - ot->exec = gp_stroke_subdivide_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_subdivide_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4011,7 +4018,7 @@ void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot) } /* ** simplify stroke *** */ -static int gp_stroke_simplify_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_simplify_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); float factor = RNA_float_get(op->ptr, "factor"); @@ -4047,8 +4054,8 @@ void GPENCIL_OT_stroke_simplify(wmOperatorType *ot) ot->description = "Simplify selected stroked reducing number of points"; /* api callbacks */ - ot->exec = gp_stroke_simplify_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_simplify_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4060,7 +4067,7 @@ void GPENCIL_OT_stroke_simplify(wmOperatorType *ot) } /* ** simplify stroke using fixed algorithm *** */ -static int gp_stroke_simplify_fixed_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_simplify_fixed_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); int steps = RNA_int_get(op->ptr, "step"); @@ -4097,8 +4104,8 @@ void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot) ot->description = "Simplify selected stroked reducing number of points using fixed algorithm"; /* api callbacks */ - ot->exec = gp_stroke_simplify_fixed_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_simplify_fixed_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4111,7 +4118,7 @@ void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot) } /* ** Resample stroke *** */ -static int gp_stroke_sample_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_sample_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); const float length = RNA_float_get(op->ptr, "length"); @@ -4146,8 +4153,8 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot) ot->description = "Sample stroke points to predefined segment length"; /* api callbacks */ - ot->exec = gp_stroke_sample_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_sample_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4164,7 +4171,7 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot) /** \name Stroke Trim Operator * \{ */ -static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4221,8 +4228,8 @@ void GPENCIL_OT_stroke_trim(wmOperatorType *ot) ot->description = "Trim selected stroke to first loop or intersection"; /* api callbacks */ - ot->exec = gp_stroke_trim_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_trim_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4243,7 +4250,7 @@ typedef enum eGP_SeparateModes { GP_SEPARATE_LAYER, } eGP_SeparateModes; -static int gp_stroke_separate_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) { Base *base_new; Main *bmain = CTX_data_main(C); @@ -4277,7 +4284,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) /* Create a new object. */ /* Take into account user preferences for duplicating actions. */ - short dupflag = (U.dupflag & USER_DUP_ACT); + const eDupli_ID_Flags dupflag = (U.dupflag & USER_DUP_ACT); base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_prev, dupflag); ob_dst = base_new->object; @@ -4347,10 +4354,12 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) } /* delete selected points from destination stroke */ - gp_stroke_delete_tagged_points(gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, 0); + gpencil_stroke_delete_tagged_points( + gpf_dst, gps_dst, NULL, GP_SPOINT_SELECT, false, 0); /* delete selected points from origin stroke */ - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); + gpencil_stroke_delete_tagged_points( + gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); } /* selected strokes mode */ else if (mode == GP_SEPARATE_STROKE) { @@ -4441,8 +4450,8 @@ void GPENCIL_OT_stroke_separate(wmOperatorType *ot) /* callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = gp_stroke_separate_exec; - ot->poll = gp_strokes_edit3d_poll; + ot->exec = gpencil_stroke_separate_exec; + ot->poll = gpencil_strokes_edit3d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4457,7 +4466,7 @@ void GPENCIL_OT_stroke_separate(wmOperatorType *ot) /** \name Stroke Split Operator * \{ */ -static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_stroke_split_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4505,10 +4514,10 @@ static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op)) } /* delete selected points from destination stroke */ - gp_stroke_delete_tagged_points(gpf, gps_dst, NULL, GP_SPOINT_SELECT, true, 0); + gpencil_stroke_delete_tagged_points(gpf, gps_dst, NULL, GP_SPOINT_SELECT, true, 0); /* delete selected points from origin stroke */ - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); + gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_SELECT, false, 0); } } /* select again tagged points */ @@ -4546,8 +4555,8 @@ void GPENCIL_OT_stroke_split(wmOperatorType *ot) ot->description = "Split selected points as new stroke on same frame"; /* callbacks */ - ot->exec = gp_stroke_split_exec; - ot->poll = gp_strokes_edit3d_poll; + ot->exec = gpencil_stroke_split_exec; + ot->poll = gpencil_strokes_edit3d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4559,7 +4568,7 @@ void GPENCIL_OT_stroke_split(wmOperatorType *ot) /** \name Stroke Smooth Operator * \{ */ -static int gp_stroke_smooth_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_smooth_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4568,7 +4577,7 @@ static int gp_stroke_smooth_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - gp_smooth_stroke(C, op); + gpencil_smooth_stroke(C, op); /* notifiers */ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -4587,8 +4596,8 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot) ot->description = "Smooth selected strokes"; /* api callbacks */ - ot->exec = gp_stroke_smooth_exec; - ot->poll = gp_active_layer_poll; + ot->exec = gpencil_stroke_smooth_exec; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -4631,8 +4640,8 @@ static bool gpencil_test_lasso(bGPDstroke *gps, const struct GP_SelectLassoUserData *data = user_data; bGPDspoint pt2; int x0, y0; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy(gsc, gps, &pt2, &x0, &y0); /* test if in lasso */ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) && BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX)); @@ -4688,7 +4697,8 @@ static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke pt->flag &= ~GP_SPOINT_TAG; } } - gp_stroke_delete_tagged_points(hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1); + gpencil_stroke_delete_tagged_points( + hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1); } } @@ -4715,7 +4725,7 @@ static int gpencil_cutter_lasso_select(bContext *C, } /* init space conversion stuff */ - gp_point_conversion_init(C, &gsc); + gpencil_point_conversion_init(C, &gsc); /* deselect all strokes first */ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { @@ -4877,7 +4887,7 @@ bool ED_object_gpencil_exit(struct Main *bmain, Object *ob) /** \name Merge By Distance Operator * \{ */ -static bool gp_merge_by_distance_poll(bContext *C) +static bool gpencil_merge_by_distance_poll(bContext *C) { Object *ob = CTX_data_active_object(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { @@ -4893,7 +4903,7 @@ static bool gp_merge_by_distance_poll(bContext *C) return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL)); } -static int gp_merge_by_distance_exec(bContext *C, wmOperator *op) +static int gpencil_merge_by_distance_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -4930,8 +4940,8 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot) ot->description = "Merge points by distance"; /* api callbacks */ - ot->exec = gp_merge_by_distance_exec; - ot->poll = gp_merge_by_distance_poll; + ot->exec = gpencil_merge_by_distance_exec; + ot->poll = gpencil_merge_by_distance_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 502097a0678..168693ff517 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -162,13 +162,13 @@ typedef struct tGPDfill { } tGPDfill; /* draw a given stroke using same thickness and color for all points */ -static void gp_draw_basic_stroke(tGPDfill *tgpf, - bGPDstroke *gps, - const float diff_mat[4][4], - const bool cyclic, - const float ink[4], - const int flag, - const float thershold) +static void gpencil_draw_basic_stroke(tGPDfill *tgpf, + bGPDstroke *gps, + const float diff_mat[4][4], + const bool cyclic, + const float ink[4], + const int flag, + const float thershold) { bGPDspoint *points = gps->points; @@ -223,7 +223,7 @@ static void gp_draw_basic_stroke(tGPDfill *tgpf, } /* loop all layers */ -static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4]) +static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) { /* duplicated: etempFlags */ enum { @@ -298,19 +298,19 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4]) /* normal strokes */ if ((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) || (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH)) { - ED_gp_draw_fill(&tgpw); + ED_gpencil_draw_fill(&tgpw); } /* 3D Lines with basic shapes and invisible lines */ if ((tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) || (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH)) { - gp_draw_basic_stroke(tgpf, - gps, - tgpw.diff_mat, - gps->flag & GP_STROKE_CYCLIC, - ink, - tgpf->flag, - tgpf->fill_threshold); + gpencil_draw_basic_stroke(tgpf, + gps, + tgpw.diff_mat, + gps->flag & GP_STROKE_CYCLIC, + ink, + tgpf->flag, + tgpf->fill_threshold); } } } @@ -319,7 +319,7 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4]) } /* draw strokes in offscreen buffer */ -static bool gp_render_offscreen(tGPDfill *tgpf) +static bool gpencil_render_offscreen(tGPDfill *tgpf) { bool is_ortho = false; float winmat[4][4]; @@ -410,7 +410,7 @@ static bool gp_render_offscreen(tGPDfill *tgpf) /* draw strokes */ float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f}; - gp_draw_datablock(tgpf, ink); + gpencil_draw_datablock(tgpf, ink); GPU_matrix_pop_projection(); GPU_matrix_pop(); @@ -472,15 +472,16 @@ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) } } -/* check if the size of the leak is narrow to determine if the stroke is closed +/** + * Check if the size of the leak is narrow to determine if the stroke is closed * this is used for strokes with small gaps between them to get a full fill * and do not get a full screen fill. * - * \param ibuf: Image pixel data - * \param maxpixel: Maximum index - * \param limit: Limit of pixels to analyze - * \param index: Index of current pixel - * \param type: 0-Horizontal 1-Vertical + * \param ibuf: Image pixel data. + * \param maxpixel: Maximum index. + * \param limit: Limit of pixels to analyze. + * \param index: Index of current pixel. + * \param type: 0-Horizontal 1-Vertical. */ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type) { @@ -576,11 +577,12 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index return (bool)(t_a && t_b); } -/* Boundary fill inside strokes +/** + * Boundary fill inside strokes * Fills the space created by a set of strokes using the stroke color as the boundary * of the shape to fill. * - * \param tgpf: Temporary fill data + * \param tgpf: Temporary fill data. */ static void gpencil_boundaryfill_area(tGPDfill *tgpf) { @@ -665,62 +667,6 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf) BLI_stack_free(stack); } -/* Check if there are some pixel not filled with green. If no points, means nothing to fill. */ -static bool UNUSED_FUNCTION(gpencil_check_borders)(tGPDfill *tgpf) -{ - ImBuf *ibuf; - void *lock; - ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock); - int idx; - int pixel = 0; - float color[4]; - bool found = false; - - /* horizontal lines */ - for (idx = 0; idx < ibuf->x; idx++) { - /* bottom line */ - get_pixel(ibuf, idx, color); - if (color[1] != 1.0f) { - found = true; - break; - } - /* top line */ - pixel = idx + (ibuf->x * (ibuf->y - 1)); - get_pixel(ibuf, pixel, color); - if (color[1] != 1.0f) { - found = true; - break; - } - } - if (!found) { - /* vertical lines */ - for (idx = 0; idx < ibuf->y; idx++) { - /* left line */ - get_pixel(ibuf, ibuf->x * idx, color); - if (color[1] != 1.0f) { - found = true; - break; - } - /* right line */ - pixel = ibuf->x * idx + (ibuf->x - 1); - get_pixel(ibuf, pixel, color); - if (color[1] != 1.0f) { - found = true; - break; - } - } - } - - /* release ibuf */ - if (ibuf) { - BKE_image_release_ibuf(tgpf->ima, ibuf, lock); - } - - tgpf->ima->id.tag |= LIB_TAG_DOIT; - - return found; -} - /* Set a border to create image limits. */ static void gpencil_set_borders(tGPDfill *tgpf, const bool transparent) { @@ -1137,12 +1083,12 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) for (int i = 0; i < tgpf->sbuffer_used && point2D; i++, point2D++, pt++) { /* convert screen-coordinates to 3D coordinates */ - gp_stroke_convertcoords_tpoint(tgpf->scene, - tgpf->region, - tgpf->ob, - point2D, - tgpf->depth_arr ? tgpf->depth_arr + i : NULL, - &pt->x); + gpencil_stroke_convertcoords_tpoint(tgpf->scene, + tgpf->region, + tgpf->ob, + point2D, + tgpf->depth_arr ? tgpf->depth_arr + i : NULL, + &pt->x); pt->pressure = 1.0f; pt->strength = 1.0f; @@ -1183,14 +1129,14 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0)) { float origin[3]; ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin); - ED_gp_project_stroke_to_plane( + ED_gpencil_project_stroke_to_plane( tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1); } /* if parented change position relative to parent object */ for (int a = 0; a < tgpf->sbuffer_used; a++) { pt = &gps->points[a]; - gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpl, pt); + gpencil_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpl, pt); } /* if camera view, reproject flat to view to avoid perspective effect */ @@ -1223,7 +1169,7 @@ static void gpencil_draw_boundary_lines(const bContext *UNUSED(C), tGPDfill *tgp return; } const float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f}; - gp_draw_datablock(tgpf, ink); + gpencil_draw_datablock(tgpf, ink); } /* Drawing callback for modal operator in 3d mode */ @@ -1266,7 +1212,7 @@ static bool gpencil_fill_poll(bContext *C) } /* Allocate memory and initialize values */ -static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op)) +static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) { tGPDfill *tgpf = MEM_callocN(sizeof(tGPDfill), "GPencil Fill Data"); @@ -1399,7 +1345,7 @@ static int gpencil_fill_init(bContext *C, wmOperator *op) } /* check context */ - tgpf = op->customdata = gp_session_init_fill(C, op); + tgpf = op->customdata = gpencil_session_init_fill(C, op); if (tgpf == NULL) { /* something wasn't set correctly in context */ gpencil_fill_exit(C, op); @@ -1499,7 +1445,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) tgpf->active_cfra = CFRA; /* render screen to temp image */ - if (gp_render_offscreen(tgpf)) { + if (gpencil_render_offscreen(tgpf)) { /* Set red borders to create a external limit. */ gpencil_set_borders(tgpf, true); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 473913c5459..bd697dbc768 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -248,7 +248,7 @@ typedef struct tGPDprimitive { } tGPDprimitive; /* Modal Operator Drawing Callbacks ------------------------ */ -void ED_gp_draw_fill(struct tGPDdraw *tgpw); +void ED_gpencil_draw_fill(struct tGPDdraw *tgpw); /* ***************************************************** */ /* Internal API */ @@ -272,83 +272,85 @@ typedef struct GP_SpaceConversion { float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */ } GP_SpaceConversion; -bool gp_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1); +bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1); -void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc); +void gpencil_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc); -void gp_point_to_xy(const GP_SpaceConversion *gsc, - const struct bGPDstroke *gps, - const struct bGPDspoint *pt, - int *r_x, - int *r_y); +void gpencil_point_to_xy(const GP_SpaceConversion *gsc, + const struct bGPDstroke *gps, + const struct bGPDspoint *pt, + int *r_x, + int *r_y); -void gp_point_to_xy_fl(const GP_SpaceConversion *gsc, - const bGPDstroke *gps, - const bGPDspoint *pt, - float *r_x, - float *r_y); +void gpencil_point_to_xy_fl(const GP_SpaceConversion *gsc, + const bGPDstroke *gps, + const bGPDspoint *pt, + float *r_x, + float *r_y); -void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt); +void gpencil_point_to_parent_space(const bGPDspoint *pt, + const float diff_mat[4][4], + bGPDspoint *r_pt); /** * Change points position relative to parent object */ -void gp_apply_parent(struct Depsgraph *depsgraph, - struct Object *obact, - bGPDlayer *gpl, - bGPDstroke *gps); +void gpencil_apply_parent(struct Depsgraph *depsgraph, + struct Object *obact, + bGPDlayer *gpl, + bGPDstroke *gps); /** * Change point position relative to parent object */ -void gp_apply_parent_point(struct Depsgraph *depsgraph, - struct Object *obact, - bGPDlayer *gpl, - bGPDspoint *pt); +void gpencil_apply_parent_point(struct Depsgraph *depsgraph, + struct Object *obact, + bGPDlayer *gpl, + bGPDspoint *pt); -void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, - const short flag, - const float pt[3], - float xy[2]); +void gpencil_point_3d_to_xy(const GP_SpaceConversion *gsc, + const short flag, + const float pt[3], + float xy[2]); -bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, - struct Scene *scene, - const float screen_co[2], - float r_out[3]); +bool gpencil_point_xy_to_3d(const GP_SpaceConversion *gsc, + struct Scene *scene, + const float screen_co[2], + float r_out[3]); /* helper to convert 2d to 3d */ -void gp_stroke_convertcoords_tpoint(struct Scene *scene, - struct ARegion *region, - struct Object *ob, - const struct tGPspoint *point2D, - float *depth, - float out[3]); +void gpencil_stroke_convertcoords_tpoint(struct Scene *scene, + struct ARegion *region, + struct Object *ob, + const struct tGPspoint *point2D, + float *depth, + float out[3]); /* Poll Callbacks ------------------------------------ */ /* gpencil_utils.c */ -bool gp_add_poll(struct bContext *C); -bool gp_active_layer_poll(struct bContext *C); -bool gp_active_brush_poll(struct bContext *C); -bool gp_brush_crt_presets_poll(bContext *C); +bool gpencil_add_poll(struct bContext *C); +bool gpencil_active_layer_poll(struct bContext *C); +bool gpencil_active_brush_poll(struct bContext *C); +bool gpencil_brush_create_presets_poll(bContext *C); /* Copy/Paste Buffer --------------------------------- */ /* gpencil_edit.c */ -extern ListBase gp_strokes_copypastebuf; +extern ListBase gpencil_strokes_copypastebuf; /* Build a map for converting between old colornames and destination-color-refs */ -struct GHash *gp_copybuf_validate_colormap(struct bContext *C); +struct GHash *gpencil_copybuf_validate_colormap(struct bContext *C); /* Stroke Editing ------------------------------------ */ -void gp_stroke_delete_tagged_points(bGPDframe *gpf, - bGPDstroke *gps, - bGPDstroke *next_stroke, - int tag_flags, - bool select, - int limit); -int gp_delete_selected_point_wrap(bContext *C); +void gpencil_stroke_delete_tagged_points(bGPDframe *gpf, + bGPDstroke *gps, + bGPDstroke *next_stroke, + int tag_flags, + bool select, + int limit); +int gpencil_delete_selected_point_wrap(bContext *C); -void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide); +void gpencil_subdivide_stroke(bGPDstroke *gps, const int subdivide); /* Layers Enums -------------------------------------- */ @@ -485,6 +487,8 @@ void GPENCIL_OT_frame_clean_fill(struct wmOperatorType *ot); void GPENCIL_OT_frame_clean_loose(struct wmOperatorType *ot); void GPENCIL_OT_convert(struct wmOperatorType *ot); +void GPENCIL_OT_bake_mesh_animation(struct wmOperatorType *ot); + void GPENCIL_OT_image_to_grease_pencil(struct wmOperatorType *ot); enum { diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 5cb49600d05..5e653187edb 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -100,10 +100,10 @@ static bool gpencil_view3d_poll(bContext *C) } /* Perform interpolation */ -static void gp_interpolate_update_points(const bGPDstroke *gps_from, - const bGPDstroke *gps_to, - bGPDstroke *new_stroke, - float factor) +static void gpencil_interpolate_update_points(const bGPDstroke *gps_from, + const bGPDstroke *gps_to, + bGPDstroke *new_stroke, + float factor) { /* update points */ for (int i = 0; i < new_stroke->totpoints; i++) { @@ -121,7 +121,7 @@ static void gp_interpolate_update_points(const bGPDstroke *gps_from, /* ****************** Interpolate Interactive *********************** */ /* Helper: free all temp strokes for display. */ -static void gp_interpolate_free_temp_strokes(bGPDframe *gpf) +static void gpencil_interpolate_free_temp_strokes(bGPDframe *gpf) { if (gpf == NULL) { return; @@ -136,9 +136,11 @@ static void gp_interpolate_free_temp_strokes(bGPDframe *gpf) } /* Helper: Untag all strokes. */ -static void gp_interpolate_untag_strokes(bGPDframe *gpf) +static void gpencil_interpolate_untag_strokes(bGPDframe *gpf) { - BLI_assert(gpf != NULL); + if (gpf == NULL) { + return; + } LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (gps->flag & GP_STROKE_TAG) { @@ -148,7 +150,7 @@ static void gp_interpolate_untag_strokes(bGPDframe *gpf) } /* Helper: Update all strokes interpolated */ -static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) +static void gpencil_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) { bGPdata *gpd = tgpi->gpd; const float shift = tgpi->shift; @@ -158,7 +160,7 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) bGPDframe *gpf = tgpil->gpl->actframe; /* Free temp strokes. */ - gp_interpolate_free_temp_strokes(gpf); + gpencil_interpolate_free_temp_strokes(gpf); LISTBASE_FOREACH (bGPDstroke *, new_stroke, &tgpil->interFrame->strokes) { bGPDstroke *gps_from, *gps_to; @@ -176,7 +178,7 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) /* update points position */ if ((gps_from) && (gps_to)) { - gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); + gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, factor); /* Add temp strokes. */ if (gpf) { @@ -193,7 +195,7 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) } /* Helper: Verify valid strokes for interpolation */ -static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) +static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd) { Object *ob = CTX_data_active_object(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -243,7 +245,7 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) } /* Helper: Create internal strokes interpolated */ -static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) +static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) { bGPdata *gpd = tgpi->gpd; bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C); @@ -262,6 +264,14 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { tGPDinterpolate_layer *tgpil; + /* Untag strokes to be sure nothing is pending. This must be done for + * all layer because it could be anything tagged and it would be removed + * at the end of the process when all tagged strokes are removed. */ + if (gpl->actframe != NULL) { + gpencil_interpolate_untag_strokes(gpl->actframe); + gpencil_interpolate_untag_strokes(gpl->actframe->next); + } + /* all layers or only active */ if (!(tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && (gpl != active_gpl)) { continue; @@ -278,10 +288,6 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) tgpil->prevFrame = gpl->actframe; tgpil->nextFrame = gpl->actframe->next; - /* Untag interpolated strokes to be sure nothing is pending. */ - gp_interpolate_untag_strokes(tgpil->prevFrame); - gp_interpolate_untag_strokes(tgpil->nextFrame); - BLI_addtail(&tgpi->ilayers, tgpil); /* create a new temporary frame */ @@ -337,7 +343,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) new_stroke->totpoints = gps_to->totpoints; } /* update points position */ - gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor); + gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor); } else { /* need an empty stroke to keep index correct for lookup, but resize to smallest size */ @@ -413,7 +419,7 @@ static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpol /* apply... */ tgpi->shift = RNA_float_get(op->ptr, "shift"); /* update points position */ - gp_interpolate_update_strokes(C, tgpi); + gpencil_interpolate_update_strokes(C, tgpi); } /* ----------------------- */ @@ -433,7 +439,7 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op) /* Clear any temp stroke. */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - gp_interpolate_free_temp_strokes(gpf); + gpencil_interpolate_free_temp_strokes(gpf); } } @@ -454,7 +460,7 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op) } /* Init new temporary interpolation data */ -static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi) +static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi) { ToolSettings *ts = CTX_data_tool_settings(C); bGPdata *gpd = CTX_data_gpencil_data(C); @@ -475,18 +481,18 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte /* set interpolation weight */ tgpi->shift = RNA_float_get(op->ptr, "shift"); /* set layers */ - gp_interpolate_set_points(C, tgpi); + gpencil_interpolate_set_points(C, tgpi); return 1; } /* Allocate memory and initialize values */ -static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op) +static tGPDinterpolate *gpencil_session_init_interpolation(bContext *C, wmOperator *op) { tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data"); /* define initial values */ - gp_interpolate_set_init_values(C, op, tgpi); + gpencil_interpolate_set_init_values(C, op, tgpi); /* return context data for running operator */ return tgpi; @@ -498,7 +504,7 @@ static int gpencil_interpolate_init(bContext *C, wmOperator *op) tGPDinterpolate *tgpi; /* check context */ - tgpi = op->customdata = gp_session_init_interpolation(C, op); + tgpi = op->customdata = gpencil_session_init_interpolation(C, op); if (tgpi == NULL) { /* something wasn't set correctly in context */ gpencil_interpolate_exit(C, op); @@ -540,7 +546,7 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent } /* need editable strokes */ - if (!gp_interpolate_check_todo(C, gpd)) { + if (!gpencil_interpolate_check_todo(C, gpd)) { BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable strokes"); return OPERATOR_CANCELLED; } @@ -731,7 +737,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) /* ****************** Interpolate Sequence *********************** */ /* Helper: Perform easing equation calculations for GP interpolation operator */ -static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_settings, float time) +static float gpencil_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_settings, float time) { const float begin = 0.0f; const float change = 1.0f; @@ -1008,7 +1014,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) } else if (ipo_settings->type >= GP_IPO_BACK) { /* easing equation... */ - factor = gp_interpolate_seq_easing_calc(ipo_settings, factor); + factor = gpencil_interpolate_seq_easing_calc(ipo_settings, factor); } /* create new strokes data with interpolated points reading original stroke */ @@ -1064,7 +1070,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) } /* update points position */ - gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); + gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, factor); /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(new_stroke); diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index e71bf2098dd..cf806e68837 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -132,7 +132,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode); /* stroke */ - bGPDstroke *gps = BKE_gpencil_stroke_new(ob->actcol - 1, totpoints, brush->size); + bGPDstroke *gps = BKE_gpencil_stroke_new(MAX2(ob->actcol - 1, 0), totpoints, brush->size); gps->flag |= GP_STROKE_SELECT; if (cyclic) { @@ -178,7 +178,7 @@ static void gpencil_dissolve_points(bContext *C) } LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0); + gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0); } } CTX_DATA_END; @@ -431,7 +431,7 @@ static int gpencil_analyze_strokes(tGPencilPointCache *src_array, return last; } -static bool gp_strokes_merge_poll(bContext *C) +static bool gpencil_strokes_merge_poll(bContext *C) { /* only supported with grease pencil objects */ Object *ob = CTX_data_active_object(C); @@ -462,7 +462,7 @@ static bool gp_strokes_merge_poll(bContext *C) return (CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0) && ED_operator_view3d_active(C); } -static int gp_stroke_merge_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_merge_exec(bContext *C, wmOperator *op) { const int mode = RNA_enum_get(op->ptr, "mode"); const bool clear_point = RNA_boolean_get(op->ptr, "clear_point"); @@ -546,8 +546,8 @@ void GPENCIL_OT_stroke_merge(wmOperatorType *ot) ot->description = "Create a new stroke with the selected stroke points"; /* api callbacks */ - ot->exec = gp_stroke_merge_exec; - ot->poll = gp_strokes_merge_poll; + ot->exec = gpencil_stroke_merge_exec; + ot->poll = gpencil_strokes_merge_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -563,7 +563,7 @@ void GPENCIL_OT_stroke_merge(wmOperatorType *ot) } /* Merge similar materials. */ -static bool gp_stroke_merge_material_poll(bContext *C) +static bool gpencil_stroke_merge_material_poll(bContext *C) { /* only supported with grease pencil objects */ Object *ob = CTX_data_active_object(C); @@ -574,7 +574,7 @@ static bool gp_stroke_merge_material_poll(bContext *C) return true; } -static int gp_stroke_merge_material_exec(bContext *C, wmOperator *op) +static int gpencil_stroke_merge_material_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -642,8 +642,8 @@ void GPENCIL_OT_stroke_merge_material(wmOperatorType *ot) ot->description = "Replace materials in strokes merging similar"; /* api callbacks */ - ot->exec = gp_stroke_merge_material_exec; - ot->poll = gp_stroke_merge_material_poll; + ot->exec = gpencil_stroke_merge_material_exec; + ot->poll = gpencil_stroke_merge_material_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c new file mode 100644 index 00000000000..763f5687edf --- /dev/null +++ b/source/blender/editors/gpencil/gpencil_mesh.c @@ -0,0 +1,404 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008, Blender Foundation + * This is a new part of Blender + * Operator for converting Grease Pencil data to geometry + */ + +/** \file + * \ingroup edgpencil + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "DNA_gpencil_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BKE_context.h" +#include "BKE_duplilist.h" +#include "BKE_global.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_scene.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "ED_gpencil.h" +#include "ED_transform_snap_object_context.h" + +#include "gpencil_intern.h" + +/* Check frame_end is always > start frame! */ +static void gpencil_bake_set_frame_end(struct Main *UNUSED(main), + struct Scene *UNUSED(scene), + struct PointerRNA *ptr) +{ + int frame_start = RNA_int_get(ptr, "frame_start"); + int frame_end = RNA_int_get(ptr, "frame_end"); + + if (frame_end <= frame_start) { + RNA_int_set(ptr, "frame_end", frame_start + 1); + } +} + +/* Extract mesh animation to Grease Pencil. */ +static bool gpencil_bake_mesh_animation_poll(bContext *C) +{ + if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT) { + return false; + } + + /* Only if the current view is 3D View. */ + ScrArea *area = CTX_wm_area(C); + return (area && area->spacetype); +} + +typedef struct GpBakeOb { + struct GPBakelist *next, *prev; + Object *ob; +} GpBakeOb; + +static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list) +{ + GpBakeOb *elem = NULL; + ListBase *lb; + DupliObject *dob; + lb = object_duplilist(depsgraph, scene, ob); + for (dob = lb->first; dob; dob = dob->next) { + if (dob->ob->type != OB_MESH) { + continue; + } + elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem->ob = dob->ob; + BLI_addtail(list, elem); + } + + free_object_duplilist(lb); +} + +static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list) +{ + GpBakeOb *elem = NULL; + + /* Add active object. In some files this could not be in selected array. */ + Object *obact = CTX_data_active_object(C); + + if (obact->type == OB_MESH) { + elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem->ob = obact; + BLI_addtail(list, elem); + } + /* Add duplilist. */ + else if (obact->type == OB_EMPTY) { + gpencil_bake_duplilist(depsgraph, scene, obact, list); + } + + /* Add other selected objects. */ + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + if (ob == obact) { + continue; + } + /* Add selected meshes.*/ + if (ob->type == OB_MESH) { + elem = MEM_callocN(sizeof(GpBakeOb), __func__); + elem->ob = ob; + BLI_addtail(list, elem); + } + + /* Add duplilist. */ + if (ob->type == OB_EMPTY) { + gpencil_bake_duplilist(depsgraph, scene, obact, list); + } + } + CTX_DATA_END; +} + +static void gpencil_bake_free_ob_list(ListBase *list) +{ + LISTBASE_FOREACH_MUTABLE (GpBakeOb *, elem, list) { + MEM_SAFE_FREE(elem); + } +} + +static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ARegion *region = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + Object *ob_gpencil = NULL; + + ListBase list = {NULL, NULL}; + gpencil_bake_ob_list(C, depsgraph, scene, &list); + + /* Cannot check this in poll because the active object changes. */ + if (list.first == NULL) { + BKE_report(op->reports, RPT_INFO, "No valid object selected"); + gpencil_bake_free_ob_list(&list); + return OPERATOR_CANCELLED; + } + + /* Grab all relevant settings. */ + const int step = RNA_int_get(op->ptr, "step"); + + const int frame_start = (scene->r.sfra > RNA_int_get(op->ptr, "frame_start")) ? + scene->r.sfra : + RNA_int_get(op->ptr, "frame_start"); + + const int frame_end = (scene->r.efra < RNA_int_get(op->ptr, "frame_end")) ? + scene->r.efra : + RNA_int_get(op->ptr, "frame_end"); + + const float angle = RNA_float_get(op->ptr, "angle"); + const int thickness = RNA_int_get(op->ptr, "thickness"); + const bool use_seams = RNA_boolean_get(op->ptr, "seams"); + const bool use_faces = RNA_boolean_get(op->ptr, "faces"); + const float offset = RNA_float_get(op->ptr, "offset"); + const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start; + char target[64]; + RNA_string_get(op->ptr, "target", target); + const int project_type = RNA_enum_get(op->ptr, "project_type"); + + /* Create a new grease pencil object in origin. */ + bool newob = false; + if (STREQ(target, "*NEW")) { + ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; + float loc[3] = {0.0f, 0.0f, 0.0f}; + ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); + newob = true; + } + else { + ob_gpencil = BLI_findstring(&bmain->objects, target, offsetof(ID, name) + 2); + } + + if ((ob_gpencil == NULL) || (ob_gpencil->type != OB_GPENCIL)) { + BKE_report(op->reports, RPT_ERROR, "Target grease pencil object not valid"); + gpencil_bake_free_ob_list(&list); + return OPERATOR_CANCELLED; + } + + bGPdata *gpd = (bGPdata *)ob_gpencil->data; + gpd->draw_mode = (project_type == GP_REPROJECT_KEEP) ? GP_DRAWMODE_3D : GP_DRAWMODE_2D; + + /* Set cursor to indicate working. */ + WM_cursor_wait(1); + + GP_SpaceConversion gsc = {NULL}; + SnapObjectContext *sctx = NULL; + if (project_type != GP_REPROJECT_KEEP) { + /* Init space conversion stuff. */ + gpencil_point_conversion_init(C, &gsc); + /* Init snap context for geometry projection. */ + sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C)); + + /* Tag all existing strokes to avoid reprojections. */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + gps->flag |= GP_STROKE_TAG; + } + } + } + } + + /* Loop all frame range. */ + int oldframe = (int)DEG_get_ctime(depsgraph); + int key = -1; + for (int i = frame_start; i < frame_end + 1; i++) { + key++; + /* Jump if not step limit but include last frame always. */ + if ((key % step != 0) && (i != frame_end)) { + continue; + } + + /* Move scene to new frame. */ + CFRA = i; + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + + /* Loop all objects in the list. */ + LISTBASE_FOREACH (GpBakeOb *, elem, &list) { + Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob); + + /* Generate strokes. */ + BKE_gpencil_convert_mesh(bmain, + depsgraph, + scene, + ob_gpencil, + elem->ob, + angle, + thickness, + offset, + ob_eval->obmat, + frame_offset, + use_seams, + use_faces); + + /* Reproject all untaged created strokes. */ + if (project_type != GP_REPROJECT_KEEP) { + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + bGPDframe *gpf = gpl->actframe; + if (gpf != NULL) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if ((gps->flag & GP_STROKE_TAG) == 0) { + ED_gpencil_stroke_reproject( + depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false); + gps->flag |= GP_STROKE_TAG; + } + } + } + } + } + } + } + + /* Return scene frame state and DB to original state. */ + CFRA = oldframe; + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + + /* Remove unused materials. */ + int actcol = ob_gpencil->actcol; + for (int slot = 1; slot <= ob_gpencil->totcol; slot++) { + while (slot <= ob_gpencil->totcol && !BKE_object_material_slot_used(ob_gpencil->data, slot)) { + ob_gpencil->actcol = slot; + BKE_object_material_slot_remove(CTX_data_main(C), ob_gpencil); + + if (actcol >= slot) { + actcol--; + } + } + } + ob_gpencil->actcol = actcol; + + /* Untag all strokes. */ + if (project_type != GP_REPROJECT_KEEP) { + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + gps->flag &= ~GP_STROKE_TAG; + } + } + } + } + + /* Free memory. */ + gpencil_bake_free_ob_list(&list); + if (sctx != NULL) { + ED_transform_snap_object_context_destroy(sctx); + } + + /* notifiers */ + if (newob) { + DEG_relations_tag_update(bmain); + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + + /* Reset cursor. */ + WM_cursor_wait(0); + + /* done */ + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) +{ + static const EnumPropertyItem reproject_type[] = { + {GP_REPROJECT_KEEP, "KEEP", 0, "No Reproject", ""}, + {GP_REPROJECT_FRONT, "FRONT", 0, "Front", "Reproject the strokes using the X-Z plane"}, + {GP_REPROJECT_SIDE, "SIDE", 0, "Side", "Reproject the strokes using the Y-Z plane"}, + {GP_REPROJECT_TOP, "TOP", 0, "Top", "Reproject the strokes using the X-Y plane"}, + {GP_REPROJECT_VIEW, + "VIEW", + 0, + "View", + "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint " + "using 'Cursor' Stroke Placement"}, + {GP_REPROJECT_CURSOR, + "CURSOR", + 0, + "Cursor", + "Reproject the strokes using the orientation of 3D cursor"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Bake Mesh Animation to Grease Pencil"; + ot->idname = "GPENCIL_OT_bake_mesh_animation"; + ot->description = "Bake Mesh Animation to Grease Pencil strokes"; + + /* callbacks */ + ot->exec = gpencil_bake_mesh_animation_exec; + ot->poll = gpencil_bake_mesh_animation_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_int( + ot->srna, "frame_start", 1, 1, 100000, "Start Frame", "The start frame", 1, 100000); + + prop = RNA_def_int( + ot->srna, "frame_end", 250, 1, 100000, "End Frame", "The end frame of animation", 1, 100000); + RNA_def_property_update_runtime(prop, gpencil_bake_set_frame_end); + + prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100); + + prop = RNA_def_float_rotation(ot->srna, + "angle", + 0, + NULL, + DEG2RADF(0.0f), + DEG2RADF(180.0f), + "Threshold Angle", + "Threshold to determine ends of the strokes", + DEG2RADF(0.0f), + DEG2RADF(180.0f)); + RNA_def_property_float_default(prop, DEG2RADF(70.0f)); + + RNA_def_int(ot->srna, "thickness", 1, 1, 100, "Thickness", "", 1, 100); + RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); + RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); + RNA_def_float_distance( + ot->srna, "offset", 0.001f, 0.0, 100.0, "Offset", "Offset strokes from fill", 0.0, 100.00); + RNA_def_int(ot->srna, "frame_target", 1, 1, 100000, "Frame Target", "", 1, 100000); + RNA_def_string(ot->srna, + "target", + "*NEW", + 64, + "Target Object", + "Target grease pencil object name. Leave empty for new object"); + + RNA_def_enum(ot->srna, "project_type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", ""); +} diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 94c86572fd3..e645668ef1c 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -63,21 +63,21 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf) /* ==================== */ /* Poll callback for stroke editing mode */ -static bool gp_stroke_editmode_poll(bContext *C) +static bool gpencil_stroke_editmode_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); return (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)); } /* Poll callback for stroke painting mode */ -static bool gp_stroke_paintmode_poll(bContext *C) +static bool gpencil_stroke_paintmode_poll(bContext *C) { /* TODO: limit this to mode, but review 2D editors */ bGPdata *gpd = CTX_data_gpencil_data(C); return (gpd && (gpd->flag & GP_DATA_STROKE_PAINTMODE)); } -static bool gp_stroke_paintmode_poll_with_tool(bContext *C, const char gpencil_tool) +static bool gpencil_stroke_paintmode_poll_with_tool(bContext *C, const char gpencil_tool) { /* TODO: limit this to mode, but review 2D editors */ bGPdata *gpd = CTX_data_gpencil_data(C); @@ -95,7 +95,7 @@ static bool gp_stroke_paintmode_poll_with_tool(bContext *C, const char gpencil_t WM_toolsystem_active_tool_is_brush(C) && (brush->gpencil_tool == gpencil_tool)); } -static bool gp_stroke_vertexmode_poll_with_tool(bContext *C, const char gpencil_vertex_tool) +static bool gpencil_stroke_vertexmode_poll_with_tool(bContext *C, const char gpencil_vertex_tool) { bGPdata *gpd = CTX_data_gpencil_data(C); if (!gpd) { @@ -113,7 +113,7 @@ static bool gp_stroke_vertexmode_poll_with_tool(bContext *C, const char gpencil_ (brush->gpencil_vertex_tool == gpencil_vertex_tool)); } -static bool gp_stroke_sculptmode_poll_with_tool(bContext *C, const char gpencil_sculpt_tool) +static bool gpencil_stroke_sculptmode_poll_with_tool(bContext *C, const char gpencil_sculpt_tool) { bGPdata *gpd = CTX_data_gpencil_data(C); if (!gpd) { @@ -131,7 +131,7 @@ static bool gp_stroke_sculptmode_poll_with_tool(bContext *C, const char gpencil_ (brush->gpencil_sculpt_tool == gpencil_sculpt_tool)); } -static bool gp_stroke_weightmode_poll_with_tool(bContext *C, const char gpencil_weight_tool) +static bool gpencil_stroke_weightmode_poll_with_tool(bContext *C, const char gpencil_weight_tool) { bGPdata *gpd = CTX_data_gpencil_data(C); if (!gpd) { @@ -150,31 +150,31 @@ static bool gp_stroke_weightmode_poll_with_tool(bContext *C, const char gpencil_ } /* Poll callback for stroke painting (draw brush) */ -static bool gp_stroke_paintmode_draw_poll(bContext *C) +static bool gpencil_stroke_paintmode_draw_poll(bContext *C) { - return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_DRAW); + return gpencil_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_DRAW); } /* Poll callback for stroke painting (erase brush) */ -static bool gp_stroke_paintmode_erase_poll(bContext *C) +static bool gpencil_stroke_paintmode_erase_poll(bContext *C) { - return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_ERASE); + return gpencil_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_ERASE); } /* Poll callback for stroke painting (fill) */ -static bool gp_stroke_paintmode_fill_poll(bContext *C) +static bool gpencil_stroke_paintmode_fill_poll(bContext *C) { - return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_FILL); + return gpencil_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_FILL); } /* Poll callback for stroke painting (tint) */ -static bool gp_stroke_paintmode_tint_poll(bContext *C) +static bool gpencil_stroke_paintmode_tint_poll(bContext *C) { - return gp_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_TINT); + return gpencil_stroke_paintmode_poll_with_tool(C, GPAINT_TOOL_TINT); } /* Poll callback for stroke sculpting mode */ -static bool gp_stroke_sculptmode_poll(bContext *C) +static bool gpencil_stroke_sculptmode_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); Object *ob = CTX_data_active_object(C); @@ -194,7 +194,7 @@ static bool gp_stroke_sculptmode_poll(bContext *C) } /* Poll callback for stroke weight paint mode */ -static bool gp_stroke_weightmode_poll(bContext *C) +static bool gpencil_stroke_weightmode_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); Object *ob = CTX_data_active_object(C); @@ -207,7 +207,7 @@ static bool gp_stroke_weightmode_poll(bContext *C) } /* Poll callback for stroke vertex paint mode */ -static bool gp_stroke_vertexmode_poll(bContext *C) +static bool gpencil_stroke_vertexmode_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); Object *ob = CTX_data_active_object(C); @@ -220,91 +220,91 @@ static bool gp_stroke_vertexmode_poll(bContext *C) } /* Poll callback for vertex painting (draw) */ -static bool gp_stroke_vertexmode_draw_poll(bContext *C) +static bool gpencil_stroke_vertexmode_draw_poll(bContext *C) { - return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_DRAW); + return gpencil_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_DRAW); } /* Poll callback for vertex painting (blur) */ -static bool gp_stroke_vertexmode_blur_poll(bContext *C) +static bool gpencil_stroke_vertexmode_blur_poll(bContext *C) { - return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_BLUR); + return gpencil_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_BLUR); } /* Poll callback for vertex painting (average) */ -static bool gp_stroke_vertexmode_average_poll(bContext *C) +static bool gpencil_stroke_vertexmode_average_poll(bContext *C) { - return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_AVERAGE); + return gpencil_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_AVERAGE); } /* Poll callback for vertex painting (smear) */ -static bool gp_stroke_vertexmode_smear_poll(bContext *C) +static bool gpencil_stroke_vertexmode_smear_poll(bContext *C) { - return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_SMEAR); + return gpencil_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_SMEAR); } /* Poll callback for vertex painting (replace) */ -static bool gp_stroke_vertexmode_replace_poll(bContext *C) +static bool gpencil_stroke_vertexmode_replace_poll(bContext *C) { - return gp_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_REPLACE); + return gpencil_stroke_vertexmode_poll_with_tool(C, GPVERTEX_TOOL_REPLACE); } /* Poll callback for sculpt (Smooth) */ -static bool gp_stroke_sculptmode_smooth_poll(bContext *C) +static bool gpencil_stroke_sculptmode_smooth_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_SMOOTH); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_SMOOTH); } /* Poll callback for sculpt (Thickness) */ -static bool gp_stroke_sculptmode_thickness_poll(bContext *C) +static bool gpencil_stroke_sculptmode_thickness_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_THICKNESS); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_THICKNESS); } /* Poll callback for sculpt (Strength) */ -static bool gp_stroke_sculptmode_strength_poll(bContext *C) +static bool gpencil_stroke_sculptmode_strength_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_STRENGTH); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_STRENGTH); } /* Poll callback for sculpt (Grab) */ -static bool gp_stroke_sculptmode_grab_poll(bContext *C) +static bool gpencil_stroke_sculptmode_grab_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_GRAB); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_GRAB); } /* Poll callback for sculpt (Push) */ -static bool gp_stroke_sculptmode_push_poll(bContext *C) +static bool gpencil_stroke_sculptmode_push_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_PUSH); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_PUSH); } /* Poll callback for sculpt (Twist) */ -static bool gp_stroke_sculptmode_twist_poll(bContext *C) +static bool gpencil_stroke_sculptmode_twist_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_TWIST); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_TWIST); } /* Poll callback for sculpt (Pinch) */ -static bool gp_stroke_sculptmode_pinch_poll(bContext *C) +static bool gpencil_stroke_sculptmode_pinch_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_PINCH); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_PINCH); } /* Poll callback for sculpt (Randomize) */ -static bool gp_stroke_sculptmode_randomize_poll(bContext *C) +static bool gpencil_stroke_sculptmode_randomize_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_RANDOMIZE); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_RANDOMIZE); } /* Poll callback for sculpt (Clone) */ -static bool gp_stroke_sculptmode_clone_poll(bContext *C) +static bool gpencil_stroke_sculptmode_clone_poll(bContext *C) { - return gp_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_CLONE); + return gpencil_stroke_sculptmode_poll_with_tool(C, GPSCULPT_TOOL_CLONE); } /* Poll callback for weight paint (Draw) */ -static bool gp_stroke_weightmode_draw_poll(bContext *C) +static bool gpencil_stroke_weightmode_draw_poll(bContext *C) { - return gp_stroke_weightmode_poll_with_tool(C, GPWEIGHT_TOOL_DRAW); + return gpencil_stroke_weightmode_poll_with_tool(C, GPWEIGHT_TOOL_DRAW); } /* Stroke Editing Keymap - Only when editmode is enabled */ @@ -313,35 +313,35 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0); /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */ - keymap->poll = gp_stroke_editmode_poll; + keymap->poll = gpencil_stroke_editmode_poll; } /* keys for draw with a drawing brush (no fill) */ static void ed_keymap_gpencil_painting_draw(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0); - keymap->poll = gp_stroke_paintmode_draw_poll; + keymap->poll = gpencil_stroke_paintmode_draw_poll; } /* keys for draw with a eraser brush (erase) */ static void ed_keymap_gpencil_painting_erase(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Erase)", 0, 0); - keymap->poll = gp_stroke_paintmode_erase_poll; + keymap->poll = gpencil_stroke_paintmode_erase_poll; } /* keys for draw with a fill brush */ static void ed_keymap_gpencil_painting_fill(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Fill)", 0, 0); - keymap->poll = gp_stroke_paintmode_fill_poll; + keymap->poll = gpencil_stroke_paintmode_fill_poll; } /* keys for draw with a tint brush */ static void ed_keymap_gpencil_painting_tint(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Tint)", 0, 0); - keymap->poll = gp_stroke_paintmode_tint_poll; + keymap->poll = gpencil_stroke_paintmode_tint_poll; } /* Stroke Painting Keymap - Only when paintmode is enabled */ @@ -349,7 +349,7 @@ static void ed_keymap_gpencil_painting(wmKeyConfig *keyconf) { /* set poll callback - so that this keymap only gets enabled when stroke paintmode is enabled */ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint Mode", 0, 0); - keymap->poll = gp_stroke_paintmode_poll; + keymap->poll = gpencil_stroke_paintmode_poll; } /* Stroke Sculpting Keymap - Only when sculptmode is enabled */ @@ -357,7 +357,7 @@ static void ed_keymap_gpencil_sculpting(wmKeyConfig *keyconf) { /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt Mode", 0, 0); - keymap->poll = gp_stroke_sculptmode_poll; + keymap->poll = gpencil_stroke_sculptmode_poll; } /* Stroke Weight Paint Keymap - Only when weight is enabled */ @@ -365,106 +365,106 @@ static void ed_keymap_gpencil_weightpainting(wmKeyConfig *keyconf) { /* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight Mode", 0, 0); - keymap->poll = gp_stroke_weightmode_poll; + keymap->poll = gpencil_stroke_weightmode_poll; } static void ed_keymap_gpencil_vertexpainting(wmKeyConfig *keyconf) { /* set poll callback - so that this keymap only gets enabled when stroke vertex is enabled */ wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex Mode", 0, 0); - keymap->poll = gp_stroke_vertexmode_poll; + keymap->poll = gpencil_stroke_vertexmode_poll; } /* keys for vertex with a draw brush */ static void ed_keymap_gpencil_vertexpainting_draw(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Draw)", 0, 0); - keymap->poll = gp_stroke_vertexmode_draw_poll; + keymap->poll = gpencil_stroke_vertexmode_draw_poll; } /* keys for vertex with a blur brush */ static void ed_keymap_gpencil_vertexpainting_blur(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Blur)", 0, 0); - keymap->poll = gp_stroke_vertexmode_blur_poll; + keymap->poll = gpencil_stroke_vertexmode_blur_poll; } /* keys for vertex with a average brush */ static void ed_keymap_gpencil_vertexpainting_average(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Average)", 0, 0); - keymap->poll = gp_stroke_vertexmode_average_poll; + keymap->poll = gpencil_stroke_vertexmode_average_poll; } /* keys for vertex with a smear brush */ static void ed_keymap_gpencil_vertexpainting_smear(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Smear)", 0, 0); - keymap->poll = gp_stroke_vertexmode_smear_poll; + keymap->poll = gpencil_stroke_vertexmode_smear_poll; } /* keys for vertex with a replace brush */ static void ed_keymap_gpencil_vertexpainting_replace(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Replace)", 0, 0); - keymap->poll = gp_stroke_vertexmode_replace_poll; + keymap->poll = gpencil_stroke_vertexmode_replace_poll; } /* keys for sculpt with a smooth brush */ static void ed_keymap_gpencil_sculptpainting_smooth(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Smooth)", 0, 0); - keymap->poll = gp_stroke_sculptmode_smooth_poll; + keymap->poll = gpencil_stroke_sculptmode_smooth_poll; } /* keys for sculpt with a thickness brush */ static void ed_keymap_gpencil_sculptpainting_thickness(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Thickness)", 0, 0); - keymap->poll = gp_stroke_sculptmode_thickness_poll; + keymap->poll = gpencil_stroke_sculptmode_thickness_poll; } /* keys for sculpt with a strength brush */ static void ed_keymap_gpencil_sculptpainting_strength(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Strength)", 0, 0); - keymap->poll = gp_stroke_sculptmode_strength_poll; + keymap->poll = gpencil_stroke_sculptmode_strength_poll; } /* keys for sculpt with a grab brush */ static void ed_keymap_gpencil_sculptpainting_grab(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Grab)", 0, 0); - keymap->poll = gp_stroke_sculptmode_grab_poll; + keymap->poll = gpencil_stroke_sculptmode_grab_poll; } /* keys for sculpt with a push brush */ static void ed_keymap_gpencil_sculptpainting_push(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Push)", 0, 0); - keymap->poll = gp_stroke_sculptmode_push_poll; + keymap->poll = gpencil_stroke_sculptmode_push_poll; } /* keys for sculpt with a twist brush */ static void ed_keymap_gpencil_sculptpainting_twist(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Twist)", 0, 0); - keymap->poll = gp_stroke_sculptmode_twist_poll; + keymap->poll = gpencil_stroke_sculptmode_twist_poll; } /* keys for sculpt with a pinch brush */ static void ed_keymap_gpencil_sculptpainting_pinch(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Pinch)", 0, 0); - keymap->poll = gp_stroke_sculptmode_pinch_poll; + keymap->poll = gpencil_stroke_sculptmode_pinch_poll; } /* keys for sculpt with a randomize brush */ static void ed_keymap_gpencil_sculptpainting_randomize(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Randomize)", 0, 0); - keymap->poll = gp_stroke_sculptmode_randomize_poll; + keymap->poll = gpencil_stroke_sculptmode_randomize_poll; } /* keys for sculpt with a clone brush */ static void ed_keymap_gpencil_sculptpainting_clone(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Clone)", 0, 0); - keymap->poll = gp_stroke_sculptmode_clone_poll; + keymap->poll = gpencil_stroke_sculptmode_clone_poll; } /* keys for weight with a draw brush */ static void ed_keymap_gpencil_weightpainting_draw(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight (Draw)", 0, 0); - keymap->poll = gp_stroke_weightmode_draw_poll; + keymap->poll = gpencil_stroke_weightmode_draw_poll; } /* ==================== */ @@ -603,6 +603,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_frame_clean_loose); WM_operatortype_append(GPENCIL_OT_convert); + WM_operatortype_append(GPENCIL_OT_bake_mesh_animation); WM_operatortype_append(GPENCIL_OT_image_to_grease_pencil); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index a9eb94498ad..95133244dfb 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -272,7 +272,7 @@ typedef struct tGPsdata { /* minimum length of new segment before new point can be added */ #define MIN_EUCLIDEAN_PX (U.gp_euclideandist) -static void gp_update_cache(bGPdata *gpd) +static void gpencil_update_cache(bGPdata *gpd) { if (gpd) { DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -280,19 +280,19 @@ static void gp_update_cache(bGPdata *gpd) } } -static void gp_stroke_added_enable(tGPsdata *p) +static void gpencil_stroke_added_enable(tGPsdata *p) { BLI_assert(p->gpf->strokes.last != NULL); p->flags |= GP_PAINTFLAG_STROKEADDED; /* drawing batch cache is dirty now */ - gp_update_cache(p->gpd); + gpencil_update_cache(p->gpd); } /* ------ */ /* Forward defines for some functions... */ -static void gp_session_validatebuffer(tGPsdata *p); +static void gpencil_session_validatebuffer(tGPsdata *p); /* ******************************************* */ /* Context Wrangling... */ @@ -352,7 +352,7 @@ static bool gpencil_project_check(tGPsdata *p) /* Utilities --------------------------------- */ /* get the reference point for stroke-point conversions */ -static void gp_get_3d_reference(tGPsdata *p, float vec[3]) +static void gpencil_get_3d_reference(tGPsdata *p, float vec[3]) { Object *ob = NULL; if (p->ownerPtr.type == &RNA_Object) { @@ -363,7 +363,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) /* Stroke Editing ---------------------------- */ /* check if the current mouse position is suitable for adding a new point */ -static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float mvalo[2]) +static bool gpencil_stroke_filtermval(tGPsdata *p, const float mval[2], float mvalo[2]) { Brush *brush = p->brush; int dx = (int)fabsf(mval[0] - mvalo[0]); @@ -410,7 +410,7 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float mvalo[2 } /* reproject stroke to plane locked to axis in 3d cursor location */ -static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps) +static void gpencil_reproject_toplane(tGPsdata *p, bGPDstroke *gps) { bGPdata *gpd = p->gpd; Object *obact = (Object *)p->ownerPtr.data; @@ -430,13 +430,15 @@ static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps) } /* get drawing origin */ - gp_get_3d_reference(p, origin); - ED_gp_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1); + gpencil_get_3d_reference(p, origin); + ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1); } /* convert screen-coordinates to buffer-coordinates */ -/* XXX this method needs a total overhaul! */ -static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[3], float *depth) +static void gpencil_stroke_convertcoords(tGPsdata *p, + const float mval[2], + float out[3], + float *depth) { bGPdata *gpd = p->gpd; @@ -476,7 +478,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ * 3D-coordinates using the 3D-cursor as reference. In general, this * works OK, but it could of course be improved. */ - gp_get_3d_reference(p, rvec); + gpencil_get_3d_reference(p, rvec); zfac = ED_view3d_calc_zfac(p->region->regiondata, rvec, NULL); if (ED_view3d_project_float_global(p->region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == @@ -492,7 +494,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ } /* Apply jitter to stroke point. */ -static void gp_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude) +static void gpencil_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude) { const float axis[2] = {0.0f, 1.0f}; /* Jitter is applied perpendicular to the mouse movement vector (2D space). */ @@ -513,8 +515,8 @@ static void gp_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude) } } -/* apply pressure change depending of the angle of the stroke to simulate a pen with shape */ -static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const float mval[2]) +/* Apply pressure change depending of the angle of the stroke to simulate a pen with shape */ +static void gpencil_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const float mval[2]) { float mvec[2]; float sen = brush->gpencil_settings->draw_angle_factor; /* sensitivity */ @@ -551,16 +553,17 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa } } -/* Apply smooth to buffer while drawing +/** + * Apply smooth to buffer while drawing * to smooth point C, use 2 before (A, B) and current point (D): * - * A----B-----C------D + * `A----B-----C------D` * * \param p: Temp data * \param inf: Influence factor * \param idx: Index of the last point (need minimum 3 points in the array) */ -static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) +static void gpencil_smooth_buffer(tGPsdata *p, float inf, int idx) { bGPdata *gpd = p->gpd; GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide; @@ -624,7 +627,7 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) } /* Helper: Apply smooth to segment from Index to Index */ -static void gp_smooth_segment(bGPdata *gpd, const float inf, int from_idx, int to_idx) +static void gpencil_smooth_segment(bGPdata *gpd, const float inf, int from_idx, int to_idx) { const short num_points = to_idx - from_idx; /* Do nothing if not enough points to smooth out */ @@ -691,12 +694,12 @@ static void gp_smooth_segment(bGPdata *gpd, const float inf, int from_idx, int t } } -static void gp_apply_randomness(tGPsdata *p, - BrushGpencilSettings *brush_settings, - tGPspoint *pt, - const bool press, - const bool strength, - const bool uv) +static void gpencil_apply_randomness(tGPsdata *p, + BrushGpencilSettings *brush_settings, + tGPspoint *pt, + const bool press, + const bool strength, + const bool uv) { bGPdata *gpd = p->gpd; GpRandomSettings random_settings = p->random_settings; @@ -764,7 +767,10 @@ static void gp_apply_randomness(tGPsdata *p, } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime) +static short gpencil_stroke_addpoint(tGPsdata *p, + const float mval[2], + float pressure, + double curtime) { bGPdata *gpd = p->gpd; Brush *brush = p->brush; @@ -860,16 +866,16 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* FIXME the +2 means minimum jitter is 4 which is a bit strange for UX. */ const float exp_factor = brush_settings->draw_jitter + 2.0f; const float fac = rand * square_f(exp_factor) * jitpress; - gp_brush_jitter(gpd, pt, fac); + gpencil_brush_jitter(gpd, pt, fac); } /* Apply other randomness. */ - gp_apply_randomness(p, brush_settings, pt, true, true, true); + gpencil_apply_randomness(p, brush_settings, pt, true, true, true); } /* apply angle of stroke to brush size */ if (brush_settings->draw_angle_factor != 0.0f) { - gp_brush_angle(gpd, brush, pt, mval); + gpencil_brush_angle(gpd, brush, pt, mval); } /* point time */ @@ -882,14 +888,14 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* get origin to reproject point */ float origin[3]; - gp_get_3d_reference(p, origin); + gpencil_get_3d_reference(p, origin); /* reproject current */ ED_gpencil_tpoint_to_point(p->region, origin, pt, &spt); - ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt); + ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(p->region, origin, ptb, &spt2); - ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2); + ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2); p->totpixlen += len_v3v3(&spt.x, &spt2.x); pt->uv_fac = p->totpixlen; } @@ -904,9 +910,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* Smooth while drawing previous points with a reduction factor for previous. */ if (brush->gpencil_settings->active_smooth > 0.0f) { for (int s = 0; s < 3; s++) { - gp_smooth_buffer(p, - brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f), - gpd->runtime.sbuffer_used - s); + gpencil_smooth_buffer(p, + brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f), + gpd->runtime.sbuffer_used - s); } } @@ -920,7 +926,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure } /* make a new stroke from the buffer data */ -static void gp_stroke_newfrombuffer(tGPsdata *p) +static void gpencil_stroke_newfrombuffer(tGPsdata *p) { bGPdata *gpd = p->gpd; bGPDlayer *gpl = p->gpl; @@ -1000,7 +1006,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->dvert = NULL; /* drawing batch cache is dirty now */ - gp_update_cache(p->gpd); + gpencil_update_cache(p->gpd); /* set pointer to first non-initialized point */ pt = gps->points + (gps->totpoints - totelem); if (gps->dvert != NULL) { @@ -1018,7 +1024,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) ptc = gpd->runtime.sbuffer; /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gpencil_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure and time */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; @@ -1052,7 +1058,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1); /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gpencil_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* copy pressure and time */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; @@ -1077,11 +1083,11 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } /* reproject to plane (only in 3d space) */ - gp_reproject_toplane(p, gps); + gpencil_reproject_toplane(p, gps); pt = gps->points; for (i = 0; i < gps->totpoints; i++, pt++) { /* if parented change position relative to parent object */ - gp_apply_parent_point(depsgraph, obact, gpl, pt); + gpencil_apply_parent_point(depsgraph, obact, gpl, pt); } /* if camera view, reproject flat to view to avoid perspective effect */ @@ -1172,7 +1178,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used && ptc; i++, ptc++, pt++) { /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); + gpencil_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); /* copy pressure and time */ pt->pressure = ptc->pressure; @@ -1194,7 +1200,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* subdivide and smooth the stroke */ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) && (subdivide > 0)) { - gp_subdivide_stroke(gps, subdivide); + gpencil_subdivide_stroke(gps, subdivide); } /* Smooth stroke after subdiv - only if there's something to do for each iteration, @@ -1229,9 +1235,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } /* reproject to plane (only in 3d space) */ - gp_reproject_toplane(p, gps); + gpencil_reproject_toplane(p, gps); /* change position relative to parent object */ - gp_apply_parent(depsgraph, obact, gpl, gps); + gpencil_apply_parent(depsgraph, obact, gpl, gps); /* if camera view, reproject flat to view to avoid perspective effect */ if (is_camera) { ED_gpencil_project_stroke_to_view(p->C, p->gpl, gps); @@ -1284,12 +1290,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gps); - gp_stroke_added_enable(p); + gpencil_stroke_added_enable(p); } /* --- 'Eraser' for 'Paint' Tool ------ */ -/* which which point is infront (result should only be used for comparison) */ +/** + * Which which point is in front (result should only be used for comparison). + */ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) { if (rv3d->is_persp) { @@ -1301,10 +1309,10 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) } /* only erase stroke points that are visible */ -static bool gp_stroke_eraser_is_occluded(tGPsdata *p, - const bGPDspoint *pt, - const int x, - const int y) +static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, + const bGPDspoint *pt, + const int x, + const int y) { Object *obact = (Object *)p->ownerPtr.data; Brush *brush = p->brush; @@ -1346,10 +1354,10 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p, } /* apply a falloff effect to brush strength, based on distance */ -static float gp_stroke_eraser_calc_influence(tGPsdata *p, - const float mval[2], - const int radius, - const int co[2]) +static float gpencil_stroke_eraser_calc_influence(tGPsdata *p, + const float mval[2], + const int radius, + const int co[2]) { Brush *brush = p->brush; /* Linear Falloff... */ @@ -1373,7 +1381,7 @@ static float gp_stroke_eraser_calc_influence(tGPsdata *p, } /* helper to free a stroke */ -static void gp_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps) +static void gpencil_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps) { if (gps->points) { MEM_freeN(gps->points); @@ -1388,7 +1396,7 @@ static void gp_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps) MEM_freeN(gps->triangles); } BLI_freelinkN(&gpf->strokes, gps); - gp_update_cache(gpd); + gpencil_update_cache(gpd); } /** @@ -1396,7 +1404,7 @@ static void gp_free_stroke(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps) * to avoid that segments gets the end points rounded. * The round caps breaks the artistic effect. */ -static void gp_stroke_soft_refine(bGPDstroke *gps) +static void gpencil_stroke_soft_refine(bGPDstroke *gps) { bGPDspoint *pt = NULL; bGPDspoint *pt2 = NULL; @@ -1431,12 +1439,12 @@ static void gp_stroke_soft_refine(bGPDstroke *gps) } /* eraser tool - evaluation per stroke */ -static void gp_stroke_eraser_dostroke(tGPsdata *p, - bGPDframe *gpf, - bGPDstroke *gps, - const float mval[2], - const int radius, - const rcti *rect) +static void gpencil_stroke_eraser_dostroke(tGPsdata *p, + bGPDframe *gpf, + bGPDstroke *gps, + const float mval[2], + const int radius, + const rcti *rect) { Brush *eraser = p->eraser; bGPDspoint *pt0, *pt1, *pt2; @@ -1449,20 +1457,20 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, if (gps->totpoints == 0) { /* just free stroke */ - gp_free_stroke(p->gpd, gpf, gps); + gpencil_free_stroke(p->gpd, gpf, gps); } else if (gps->totpoints == 1) { /* only process if it hasn't been masked out... */ if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) { bGPDspoint pt_temp; - gp_point_to_parent_space(gps->points, p->diff_mat, &pt_temp); - gp_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(gps->points, p->diff_mat, &pt_temp); + gpencil_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]); /* do boundbox check first */ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { /* only check if point is inside */ if (len_v2v2_int(mval_i, pc1) <= radius) { /* free stroke */ - gp_free_stroke(p->gpd, gpf, gps); + gpencil_free_stroke(p->gpd, gpf, gps); } } } @@ -1479,15 +1487,15 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* get points to work with */ pt1 = gps->points + i; bGPDspoint npt; - gp_point_to_parent_space(pt1, p->diff_mat, &npt); - gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(pt1, p->diff_mat, &npt); + gpencil_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]); /* do boundbox check first */ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { /* only check if point is inside */ if (len_v2v2_int(mval_i, pc1) <= radius) { /* free stroke */ - gp_free_stroke(p->gpd, gpf, gps); + gpencil_free_stroke(p->gpd, gpf, gps); return; } } @@ -1531,19 +1539,19 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, bGPDspoint npt; if (pt0) { - gp_point_to_parent_space(pt0, p->diff_mat, &npt); - gp_point_to_xy(&p->gsc, gps, &npt, &pc0[0], &pc0[1]); + gpencil_point_to_parent_space(pt0, p->diff_mat, &npt); + gpencil_point_to_xy(&p->gsc, gps, &npt, &pc0[0], &pc0[1]); } else { /* avoid null values */ copy_v2_v2_int(pc0, pc1); } - gp_point_to_parent_space(pt1, p->diff_mat, &npt); - gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(pt1, p->diff_mat, &npt); + gpencil_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]); - gp_point_to_parent_space(pt2, p->diff_mat, &npt); - gp_point_to_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]); + gpencil_point_to_parent_space(pt2, p->diff_mat, &npt); + gpencil_point_to_xy(&p->gsc, gps, &npt, &pc2[0], &pc2[1]); /* Check that point segment of the boundbox of the eraser stroke */ if (((!ELEM(V2D_IS_CLIPPED, pc0[0], pc0[1])) && BLI_rcti_isect_pt(rect, pc0[0], pc0[1])) || @@ -1553,10 +1561,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { - if ((gp_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) || - (gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || - (gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { + if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { + if ((gpencil_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) || + (gpencil_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || + (gpencil_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { /* Point is affected: */ /* Adjust thickness * - Influence of eraser falls off with distance from the middle of the eraser @@ -1570,18 +1578,18 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, float influence = 0.0f; if (pt0) { - influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc0); + influence = gpencil_stroke_eraser_calc_influence(p, mval, radius, pc0); pt0->strength -= influence * strength * f_strength * 0.5f; CLAMP_MIN(pt0->strength, 0.0f); pt0->pressure -= influence * strength * f_thickness * 0.5f; } - influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc1); + influence = gpencil_stroke_eraser_calc_influence(p, mval, radius, pc1); pt1->strength -= influence * strength * f_strength; CLAMP_MIN(pt1->strength, 0.0f); pt1->pressure -= influence * strength * f_thickness; - influence = gp_stroke_eraser_calc_influence(p, mval, radius, pc2); + influence = gpencil_stroke_eraser_calc_influence(p, mval, radius, pc2); pt2->strength -= influence * strength * f_strength * 0.5f; CLAMP_MIN(pt2->strength, 0.0f); pt2->pressure -= influence * strength * f_thickness * 0.5f; @@ -1604,9 +1612,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, } } else { - pt1->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc1) * strength; - pt2->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc2) * strength * - 0.5f; + pt1->pressure -= gpencil_stroke_eraser_calc_influence(p, mval, radius, pc1) * + strength; + pt2->pressure -= gpencil_stroke_eraser_calc_influence(p, mval, radius, pc2) * + strength * 0.5f; } /* 2) Tag any point with overly low influence for removal in the next pass */ @@ -1630,17 +1639,17 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* if soft eraser, must analyze points to be sure the stroke ends * don't get rounded */ if (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_SOFT) { - gp_stroke_soft_refine(gps); + gpencil_stroke_soft_refine(gps); } - gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0); + gpencil_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0); } - gp_update_cache(p->gpd); + gpencil_update_cache(p->gpd); } } /* erase strokes which fall under the eraser strokes */ -static void gp_stroke_doeraser(tGPsdata *p) +static void gpencil_stroke_doeraser(tGPsdata *p) { rcti rect; Brush *brush = p->brush; @@ -1710,7 +1719,7 @@ static void gp_stroke_doeraser(tGPsdata *p) * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) */ if (ED_gpencil_stroke_can_use_direct(p->area, gps)) { - gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect); + gpencil_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect); } } } @@ -1720,7 +1729,7 @@ static void gp_stroke_doeraser(tGPsdata *p) /* Sketching Operator */ /* clear the session buffers (call this before AND after a paint operation) */ -static void gp_session_validatebuffer(tGPsdata *p) +static void gpencil_session_validatebuffer(tGPsdata *p) { bGPdata *gpd = p->gpd; Brush *brush = p->brush; @@ -1742,7 +1751,7 @@ static void gp_session_validatebuffer(tGPsdata *p) } /* helper to get default eraser and create one if no eraser brush */ -static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts) +static Brush *gpencil_get_default_eraser(Main *bmain, ToolSettings *ts) { Brush *brush_dft = NULL; Paint *paint = &ts->gp_paint->paint; @@ -1784,7 +1793,7 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts) } /* helper to set default eraser and disable others */ -static void gp_set_default_eraser(Main *bmain, Brush *brush_dft) +static void gpencil_set_default_eraser(Main *bmain, Brush *brush_dft) { if (brush_dft == NULL) { return; @@ -1803,7 +1812,7 @@ static void gp_set_default_eraser(Main *bmain, Brush *brush_dft) } /* initialize a drawing brush */ -static void gp_init_drawing_brush(bContext *C, tGPsdata *p) +static void gpencil_init_drawing_brush(bContext *C, tGPsdata *p) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -1831,13 +1840,13 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) /* assign to temp tGPsdata */ p->brush = paint->brush; if (paint->brush->gpencil_tool != GPAINT_TOOL_ERASE) { - p->eraser = gp_get_default_eraser(p->bmain, ts); + p->eraser = gpencil_get_default_eraser(p->bmain, ts); } else { p->eraser = paint->brush; } /* set new eraser as default */ - gp_set_default_eraser(p->bmain, p->eraser); + gpencil_set_default_eraser(p->bmain, p->eraser); /* use radius of eraser */ p->radius = (short)p->eraser->size; @@ -1849,7 +1858,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) } /* initialize a paint brush and a default color if not exist */ -static void gp_init_colors(tGPsdata *p) +static void gpencil_init_colors(tGPsdata *p) { bGPdata *gpd = p->gpd; Brush *brush = p->brush; @@ -1862,7 +1871,7 @@ static void gp_init_colors(tGPsdata *p) } /* (re)init new painting data */ -static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p) +static bool gpencil_session_initdata(bContext *C, wmOperator *op, tGPsdata *p) { Main *bmain = CTX_data_main(C); bGPdata **gpd_ptr = NULL; @@ -1959,15 +1968,15 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p) } /* clear out buffer (stored in gp-data), in case something contaminated it */ - gp_session_validatebuffer(p); + gpencil_session_validatebuffer(p); /* set brush and create a new one if null */ - gp_init_drawing_brush(C, p); + gpencil_init_drawing_brush(C, p); /* setup active color */ /* region where paint was originated */ int totcol = p->ob->totcol; - gp_init_colors(p); + gpencil_init_colors(p); /* check whether the material was newly added */ if (totcol != p->ob->totcol) { @@ -1987,7 +1996,7 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p) } /* init new painting session */ -static tGPsdata *gp_session_initpaint(bContext *C, wmOperator *op) +static tGPsdata *gpencil_session_initpaint(bContext *C, wmOperator *op) { tGPsdata *p = NULL; @@ -1997,7 +2006,7 @@ static tGPsdata *gp_session_initpaint(bContext *C, wmOperator *op) /* Try to initialize context data * WARNING: This may not always succeed (e.g. using GP in an annotation-only context) */ - if (gp_session_initdata(C, op, p) == 0) { + if (gpencil_session_initdata(C, op, p) == 0) { /* Invalid state - Exit * NOTE: It should be safe to just free the data, since failing context checks should * only happen when no data has been allocated. @@ -2016,7 +2025,7 @@ static tGPsdata *gp_session_initpaint(bContext *C, wmOperator *op) } /* cleanup after a painting session */ -static void gp_session_cleanup(tGPsdata *p) +static void gpencil_session_cleanup(tGPsdata *p) { bGPdata *gpd = (p) ? p->gpd : NULL; @@ -2038,7 +2047,7 @@ static void gp_session_cleanup(tGPsdata *p) p->inittime = 0.0; } -static void gp_session_free(tGPsdata *p) +static void gpencil_session_free(tGPsdata *p) { if (p->rng != NULL) { BLI_rng_free(p->rng); @@ -2048,7 +2057,9 @@ static void gp_session_free(tGPsdata *p) } /* init new stroke */ -static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph) +static void gpencil_paint_initstroke(tGPsdata *p, + eGPencil_PaintModes paintmode, + Depsgraph *depsgraph) { Scene *scene = p->scene; ToolSettings *ts = scene->toolsettings; @@ -2209,12 +2220,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps gpd_eval->runtime.sbuffer_brush = p->gpd->runtime.sbuffer_brush; } else { - gp_update_cache(p->gpd); + gpencil_update_cache(p->gpd); } } /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */ -static void gp_paint_strokeend(tGPsdata *p) +static void gpencil_paint_strokeend(tGPsdata *p) { ToolSettings *ts = p->scene->toolsettings; /* for surface sketching, need to set the right OpenGL context stuff so that @@ -2232,22 +2243,22 @@ static void gp_paint_strokeend(tGPsdata *p) /* check if doing eraser or not */ if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* transfer stroke to frame */ - gp_stroke_newfrombuffer(p); + gpencil_stroke_newfrombuffer(p); } /* clean up buffer now */ - gp_session_validatebuffer(p); + gpencil_session_validatebuffer(p); } /* finish off stroke painting operation */ -static void gp_paint_cleanup(tGPsdata *p) +static void gpencil_paint_cleanup(tGPsdata *p) { /* p->gpd==NULL happens when stroke failed to initialize, * for example when GP is hidden in current space (sergey) */ if (p->gpd) { /* finish off a stroke */ - gp_paint_strokeend(p); + gpencil_paint_strokeend(p); } /* "unlock" frame */ @@ -2357,19 +2368,19 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) else { /* drawing batch cache is dirty now */ bGPdata *gpd = CTX_data_gpencil_data(C); - gp_update_cache(gpd); + gpencil_update_cache(gpd); } /* clear undo stack */ gpencil_undo_finish(); /* cleanup */ - gp_paint_cleanup(p); - gp_session_cleanup(p); + gpencil_paint_cleanup(p); + gpencil_session_cleanup(p); ED_gpencil_toggle_brush_cursor(C, true, NULL); /* finally, free the temp data */ - gp_session_free(p); + gpencil_session_free(p); p = NULL; } @@ -2399,7 +2410,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) } /* check context */ - p = op->customdata = gp_session_initpaint(C, op); + p = op->customdata = gpencil_session_initpaint(C, op); if ((p == NULL) || (p->status == GP_STATUS_ERROR)) { /* something wasn't set correctly in context */ gpencil_draw_exit(C, op); @@ -2407,7 +2418,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) } /* init painting data */ - gp_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C)); + gpencil_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C)); if (p->status == GP_STATUS_ERROR) { gpencil_draw_exit(C, op); return 0; @@ -2493,10 +2504,10 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p) /* ------------------------------- */ /* Helper to rotate point around origin */ -static void gp_rotate_v2_v2v2fl(float v[2], - const float p[2], - const float origin[2], - const float angle) +static void gpencil_rotate_v2_v2v2fl(float v[2], + const float p[2], + const float origin[2], + const float angle) { float pt[2]; float r[2]; @@ -2506,7 +2517,7 @@ static void gp_rotate_v2_v2v2fl(float v[2], } /* Helper to snap value to grid */ -static float gp_snap_to_grid_fl(float v, const float offset, const float spacing) +static float gpencil_snap_to_grid_fl(float v, const float offset, const float spacing) { if (spacing > 0.0f) { v -= spacing * 0.5f; @@ -2521,25 +2532,25 @@ static float gp_snap_to_grid_fl(float v, const float offset, const float spacing } /* Helper to snap value to grid */ -static void gp_snap_to_rotated_grid_fl(float v[2], - const float origin[2], - const float spacing, - const float angle) +static void gpencil_snap_to_rotated_grid_fl(float v[2], + const float origin[2], + const float spacing, + const float angle) { - gp_rotate_v2_v2v2fl(v, v, origin, -angle); - v[1] = gp_snap_to_grid_fl(v[1], origin[1], spacing); - gp_rotate_v2_v2v2fl(v, v, origin, angle); + gpencil_rotate_v2_v2v2fl(v, v, origin, -angle); + v[1] = gpencil_snap_to_grid_fl(v[1], origin[1], spacing); + gpencil_rotate_v2_v2v2fl(v, v, origin, angle); } /* get reference point - screen coords to buffer coords */ -static void gp_origin_set(wmOperator *op, const int mval[2]) +static void gpencil_origin_set(wmOperator *op, const int mval[2]) { tGPsdata *p = op->customdata; GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide; float origin[2]; float point[3]; copy_v2fl_v2i(origin, mval); - gp_stroke_convertcoords(p, origin, point, NULL); + gpencil_stroke_convertcoords(p, origin, point, NULL); if (guide->reference_point == GP_GUIDE_REF_CUSTOM) { copy_v3_v3(guide->location, point); } @@ -2549,7 +2560,7 @@ static void gp_origin_set(wmOperator *op, const int mval[2]) } /* get reference point - buffer coords to screen coords */ -static void gp_origin_get(tGPsdata *p, float origin[2]) +static void gpencil_origin_get(tGPsdata *p, float origin[2]) { GP_Sculpt_Guide *guide = &p->scene->toolsettings->gp_sculpt.guide; float location[3]; @@ -2563,7 +2574,7 @@ static void gp_origin_get(tGPsdata *p, float origin[2]) copy_v3_v3(location, p->scene->cursor.location); } GP_SpaceConversion *gsc = &p->gsc; - gp_point_3d_to_xy(gsc, p->gpd->runtime.sbuffer_sflag, location, origin); + gpencil_point_3d_to_xy(gsc, p->gpd->runtime.sbuffer_sflag, location, origin); } /* speed guide initial values */ @@ -2574,7 +2585,7 @@ static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide) float scale = 1.0f; if (rv3d->is_persp) { float vec[3]; - gp_get_3d_reference(p, vec); + gpencil_get_3d_reference(p, vec); mul_m4_v3(rv3d->persmat, vec); scale = vec[2] * rv3d->pixsize; } @@ -2583,7 +2594,7 @@ static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide) } p->guide.spacing = guide->spacing / scale; p->guide.half_spacing = p->guide.spacing * 0.5f; - gp_origin_get(p, p->guide.origin); + gpencil_origin_get(p, p->guide.origin); /* reference for angled snap */ copy_v2_v2(p->guide.unit, p->mvali); @@ -2595,7 +2606,7 @@ static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide) p->guide.origin_distance = len_v2v2(p->mvali, p->guide.origin); if (guide->use_snapping && (guide->spacing > 0.0f)) { - p->guide.origin_distance = gp_snap_to_grid_fl( + p->guide.origin_distance = gpencil_snap_to_grid_fl( p->guide.origin_distance, 0.0f, p->guide.spacing); } @@ -2605,10 +2616,10 @@ static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide) angle = p->guide.origin_angle + guide->angle; angle = fmodf(angle + half_angle, guide->angle_snap); angle -= half_angle; - gp_rotate_v2_v2v2fl(p->guide.rot_point, p->mvali, p->guide.origin, -angle); + gpencil_rotate_v2_v2v2fl(p->guide.rot_point, p->mvali, p->guide.origin, -angle); } else { - gp_rotate_v2_v2v2fl(p->guide.rot_point, p->guide.unit, p->mvali, guide->angle); + gpencil_rotate_v2_v2v2fl(p->guide.rot_point, p->guide.unit, p->mvali, guide->angle); } } @@ -2633,14 +2644,15 @@ static void gpencil_snap_to_guide(const tGPsdata *p, const GP_Sculpt_Guide *guid case GP_GUIDE_PARALLEL: { closest_to_line_v2(point, point, p->mvali, p->guide.rot_point); if (guide->use_snapping && (guide->spacing > 0.0f)) { - gp_snap_to_rotated_grid_fl(point, p->guide.origin, p->guide.spacing, guide->angle); + gpencil_snap_to_rotated_grid_fl(point, p->guide.origin, p->guide.spacing, guide->angle); } break; } case GP_GUIDE_ISO: { closest_to_line_v2(point, point, p->mvali, p->guide.rot_point); if (guide->use_snapping && (guide->spacing > 0.0f)) { - gp_snap_to_rotated_grid_fl(point, p->guide.origin, p->guide.spacing, p->guide.rot_angle); + gpencil_snap_to_rotated_grid_fl( + point, p->guide.origin, p->guide.spacing, p->guide.rot_angle); } break; } @@ -2648,10 +2660,10 @@ static void gpencil_snap_to_guide(const tGPsdata *p, const GP_Sculpt_Guide *guid if (guide->use_snapping && (guide->spacing > 0.0f)) { closest_to_line_v2(point, point, p->mvali, p->guide.rot_point); if (p->straight == STROKE_HORIZONTAL) { - point[1] = gp_snap_to_grid_fl(point[1], p->guide.origin[1], p->guide.spacing); + point[1] = gpencil_snap_to_grid_fl(point[1], p->guide.origin[1], p->guide.spacing); } else { - point[0] = gp_snap_to_grid_fl(point[0], p->guide.origin[0], p->guide.spacing); + point[0] = gpencil_snap_to_grid_fl(point[0], p->guide.origin[0], p->guide.spacing); } } else if (p->straight == STROKE_HORIZONTAL) { @@ -2674,7 +2686,7 @@ static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgra /* handle drawing/erasing -> test for erasing first */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* do 'live' erasing now */ - gp_stroke_doeraser(p); + gpencil_stroke_doeraser(p); /* store used values */ copy_v2_v2(p->mvalo, p->mval); @@ -2682,7 +2694,7 @@ static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgra } /* Only add current point to buffer if mouse moved * (even though we got an event, it might be just noise). */ - else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { + else if (gpencil_stroke_filtermval(p, p->mval, p->mvalo)) { /* if lazy mouse, interpolate the last and current mouse positions */ if (GPENCIL_LAZY_MODE(p->brush, p->shift)) { @@ -2702,26 +2714,26 @@ static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgra } /* try to add point */ - short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); + short ok = gpencil_stroke_addpoint(p, p->mval, p->pressure, p->curtime); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ - gp_paint_strokeend(p); + gpencil_paint_strokeend(p); /* And start a new one!!! Else, projection errors! */ - gp_paint_initstroke(p, p->paintmode, depsgraph); + gpencil_paint_initstroke(p, p->paintmode, depsgraph); /* start a new stroke, starting from previous point */ /* XXX Must manually reset inittime... */ /* XXX We only need to reuse previous point if overflow! */ if (ok == GP_STROKEADD_OVERFLOW) { p->inittime = p->ocurtime; - gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); + gpencil_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); } else { p->inittime = p->curtime; } - gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); + gpencil_stroke_addpoint(p, p->mval, p->pressure, p->curtime); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -2889,13 +2901,13 @@ static void gpencil_draw_apply_event(bContext *C, else { p->guide.rot_angle = DEG2RAD(90); } - gp_rotate_v2_v2v2fl(p->guide.rot_point, p->guide.unit, p->mvali, p->guide.rot_angle); + gpencil_rotate_v2_v2v2fl(p->guide.rot_point, p->guide.unit, p->mvali, p->guide.rot_angle); } else if (ELEM(guide->type, GP_GUIDE_GRID)) { - gp_rotate_v2_v2v2fl(p->guide.rot_point, - p->guide.unit, - p->mvali, - (p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f); + gpencil_rotate_v2_v2v2fl(p->guide.rot_point, + p->guide.unit, + p->mvali, + (p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f); } } @@ -2968,8 +2980,8 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) */ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) { /* TODO: both of these ops can set error-status, but we probably don't need to worry */ - gp_paint_strokeend(p); - gp_paint_initstroke(p, p->paintmode, depsgraph); + gpencil_paint_strokeend(p); + gpencil_paint_initstroke(p, p->paintmode, depsgraph); } } @@ -3227,8 +3239,8 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) } /* we may need to set up paint env again if we're resuming */ - if (gp_session_initdata(C, op, p)) { - gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph_pointer(C)); + if (gpencil_session_initdata(C, op, p)) { + gpencil_paint_initstroke(p, p->paintmode, CTX_data_depsgraph_pointer(C)); } if (p->status != GP_STATUS_ERROR) { @@ -3240,7 +3252,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) } /* Apply pressure change depending of the angle of the stroke for a segment. */ -static void gp_brush_angle_segment(tGPsdata *p, tGPspoint *pt_prev, tGPspoint *pt) +static void gpencil_brush_angle_segment(tGPsdata *p, tGPspoint *pt_prev, tGPspoint *pt) { Brush *brush = p->brush; /* Sensitivity. */ @@ -3284,7 +3296,7 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) /* Apply other randomness to first points. */ for (int i = 0; i < gpd->runtime.sbuffer_used; i++) { tGPspoint *pt = &points[i]; - gp_apply_randomness(p, brush_settings, pt, false, false, true); + gpencil_apply_randomness(p, brush_settings, pt, false, false, true); } return; } @@ -3359,14 +3371,14 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) /* Apply angle of stroke to brush size to interpolated points but slightly attenuated.. */ if (brush_settings->draw_angle_factor != 0.0f) { - gp_brush_angle_segment(p, pt_step, pt); + gpencil_brush_angle_segment(p, pt_step, pt); CLAMP(pt->pressure, pt_prev->pressure * 0.5f, 1.0f); /* Use the previous interpolated point for next segment. */ pt_step = pt; } /* Apply other randomness. */ - gp_apply_randomness(p, brush_settings, pt, false, false, true); + gpencil_apply_randomness(p, brush_settings, pt, false, false, true); a += step; } @@ -3411,7 +3423,7 @@ static void gpencil_add_guide_points(const tGPsdata *p, for (int i = 0; i < segments; i++) { pt = &points[idx_prev + i - 1]; - gp_rotate_v2_v2v2fl(&pt->x, start, p->guide.origin, -a); + gpencil_rotate_v2_v2v2fl(&pt->x, start, p->guide.origin, -a); gpencil_snap_to_guide(p, guide, &pt->x); a += step; @@ -3547,7 +3559,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* set */ case LEFTMOUSE: { if (ELEM(event->val, KM_RELEASE)) { - gp_origin_set(op, event->mval); + gpencil_origin_set(op, event->mval); drawmode = true; } break; @@ -3750,7 +3762,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * the 0.15 value gets a good result in Windows and Linux. */ if (!is_speed_guide && (size_after - size_before > 1)) { for (int r = 0; r < 5; r++) { - gp_smooth_segment(p->gpd, 0.15f, size_before - 1, size_after - 1); + gpencil_smooth_segment(p->gpd, 0.15f, size_before - 1, size_after - 1); } } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 82ae99b30be..6bb9f9628fa 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -111,7 +111,7 @@ /* Core/Shared Utilities */ /* clear the session buffers (call this before AND after a paint operation) */ -static void gp_session_validatebuffer(tGPDprimitive *p) +static void gpencil_session_validatebuffer(tGPDprimitive *p) { bGPdata *gpd = p->gpd; @@ -137,7 +137,7 @@ static void gp_session_validatebuffer(tGPDprimitive *p) } } -static void gp_init_colors(tGPDprimitive *p) +static void gpencil_init_colors(tGPDprimitive *p) { bGPdata *gpd = p->gpd; Brush *brush = p->brush; @@ -196,10 +196,10 @@ static void gpencil_primitive_constrain(tGPDprimitive *tgpi, bool line_mode) } /* Helper to rotate point around origin */ -static void gp_rotate_v2_v2v2fl(float v[2], - const float p[2], - const float origin[2], - const float angle) +static void gpencil_rotate_v2_v2v2fl(float v[2], + const float p[2], + const float origin[2], + const float angle) { float pt[2]; float r[2]; @@ -209,17 +209,17 @@ static void gp_rotate_v2_v2v2fl(float v[2], } /* Helper to rotate line around line center. */ -static void gp_primitive_rotate_line( +static void gpencil_primitive_rotate_line( float va[2], float vb[2], const float a[2], const float b[2], const float angle) { float midpoint[2]; mid_v2_v2v2(midpoint, a, b); - gp_rotate_v2_v2v2fl(va, a, midpoint, angle); - gp_rotate_v2_v2v2fl(vb, b, midpoint, angle); + gpencil_rotate_v2_v2v2fl(va, a, midpoint, angle); + gpencil_rotate_v2_v2v2fl(vb, b, midpoint, angle); } /* Helper to update cps */ -static void gp_primitive_update_cps(tGPDprimitive *tgpi) +static void gpencil_primitive_update_cps(tGPDprimitive *tgpi) { if (!tgpi->curve) { mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end); @@ -233,10 +233,10 @@ static void gp_primitive_update_cps(tGPDprimitive *tgpi) } else if (tgpi->type == GP_STROKE_ARC) { if (tgpi->flip) { - gp_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->start, tgpi->end, M_PI_2); + gpencil_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->start, tgpi->end, M_PI_2); } else { - gp_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->end, tgpi->start, M_PI_2); + gpencil_primitive_rotate_line(tgpi->cp1, tgpi->cp2, tgpi->end, tgpi->start, M_PI_2); } } } @@ -294,7 +294,7 @@ static void gpencil_primitive_allocate_memory(tGPDprimitive *tgpi) /* ****************** Primitive Interactive *********************** */ /* Helper: Create internal strokes primitives data */ -static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) +static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; @@ -378,7 +378,7 @@ static void gpencil_primitive_add_segment(tGPDprimitive *tgpi) } /* Helper: set control point */ -static void gp_primitive_set_cp(tGPDprimitive *tgpi, float p[2], float color[4], int size) +static void gpencil_primitive_set_cp(tGPDprimitive *tgpi, float p[2], float color[4], int size) { if (tgpi->flag == IN_PROGRESS) { return; @@ -500,7 +500,7 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi } /* create a rectangle */ -static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D) +static void gpencil_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D) { float coords[5][2]; @@ -531,20 +531,20 @@ static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D) mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end); float color[4]; UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); if (tgpi->tot_stored_edges) { UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); } else { - gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); } UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->midpoint, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->midpoint, color, SMALL_SIZE_CTL); } /* create a line */ -static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool editable) +static void gpencil_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool editable) { const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges); const float step = 1.0f / (float)(tgpi->tot_edges - 1); @@ -559,24 +559,24 @@ static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool edi if (editable) { float color[4]; UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); if (tgpi->tot_stored_edges) { UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); } else { - gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); } } else { float color[4]; UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); } } /* create an arc */ -static void gp_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D) +static void gpencil_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D) { const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges); const float step = M_PI_2 / (float)(tgpi->tot_edges - 1); @@ -604,20 +604,20 @@ static void gp_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D) } float color[4]; UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); if (tgpi->tot_stored_edges) { UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); } else { - gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); } UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color); - gp_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f); + gpencil_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f); } /* create a bezier */ -static void gp_primitive_bezier(tGPDprimitive *tgpi, tGPspoint *points2D) +static void gpencil_primitive_bezier(tGPDprimitive *tgpi, tGPspoint *points2D) { const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges); const float step = 1.0f / (float)(tgpi->tot_edges - 1); @@ -639,21 +639,21 @@ static void gp_primitive_bezier(tGPDprimitive *tgpi, tGPspoint *points2D) } float color[4]; UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); if (tgpi->tot_stored_edges) { UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL); } else { - gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); } UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color); - gp_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f); - gp_primitive_set_cp(tgpi, tgpi->cp2, color, BIG_SIZE_CTL * 0.9f); + gpencil_primitive_set_cp(tgpi, tgpi->cp1, color, BIG_SIZE_CTL * 0.9f); + gpencil_primitive_set_cp(tgpi, tgpi->cp2, color, BIG_SIZE_CTL * 0.9f); } /* create a circle */ -static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D) +static void gpencil_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D) { const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges); const float step = (2.0f * M_PI) / (float)(tgpi->tot_edges); @@ -674,14 +674,14 @@ static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D) } float color[4]; UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); - gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL); UI_GetThemeColor4fv(TH_REDALERT, color); - gp_primitive_set_cp(tgpi, center, color, SMALL_SIZE_CTL); + gpencil_primitive_set_cp(tgpi, center, color, SMALL_SIZE_CTL); } /* Helper: Update shape of the stroke */ -static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) +static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) { ToolSettings *ts = tgpi->scene->toolsettings; bGPdata *gpd = tgpi->gpd; @@ -715,30 +715,30 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) if (tgpi->tot_edges > 1) { switch (tgpi->type) { case GP_STROKE_BOX: - gp_primitive_rectangle(tgpi, points2D); + gpencil_primitive_rectangle(tgpi, points2D); break; case GP_STROKE_LINE: - gp_primitive_line(tgpi, points2D, true); + gpencil_primitive_line(tgpi, points2D, true); break; case GP_STROKE_POLYLINE: - gp_primitive_line(tgpi, points2D, false); + gpencil_primitive_line(tgpi, points2D, false); break; case GP_STROKE_CIRCLE: - gp_primitive_circle(tgpi, points2D); + gpencil_primitive_circle(tgpi, points2D); break; case GP_STROKE_ARC: - gp_primitive_arc(tgpi, points2D); + gpencil_primitive_arc(tgpi, points2D); break; case GP_STROKE_CURVE: - gp_primitive_bezier(tgpi, points2D); + gpencil_primitive_bezier(tgpi, points2D); default: break; } } /* convert screen-coordinates to 3D coordinates */ - gp_session_validatebuffer(tgpi); - gp_init_colors(tgpi); + gpencil_session_validatebuffer(tgpi); + gpencil_init_colors(tgpi); if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) { BKE_curvemapping_initialize(ts->gp_sculpt.cur_primitive); } @@ -982,12 +982,12 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); /* reproject current */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt); - ED_gp_project_point_to_plane( + ED_gpencil_project_point_to_plane( tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2); - ED_gp_project_point_to_plane( + ED_gpencil_project_point_to_plane( tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x); tpt->uv_fac = tgpi->totpixlen; @@ -1011,7 +1011,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) } /* convert screen-coordinates to 3D coordinates */ - gp_stroke_convertcoords_tpoint( + gpencil_stroke_convertcoords_tpoint( tgpi->scene, tgpi->region, tgpi->ob, p2d, depth_arr ? depth_arr + i : NULL, &pt->x); pt->pressure = pressure; @@ -1036,7 +1036,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) bGPDcontrolpoint *cps = tgpi->gpd->runtime.cp_points; for (int i = 0; i < tgpi->gpd->runtime.tot_cp_points; i++) { bGPDcontrolpoint *cp = &cps[i]; - gp_stroke_convertcoords_tpoint( + gpencil_stroke_convertcoords_tpoint( tgpi->scene, tgpi->region, tgpi->ob, (tGPspoint *)cp, NULL, &cp->x); } } @@ -1045,14 +1045,14 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) if (!is_depth) { float origin[3]; ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); - ED_gp_project_stroke_to_plane( + ED_gpencil_project_stroke_to_plane( tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1); } /* if parented change position relative to parent object */ for (int i = 0; i < gps->totpoints; i++) { bGPDspoint *pt = &gps->points[i]; - gp_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpl, pt); + gpencil_apply_parent_point(tgpi->depsgraph, tgpi->ob, tgpi->gpl, pt); } /* if camera view, reproject flat to view to avoid perspective effect */ @@ -1082,7 +1082,7 @@ static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive tgpi->type = RNA_enum_get(op->ptr, "type"); tgpi->tot_edges = RNA_int_get(op->ptr, "edges"); /* update points position */ - gp_primitive_update_strokes(C, tgpi); + gpencil_primitive_update_strokes(C, tgpi); } /* Initialise mouse points */ @@ -1237,7 +1237,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) tgpi->lock_axis = ts->gp_sculpt.lock_axis; /* set temp layer, frame and stroke */ - gp_primitive_set_initdata(C, tgpi); + gpencil_primitive_set_initdata(C, tgpi); } /* Invoke handler: Initialize the operator */ @@ -1396,14 +1396,14 @@ static void gpencil_primitive_edit_event_handling( gpencil_primitive_add_segment(tgpi); copy_v2_v2(tgpi->start, tgpi->end); copy_v2_v2(tgpi->origin, tgpi->start); - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); tgpi->flag = IN_POLYLINE; WM_cursor_modal_set(win, WM_CURSOR_CROSS); } else { tgpi->flag = IN_CURVE_EDIT; - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); gpencil_primitive_update(C, op, tgpi); } } @@ -1460,7 +1460,7 @@ static void gpencil_primitive_edit_event_handling( case EVT_MKEY: { if ((event->val == KM_PRESS) && (tgpi->curve) && (ELEM(tgpi->orign_type, GP_STROKE_ARC))) { tgpi->flip ^= 1; - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); gpencil_primitive_update(C, op, tgpi); } break; @@ -1472,7 +1472,7 @@ static void gpencil_primitive_edit_event_handling( gpencil_primitive_add_segment(tgpi); copy_v2_v2(tgpi->start, tgpi->end); copy_v2_v2(tgpi->origin, tgpi->start); - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); } break; } @@ -1625,7 +1625,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e if (event->val == KM_PRESS) { tgpi->flag = IDLE; tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0; - gp_primitive_update_strokes(C, tgpi); + gpencil_primitive_update_strokes(C, tgpi); gpencil_primitive_interaction_end(C, op, win, tgpi); return OPERATOR_FINISHED; } @@ -1749,7 +1749,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e (!ELEM(tgpi->type, GP_STROKE_POLYLINE))) { /* set control points and enter edit mode */ tgpi->flag = IN_CURVE_EDIT; - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); gpencil_primitive_update(C, op, tgpi); } else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) && @@ -1792,7 +1792,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e if (tgpi->tot_stored_edges > 0) { tgpi->flag = IDLE; tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0; - gp_primitive_update_strokes(C, tgpi); + gpencil_primitive_update_strokes(C, tgpi); gpencil_primitive_interaction_end(C, op, win, tgpi); /* done! */ return OPERATOR_FINISHED; @@ -1871,7 +1871,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e } RNA_enum_set(op->ptr, "type", tgpi->type); - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); gpencil_primitive_update(C, op, tgpi); } break; @@ -1880,7 +1880,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e if (tgpi->flag == IN_CURVE_EDIT) { tgpi->flag = IN_PROGRESS; WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL); - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); gpencil_primitive_update(C, op, tgpi); } break; @@ -1908,7 +1908,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]); tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]); } - gp_primitive_update_cps(tgpi); + gpencil_primitive_update_cps(tgpi); /* update screen */ gpencil_primitive_update(C, op, tgpi); } diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 6bd945160a6..d0adcea25c1 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -172,9 +172,9 @@ typedef bool (*GP_BrushApplyCb)(tGP_BrushEditData *gso, /* Utility Functions */ /* apply lock axis reset */ -static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso, - bGPDspoint *pt, - const float save_pt[3]) +static void gpencil_sculpt_compute_lock_axis(tGP_BrushEditData *gso, + bGPDspoint *pt, + const float save_pt[3]) { const ToolSettings *ts = gso->scene->toolsettings; const View3DCursor *cursor = &gso->scene->cursor; @@ -221,7 +221,7 @@ static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso, /* Context ---------------------------------------- */ /* Get the sculpting settings */ -static GP_Sculpt_Settings *gpsculpt_get_settings(Scene *scene) +static GP_Sculpt_Settings *gpencil_sculpt_get_settings(Scene *scene) { return &scene->toolsettings->gp_sculpt; } @@ -229,7 +229,7 @@ static GP_Sculpt_Settings *gpsculpt_get_settings(Scene *scene) /* Brush Operations ------------------------------- */ /* Invert behavior of brush? */ -static bool gp_brush_invert_check(tGP_BrushEditData *gso) +static bool gpencil_brush_invert_check(tGP_BrushEditData *gso) { /* The basic setting is the brush's setting (from the panel) */ bool invert = ((gso->brush->gpencil_settings->sculpt_flag & GP_SCULPT_FLAG_INVERT) != 0) || @@ -251,7 +251,9 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso) } /* Compute strength of effect */ -static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, const int co[2]) +static float gpencil_brush_influence_calc(tGP_BrushEditData *gso, + const int radius, + const int co[2]) { Brush *brush = gso->brush; @@ -322,14 +324,14 @@ static void gpencil_update_geometry(bGPdata *gpd) /* A simple (but slower + inaccurate) * smooth-brush implementation to test the algorithm for stroke smoothing. */ -static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_smooth_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { - float inf = gp_brush_influence_calc(gso, radius, co); + float inf = gpencil_brush_influence_calc(gso, radius, co); /* perform smoothing */ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) { @@ -352,12 +354,12 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, /* Line Thickness Brush */ /* Make lines thicker or thinner by the specified amounts */ -static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_thickness_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { bGPDspoint *pt = gps->points + pt_index; float inf; @@ -366,12 +368,12 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, * - We divide the strength by 10, so that users can set "sane" values. * Otherwise, good default values are in the range of 0.093 */ - inf = gp_brush_influence_calc(gso, radius, co) / 10.0f; + inf = gpencil_brush_influence_calc(gso, radius, co) / 10.0f; /* apply */ /* XXX: this is much too strong, * and it should probably do some smoothing with the surrounding stuff. */ - if (gp_brush_invert_check(gso)) { + if (gpencil_brush_invert_check(gso)) { /* make line thinner - reduce stroke pressure */ pt->pressure -= inf; } @@ -396,21 +398,21 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, /* Color Strength Brush */ /* Make color more or less transparent by the specified amounts */ -static bool gp_brush_strength_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_strength_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { bGPDspoint *pt = gps->points + pt_index; float inf; /* Compute strength of effect */ - inf = gp_brush_influence_calc(gso, radius, co) * 0.125f; + inf = gpencil_brush_influence_calc(gso, radius, co) * 0.125f; /* Invert effect. */ - if (gp_brush_invert_check(gso)) { + if (gpencil_brush_invert_check(gso)) { inf *= -1.0f; } @@ -443,7 +445,7 @@ typedef struct tGPSB_Grab_StrokeData { } tGPSB_Grab_StrokeData; /* initialise custom data for handling this stroke */ -static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) +static void gpencil_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) { tGPSB_Grab_StrokeData *data = NULL; @@ -481,15 +483,15 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) } /* store references to stroke points in the initial stage */ -static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, - bGPDstroke *gps, - float rot_eval, - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_grab_store_points(tGP_BrushEditData *gso, + bGPDstroke *gps, + float rot_eval, + int pt_index, + const int radius, + const int co[2]) { tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps); - float inf = gp_brush_influence_calc(gso, radius, co); + float inf = gpencil_brush_influence_calc(gso, radius, co); BLI_assert(data != NULL); BLI_assert(data->size < data->capacity); @@ -505,7 +507,7 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, } /* Compute effect vector for grab brush */ -static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso) +static void gpencil_brush_grab_calc_dvec(tGP_BrushEditData *gso) { /* Convert mouse-movements to movement vector */ RegionView3D *rv3d = gso->region->regiondata; @@ -532,9 +534,9 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso) } /* Apply grab transform to all relevant points of the affected strokes */ -static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, - bGPDstroke *gps, - const float diff_mat[4][4]) +static void gpencil_brush_grab_apply_cached(tGP_BrushEditData *gso, + bGPDstroke *gps, + const float diff_mat[4][4]) { tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps); /* If a new frame is created, could be impossible find the stroke. */ @@ -553,7 +555,7 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, /* get evaluated transformation */ gso->rot_eval = data->rot_eval[i]; - gp_brush_grab_calc_dvec(gso); + gpencil_brush_grab_calc_dvec(gso); /* adjust the amount of displacement to apply */ mul_v3_v3fl(delta, gso->dvec, data->weights[i]); @@ -569,12 +571,12 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, mul_m4_v3(inverse_diff_mat, &pt->x); /* compute lock axis */ - gpsculpt_compute_lock_axis(gso, pt, save_pt); + gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); } } /* free customdata used for handling this stroke */ -static void gp_brush_grab_stroke_free(void *ptr) +static void gpencil_brush_grab_stroke_free(void *ptr) { tGPSB_Grab_StrokeData *data = (tGPSB_Grab_StrokeData *)ptr; @@ -589,19 +591,19 @@ static void gp_brush_grab_stroke_free(void *ptr) /* ----------------------------------------------- */ /* Push Brush */ -/* NOTE: Depends on gp_brush_grab_calc_dvec() */ -static bool gp_brush_push_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +/* NOTE: Depends on gpencil_brush_grab_calc_dvec() */ +static bool gpencil_brush_push_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { bGPDspoint *pt = gps->points + pt_index; float save_pt[3]; copy_v3_v3(save_pt, &pt->x); - float inf = gp_brush_influence_calc(gso, radius, co); + float inf = gpencil_brush_influence_calc(gso, radius, co); float delta[3] = {0.0f}; /* adjust the amount of displacement to apply */ @@ -612,7 +614,7 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso, add_v3_v3(&pt->x, delta); /* compute lock axis */ - gpsculpt_compute_lock_axis(gso, pt, save_pt); + gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); /* done */ return true; @@ -621,10 +623,10 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso, /* ----------------------------------------------- */ /* Pinch Brush */ /* Compute reference midpoint for the brush - this is what we'll be moving towards */ -static void gp_brush_calc_midpoint(tGP_BrushEditData *gso) +static void gpencil_brush_calc_midpoint(tGP_BrushEditData *gso) { /* Convert mouse position to 3D space - * See: gpencil_paint.c :: gp_stroke_convertcoords() + * See: gpencil_paint.c :: gpencil_stroke_convertcoords() */ RegionView3D *rv3d = gso->region->regiondata; const float *rvec = gso->object->loc; @@ -647,12 +649,12 @@ static void gp_brush_calc_midpoint(tGP_BrushEditData *gso) } /* Shrink distance between midpoint and this point... */ -static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_pinch_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { bGPDspoint *pt = gps->points + pt_index; float fac, inf; @@ -665,7 +667,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, * - Div 10 = Not enough effect * - Div 5 = Happy medium... (by trial and error) */ - inf = gp_brush_influence_calc(gso, radius, co) / 5.0f; + inf = gpencil_brush_influence_calc(gso, radius, co) / 5.0f; /* 1) Make this point relative to the cursor/midpoint (dvec) */ float fpt[3]; @@ -677,7 +679,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, * OR * Increase the distance (if inverting the brush action!) */ - if (gp_brush_invert_check(gso)) { + if (gpencil_brush_invert_check(gso)) { /* Inflate (inverse) */ fac = 1.0f + (inf * inf); /* squared to temper the effect... */ } @@ -692,7 +694,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, mul_v3_m4v3(&pt->x, gso->object->imat, fpt); /* compute lock axis */ - gpsculpt_compute_lock_axis(gso, pt, save_pt); + gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); /* done */ return true; @@ -704,12 +706,12 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, * convert the rotated point and convert it into "data" space */ -static bool gp_brush_twist_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_twist_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { bGPDspoint *pt = gps->points + pt_index; float angle, inf; @@ -717,10 +719,10 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, copy_v3_v3(save_pt, &pt->x); /* Angle to rotate by */ - inf = gp_brush_influence_calc(gso, radius, co); + inf = gpencil_brush_influence_calc(gso, radius, co); angle = DEG2RADF(1.0f) * inf; - if (gp_brush_invert_check(gso)) { + if (gpencil_brush_invert_check(gso)) { /* invert angle that we rotate by */ angle *= -1; } @@ -749,7 +751,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, mul_v3_m4v3(&pt->x, gso->object->imat, fpt); /* compute lock axis */ - gpsculpt_compute_lock_axis(gso, pt, save_pt); + gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); } else { const float axis[3] = {0.0f, 0.0f, 1.0f}; @@ -787,12 +789,12 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, /* ----------------------------------------------- */ /* Randomize Brush */ /* Apply some random jitter to the point */ -static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, - bGPDstroke *gps, - float UNUSED(rot_eval), - int pt_index, - const int radius, - const int co[2]) +static bool gpencil_brush_randomize_apply(tGP_BrushEditData *gso, + bGPDstroke *gps, + float UNUSED(rot_eval), + int pt_index, + const int radius, + const int co[2]) { bGPDspoint *pt = gps->points + pt_index; float save_pt[3]; @@ -801,7 +803,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, /* Amount of jitter to apply depends on the distance of the point to the cursor, * as well as the strength of the brush */ - const float inf = gp_brush_influence_calc(gso, radius, co) / 2.0f; + const float inf = gpencil_brush_influence_calc(gso, radius, co) / 2.0f; const float fac = BLI_rng_get_float(gso->rng) * inf; /* apply random to position */ @@ -840,7 +842,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, ED_view3d_win_to_delta(gso->gsc.region, svec, dvec, zfac); add_v3_v3(&pt->x, dvec); /* compute lock axis */ - gpsculpt_compute_lock_axis(gso, pt, save_pt); + gpencil_sculpt_compute_lock_axis(gso, pt, save_pt); } } } @@ -909,7 +911,7 @@ typedef struct tGPSB_CloneBrushData { } tGPSB_CloneBrushData; /* Initialise "clone" brush data */ -static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso) +static void gpencil_brush_clone_init(bContext *C, tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data; bGPDstroke *gps; @@ -918,7 +920,7 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso) gso->customdata = data = MEM_callocN(sizeof(tGPSB_CloneBrushData), "CloneBrushData"); /* compute midpoint of strokes on clipboard */ - for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { + for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { const float dfac = 1.0f / ((float)gps->totpoints); float mid[3] = {0.0f}; @@ -954,11 +956,11 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso) /* Init colormap for mapping between the pasted stroke's source color (names) * and the final colors that will be used here instead. */ - data->new_colors = gp_copybuf_validate_colormap(C); + data->new_colors = gpencil_copybuf_validate_colormap(C); } /* Free custom data used for "clone" brush */ -static void gp_brush_clone_free(tGP_BrushEditData *gso) +static void gpencil_brush_clone_free(tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data = gso->customdata; @@ -980,7 +982,7 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso) } /* Create new copies of the strokes on the clipboard */ -static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) +static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data = gso->customdata; @@ -995,11 +997,11 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) /* Compute amount to offset the points by */ /* NOTE: This assumes that screenspace strokes are NOT used in the 3D view... */ - gp_brush_calc_midpoint(gso); /* this puts the cursor location into gso->dvec */ + gpencil_brush_calc_midpoint(gso); /* this puts the cursor location into gso->dvec */ sub_v3_v3v3(delta, gso->dvec, data->buffer_midpoint); /* Copy each stroke into the layer */ - for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { + for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { bGPDstroke *new_stroke; bGPDspoint *pt; @@ -1051,14 +1053,14 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) } /* Move newly-added strokes around - "Stamp" mode of the Clone brush */ -static void gp_brush_clone_adjust(tGP_BrushEditData *gso) +static void gpencil_brush_clone_adjust(tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data = gso->customdata; size_t snum; /* Compute the amount of movement to apply (overwrites dvec) */ gso->rot_eval = 0.0f; - gp_brush_grab_calc_dvec(gso); + gpencil_brush_grab_calc_dvec(gso); /* For each of the stored strokes, apply the offset to each point */ /* NOTE: Again this assumes that in the 3D view, @@ -1075,8 +1077,8 @@ static void gp_brush_clone_adjust(tGP_BrushEditData *gso) float influence; /* compute influence on point */ - gp_point_to_xy(&gso->gsc, gps, pt, &sco[0], &sco[1]); - influence = gp_brush_influence_calc(gso, gso->brush->size, sco); + gpencil_point_to_xy(&gso->gsc, gps, pt, &sco[0], &sco[1]); + influence = gpencil_brush_influence_calc(gso, gso->brush->size, sco); /* adjust the amount of displacement to apply */ mul_v3_v3fl(delta, gso->dvec, influence); @@ -1088,24 +1090,24 @@ static void gp_brush_clone_adjust(tGP_BrushEditData *gso) } /* Entrypoint for applying "clone" brush */ -static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) +static bool gpencil_sculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) { /* Which "mode" are we operating in? */ if (gso->first) { /* Create initial clones */ - gp_brush_clone_add(C, gso); + gpencil_brush_clone_add(C, gso); } else { /* Stamp or Continuous Mode */ if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) { /* Stamp - Proceed to translate the newly added strokes */ - gp_brush_clone_adjust(gso); + gpencil_brush_clone_adjust(gso); } else { /* Continuous - Just keep pasting everytime we move */ /* TODO: The spacing of repeat should be controlled using a * "stepsize" or similar property? */ - gp_brush_clone_add(C, gso); + gpencil_brush_clone_add(C, gso); } } @@ -1115,7 +1117,7 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) /* ************************************************ */ /* Header Info for GPencil Sculpt */ -static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso) +static void gpencil_sculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso) { Brush *brush = gso->brush; char str[UI_MAX_DRAW_STR] = ""; @@ -1135,7 +1137,7 @@ static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso) /* Init/Exit ----------------------------------------------- */ -static bool gpsculpt_brush_init(bContext *C, wmOperator *op) +static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; @@ -1151,7 +1153,7 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) gso->depsgraph = CTX_data_ensure_evaluated_depsgraph(C); gso->bmain = CTX_data_main(C); /* store state */ - gso->settings = gpsculpt_get_settings(scene); + gso->settings = gpencil_sculpt_get_settings(scene); /* Random generator, only init once. */ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX); @@ -1209,7 +1211,7 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) bool found = false; /* check that there are some usable strokes in the buffer */ - for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { + for (gps = gpencil_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { found = true; break; @@ -1229,7 +1231,7 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) } else { /* initialise customdata */ - gp_brush_clone_init(C, gso); + gpencil_brush_clone_init(C, gso); } break; } @@ -1246,15 +1248,15 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) } /* setup space conversions */ - gp_point_conversion_init(C, &gso->gsc); + gpencil_point_conversion_init(C, &gso->gsc); /* update header */ - gpsculpt_brush_header_set(C, gso); + gpencil_sculpt_brush_header_set(C, gso); return true; } -static void gpsculpt_brush_exit(bContext *C, wmOperator *op) +static void gpencil_sculpt_brush_exit(bContext *C, wmOperator *op) { tGP_BrushEditData *gso = op->customdata; wmWindow *win = CTX_wm_window(C); @@ -1267,13 +1269,13 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op) * - Keys don't need to be freed, as those are the strokes * - Values assigned to those keys do, as they are custom structs */ - BLI_ghash_free(gso->stroke_customdata, NULL, gp_brush_grab_stroke_free); + BLI_ghash_free(gso->stroke_customdata, NULL, gpencil_brush_grab_stroke_free); break; } case GPSCULPT_TOOL_CLONE: { /* Free customdata */ - gp_brush_clone_free(gso); + gpencil_brush_clone_free(gso); break; } @@ -1305,7 +1307,7 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op) } /* poll callback for stroke sculpting operator(s) */ -static bool gpsculpt_brush_poll(bContext *C) +static bool gpencil_sculpt_brush_poll(bContext *C) { ScrArea *area = CTX_wm_area(C); if (area && area->spacetype != SPACE_VIEW3D) { @@ -1318,7 +1320,7 @@ static bool gpsculpt_brush_poll(bContext *C) /* Init Sculpt Stroke ---------------------------------- */ -static void gpsculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso) +static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso) { bGPdata *gpd = gso->gpd; @@ -1360,10 +1362,10 @@ static void gpsculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso) * For strokes with one point only this is impossible to calculate because there isn't a * valid reference point. */ -static float gpsculpt_rotation_eval_get(tGP_BrushEditData *gso, - bGPDstroke *gps_eval, - bGPDspoint *pt_eval, - int idx_eval) +static float gpencil_sculpt_rotation_eval_get(tGP_BrushEditData *gso, + bGPDstroke *gps_eval, + bGPDspoint *pt_eval, + int idx_eval) { /* If multiframe or no modifiers, return 0. */ if ((GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd)) || (!gso->is_transformed)) { @@ -1402,22 +1404,22 @@ static float gpsculpt_rotation_eval_get(tGP_BrushEditData *gso, /* create 2D vectors of the stroke segments */ float v_orig_a[2], v_orig_b[2], v_eval_a[2], v_eval_b[2]; - gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig->x, v_orig_a); - gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig_prev->x, v_orig_b); + gpencil_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig->x, v_orig_a); + gpencil_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig_prev->x, v_orig_b); sub_v2_v2(v_orig_a, v_orig_b); - gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_eval->x, v_eval_a); - gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_prev_eval->x, v_eval_b); + gpencil_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_eval->x, v_eval_a); + gpencil_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_prev_eval->x, v_eval_b); sub_v2_v2(v_eval_a, v_eval_b); return angle_v2v2(v_orig_a, v_eval_a); } /* Apply brush operation to points in this stroke */ -static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, - bGPDstroke *gps, - const float diff_mat[4][4], - GP_BrushApplyCb apply) +static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, + bGPDstroke *gps, + const float diff_mat[4][4], + GP_BrushApplyCb apply) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -1447,8 +1449,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; - gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); - gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp); + gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* do boundbox check first */ @@ -1459,7 +1461,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, if (len_v2v2_int(mval_i, pc1) <= radius) { /* apply operation to this point */ if (pt_active != NULL) { - rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, 0); + rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, 0); changed = apply(gso, gps_active, rot_eval, 0, radius, pc1); } } @@ -1483,11 +1485,11 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, } } bGPDspoint npt; - gp_point_to_parent_space(pt1, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(pt1, diff_mat, &npt); + gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]); - gp_point_to_parent_space(pt2, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]); + gpencil_point_to_parent_space(pt2, diff_mat, &npt); + gpencil_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]); /* Check that point segment of the boundbox of the selection stroke */ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) || @@ -1496,7 +1498,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, * brush region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* Apply operation to these points */ bool ok = false; @@ -1513,7 +1515,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, } index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if ((pt_active != NULL) && (index < gps_active->totpoints)) { - rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i); + rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, i); ok = apply(gso, gps_active, rot_eval, index, radius, pc1); } @@ -1530,7 +1532,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1; if ((pt_active != NULL) && (index < gps_active->totpoints)) { - rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i + 1); + rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, i + 1); ok |= apply(gso, gps_active, rot_eval, index, radius, pc2); include_last = false; } @@ -1551,7 +1553,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if ((pt_active != NULL) && (index < gps_active->totpoints)) { - rot_eval = gpsculpt_rotation_eval_get(gso, gps, pt, i); + rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, i); changed |= apply(gso, gps_active, rot_eval, index, radius, pc1); include_last = false; } @@ -1564,11 +1566,11 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, } /* Apply sculpt brushes to strokes in the given frame */ -static bool gpsculpt_brush_do_frame(bContext *C, - tGP_BrushEditData *gso, - bGPDlayer *gpl, - bGPDframe *gpf, - const float diff_mat[4][4]) +static bool gpencil_sculpt_brush_do_frame(bContext *C, + tGP_BrushEditData *gso, + bGPDlayer *gpl, + bGPDframe *gpf, + const float diff_mat[4][4]) { bool changed = false; bool redo_geom = false; @@ -1588,20 +1590,22 @@ static bool gpsculpt_brush_do_frame(bContext *C, switch (tool) { case GPSCULPT_TOOL_SMOOTH: /* Smooth strokes */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_smooth_apply); + changed |= gpencil_sculpt_brush_do_stroke(gso, gps, diff_mat, gpencil_brush_smooth_apply); redo_geom |= changed; break; } case GPSCULPT_TOOL_THICKNESS: /* Adjust stroke thickness */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_thickness_apply); + changed |= gpencil_sculpt_brush_do_stroke( + gso, gps, diff_mat, gpencil_brush_thickness_apply); break; } case GPSCULPT_TOOL_STRENGTH: /* Adjust stroke color strength */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_strength_apply); + changed |= gpencil_sculpt_brush_do_stroke( + gso, gps, diff_mat, gpencil_brush_strength_apply); break; } @@ -1614,13 +1618,13 @@ static bool gpsculpt_brush_do_frame(bContext *C, * 1) Prepare data buffers (init/clear) for this stroke * 2) Use the points now under the cursor */ - gp_brush_grab_stroke_init(gso, gps_active); - changed |= gpsculpt_brush_do_stroke( - gso, gps_active, diff_mat, gp_brush_grab_store_points); + gpencil_brush_grab_stroke_init(gso, gps_active); + changed |= gpencil_sculpt_brush_do_stroke( + gso, gps_active, diff_mat, gpencil_brush_grab_store_points); } else { /* Apply effect to the stored points */ - gp_brush_grab_apply_cached(gso, gps_active, diff_mat); + gpencil_brush_grab_apply_cached(gso, gps_active, diff_mat); changed |= true; } } @@ -1630,28 +1634,29 @@ static bool gpsculpt_brush_do_frame(bContext *C, case GPSCULPT_TOOL_PUSH: /* Push points */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_push_apply); + changed |= gpencil_sculpt_brush_do_stroke(gso, gps, diff_mat, gpencil_brush_push_apply); redo_geom |= changed; break; } case GPSCULPT_TOOL_PINCH: /* Pinch points */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_pinch_apply); + changed |= gpencil_sculpt_brush_do_stroke(gso, gps, diff_mat, gpencil_brush_pinch_apply); redo_geom |= changed; break; } case GPSCULPT_TOOL_TWIST: /* Twist points around midpoint */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_twist_apply); + changed |= gpencil_sculpt_brush_do_stroke(gso, gps, diff_mat, gpencil_brush_twist_apply); redo_geom |= changed; break; } case GPSCULPT_TOOL_RANDOMIZE: /* Apply jitter */ { - changed |= gpsculpt_brush_do_stroke(gso, gps, diff_mat, gp_brush_randomize_apply); + changed |= gpencil_sculpt_brush_do_stroke( + gso, gps, diff_mat, gpencil_brush_randomize_apply); redo_geom |= changed; break; } @@ -1685,7 +1690,7 @@ static bool gpsculpt_brush_do_frame(bContext *C, } /* Perform two-pass brushes which modify the existing strokes */ -static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) +static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) { ToolSettings *ts = gso->scene->toolsettings; Depsgraph *depsgraph = gso->depsgraph; @@ -1703,7 +1708,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) { /* calculate amount of displacement to apply */ gso->rot_eval = 0.0f; - gp_brush_grab_calc_dvec(gso); + gpencil_brush_grab_calc_dvec(gso); break; } @@ -1711,7 +1716,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) case GPSCULPT_TOOL_TWIST: /* Twist points around midpoint */ { /* calculate midpoint of the brush (in data space) */ - gp_brush_calc_midpoint(gso); + gpencil_brush_calc_midpoint(gso); break; } @@ -1719,7 +1724,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) { /* compute the displacement vector for the cursor (in data space) */ gso->rot_eval = 0.0f; - gp_brush_grab_calc_dvec(gso); + gpencil_brush_grab_calc_dvec(gso); break; } @@ -1764,7 +1769,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) } /* affect strokes in this frame */ - changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_sculpt_brush_do_frame(C, gso, gpl, gpf, diff_mat); } } } @@ -1772,7 +1777,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) if (gpl->actframe != NULL) { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_sculpt_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); } } } @@ -1781,7 +1786,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) } /* Calculate settings for applying brush */ -static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) +static void gpencil_sculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) { tGP_BrushEditData *gso = op->customdata; Brush *brush = gso->brush; @@ -1821,10 +1826,10 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt /* Apply brush */ char tool = gso->brush->gpencil_sculpt_tool; if (tool == GPSCULPT_TOOL_CLONE) { - changed = gpsculpt_brush_apply_clone(C, gso); + changed = gpencil_sculpt_brush_apply_clone(C, gso); } else { - changed = gpsculpt_brush_apply_standard(C, gso); + changed = gpencil_sculpt_brush_apply_standard(C, gso); } /* Updates */ @@ -1841,7 +1846,7 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt } /* Running --------------------------------------------- */ -static Brush *gpsculpt_get_smooth_brush(tGP_BrushEditData *gso) +static Brush *gpencil_sculpt_get_smooth_brush(tGP_BrushEditData *gso) { Main *bmain = gso->bmain; Brush *brush = BLI_findstring(&bmain->brushes, "Smooth Stroke", offsetof(ID, name) + 2); @@ -1850,7 +1855,7 @@ static Brush *gpsculpt_get_smooth_brush(tGP_BrushEditData *gso) } /* helper - a record stroke, and apply paint event */ -static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event) +static void gpencil_sculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushEditData *gso = op->customdata; PointerRNA itemptr; @@ -1878,7 +1883,7 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven if (event->shift) { gso->brush_prev = gso->brush; - gso->brush = gpsculpt_get_smooth_brush(gso); + gso->brush = gpencil_sculpt_get_smooth_brush(gso); if (gso->brush == NULL) { gso->brush = gso->brush_prev; } @@ -1890,28 +1895,28 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven } /* apply */ - gpsculpt_brush_apply(C, op, &itemptr); + gpencil_sculpt_brush_apply(C, op, &itemptr); } /* reapply */ -static int gpsculpt_brush_exec(bContext *C, wmOperator *op) +static int gpencil_sculpt_brush_exec(bContext *C, wmOperator *op) { - if (!gpsculpt_brush_init(C, op)) { + if (!gpencil_sculpt_brush_init(C, op)) { return OPERATOR_CANCELLED; } RNA_BEGIN (op->ptr, itemptr, "stroke") { - gpsculpt_brush_apply(C, op, &itemptr); + gpencil_sculpt_brush_apply(C, op, &itemptr); } RNA_END; - gpsculpt_brush_exit(C, op); + gpencil_sculpt_brush_exit(C, op); return OPERATOR_FINISHED; } /* start modal painting */ -static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int gpencil_sculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushEditData *gso = NULL; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -1927,7 +1932,7 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve } /* init painting data */ - if (!gpsculpt_brush_init(C, op)) { + if (!gpencil_sculpt_brush_init(C, op)) { return OPERATOR_CANCELLED; } @@ -1974,11 +1979,11 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve ARegion *region = CTX_wm_region(C); /* ensure that we'll have a new frame to draw on */ - gpsculpt_brush_init_stroke(C, gso); + gpencil_sculpt_brush_init_stroke(C, gso); /* apply first dab... */ gso->is_painting = true; - gpsculpt_brush_apply_event(C, op, event); + gpencil_sculpt_brush_apply_event(C, op, event); /* redraw view with feedback */ ED_region_tag_redraw(region); @@ -1988,7 +1993,7 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve } /* painting - handle events */ -static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *event) +static int gpencil_sculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushEditData *gso = op->customdata; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -2003,7 +2008,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even case MOUSEMOVE: case INBETWEEN_MOUSEMOVE: /* apply brush effect at new position */ - gpsculpt_brush_apply_event(C, op, event); + gpencil_sculpt_brush_apply_event(C, op, event); /* force redraw, so that the cursor will at least be valid */ redraw_region = true; @@ -2013,7 +2018,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even case TIMER: if (event->customdata == gso->timer) { gso->timerTick = true; - gpsculpt_brush_apply_event(C, op, event); + gpencil_sculpt_brush_apply_event(C, op, event); gso->timerTick = false; } break; @@ -2029,7 +2034,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even /* end sculpt session, since we're not modal */ gso->is_painting = false; - gpsculpt_brush_exit(C, op); + gpencil_sculpt_brush_exit(C, op); return OPERATOR_FINISHED; } break; @@ -2038,7 +2043,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even case MIDDLEMOUSE: case RIGHTMOUSE: case EVT_ESCKEY: - gpsculpt_brush_exit(C, op); + gpencil_sculpt_brush_exit(C, op); return OPERATOR_FINISHED; } } @@ -2053,14 +2058,14 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even gso->is_painting = true; gso->first = true; - gpsculpt_brush_init_stroke(C, gso); - gpsculpt_brush_apply_event(C, op, event); + gpencil_sculpt_brush_init_stroke(C, gso); + gpencil_sculpt_brush_apply_event(C, op, event); break; /* Exit modal operator, based on the "standard" ops */ case RIGHTMOUSE: case EVT_ESCKEY: - gpsculpt_brush_exit(C, op); + gpencil_sculpt_brush_exit(C, op); return OPERATOR_FINISHED; /* MMB is often used for view manipulations */ @@ -2124,11 +2129,11 @@ void GPENCIL_OT_sculpt_paint(wmOperatorType *ot) ot->description = "Apply tweaks to strokes by painting over the strokes"; // XXX /* api callbacks */ - ot->exec = gpsculpt_brush_exec; - ot->invoke = gpsculpt_brush_invoke; - ot->modal = gpsculpt_brush_modal; - ot->cancel = gpsculpt_brush_exit; - ot->poll = gpsculpt_brush_poll; + ot->exec = gpencil_sculpt_brush_exec; + ot->invoke = gpencil_sculpt_brush_invoke; + ot->modal = gpencil_sculpt_brush_modal; + ot->cancel = gpencil_sculpt_brush_exit; + ot->poll = gpencil_sculpt_brush_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index c41b2993a80..ea6f53d24bb 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -369,7 +369,7 @@ typedef enum eGP_SelectGrouped { /* ----------------------------------- */ /* On each visible layer, check for selected strokes - if found, select all others */ -static void gp_select_same_layer(bContext *C) +static void gpencil_select_same_layer(bContext *C) { Scene *scene = CTX_data_scene(C); @@ -412,7 +412,7 @@ static void gp_select_same_layer(bContext *C) } /* Select all strokes with same colors as selected ones */ -static void gp_select_same_material(bContext *C) +static void gpencil_select_same_material(bContext *C) { /* First, build set containing all the colors of selected strokes */ GSet *selected_colors = BLI_gset_str_new("GP Selected Colors"); @@ -462,10 +462,10 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op) switch (mode) { case GP_SEL_SAME_LAYER: - gp_select_same_layer(C); + gpencil_select_same_layer(C); break; case GP_SEL_SAME_MATERIAL: - gp_select_same_material(C); + gpencil_select_same_material(C); break; default: @@ -853,142 +853,87 @@ void GPENCIL_OT_select_less(wmOperatorType *ot) * Helper to check if a given stroke is within the area. * * \note Code here is adapted (i.e. copied directly) - * from gpencil_paint.c #gp_stroke_eraser_dostroke(). + * from gpencil_paint.c #gpencil_stroke_eraser_dostroke(). * It would be great to de-duplicate the logic here sometime, but that can wait. */ -static bool gp_stroke_do_circle_sel(bGPdata *UNUSED(gpd), - bGPDlayer *gpl, - bGPDstroke *gps, - GP_SpaceConversion *gsc, - const int mx, - const int my, - const int radius, - const bool select, - rcti *rect, - const float diff_mat[4][4], - const int selectmode, - const float scale) +static bool gpencil_stroke_do_circle_sel(bGPdata *UNUSED(gpd), + bGPDlayer *gpl, + bGPDstroke *gps, + GP_SpaceConversion *gsc, + const int mx, + const int my, + const int radius, + const bool select, + rcti *rect, + const float diff_mat[4][4], + const int selectmode, + const float scale) { - bGPDspoint *pt1 = NULL; - bGPDspoint *pt2 = NULL; - int x0 = 0, y0 = 0, x1 = 0, y1 = 0; + bGPDspoint *pt = NULL; + int x0 = 0, y0 = 0; int i; bool changed = false; bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; bGPDspoint *pt_active = NULL; + bool hit = false; + + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; - if (gps->totpoints == 1) { bGPDspoint pt_temp; - gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); - gp_point_to_xy(gsc, gps, &pt_temp, &x0, &y0); + gpencil_point_to_parent_space(pt_active, diff_mat, &pt_temp); + gpencil_point_to_xy(gsc, gps, &pt_temp, &x0, &y0); /* do boundbox check first */ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) { + hit = true; + /* change selection */ if (select) { - gps_active->points->flag |= GP_SPOINT_SELECT; + pt_active->flag |= GP_SPOINT_SELECT; gps_active->flag |= GP_STROKE_SELECT; } else { - gps_active->points->flag &= ~GP_SPOINT_SELECT; + pt_active->flag &= ~GP_SPOINT_SELECT; gps_active->flag &= ~GP_STROKE_SELECT; } + changed = true; + /* if stroke mode, don't check more points */ + if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) { + break; + } - return true; - } - } - } - else { - /* Loop over the points in the stroke, checking for intersections - * - an intersection means that we touched the stroke - */ - bool hit = false; - for (i = 0; (i + 1) < gps->totpoints; i++) { - /* get points to work with */ - pt1 = gps->points + i; - pt2 = gps->points + i + 1; - bGPDspoint npt; - gp_point_to_parent_space(pt1, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &x0, &y0); - - gp_point_to_parent_space(pt2, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &x1, &y1); - - /* check that point segment of the boundbox of the selection stroke */ - if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || - ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { - float mval[2] = {(float)mx, (float)my}; - - /* check if point segment of stroke had anything to do with - * eraser region (either within stroke painted, or on its lines) - * - this assumes that linewidth is irrelevant - */ - if (gp_stroke_inside_circle(mval, radius, x0, y0, x1, y1)) { - /* change selection of stroke, and then of both points - * (as the last point otherwise wouldn't get selected - * as we only do n-1 loops through). - */ - hit = true; - if (select) { - pt_active = pt1->runtime.pt_orig; - if (pt_active != NULL) { - pt_active->flag |= GP_SPOINT_SELECT; - } - pt_active = pt2->runtime.pt_orig; - if (pt_active != NULL) { - pt_active->flag |= GP_SPOINT_SELECT; - } - changed = true; - } - else { - pt_active = pt1->runtime.pt_orig; - if (pt_active != NULL) { - pt_active->flag &= ~GP_SPOINT_SELECT; - } - pt_active = pt2->runtime.pt_orig; - if (pt_active != NULL) { - pt_active->flag &= ~GP_SPOINT_SELECT; - } - changed = true; - } + /* Expand selection to segment. */ + if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select) && (pt_active != NULL)) { + float r_hita[3], r_hitb[3]; + bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT); + ED_gpencil_select_stroke_segment( + gpl, gps_active, pt_active, hit_select, false, scale, r_hita, r_hitb); } } - /* if stroke mode, don't check more points */ - if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) { - break; - } } + } - /* if stroke mode expand selection */ - if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) { - for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) { - pt_active = (pt1->runtime.pt_orig) ? pt1->runtime.pt_orig : pt1; - if (pt_active != NULL) { - if (select) { - pt_active->flag |= GP_SPOINT_SELECT; - } - else { - pt_active->flag &= ~GP_SPOINT_SELECT; - } + /* If stroke mode expand selection. */ + if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; + if (pt_active != NULL) { + if (select) { + pt_active->flag |= GP_SPOINT_SELECT; + } + else { + pt_active->flag &= ~GP_SPOINT_SELECT; } } } - - /* expand selection to segment */ - pt_active = (pt1->runtime.pt_orig) ? pt1->runtime.pt_orig : pt1; - if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select) && (pt_active != NULL)) { - float r_hita[3], r_hitb[3]; - bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT); - ED_gpencil_select_stroke_segment( - gpl, gps_active, pt_active, hit_select, false, scale, r_hita, r_hitb); - } - - /* Ensure that stroke selection is in sync with its points */ - BKE_gpencil_stroke_sync_selection(gps_active); } + /* Ensure that stroke selection is in sync with its points. */ + BKE_gpencil_stroke_sync_selection(gps_active); + return changed; } @@ -1043,7 +988,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) } /* init space conversion stuff */ - gp_point_conversion_init(C, &gsc); + gpencil_point_conversion_init(C, &gsc); /* rect is rectangle of selection circle */ rect.xmin = mx - radius; @@ -1053,18 +998,18 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) /* find visible strokes, and select if hit */ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - changed |= gp_stroke_do_circle_sel(gpd, - gpl, - gps, - &gsc, - mx, - my, - radius, - select, - &rect, - gpstroke_iter.diff_mat, - selectmode, - scale); + changed |= gpencil_stroke_do_circle_sel(gpd, + gpl, + gps, + &gsc, + mx, + my, + radius, + select, + &rect, + gpstroke_iter.diff_mat, + selectmode, + scale); } GP_EVALUATED_STROKES_END(gpstroke_iter); @@ -1157,7 +1102,7 @@ static int gpencil_generic_select_exec( } /* init space conversion stuff */ - gp_point_conversion_init(C, &gsc); + gpencil_point_conversion_init(C, &gsc); /* deselect all strokes first? */ if (SEL_OP_USE_PRE_DESELECT(sel_op) || (GPENCIL_PAINT_MODE(gpd))) { @@ -1255,7 +1200,7 @@ static int gpencil_generic_select_exec( /* if paint mode,delete selected points */ if (GPENCIL_PAINT_MODE(gpd)) { - gp_delete_selected_point_wrap(C); + gpencil_delete_selected_point_wrap(C); changed = true; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); } @@ -1292,8 +1237,8 @@ static bool gpencil_test_box(bGPDstroke *gps, const struct GP_SelectBoxUserData *data = user_data; bGPDspoint pt2; int x0, y0; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy(gsc, gps, &pt2, &x0, &y0); return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0)); } @@ -1349,8 +1294,8 @@ static bool gpencil_test_lasso(bGPDstroke *gps, const struct GP_SelectLassoUserData *data = user_data; bGPDspoint pt2; int x0, y0; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy(gsc, gps, &pt2, &x0, &y0); /* test if in lasso boundbox + within the lasso noose */ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) && BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX)); @@ -1431,7 +1376,6 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */ const float radius = 0.4f * U.widget_unit; @@ -1473,7 +1417,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) } /* init space conversion stuff */ - gp_point_conversion_init(C, &gsc); + gpencil_point_conversion_init(C, &gsc); /* get mouse location */ RNA_int_get_array(op->ptr, "location", mval); @@ -1484,24 +1428,13 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) bGPDspoint *pt; int i; - /* Check boundbox to speedup. */ - float fmval[2]; - copy_v2fl_v2i(fmval, mval); - if (!ED_gpencil_stroke_check_collision( - &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) { - continue; - } - /* firstly, check for hit-point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { int xy[2]; - if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) { - continue; - } bGPDspoint pt2; - gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2); - gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]); + gpencil_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2); + gpencil_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]); /* do boundbox check first */ if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) { @@ -1513,27 +1446,12 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) if (pt_distance < hit_distance) { hit_layer = gpl; hit_stroke = gps_active; - hit_point = (!is_multiedit) ? pt->runtime.pt_orig : pt; + hit_point = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; hit_distance = pt_distance; } } } } - if (ELEM(NULL, hit_stroke, hit_point)) { - /* If nothing hit, check if the mouse is inside any filled stroke. - * Only check filling materials. */ - MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); - if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { - continue; - } - bool hit_fill = ED_gpencil_stroke_point_is_inside(gps, &gsc, mval, gpstroke_iter.diff_mat); - if (hit_fill) { - hit_stroke = gps_active; - hit_point = &gps_active->points[0]; - /* Extend selection to all stroke. */ - whole = true; - } - } } GP_EVALUATED_STROKES_END(gpstroke_iter); diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 467b7ee86bf..7f77999a17b 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -94,7 +94,7 @@ /* Context Wrangling... */ /** - * Get pointer to active Grease Pencil datablock, + * Get pointer to active Grease Pencil data-block, * and an RNA-pointer to trace back to whatever owns it, * when context info is not available. */ @@ -107,7 +107,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *area, Object *ob, Pointer switch (area->spacetype) { case SPACE_PROPERTIES: /* properties */ case SPACE_INFO: /* header info */ - case SPACE_TOPBAR: /* Topbar */ + case SPACE_TOPBAR: /* Top-bar */ case SPACE_VIEW3D: /* 3D-View */ { if (ob && (ob->type == OB_GPENCIL)) { @@ -132,7 +132,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ScrArea *area, Object *ob, Pointer } /** - * Get pointer to active Grease Pencil datablock for annotations, + * Get pointer to active Grease Pencil data-block for annotations, * and an RNA-pointer to trace back to whatever owns it, * when context info is not available. */ @@ -154,7 +154,7 @@ bGPdata **ED_annotation_data_get_pointers_direct(ID *screen_id, break; } - case SPACE_TOPBAR: /* Topbar */ + case SPACE_TOPBAR: /* Top-bar */ case SPACE_VIEW3D: /* 3D-View */ { if (r_ptr) { @@ -237,8 +237,10 @@ bGPdata **ED_annotation_data_get_pointers_direct(ID *screen_id, return NULL; } -/* Get pointer to active Grease Pencil datablock, - * and an RNA-pointer to trace back to whatever owns it. */ +/** + * Get pointer to active Grease Pencil data-block, + * and an RNA-pointer to trace back to whatever owns it. + */ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr) { ScrArea *area = CTX_wm_area(C); @@ -247,8 +249,10 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr) return ED_gpencil_data_get_pointers_direct(area, ob, r_ptr); } -/* Get pointer to active Grease Pencil datablock, - * and an RNA-pointer to trace back to whatever owns it. */ +/** + * Get pointer to active Grease Pencil data-block, + * and an RNA-pointer to trace back to whatever owns it. + */ bGPdata **ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr) { ID *screen_id = (ID *)CTX_wm_screen(C); @@ -259,14 +263,14 @@ bGPdata **ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr) } /* -------------------------------------------------------- */ -/* Get the active Grease Pencil datablock, when context is not available */ +/* Get the active Grease Pencil data-block, when context is not available */ bGPdata *ED_gpencil_data_get_active_direct(ScrArea *area, Object *ob) { bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(area, ob, NULL); return (gpd_ptr) ? *(gpd_ptr) : NULL; } -/* Get the active Grease Pencil datablock, when context is not available */ +/* Get the active Grease Pencil data-block, when context is not available */ bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scene *scene) { bGPdata **gpd_ptr = ED_annotation_data_get_pointers_direct(screen_id, area, scene, NULL); @@ -274,7 +278,7 @@ bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scen } /** - * Get the active Grease Pencil datablock + * Get the active Grease Pencil data-block */ bGPdata *ED_gpencil_data_get_active(const bContext *C) { @@ -285,9 +289,10 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C) return ob->data; } -/* Get the active Grease Pencil datablock - * \note This is the original (bmain) copy of the datablock, stored in files. - * Do not use for reading evaluated copies of GP Objects data +/** + * Get the active Grease Pencil data-block + * \note This is the original (#G.main) copy of the data-block, stored in files. + * Do not use for reading evaluated copies of GP Objects data. */ bGPdata *ED_annotation_data_get_active(const bContext *C) { @@ -295,11 +300,11 @@ bGPdata *ED_annotation_data_get_active(const bContext *C) return (gpd_ptr) ? *(gpd_ptr) : NULL; } /** - * Get the evaluated copy of the active Grease Pencil datablock (where applicable) - * - For the 3D View (i.e. "GP Objects"), this gives the evaluated copy of the GP datablock - * (i.e. a copy of the active GP datablock for the active object, where modifiers have been + * Get the evaluated copy of the active Grease Pencil data-block (where applicable) + * - For the 3D View (i.e. "GP Objects"), this gives the evaluated copy of the GP data-block + * (i.e. a copy of the active GP data-block for the active object, where modifiers have been * applied). This is needed to correctly work with "Copy-on-Write". - * - For all other editors (i.e. "GP Annotations"), this just gives the active datablock + * - For all other editors (i.e. "GP Annotations"), this just gives the active data-block * like for #ED_gpencil_data_get_active() */ bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C) @@ -322,8 +327,7 @@ bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C) bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr) { /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data. - * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else) - */ + * Otherwise, the GP data-block is being used for annotations (i.e. everywhere else). */ return ((owner_ptr) && (owner_ptr->type != &RNA_Object)); } @@ -354,7 +358,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra) /* Poll Callbacks */ /* poll callback for adding data/layers - special */ -bool gp_add_poll(bContext *C) +bool gpencil_add_poll(bContext *C) { Object *ob = CTX_data_active_object(C); if (ob == NULL) { @@ -366,7 +370,7 @@ bool gp_add_poll(bContext *C) } /* poll callback for checking if there is an active layer */ -bool gp_active_layer_poll(bContext *C) +bool gpencil_active_layer_poll(bContext *C) { Object *ob = CTX_data_active_object(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { @@ -379,7 +383,7 @@ bool gp_active_layer_poll(bContext *C) } /* poll callback for checking if there is an active brush */ -bool gp_active_brush_poll(bContext *C) +bool gpencil_active_brush_poll(bContext *C) { ToolSettings *ts = CTX_data_tool_settings(C); Paint *paint = &ts->gp_paint->paint; @@ -527,13 +531,12 @@ const EnumPropertyItem *ED_gpencil_material_enum_itemf(bContext *C, * Check whether a given stroke segment is inside a circular brush * * \param mval: The current screen-space coordinates (midpoint) of the brush - * \param mvalo: The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED) * \param rad: The radius of the brush * * \param x0, y0: The screen-space x and y coordinates of the start of the stroke segment * \param x1, y1: The screen-space x and y coordinates of the end of the stroke segment */ -bool gp_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1) +bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1) { /* simple within-radius check for now */ const float screen_co_a[2] = {x0, y0}; @@ -611,7 +614,7 @@ bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstr * * \param r_gsc: [out] The space conversion settings struct, populated with necessary params */ -void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) +void gpencil_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) { ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); @@ -658,7 +661,9 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) * \param diff_mat: Matrix with the difference between original parent matrix * \param[out] r_pt: Pointer to new point after apply matrix */ -void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt) +void gpencil_point_to_parent_space(const bGPDspoint *pt, + const float diff_mat[4][4], + bGPDspoint *r_pt) { float fpt[3]; @@ -669,7 +674,7 @@ void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], /** * Change position relative to parent object */ -void gp_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDstroke *gps) +void gpencil_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDstroke *gps) { bGPDspoint *pt; int i; @@ -692,7 +697,10 @@ void gp_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDst /** * Change point position relative to parent object */ -void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, bGPDspoint *pt) +void gpencil_apply_parent_point(Depsgraph *depsgraph, + Object *obact, + bGPDlayer *gpl, + bGPDspoint *pt) { /* undo matrix */ float diff_mat[4][4]; @@ -715,7 +723,7 @@ void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, * \warning This assumes that the caller has already checked * whether the stroke in question can be drawn. */ -void gp_point_to_xy( +void gpencil_point_to_xy( const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y) { const ARegion *region = gsc->region; @@ -760,21 +768,21 @@ void gp_point_to_xy( /** * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D). * - * Just like #gp_point_to_xy(), except the resulting coordinates are floats not ints. + * Just like #gpencil_point_to_xy(), except the resulting coordinates are floats not ints. * Use this version to solve "stair-step" artifacts which may arise when * roundtripping the calculations. * - * \param r_x[out]: The screen-space x-coordinate of the point. - * \param r_y[out]: The screen-space y-coordinate of the point. + * \param r_x: The screen-space x-coordinate of the point. + * \param r_y: The screen-space y-coordinate of the point. * * \warning This assumes that the caller has already checked * whether the stroke in question can be drawn. */ -void gp_point_to_xy_fl(const GP_SpaceConversion *gsc, - const bGPDstroke *gps, - const bGPDspoint *pt, - float *r_x, - float *r_y) +void gpencil_point_to_xy_fl(const GP_SpaceConversion *gsc, + const bGPDstroke *gps, + const bGPDspoint *pt, + float *r_x, + float *r_y) { const ARegion *region = gsc->region; const View2D *v2d = gsc->v2d; @@ -828,12 +836,12 @@ void gp_point_to_xy_fl(const GP_SpaceConversion *gsc, } /** - * generic based on gp_point_to_xy_fl + * generic based on gpencil_point_to_xy_fl */ -void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, - const short flag, - const float pt[3], - float xy[2]) +void gpencil_point_3d_to_xy(const GP_SpaceConversion *gsc, + const short flag, + const float pt[3], + float xy[2]) { const ARegion *region = gsc->region; const View2D *v2d = gsc->v2d; @@ -899,10 +907,10 @@ void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, * * \warning Assumes that it is getting called in a 3D view only. */ -bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, - Scene *scene, - const float screen_co[2], - float r_out[3]) +bool gpencil_point_xy_to_3d(const GP_SpaceConversion *gsc, + Scene *scene, + const float screen_co[2], + float r_out[3]) { const RegionView3D *rv3d = gsc->region->regiondata; float rvec[3]; @@ -935,16 +943,16 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, * Convert tGPspoint (temporary 2D/screenspace point data used by GP modal operators) * to 3D coordinates. * - * \param point2D: The screenspace 2D point data to convert. + * \param point2D: The screen-space 2D point data to convert. * \param depth: Depth array (via #ED_view3d_autodist_depth()). - * \param[out] r_out: The resulting 2D point data. + * \param r_out: The resulting 2D point data. */ -void gp_stroke_convertcoords_tpoint(Scene *scene, - ARegion *region, - Object *ob, - const tGPspoint *point2D, - float *depth, - float r_out[3]) +void gpencil_stroke_convertcoords_tpoint(Scene *scene, + ARegion *region, + Object *ob, + const tGPspoint *point2D, + float *depth, + float r_out[3]) { ToolSettings *ts = scene->toolsettings; @@ -982,7 +990,7 @@ void gp_stroke_convertcoords_tpoint(Scene *scene, /** * Get drawing reference point for conversion or projection of the stroke - * \param[out] r_vec : Reference point found + * \param r_vec: Reference point found */ void ED_gpencil_drawing_reference_get(const Scene *scene, const Object *ob, @@ -1024,7 +1032,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * float inverse_diff_mat[4][4]; /* init space conversion stuff */ - gp_point_conversion_init(C, &gsc); + gpencil_point_conversion_init(C, &gsc); BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); @@ -1034,11 +1042,11 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * float xy[2]; bGPDspoint pt2; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); /* Planar - All on same plane parallel to the viewplane */ - gp_point_xy_to_3d(&gsc, scene, xy, &pt->x); + gpencil_point_xy_to_3d(&gsc, scene, xy, &pt->x); /* Unapply parent corrections */ mul_m4_v3(inverse_diff_mat, &pt->x); @@ -1048,12 +1056,12 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * /** * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset */ -void ED_gp_project_stroke_to_plane(const Scene *scene, - const Object *ob, - const RegionView3D *rv3d, - bGPDstroke *gps, - const float origin[3], - const int axis) +void ED_gpencil_project_stroke_to_plane(const Scene *scene, + const Object *ob, + const RegionView3D *rv3d, + bGPDstroke *gps, + const float origin[3], + const int axis) { const ToolSettings *ts = scene->toolsettings; const View3DCursor *cursor = &scene->cursor; @@ -1165,13 +1173,13 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, float xy[2]; /* 3D to Screen-space */ - /* Note: We can't use gp_point_to_xy() here because that uses ints for the screen-space + /* Note: We can't use gpencil_point_to_xy() here because that uses ints for the screen-space * coordinates, resulting in lost precision, which in turn causes stair-stepping * artifacts in the final points. */ bGPDspoint pt2; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy_fl(gsc, gps_active, &pt2, &xy[0], &xy[1]); + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy_fl(gsc, gps_active, &pt2, &xy[0], &xy[1]); /* Project stroke in one axis */ if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) { @@ -1199,18 +1207,18 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } } - ED_gp_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2); + ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2); copy_v3_v3(&pt->x, &pt2.x); /* apply parent again */ - gp_apply_parent_point(depsgraph, gsc->ob, gpl, pt); + gpencil_apply_parent_point(depsgraph, gsc->ob, gpl, pt); } /* Project screen-space back to 3D space (from current perspective) * so that all points have been treated the same way. */ else if (mode == GP_REPROJECT_VIEW) { /* Planar - All on same plane parallel to the view-plane. */ - gp_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x); + gpencil_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x); } else { /* Geometry - Snap to surfaces of visible geometry */ @@ -1238,7 +1246,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } else { /* Default to planar */ - gp_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x); + gpencil_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x); } } @@ -1251,14 +1259,14 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, /** * Reproject given point to a plane locked to axis to avoid stroke offset - * \param[in,out] pt: Point to affect + * \param pt: Point to affect (used for input & output). */ -void ED_gp_project_point_to_plane(const Scene *scene, - const Object *ob, - const RegionView3D *rv3d, - const float origin[3], - const int axis, - bGPDspoint *pt) +void ED_gpencil_project_point_to_plane(const Scene *scene, + const Object *ob, + const RegionView3D *rv3d, + const float origin[3], + const int axis, + bGPDspoint *pt) { const ToolSettings *ts = scene->toolsettings; const View3DCursor *cursor = &scene->cursor; @@ -1330,7 +1338,7 @@ void ED_gp_project_point_to_plane(const Scene *scene, * \param gps: Stroke data * \param subdivide: Number of times to subdivide */ -void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide) +void gpencil_subdivide_stroke(bGPDstroke *gps, const int subdivide) { bGPDspoint *temp_points; int totnewpoints, oldtotpoints; @@ -1730,7 +1738,7 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob) /* Cursor drawing */ /* check if cursor is in drawing region */ -static bool gp_check_cursor_region(bContext *C, int mval_i[2]) +static bool gpencil_check_cursor_region(bContext *C, int mval_i[2]) { ARegion *region = CTX_wm_region(C); ScrArea *area = CTX_wm_area(C); @@ -1802,7 +1810,7 @@ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y) GPU_line_smooth(false); } -static bool gp_brush_cursor_poll(bContext *C) +static bool gpencil_brush_cursor_poll(bContext *C) { if (WM_toolsystem_active_tool_is_brush(C)) { return true; @@ -1810,8 +1818,10 @@ static bool gp_brush_cursor_poll(bContext *C) return false; } -/* Helper callback for drawing the cursor itself */ -static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata) +/** + * Helper callback for drawing the cursor itself. + */ +static void gpencil_brush_cursor_draw(bContext *C, int x, int y, void *customdata) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); @@ -1830,8 +1840,8 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata) float radius = 3.0f; int mval_i[2] = {x, y}; - /* check if cursor is in drawing region and has valid datablock */ - if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) { + /* Check if cursor is in drawing region and has valid data-block. */ + if ((!gpencil_check_cursor_region(C, mval_i)) || (gpd == NULL)) { return; } @@ -2016,8 +2026,8 @@ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata) /* enable cursor */ gset->paintcursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, - gp_brush_cursor_poll, - gp_brush_cursor_draw, + gpencil_brush_cursor_poll, + gpencil_brush_cursor_draw, (lastpost) ? customdata : NULL); } } @@ -2081,7 +2091,9 @@ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode) } } -/* helper to convert 2d to 3d for simple drawing buffer */ +/** + * Helper to convert 2d to 3d for simple drawing buffer. + */ static void gpencil_stroke_convertcoords(ARegion *region, const tGPspoint *point2D, const float origin[3], @@ -2107,7 +2119,9 @@ static void gpencil_stroke_convertcoords(ARegion *region, } } -/* convert 2d tGPspoint to 3d bGPDspoint */ +/** + * Convert 2d #tGPspoint to 3d #bGPDspoint. + */ void ED_gpencil_tpoint_to_point(ARegion *region, float origin[3], const tGPspoint *tpt, @@ -2125,7 +2139,9 @@ void ED_gpencil_tpoint_to_point(ARegion *region, pt->uv_rot = tpt->uv_rot; } -/* recalc uv for any stroke using the material */ +/** + * Recalculate UV for any stroke using the material. + */ void ED_gpencil_update_color_uv(Main *bmain, Material *mat) { Material *gps_ma = NULL; @@ -2212,7 +2228,8 @@ static bool gpencil_check_collision(bGPDstroke *gps, return hit; } -static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2) +static void gpencil_copy_points( + bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2) { /* don't copy same point */ if (i == i2) { @@ -2244,7 +2261,7 @@ static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final } } -static void gp_insert_point( +static void gpencil_insert_point( bGPDstroke *gps, bGPDspoint *a_pt, bGPDspoint *b_pt, const float co_a[3], float co_b[3]) { bGPDspoint *temp_points; @@ -2287,16 +2304,16 @@ static void gp_insert_point( for (int i = 0; i < oldtotpoints; i++) { bGPDspoint *pt = &temp_points[i]; bGPDspoint *pt_final = &gps->points[i2]; - gp_copy_points(gps, pt, pt_final, i, i2); + gpencil_copy_points(gps, pt, pt_final, i, i2); /* create new point duplicating point and copy location */ if ((i == a_idx) || (i == b_idx)) { i2++; pt_final = &gps->points[i2]; - gp_copy_points(gps, pt, pt_final, i, i2); + gpencil_copy_points(gps, pt, pt_final, i, i2); copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b); - /* unselect */ + /* Un-select. */ pt_final->flag &= ~GP_SPOINT_SELECT; /* tag to avoid more checking with this point */ pt_final->flag |= GP_SPOINT_TAG; @@ -2304,13 +2321,13 @@ static void gp_insert_point( i2++; } - /* Calc geometry data. */ + /* Calculate geometry data. */ BKE_gpencil_stroke_geometry_update(gps); MEM_SAFE_FREE(temp_points); } -static float gp_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2]) +static float gpencil_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2]) { float dist1 = len_squared_v2v2(p2d_a1, p2d_a2); float dist2 = len_squared_v2v2(p2d_a1, r_hit2d); @@ -2435,7 +2452,7 @@ int ED_gpencil_select_stroke_segment(bGPDlayer *gpl, } if (hit_a) { - f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d); + f = gpencil_calc_factor(p2d_a1, p2d_a2, r_hit2d); interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f); if (f > min_factor) { hit_pointa = pta2; /* first point is second (inverted loop) */ @@ -2468,7 +2485,7 @@ int ED_gpencil_select_stroke_segment(bGPDlayer *gpl, } if (hit_b) { - f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d); + f = gpencil_calc_factor(p2d_a1, p2d_a2, r_hit2d); interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f); if (f > min_factor) { hit_pointb = pta1; @@ -2482,7 +2499,7 @@ int ED_gpencil_select_stroke_segment(bGPDlayer *gpl, /* insert new point in the collision points */ if (insert) { - gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb); + gpencil_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb); } /* free memory */ @@ -2610,7 +2627,10 @@ void ED_gpencil_select_toggle_all(bContext *C, int action) } } -/* Ensure the SBuffer (while drawing stroke) size is enough to save all points of the stroke */ +/** + * Ensure the #tGPspoint buffer (while drawing stroke) + * size is enough to save all points of the stroke. + */ tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array, int *buffer_size, int *buffer_used, @@ -2661,10 +2681,12 @@ void ED_gpencil_sbuffer_update_eval(bGPdata *gpd, Object *ob_eval) gpd_eval->runtime.cp_points = gpd->runtime.cp_points; } -/* Tag all scene grease pencil object to update. */ +/** + * Tag all scene grease pencil object to update. + */ void ED_gpencil_tag_scene_gpencil(Scene *scene) { - /* mark all grease pencil datablocks of the scene */ + /* Mark all grease pencil data-blocks of the scene. */ FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { if (ob->type == OB_GPENCIL) { @@ -2748,7 +2770,7 @@ void ED_gpencil_init_random_settings(Brush *brush, random_settings->pressure = BLI_hash_int_01(BLI_hash_int_2d(ix + iz, iy + iz)) * 2.0f - 1.0f; } - /* Randomn to color strength. */ + /* Random to color strength. */ if (brush_settings->draw_random_strength) { random_settings->strength = BLI_hash_int_01(BLI_hash_int_2d(ix + iy, iy + iz + ix)) * 2.0f - 1.0f; @@ -2881,8 +2903,8 @@ void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, /* Random Color. */ gpencil_sbuffer_vertex_color_random(gpd, brush, tpt, random_color, pen_pressure); - /* Copy to eval data because paint operators don't tag refresh until end for speedup - painting. */ + /* Copy to evaluate data because paint operators don't tag refresh until end for speedup + * painting. */ if (gpd_eval != NULL) { copy_v4_v4(gpd_eval->runtime.vert_color_fill, gpd->runtime.vert_color_fill); gpd_eval->runtime.matid = gpd->runtime.matid; @@ -2908,12 +2930,12 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, /* Convert bound box to 2d */ copy_v3_v3(&pt_dummy.x, gps->boundbox_min); - gp_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); - gp_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_min[0], &boundbox_min[1]); + gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); + gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_min[0], &boundbox_min[1]); copy_v3_v3(&pt_dummy.x, gps->boundbox_max); - gp_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); - gp_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_max[0], &boundbox_max[1]); + gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps); + gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_max[0], &boundbox_max[1]); /* Ensure the bounding box is oriented to axis. */ if (boundbox_max[0] < boundbox_min[0]) { @@ -2925,7 +2947,7 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, rcti rect_stroke = {boundbox_min[0], boundbox_max[0], boundbox_min[1], boundbox_max[1]}; - /* For mouse, add a small offet to avoid false negative in corners. */ + /* For mouse, add a small offset to avoid false negative in corners. */ rcti rect_mouse = {mouse[0] - offset, mouse[0] + offset, mouse[1] - offset, mouse[1] + offset}; /* Check collision between both rectangles. */ @@ -2933,12 +2955,13 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, } /** - * Check if a point is inside of the stroke - * \param gps: Stroke to check - * \param gsc: SpaceConversion data - * \param mouse: Mouse position - * \param diff_mat: View matrix - * \return True if the point is inside + * Check if a point is inside of the stroke. + * + * \param gps: Stroke to check. + * \param gsc: Space conversion data. + * \param mouse: Mouse position. + * \param diff_mat: View matrix. + * \return True if the point is inside. */ bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps, GP_SpaceConversion *gsc, @@ -2959,11 +2982,11 @@ bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps, int i; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { bGPDspoint pt2; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); + gpencil_point_to_parent_space(pt, diff_mat, &pt2); + gpencil_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); } - /* Compute boundbox of lasso (for faster testing later). */ + /* Compute bound-box of lasso (for faster testing later). */ rcti rect; BLI_lasso_boundbox(&rect, mcoords, len); diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c index 0dfc7e0728e..e21b2049028 100644 --- a/source/blender/editors/gpencil/gpencil_uv.c +++ b/source/blender/editors/gpencil/gpencil_uv.c @@ -148,7 +148,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op) opdata->ob = CTX_data_active_object(C); opdata->gpd = (bGPdata *)opdata->ob->data; - gp_point_conversion_init(C, &opdata->gsc); + gpencil_point_conversion_init(C, &opdata->gsc); opdata->array_loc = NULL; opdata->array_rot = NULL; opdata->array_scale = NULL; @@ -197,7 +197,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op) GP_EDITABLE_STROKES_END(gpstroke_iter); } /* Convert to 2D. */ - gp_point_3d_to_xy(&opdata->gsc, GP_STROKE_3DSPACE, center, opdata->mcenter); + gpencil_point_3d_to_xy(&opdata->gsc, GP_STROKE_3DSPACE, center, opdata->mcenter); return true; } diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index 4db88bd552f..36ce7d3dc47 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -74,7 +74,7 @@ static const EnumPropertyItem gpencil_modesEnumPropertyItem_mode[] = { }; /* Poll callback for stroke vertex paint operator. */ -static bool gp_vertexpaint_mode_poll(bContext *C) +static bool gpencil_vertexpaint_mode_poll(bContext *C) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); @@ -97,7 +97,7 @@ static bool gp_vertexpaint_mode_poll(bContext *C) return false; } -static int gp_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator *op) +static int gpencil_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -178,8 +178,8 @@ void GPENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot) ot->description = "Adjust vertex color brightness/contrast"; /* api callbacks */ - ot->exec = gp_vertexpaint_brightness_contrast_exec; - ot->poll = gp_vertexpaint_mode_poll; + ot->exec = gpencil_vertexpaint_brightness_contrast_exec; + ot->poll = gpencil_vertexpaint_mode_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -192,7 +192,7 @@ void GPENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot) RNA_def_property_ui_range(prop, min, max, 1, 1); } -static int gp_vertexpaint_hsv_exec(bContext *C, wmOperator *op) +static int gpencil_vertexpaint_hsv_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -273,8 +273,8 @@ void GPENCIL_OT_vertex_color_hsv(wmOperatorType *ot) ot->description = "Adjust vertex color HSV values"; /* api callbacks */ - ot->exec = gp_vertexpaint_hsv_exec; - ot->poll = gp_vertexpaint_mode_poll; + ot->exec = gpencil_vertexpaint_hsv_exec; + ot->poll = gpencil_vertexpaint_mode_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -286,7 +286,7 @@ void GPENCIL_OT_vertex_color_hsv(wmOperatorType *ot) RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f); } -static int gp_vertexpaint_invert_exec(bContext *C, wmOperator *op) +static int gpencil_vertexpaint_invert_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -344,8 +344,8 @@ void GPENCIL_OT_vertex_color_invert(wmOperatorType *ot) ot->description = "Invert RGB values"; /* api callbacks */ - ot->exec = gp_vertexpaint_invert_exec; - ot->poll = gp_vertexpaint_mode_poll; + ot->exec = gpencil_vertexpaint_invert_exec; + ot->poll = gpencil_vertexpaint_mode_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -354,7 +354,7 @@ void GPENCIL_OT_vertex_color_invert(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", ""); } -static int gp_vertexpaint_levels_exec(bContext *C, wmOperator *op) +static int gpencil_vertexpaint_levels_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; @@ -413,8 +413,8 @@ void GPENCIL_OT_vertex_color_levels(wmOperatorType *ot) ot->description = "Adjust levels of vertex colors"; /* api callbacks */ - ot->exec = gp_vertexpaint_levels_exec; - ot->poll = gp_vertexpaint_mode_poll; + ot->exec = gpencil_vertexpaint_levels_exec; + ot->poll = gpencil_vertexpaint_mode_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -428,13 +428,13 @@ void GPENCIL_OT_vertex_color_levels(wmOperatorType *ot) ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply colors by", 0.0f, 10.0f); } -static int gp_vertexpaint_set_exec(bContext *C, wmOperator *op) +static int gpencil_vertexpaint_set_exec(bContext *C, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; Paint *paint = &ts->gp_vertexpaint->paint; - Brush *brush = brush = paint->brush; + Brush *brush = paint->brush; bool changed = false; int i; @@ -485,8 +485,8 @@ void GPENCIL_OT_vertex_color_set(wmOperatorType *ot) ot->description = "Set active color to all selected vertex"; /* api callbacks */ - ot->exec = gp_vertexpaint_set_exec; - ot->poll = gp_vertexpaint_mode_poll; + ot->exec = gpencil_vertexpaint_set_exec; + ot->poll = gpencil_vertexpaint_mode_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -497,7 +497,9 @@ void GPENCIL_OT_vertex_color_set(wmOperatorType *ot) } /* Helper to extract color from vertex color to create a palette. */ -static bool gp_extract_palette_from_vertex(bContext *C, const bool selected, const int threshold) +static bool gpencil_extract_palette_from_vertex(bContext *C, + const bool selected, + const int threshold) { Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); @@ -657,7 +659,7 @@ static uint get_material_type(MaterialGPencilStyle *gp_style, return r_i; } -static bool gp_material_to_vertex_poll(bContext *C) +static bool gpencil_material_to_vertex_poll(bContext *C) { /* only supported with grease pencil objects */ Object *ob = CTX_data_active_object(C); @@ -668,7 +670,7 @@ static bool gp_material_to_vertex_poll(bContext *C) return true; } -static int gp_material_to_vertex_exec(bContext *C, wmOperator *op) +static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); @@ -814,7 +816,7 @@ static int gp_material_to_vertex_exec(bContext *C, wmOperator *op) /* Generate a Palette. */ if (palette) { - gp_extract_palette_from_vertex(C, selected, 1); + gpencil_extract_palette_from_vertex(C, selected, 1); } /* Clean unused materials. */ @@ -834,8 +836,8 @@ void GPENCIL_OT_material_to_vertex_color(wmOperatorType *ot) ot->description = "Replace materials in strokes with Vertex Color"; /* api callbacks */ - ot->exec = gp_material_to_vertex_exec; - ot->poll = gp_material_to_vertex_poll; + ot->exec = gpencil_material_to_vertex_exec; + ot->poll = gpencil_material_to_vertex_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -852,7 +854,7 @@ void GPENCIL_OT_material_to_vertex_color(wmOperatorType *ot) } /* Extract Palette from Vertex Color. */ -static bool gp_extract_palette_vertex_poll(bContext *C) +static bool gpencil_extract_palette_vertex_poll(bContext *C) { /* only supported with grease pencil objects */ Object *ob = CTX_data_active_object(C); @@ -863,12 +865,12 @@ static bool gp_extract_palette_vertex_poll(bContext *C) return true; } -static int gp_extract_palette_vertex_exec(bContext *C, wmOperator *op) +static int gpencil_extract_palette_vertex_exec(bContext *C, wmOperator *op) { const bool selected = RNA_boolean_get(op->ptr, "selected"); const int threshold = RNA_int_get(op->ptr, "threshold"); - if (gp_extract_palette_from_vertex(C, selected, threshold)) { + if (gpencil_extract_palette_from_vertex(C, selected, threshold)) { BKE_reportf(op->reports, RPT_INFO, "Palette created"); } else { @@ -886,8 +888,8 @@ void GPENCIL_OT_extract_palette_vertex(wmOperatorType *ot) ot->description = "Extract all colors used in Grease Pencil Vertex and create a Palette"; /* api callbacks */ - ot->exec = gp_extract_palette_vertex_exec; - ot->poll = gp_extract_palette_vertex_poll; + ot->exec = gpencil_extract_palette_vertex_exec; + ot->poll = gpencil_extract_palette_vertex_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index fe3f0871fdc..99d55350527 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -263,7 +263,7 @@ static void brush_calc_dvec_2d(tGP_BrushVertexpaintData *gso) * number of pixels (see: GP_GRID_PIXEL_SIZE) */ -static void gp_grid_cells_init(tGP_BrushVertexpaintData *gso) +static void gpencil_grid_cells_init(tGP_BrushVertexpaintData *gso) { tGP_Grid *grid; float bottom[2]; @@ -298,7 +298,7 @@ static void gp_grid_cells_init(tGP_BrushVertexpaintData *gso) } /* Get the index used in the grid base on dvec. */ -static void gp_grid_cell_average_color_idx_get(tGP_BrushVertexpaintData *gso, int r_idx[2]) +static void gpencil_grid_cell_average_color_idx_get(tGP_BrushVertexpaintData *gso, int r_idx[2]) { /* Lower direction. */ if (gso->dvec[1] < 0.0f) { @@ -348,7 +348,7 @@ static void gp_grid_cell_average_color_idx_get(tGP_BrushVertexpaintData *gso, in } } -static int gp_grid_cell_index_get(tGP_BrushVertexpaintData *gso, int pc[2]) +static int gpencil_grid_cell_index_get(tGP_BrushVertexpaintData *gso, int pc[2]) { float bottom[2], top[2]; @@ -366,7 +366,7 @@ static int gp_grid_cell_index_get(tGP_BrushVertexpaintData *gso, int pc[2]) } /* Fill the grid with the color in each cell and assign point cell index. */ -static void gp_grid_colors_calc(tGP_BrushVertexpaintData *gso) +static void gpencil_grid_colors_calc(tGP_BrushVertexpaintData *gso) { tGP_Selected *selected = NULL; bGPDstroke *gps_selected = NULL; @@ -383,7 +383,7 @@ static void gp_grid_colors_calc(tGP_BrushVertexpaintData *gso) selected = &gso->pbuffer[i]; gps_selected = selected->gps; pt = &gps_selected->points[selected->pt_index]; - int grid_index = gp_grid_cell_index_get(gso, selected->pc); + int grid_index = gpencil_grid_cell_index_get(gso, selected->pc); if (grid_index > -1) { grid = &gso->grid[grid_index]; @@ -639,7 +639,7 @@ static bool brush_smear_apply(tGP_BrushVertexpaintData *gso, /* Need get average colors in the grid. */ if ((!gso->grid_ready) && (gso->pbuffer_used > 0)) { - gp_grid_colors_calc(gso); + gpencil_grid_colors_calc(gso); } /* The influence is equal to strength and no decay around brush radius. */ @@ -657,10 +657,10 @@ static bool brush_smear_apply(tGP_BrushVertexpaintData *gso, inf *= fac; /* Retry row and col for average color. */ - gp_grid_cell_average_color_idx_get(gso, average_idx); + gpencil_grid_cell_average_color_idx_get(gso, average_idx); /* Retry average color cell. */ - int grid_index = gp_grid_cell_index_get(gso, selected->pc); + int grid_index = gpencil_grid_cell_index_get(gso, selected->pc); if (grid_index > -1) { int row = grid_index / gso->grid_size; int col = grid_index - (gso->grid_size * row); @@ -700,7 +700,7 @@ static bool brush_smear_apply(tGP_BrushVertexpaintData *gso, /* ************************************************ */ /* Header Info */ -static void gp_vertexpaint_brush_header_set(bContext *C) +static void gpencil_vertexpaint_brush_header_set(bContext *C) { ED_workspace_status_text(C, TIP_("GPencil Vertex Paint: LMB to paint | RMB/Escape to Exit" @@ -712,7 +712,7 @@ static void gp_vertexpaint_brush_header_set(bContext *C) /* Init/Exit ----------------------------------------------- */ -static bool gp_vertexpaint_brush_init(bContext *C, wmOperator *op) +static bool gpencil_vertexpaint_brush_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -765,15 +765,15 @@ static bool gp_vertexpaint_brush_init(bContext *C, wmOperator *op) } /* Setup space conversions. */ - gp_point_conversion_init(C, &gso->gsc); + gpencil_point_conversion_init(C, &gso->gsc); /* Update header. */ - gp_vertexpaint_brush_header_set(C); + gpencil_vertexpaint_brush_header_set(C); return true; } -static void gp_vertexpaint_brush_exit(bContext *C, wmOperator *op) +static void gpencil_vertexpaint_brush_exit(bContext *C, wmOperator *op) { tGP_BrushVertexpaintData *gso = op->customdata; @@ -791,17 +791,17 @@ static void gp_vertexpaint_brush_exit(bContext *C, wmOperator *op) } /* Poll callback for stroke vertex paint operator. */ -static bool gp_vertexpaint_brush_poll(bContext *C) +static bool gpencil_vertexpaint_brush_poll(bContext *C) { /* NOTE: this is a bit slower, but is the most accurate... */ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0; } /* Helper to save the points selected by the brush. */ -static void gp_save_selected_point(tGP_BrushVertexpaintData *gso, - bGPDstroke *gps, - int index, - int pc[2]) +static void gpencil_save_selected_point(tGP_BrushVertexpaintData *gso, + bGPDstroke *gps, + int index, + int pc[2]) { tGP_Selected *selected; bGPDspoint *pt = &gps->points[index]; @@ -822,10 +822,10 @@ static void gp_save_selected_point(tGP_BrushVertexpaintData *gso, } /* Select points in this stroke and add to an array to be used later. */ -static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, - bGPDstroke *gps, - const char tool, - const float diff_mat[4][4]) +static void gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, + bGPDstroke *gps, + const char tool, + const float diff_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -851,8 +851,8 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; - gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); - gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp); + gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* do boundbox check first */ @@ -863,7 +863,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, if (len_v2v2_int(mval_i, pc1) <= radius) { /* apply operation to this point */ if (pt_active != NULL) { - gp_save_selected_point(gso, gps_active, 0, pc1); + gpencil_save_selected_point(gso, gps_active, 0, pc1); } } } @@ -888,11 +888,11 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, } bGPDspoint npt; - gp_point_to_parent_space(pt1, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(pt1, diff_mat, &npt); + gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]); - gp_point_to_parent_space(pt2, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]); + gpencil_point_to_parent_space(pt2, diff_mat, &npt); + gpencil_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]); /* Check that point segment of the boundbox of the selection stroke */ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) || @@ -901,7 +901,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, * brush region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* To each point individually... */ pt = &gps->points[i]; @@ -914,7 +914,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, continue; } hit = true; - gp_save_selected_point(gso, gps_active, index, pc1); + gpencil_save_selected_point(gso, gps_active, index, pc1); } /* Only do the second point if this is the last segment, @@ -931,7 +931,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1; if (pt_active != NULL) { hit = true; - gp_save_selected_point(gso, gps_active, index, pc2); + gpencil_save_selected_point(gso, gps_active, index, pc2); include_last = false; } } @@ -950,7 +950,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if (pt_active != NULL) { hit = true; - gp_save_selected_point(gso, gps_active, index, pc1); + gpencil_save_selected_point(gso, gps_active, index, pc1); include_last = false; } @@ -970,7 +970,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, /* Need repeat the effect because if we don't do that the tint process * is very slow. */ for (int repeat = 0; repeat < 50; repeat++) { - gp_save_selected_point(gso, gps_active, -1, NULL); + gpencil_save_selected_point(gso, gps_active, -1, NULL); } } } @@ -979,11 +979,11 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, } /* Apply vertex paint brushes to strokes in the given frame. */ -static bool gp_vertexpaint_brush_do_frame(bContext *C, - tGP_BrushVertexpaintData *gso, - bGPDlayer *gpl, - bGPDframe *gpf, - const float diff_mat[4][4]) +static bool gpencil_vertexpaint_brush_do_frame(bContext *C, + tGP_BrushVertexpaintData *gso, + bGPDlayer *gpl, + bGPDframe *gpf, + const float diff_mat[4][4]) { Object *ob = CTX_data_active_object(C); const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : @@ -1010,7 +1010,7 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C, } /* Check points below the brush. */ - gp_vertexpaint_select_stroke(gso, gps, tool, diff_mat); + gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat); } /* For Average tool, need calculate the average resulting color from all colors @@ -1092,7 +1092,7 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C, } /* Apply brush effect to all layers. */ -static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpaintData *gso) +static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpaintData *gso) { ToolSettings *ts = CTX_data_tool_settings(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -1138,7 +1138,7 @@ static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpai } /* affect strokes in this frame */ - changed |= gp_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); } } } @@ -1146,7 +1146,7 @@ static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpai /* Apply to active frame's strokes */ if (gpl->actframe != NULL) { gso->mf_falloff = 1.0f; - changed |= gp_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); } } } @@ -1155,7 +1155,7 @@ static bool gp_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpai } /* Calculate settings for applying brush */ -static void gp_vertexpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) +static void gpencil_vertexpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) { tGP_BrushVertexpaintData *gso = op->customdata; Brush *brush = gso->brush; @@ -1196,9 +1196,9 @@ static void gp_vertexpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA * brush_calc_dvec_2d(gso); /* Calc grid for smear tool. */ - gp_grid_cells_init(gso); + gpencil_grid_cells_init(gso); - changed = gp_vertexpaint_brush_apply_to_layers(C, gso); + changed = gpencil_vertexpaint_brush_apply_to_layers(C, gso); /* Updates */ if (changed) { @@ -1216,7 +1216,9 @@ static void gp_vertexpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA * /* Running --------------------------------------------- */ /* helper - a record stroke, and apply paint event */ -static void gp_vertexpaint_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event) +static void gpencil_vertexpaint_brush_apply_event(bContext *C, + wmOperator *op, + const wmEvent *event) { tGP_BrushVertexpaintData *gso = op->customdata; PointerRNA itemptr; @@ -1238,28 +1240,28 @@ static void gp_vertexpaint_brush_apply_event(bContext *C, wmOperator *op, const RNA_float_set(&itemptr, "pressure", pressure); /* apply */ - gp_vertexpaint_brush_apply(C, op, &itemptr); + gpencil_vertexpaint_brush_apply(C, op, &itemptr); } /* reapply */ -static int gp_vertexpaint_brush_exec(bContext *C, wmOperator *op) +static int gpencil_vertexpaint_brush_exec(bContext *C, wmOperator *op) { - if (!gp_vertexpaint_brush_init(C, op)) { + if (!gpencil_vertexpaint_brush_init(C, op)) { return OPERATOR_CANCELLED; } RNA_BEGIN (op->ptr, itemptr, "stroke") { - gp_vertexpaint_brush_apply(C, op, &itemptr); + gpencil_vertexpaint_brush_apply(C, op, &itemptr); } RNA_END; - gp_vertexpaint_brush_exit(C, op); + gpencil_vertexpaint_brush_exit(C, op); return OPERATOR_FINISHED; } /* start modal painting */ -static int gp_vertexpaint_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int gpencil_vertexpaint_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushVertexpaintData *gso = NULL; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -1273,7 +1275,7 @@ static int gp_vertexpaint_brush_invoke(bContext *C, wmOperator *op, const wmEven } /* init painting data */ - if (!gp_vertexpaint_brush_init(C, op)) { + if (!gpencil_vertexpaint_brush_init(C, op)) { return OPERATOR_CANCELLED; } @@ -1288,7 +1290,7 @@ static int gp_vertexpaint_brush_invoke(bContext *C, wmOperator *op, const wmEven /* apply first dab... */ gso->is_painting = true; - gp_vertexpaint_brush_apply_event(C, op, event); + gpencil_vertexpaint_brush_apply_event(C, op, event); /* redraw view with feedback */ ED_region_tag_redraw(region); @@ -1298,7 +1300,7 @@ static int gp_vertexpaint_brush_invoke(bContext *C, wmOperator *op, const wmEven } /* painting - handle events */ -static int gp_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event) +static int gpencil_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushVertexpaintData *gso = op->customdata; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -1313,7 +1315,7 @@ static int gp_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent case MOUSEMOVE: case INBETWEEN_MOUSEMOVE: /* apply brush effect at new position */ - gp_vertexpaint_brush_apply_event(C, op, event); + gpencil_vertexpaint_brush_apply_event(C, op, event); /* force redraw, so that the cursor will at least be valid */ redraw_region = true; @@ -1329,7 +1331,7 @@ static int gp_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent /* end painting, since we're not modal */ gso->is_painting = false; - gp_vertexpaint_brush_exit(C, op); + gpencil_vertexpaint_brush_exit(C, op); return OPERATOR_FINISHED; } break; @@ -1338,7 +1340,7 @@ static int gp_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent case MIDDLEMOUSE: case RIGHTMOUSE: case EVT_ESCKEY: - gp_vertexpaint_brush_exit(C, op); + gpencil_vertexpaint_brush_exit(C, op); return OPERATOR_FINISHED; } } @@ -1353,13 +1355,13 @@ static int gp_vertexpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent gso->is_painting = true; gso->first = true; - gp_vertexpaint_brush_apply_event(C, op, event); + gpencil_vertexpaint_brush_apply_event(C, op, event); break; /* Exit modal operator, based on the "standard" ops */ case RIGHTMOUSE: case EVT_ESCKEY: - gp_vertexpaint_brush_exit(C, op); + gpencil_vertexpaint_brush_exit(C, op); return OPERATOR_FINISHED; /* MMB is often used for view manipulations */ @@ -1421,11 +1423,11 @@ void GPENCIL_OT_vertex_paint(wmOperatorType *ot) ot->description = "Paint stroke points with a color"; /* api callbacks */ - ot->exec = gp_vertexpaint_brush_exec; - ot->invoke = gp_vertexpaint_brush_invoke; - ot->modal = gp_vertexpaint_brush_modal; - ot->cancel = gp_vertexpaint_brush_exit; - ot->poll = gp_vertexpaint_brush_poll; + ot->exec = gpencil_vertexpaint_brush_exec; + ot->invoke = gpencil_vertexpaint_brush_invoke; + ot->modal = gpencil_vertexpaint_brush_modal; + ot->cancel = gpencil_vertexpaint_brush_exit; + ot->poll = gpencil_vertexpaint_brush_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 2ebf1aba353..e41146575e4 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -268,7 +268,7 @@ static bool brush_draw_apply(tGP_BrushWeightpaintData *gso, /* ************************************************ */ /* Header Info */ -static void gp_weightpaint_brush_header_set(bContext *C) +static void gpencil_weightpaint_brush_header_set(bContext *C) { ED_workspace_status_text(C, TIP_("GPencil Weight Paint: LMB to paint | RMB/Escape to Exit")); } @@ -278,7 +278,7 @@ static void gp_weightpaint_brush_header_set(bContext *C) /* Init/Exit ----------------------------------------------- */ -static bool gp_weightpaint_brush_init(bContext *C, wmOperator *op) +static bool gpencil_weightpaint_brush_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -330,15 +330,15 @@ static bool gp_weightpaint_brush_init(bContext *C, wmOperator *op) } /* Setup space conversions. */ - gp_point_conversion_init(C, &gso->gsc); + gpencil_point_conversion_init(C, &gso->gsc); /* Update header. */ - gp_weightpaint_brush_header_set(C); + gpencil_weightpaint_brush_header_set(C); return true; } -static void gp_weightpaint_brush_exit(bContext *C, wmOperator *op) +static void gpencil_weightpaint_brush_exit(bContext *C, wmOperator *op) { tGP_BrushWeightpaintData *gso = op->customdata; @@ -352,17 +352,17 @@ static void gp_weightpaint_brush_exit(bContext *C, wmOperator *op) } /* Poll callback for stroke weight paint operator. */ -static bool gp_weightpaint_brush_poll(bContext *C) +static bool gpencil_weightpaint_brush_poll(bContext *C) { /* NOTE: this is a bit slower, but is the most accurate... */ return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0; } /* Helper to save the points selected by the brush. */ -static void gp_save_selected_point(tGP_BrushWeightpaintData *gso, - bGPDstroke *gps, - int index, - int pc[2]) +static void gpencil_save_selected_point(tGP_BrushWeightpaintData *gso, + bGPDstroke *gps, + int index, + int pc[2]) { tGP_Selected *selected; bGPDspoint *pt = &gps->points[index]; @@ -381,9 +381,9 @@ static void gp_save_selected_point(tGP_BrushWeightpaintData *gso, } /* Select points in this stroke and add to an array to be used later. */ -static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, - bGPDstroke *gps, - const float diff_mat[4][4]) +static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, + bGPDstroke *gps, + const float diff_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -409,8 +409,8 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; - gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); - gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp); + gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* do boundbox check first */ @@ -421,7 +421,7 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, if (len_v2v2_int(mval_i, pc1) <= radius) { /* apply operation to this point */ if (pt_active != NULL) { - gp_save_selected_point(gso, gps_active, 0, pc1); + gpencil_save_selected_point(gso, gps_active, 0, pc1); } } } @@ -436,11 +436,11 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, pt2 = gps->points + i + 1; bGPDspoint npt; - gp_point_to_parent_space(pt1, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]); + gpencil_point_to_parent_space(pt1, diff_mat, &npt); + gpencil_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]); - gp_point_to_parent_space(pt2, diff_mat, &npt); - gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]); + gpencil_point_to_parent_space(pt2, diff_mat, &npt); + gpencil_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]); /* Check that point segment of the boundbox of the selection stroke */ if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) || @@ -449,14 +449,14 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, * brush region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gpencil_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* To each point individually... */ pt = &gps->points[i]; pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if (pt_active != NULL) { - gp_save_selected_point(gso, gps_active, index, pc1); + gpencil_save_selected_point(gso, gps_active, index, pc1); } /* Only do the second point if this is the last segment, @@ -472,7 +472,7 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1; if (pt_active != NULL) { - gp_save_selected_point(gso, gps_active, index, pc2); + gpencil_save_selected_point(gso, gps_active, index, pc2); include_last = false; } } @@ -490,7 +490,7 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if (pt_active != NULL) { - gp_save_selected_point(gso, gps_active, index, pc1); + gpencil_save_selected_point(gso, gps_active, index, pc1); include_last = false; } @@ -501,11 +501,11 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, } /* Apply weight paint brushes to strokes in the given frame. */ -static bool gp_weightpaint_brush_do_frame(bContext *C, - tGP_BrushWeightpaintData *gso, - bGPDlayer *gpl, - bGPDframe *gpf, - const float diff_mat[4][4]) +static bool gpencil_weightpaint_brush_do_frame(bContext *C, + tGP_BrushWeightpaintData *gso, + bGPDlayer *gpl, + bGPDframe *gpf, + const float diff_mat[4][4]) { Object *ob = CTX_data_active_object(C); char tool = gso->brush->gpencil_weight_tool; @@ -531,7 +531,7 @@ static bool gp_weightpaint_brush_do_frame(bContext *C, } /* Check points below the brush. */ - gp_weightpaint_select_stroke(gso, gps, diff_mat); + gpencil_weightpaint_select_stroke(gso, gps, diff_mat); } /*--------------------------------------------------------------------- @@ -561,7 +561,7 @@ static bool gp_weightpaint_brush_do_frame(bContext *C, } /* Apply brush effect to all layers. */ -static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpaintData *gso) +static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpaintData *gso) { ToolSettings *ts = CTX_data_tool_settings(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -608,7 +608,7 @@ static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpai } /* affect strokes in this frame */ - changed |= gp_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); } } } @@ -616,7 +616,7 @@ static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpai if (gpl->actframe != NULL) { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gp_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); } } } @@ -625,7 +625,7 @@ static bool gp_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeightpai } /* Calculate settings for applying brush */ -static void gp_weightpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) +static void gpencil_weightpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) { tGP_BrushWeightpaintData *gso = op->customdata; Brush *brush = gso->brush; @@ -658,7 +658,7 @@ static void gp_weightpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA * /* Calculate 2D direction vector and relative angle. */ brush_calc_dvec_2d(gso); - changed = gp_weightpaint_brush_apply_to_layers(C, gso); + changed = gpencil_weightpaint_brush_apply_to_layers(C, gso); /* Updates */ if (changed) { @@ -676,7 +676,9 @@ static void gp_weightpaint_brush_apply(bContext *C, wmOperator *op, PointerRNA * /* Running --------------------------------------------- */ /* helper - a record stroke, and apply paint event */ -static void gp_weightpaint_brush_apply_event(bContext *C, wmOperator *op, const wmEvent *event) +static void gpencil_weightpaint_brush_apply_event(bContext *C, + wmOperator *op, + const wmEvent *event) { tGP_BrushWeightpaintData *gso = op->customdata; PointerRNA itemptr; @@ -698,28 +700,28 @@ static void gp_weightpaint_brush_apply_event(bContext *C, wmOperator *op, const RNA_float_set(&itemptr, "pressure", pressure); /* apply */ - gp_weightpaint_brush_apply(C, op, &itemptr); + gpencil_weightpaint_brush_apply(C, op, &itemptr); } /* reapply */ -static int gp_weightpaint_brush_exec(bContext *C, wmOperator *op) +static int gpencil_weightpaint_brush_exec(bContext *C, wmOperator *op) { - if (!gp_weightpaint_brush_init(C, op)) { + if (!gpencil_weightpaint_brush_init(C, op)) { return OPERATOR_CANCELLED; } RNA_BEGIN (op->ptr, itemptr, "stroke") { - gp_weightpaint_brush_apply(C, op, &itemptr); + gpencil_weightpaint_brush_apply(C, op, &itemptr); } RNA_END; - gp_weightpaint_brush_exit(C, op); + gpencil_weightpaint_brush_exit(C, op); return OPERATOR_FINISHED; } /* start modal painting */ -static int gp_weightpaint_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int gpencil_weightpaint_brush_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushWeightpaintData *gso = NULL; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -733,7 +735,7 @@ static int gp_weightpaint_brush_invoke(bContext *C, wmOperator *op, const wmEven } /* init painting data */ - if (!gp_weightpaint_brush_init(C, op)) { + if (!gpencil_weightpaint_brush_init(C, op)) { return OPERATOR_CANCELLED; } @@ -748,7 +750,7 @@ static int gp_weightpaint_brush_invoke(bContext *C, wmOperator *op, const wmEven /* apply first dab... */ gso->is_painting = true; - gp_weightpaint_brush_apply_event(C, op, event); + gpencil_weightpaint_brush_apply_event(C, op, event); /* redraw view with feedback */ ED_region_tag_redraw(region); @@ -758,7 +760,7 @@ static int gp_weightpaint_brush_invoke(bContext *C, wmOperator *op, const wmEven } /* painting - handle events */ -static int gp_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event) +static int gpencil_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGP_BrushWeightpaintData *gso = op->customdata; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -773,7 +775,7 @@ static int gp_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent case MOUSEMOVE: case INBETWEEN_MOUSEMOVE: /* apply brush effect at new position */ - gp_weightpaint_brush_apply_event(C, op, event); + gpencil_weightpaint_brush_apply_event(C, op, event); /* force redraw, so that the cursor will at least be valid */ redraw_region = true; @@ -789,7 +791,7 @@ static int gp_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent /* end painting, since we're not modal */ gso->is_painting = false; - gp_weightpaint_brush_exit(C, op); + gpencil_weightpaint_brush_exit(C, op); return OPERATOR_FINISHED; } break; @@ -798,7 +800,7 @@ static int gp_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent case MIDDLEMOUSE: case RIGHTMOUSE: case EVT_ESCKEY: - gp_weightpaint_brush_exit(C, op); + gpencil_weightpaint_brush_exit(C, op); return OPERATOR_FINISHED; } } @@ -813,13 +815,13 @@ static int gp_weightpaint_brush_modal(bContext *C, wmOperator *op, const wmEvent gso->is_painting = true; gso->first = true; - gp_weightpaint_brush_apply_event(C, op, event); + gpencil_weightpaint_brush_apply_event(C, op, event); break; /* Exit modal operator, based on the "standard" ops */ case RIGHTMOUSE: case EVT_ESCKEY: - gp_weightpaint_brush_exit(C, op); + gpencil_weightpaint_brush_exit(C, op); return OPERATOR_FINISHED; /* MMB is often used for view manipulations */ @@ -881,11 +883,11 @@ void GPENCIL_OT_weight_paint(wmOperatorType *ot) ot->description = "Paint stroke points with a color"; /* api callbacks */ - ot->exec = gp_weightpaint_brush_exec; - ot->invoke = gp_weightpaint_brush_invoke; - ot->modal = gp_weightpaint_brush_modal; - ot->cancel = gp_weightpaint_brush_exit; - ot->poll = gp_weightpaint_brush_poll; + ot->exec = gpencil_weightpaint_brush_exec; + ot->invoke = gpencil_weightpaint_brush_invoke; + ot->modal = gpencil_weightpaint_brush_modal; + ot->cancel = gpencil_weightpaint_brush_exit; + ot->poll = gpencil_weightpaint_brush_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 426a470b128..3aecec0d6b6 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -281,10 +281,13 @@ typedef enum eAnim_Update_Flags { /* filtering flags - under what circumstances should a channel be returned */ typedef enum eAnimFilter_Flags { - /** data which channel represents is fits the dopesheet filters - * (i.e. scene visibility criteria) */ - /* XXX: it's hard to think of any examples where this *ISN'T* the case... - * perhaps becomes implicit?. */ + /** + * Data which channel represents is fits the dope-sheet filters + * (i.e. scene visibility criteria). + * + * XXX: it's hard to think of any examples where this *ISN'T* the case... + * perhaps becomes implicit?. + */ ANIMFILTER_DATA_VISIBLE = (1 << 0), /** channel is visible within the channel-list hierarchy * (i.e. F-Curves within Groups in ActEdit) */ @@ -297,7 +300,7 @@ typedef enum eAnimFilter_Flags { /** for its type, channel should be "active" one */ ANIMFILTER_ACTIVE = (1 << 4), - /** channel is a child of the active group (* Actions speciality) */ + /** channel is a child of the active group (* Actions specialty) */ ANIMFILTER_ACTGROUPED = (1 << 5), /** channel must be selected/not-selected, but both must not be set together */ @@ -310,8 +313,10 @@ typedef enum eAnimFilter_Flags { * for Graph Editor's option for keys on select curves only */ ANIMFILTER_SELEDIT = (1 << 9), - /** flags used to enforce certain data types - * \node the ones for curves and NLA tracks were redundant and have been removed for now... + /** + * Flags used to enforce certain data types. + * + * \note The ones for curves and NLA tracks were redundant and have been removed for now. */ ANIMFILTER_ANIMDATA = (1 << 10), @@ -321,7 +326,7 @@ typedef enum eAnimFilter_Flags { /** for checking if we should keep some collapsed channel around (internal use only!) */ ANIMFILTER_TMP_PEEK = (1 << 30), - /** ignore ONLYSEL flag from filterflag, (internal use only!) */ + /** Ignore ONLYSEL flag from #bDopeSheet.filterflag (internal use only!) */ ANIMFILTER_TMP_IGNORE_ONLYSEL = (1u << 31), } eAnimFilter_Flags; @@ -640,14 +645,14 @@ bool ANIM_remove_empty_action_from_animdata(struct AnimData *adt); /* ---------- Current Frame Drawing ---------------- */ /* flags for Current Frame Drawing */ -enum eAnimEditDraw_CurrentFrame { +typedef enum eAnimEditDraw_CurrentFrame { /* plain time indicator with no special indicators */ /* DRAWCFRA_PLAIN = 0, */ /* UNUSED */ /* time indication in seconds or frames */ DRAWCFRA_UNIT_SECONDS = (1 << 0), /* draw indicator extra wide (for timeline) */ DRAWCFRA_WIDE = (1 << 1), -}; +} eAnimEditDraw_CurrentFrame; /* main call to draw current-frame indicator in an Animation Editor */ void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag); diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 541e2633512..eef431c40fa 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -174,7 +174,7 @@ void ED_operatormacros_armature(void); void ED_keymap_armature(struct wmKeyConfig *keyconf); /* armature_relations.c */ -int join_armature_exec(struct bContext *C, struct wmOperator *op); +int ED_armature_join_objects_exec(struct bContext *C, struct wmOperator *op); /* armature_select.c */ struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases, diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 95c454043da..79f5f62f293 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -66,7 +66,7 @@ int ED_curve_nurb_select_count(struct View3D *v3d, struct Nurb *nu); bool ED_curve_nurb_select_all(const struct Nurb *nu); bool ED_curve_nurb_deselect_all(const struct Nurb *nu); -int join_curve_exec(struct bContext *C, struct wmOperator *op); +int ED_curve_join_objects_exec(struct bContext *C, struct wmOperator *op); /* editcurve_select.c */ bool ED_curve_select_check(struct View3D *v3d, struct EditNurb *editnurb); diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 2a1d9c2dd6c..f961f835f12 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -87,15 +87,24 @@ typedef enum eGP_ReprojectModes { * Used as part of the 'stroke cache' used during drawing of new strokes */ typedef struct tGPspoint { - float x, y; /* x and y coordinates of cursor (in relative to area) */ - float pressure; /* pressure of tablet at this point */ - float strength; /* pressure of tablet at this point for alpha factor */ - float time; /* Time relative to stroke start (used when converting to path) */ - float uv_fac; /* factor of uv along the stroke */ - float uv_rot; /* uv rotation for dor mode */ - float rnd[3]; /* rnd value */ - bool rnd_dirty; /* rnd flag */ - float vert_color[4]; /* Point vertex color. */ + /** Coordinates x and y of cursor (in relative to area). */ + float x, y; + /** Pressure of tablet at this point. */ + float pressure; + /** Pressure of tablet at this point for alpha factor. */ + float strength; + /** Time relative to stroke start (used when converting to path). */ + float time; + /** Factor of uv along the stroke. */ + float uv_fac; + /** UV rotation for dot mode. */ + float uv_rot; + /** Random value. */ + float rnd[3]; + /** Random flag. */ + bool rnd_dirty; + /** Point vertex color. */ + float vert_color[4]; } tGPspoint; /* ----------- Grease Pencil Tools/Context ------------- */ @@ -166,28 +175,31 @@ void ED_annotation_draw_ex(struct Scene *scene, const char spacetype); /* ----------- Grease-Pencil AnimEdit API ------------------ */ -bool ED_gplayer_frames_looper(struct bGPDlayer *gpl, - struct Scene *scene, - short (*gpf_cb)(struct bGPDframe *, struct Scene *)); -void ED_gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, bool onlysel); - -bool ED_gplayer_frame_select_check(struct bGPDlayer *gpl); -void ED_gplayer_frame_select_set(struct bGPDlayer *gpl, short mode); -void ED_gplayer_frames_select_box(struct bGPDlayer *gpl, float min, float max, short select_mode); -void ED_gplayer_frames_select_region(struct KeyframeEditData *ked, - struct bGPDlayer *gpl, - short tool, - short select_mode); +bool ED_gpencil_layer_frames_looper(struct bGPDlayer *gpl, + struct Scene *scene, + short (*gpf_cb)(struct bGPDframe *, struct Scene *)); +void ED_gpencil_layer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, bool onlysel); + +bool ED_gpencil_layer_frame_select_check(struct bGPDlayer *gpl); +void ED_gpencil_layer_frame_select_set(struct bGPDlayer *gpl, short mode); +void ED_gpencil_layer_frames_select_box(struct bGPDlayer *gpl, + float min, + float max, + short select_mode); +void ED_gpencil_layer_frames_select_region(struct KeyframeEditData *ked, + struct bGPDlayer *gpl, + short tool, + short select_mode); void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode); void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode); -bool ED_gplayer_frames_delete(struct bGPDlayer *gpl); -void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl); +bool ED_gpencil_layer_frames_delete(struct bGPDlayer *gpl); +void ED_gpencil_layer_frames_duplicate(struct bGPDlayer *gpl); -void ED_gplayer_frames_keytype_set(struct bGPDlayer *gpl, short type); +void ED_gpencil_layer_frames_keytype_set(struct bGPDlayer *gpl, short type); -void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode); -void ED_gplayer_mirror_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode); +void ED_gpencil_layer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode); +void ED_gpencil_layer_mirror_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode); void ED_gpencil_anim_copybuf_free(void); bool ED_gpencil_anim_copybuf_copy(struct bAnimContext *ac); @@ -242,18 +254,18 @@ void ED_gpencil_add_defaults(struct bContext *C, struct Object *ob); void ED_gpencil_setup_modes(struct bContext *C, struct bGPdata *gpd, int newmode); bool ED_object_gpencil_exit(struct Main *bmain, struct Object *ob); -void ED_gp_project_stroke_to_plane(const struct Scene *scene, - const struct Object *ob, - const struct RegionView3D *rv3d, - struct bGPDstroke *gps, - const float origin[3], - const int axis); -void ED_gp_project_point_to_plane(const struct Scene *scene, - const struct Object *ob, - const struct RegionView3D *rv3d, - const float origin[3], - const int axis, - struct bGPDspoint *pt); +void ED_gpencil_project_stroke_to_plane(const struct Scene *scene, + const struct Object *ob, + const struct RegionView3D *rv3d, + struct bGPDstroke *gps, + const float origin[3], + const int axis); +void ED_gpencil_project_point_to_plane(const struct Scene *scene, + const struct Object *ob, + const struct RegionView3D *rv3d, + const float origin[3], + const int axis, + struct bGPDspoint *pt); void ED_gpencil_drawing_reference_get(const struct Scene *scene, const struct Object *ob, char align_flag, diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h index 938d1059f90..5c2106b934c 100644 --- a/source/blender/editors/include/ED_mball.h +++ b/source/blender/editors/include/ED_mball.h @@ -38,8 +38,12 @@ void ED_operatortypes_metaball(void); void ED_operatormacros_metaball(void); void ED_keymap_metaball(struct wmKeyConfig *keyconf); -struct MetaElem *ED_mball_add_primitive( - struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type); +struct MetaElem *ED_mball_add_primitive(struct bContext *C, + struct Object *obedit, + bool obedit_is_new, + float mat[4][4], + float dia, + int type); bool ED_mball_select_pick( struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 20e54df1ccb..9c49d991182 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -426,6 +426,15 @@ bool ED_mesh_color_remove_index(struct Mesh *me, const int n); bool ED_mesh_color_remove_active(struct Mesh *me); bool ED_mesh_color_remove_named(struct Mesh *me, const char *name); +bool ED_mesh_sculpt_color_ensure(struct Mesh *me, const char *name); +int ED_mesh_sculpt_color_add(struct Mesh *me, + const char *name, + const bool active_set, + const bool do_init); +bool ED_mesh_sculpt_color_remove_index(struct Mesh *me, const int n); +bool ED_mesh_sculpt_color_remove_active(struct Mesh *me); +bool ED_mesh_sculpt_color_remove_named(struct Mesh *me, const char *name); + void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail); void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, char selectmode); @@ -445,8 +454,8 @@ void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalct void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess); /* *** meshtools.c *** */ -int join_mesh_exec(struct bContext *C, struct wmOperator *op); -int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op); +int ED_mesh_join_objects_exec(struct bContext *C, struct wmOperator *op); +int ED_mesh_shapes_join_objects_exec(struct bContext *C, struct wmOperator *op); /* mirror lookup api */ /* Spatial Mirror */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 5c33513f0a4..73c58753531 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -185,7 +185,7 @@ struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Base *base, - int dupflag); + const uint dupflag); void ED_object_parent(struct Object *ob, struct Object *parent, @@ -421,6 +421,10 @@ int ED_object_gpencil_modifier_move_down(struct ReportList *reports, int ED_object_gpencil_modifier_move_up(struct ReportList *reports, struct Object *ob, struct GpencilModifierData *md); +bool ED_object_gpencil_modifier_move_to_index(struct ReportList *reports, + struct Object *ob, + struct GpencilModifierData *md, + const int index); int ED_object_gpencil_modifier_apply(struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph, @@ -449,6 +453,10 @@ int ED_object_shaderfx_move_down(struct ReportList *reports, int ED_object_shaderfx_move_up(struct ReportList *reports, struct Object *ob, struct ShaderFxData *fx); +bool ED_object_shaderfx_move_to_index(struct ReportList *reports, + struct Object *ob, + struct ShaderFxData *fx, + const int index); /* object_select.c */ void ED_object_select_linked_by_id(struct bContext *C, struct ID *id); diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index f03739c74c4..ba70abcc055 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -47,7 +47,7 @@ void ED_operatortypes_render(void); /* render_update.c */ -void ED_render_engine_changed(struct Main *bmain); +void ED_render_engine_changed(struct Main *bmain, const bool update_scene_data); void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *area); void ED_render_view_layer_changed(struct Main *bmain, struct bScreen *screen); diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 51f3eea74fa..9826ec8c3b8 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -131,7 +131,7 @@ enum { */ AZONE_FULLSCREEN, /** - * Hotspot azone around scroll-bars to show/hide them. + * Hot-spot #AZone around scroll-bars to show/hide them. * Only show the scroll-bars when the cursor is close. */ AZONE_REGION_SCROLL, diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h index d5b9fa2a553..483dce56577 100644 --- a/source/blender/editors/include/ED_time_scrub_ui.h +++ b/source/blender/editors/include/ED_time_scrub_ui.h @@ -32,6 +32,11 @@ struct bContext; struct bDopeSheet; struct wmEvent; +void ED_time_scrub_draw_current_frame(const struct ARegion *region, + const struct Scene *scene, + bool display_seconds, + bool draw_vert_line); + void ED_time_scrub_draw(const struct ARegion *region, const struct Scene *scene, bool display_seconds, diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 59dcc9a8ace..1cedd4e122f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1706,12 +1706,17 @@ void UI_panel_category_draw_all(struct ARegion *region, const char *category_id_ struct PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname); +struct PointerRNA *UI_region_panel_custom_data_under_cursor(const struct bContext *C, + const struct wmEvent *event); +void UI_panel_custom_data_set(struct Panel *panel, struct PointerRNA *custom_data); + /* Polyinstantiated panels for representing a list of data. */ struct Panel *UI_panel_add_instanced(struct ScrArea *area, struct ARegion *region, struct ListBase *panels, char *panel_idname, - int list_index); + int list_index, + struct PointerRNA *custom_data); void UI_panels_free_instanced(struct bContext *C, struct ARegion *region); #define LIST_PANEL_UNIQUE_STR_LEN 4 @@ -2004,6 +2009,10 @@ void uiTemplatePathBuilder(uiLayout *layout, struct PointerRNA *root_ptr, const char *text); void uiTemplateModifiers(uiLayout *layout, struct bContext *C); +void uiTemplateGpencilModifiers(uiLayout *layout, struct bContext *C); +void uiTemplateShaderFx(uiLayout *layout, struct bContext *C); +void uiTemplateConstraints(uiLayout *layout, struct bContext *C, bool use_bone_constraints); + uiLayout *uiTemplateGpencilModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr); void uiTemplateGpencilColorPreview(uiLayout *layout, struct bContext *C, @@ -2014,11 +2023,9 @@ void uiTemplateGpencilColorPreview(uiLayout *layout, float scale, int filter); -uiLayout *uiTemplateShaderFx(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr); - void uiTemplateOperatorRedoProperties(uiLayout *layout, const struct bContext *C); -uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); +void uiTemplateConstraintHeader(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct bContext *C, struct ID *id, diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index a304c76bc9d..0529ee08da6 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -106,6 +106,7 @@ struct PreviewImage *UI_icon_to_preview(int icon_id); int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big); int UI_idcode_icon_get(const int idcode); +int UI_library_icon_get(const struct ID *id); #ifdef __cplusplus } diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index ffc06e94a90..0ddc45f4878 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -180,9 +180,10 @@ void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *region, int colorid); /* scrollbar drawing */ -View2DScrollers *UI_view2d_scrollers_calc(struct View2D *v2d, const struct rcti *mask_custom); -void UI_view2d_scrollers_draw(struct View2D *v2d, View2DScrollers *scrollers); -void UI_view2d_scrollers_free(View2DScrollers *scrollers); +void UI_view2d_scrollers_calc(struct View2D *v2d, + const struct rcti *mask_custom, + struct View2DScrollers *r_scrollers); +void UI_view2d_scrollers_draw(struct View2D *v2d, const struct rcti *mask_custom); /* list view tools */ void UI_view2d_listview_view_to_cell(float columnwidth, diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 04c259ab092..55f41913499 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1504,7 +1504,7 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block) void ui_but_override_flag(uiBut *but) { - const int override_status = RNA_property_override_library_status( + const uint override_status = RNA_property_override_library_status( &but->rnapoin, but->rnaprop, but->rnaindex); if (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN) { @@ -6422,7 +6422,7 @@ void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn co } /** - * \param separator_string: when not NULL, this string is used as a separator, + * \param search_sep_string: when not NULL, this string is used as a separator, * showing the icon and highlighted text after the last instance of this string. */ void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string) diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index cc370113422..15d00d8537b 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -561,7 +561,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const bool is_array_component = (is_array && but->rnaindex != -1); const bool is_whole_array = (is_array && but->rnaindex == -1); - const int override_status = RNA_property_override_library_status(ptr, prop, -1); + const uint override_status = RNA_property_override_library_status(ptr, prop, -1); const bool is_overridable = (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; /* Set the (button_pointer, button_prop) diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 499d2f7f1fa..720a5bcff37 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -25,6 +25,7 @@ #include <string.h> #include "DNA_color_types.h" +#include "DNA_curve_types.h" #include "DNA_curveprofile_types.h" #include "DNA_movieclip_types.h" #include "DNA_screen_types.h" @@ -118,51 +119,53 @@ void UI_draw_roundbox_aa( bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]) { uiWidgetBaseParameters widget_params = { - .recti.xmin = minx, - .recti.ymin = miny, - .recti.xmax = maxx, - .recti.ymax = maxy, + .recti.xmin = minx + U.pixelsize, + .recti.ymin = miny + U.pixelsize, + .recti.xmax = maxx - U.pixelsize, + .recti.ymax = maxy - U.pixelsize, + .rect.xmin = minx, + .rect.ymin = miny, + .rect.xmax = maxx, + .rect.ymax = maxy, .radi = rad, + .rad = rad, .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = color[0], - .color_inner2[0] = color[0], - .color_inner1[1] = color[1], - .color_inner2[1] = color[1], - .color_inner1[2] = color[2], - .color_inner2[2] = color[2], - .color_inner1[3] = color[3], - .color_inner2[3] = color[3], + .color_inner1[0] = filled ? color[0] : 0.0f, + .color_inner1[1] = filled ? color[1] : 0.0f, + .color_inner1[2] = filled ? color[2] : 0.0f, + .color_inner1[3] = filled ? color[3] : 0.0f, + .color_inner2[0] = filled ? color[0] : 0.0f, + .color_inner2[1] = filled ? color[1] : 0.0f, + .color_inner2[2] = filled ? color[2] : 0.0f, + .color_inner2[3] = filled ? color[3] : 0.0f, + .color_outline[0] = color[0], + .color_outline[1] = color[1], + .color_outline[2] = color[2], + .color_outline[3] = color[3], .alpha_discard = 1.0f, }; - GPU_blend(true); - + /* XXX this is to emulate previous behavior of semitransparent fills but that's was a side effect + * of the previous AA method. Better fix the callers. */ if (filled) { - /* plain antialiased filled box */ - widget_params.color_inner1[3] *= 0.125f; - widget_params.color_inner2[3] *= 0.125f; - - /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. - * If it has been scaled, then it's no longer valid. */ - GPUBatch *batch = ui_batch_roundbox_get(filled, true); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params); - GPU_batch_draw(batch); + widget_params.color_inner1[3] *= 0.65f; + widget_params.color_inner2[3] *= 0.65f; + widget_params.color_outline[3] *= 0.65f; } - else { - /* plain antialiased unfilled box */ - GPU_line_smooth(true); - GPUBatch *batch = ui_batch_roundbox_get(filled, false); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params); - GPU_batch_draw(batch); + /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. + * If it has been scaled, then it's no longer valid. */ - GPU_line_smooth(false); - } + GPUBatch *batch = ui_batch_roundbox_widget_get(); + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); + GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params); + + GPU_blend(true); + + GPU_batch_draw(batch); GPU_blend(false); } @@ -251,32 +254,49 @@ void UI_draw_roundbox_4fv( immEnd(); immUnbindProgram(); #endif - uiWidgetBaseParameters widget_params = { - .recti.xmin = minx, - .recti.ymin = miny, - .recti.xmax = maxx, - .recti.ymax = maxy, + .recti.xmin = minx + U.pixelsize, + .recti.ymin = miny + U.pixelsize, + .recti.xmax = maxx - U.pixelsize, + .recti.ymax = maxy - U.pixelsize, + .rect.xmin = minx, + .rect.ymin = miny, + .rect.xmax = maxx, + .rect.ymax = maxy, .radi = rad, + .rad = rad, .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = col[0], - .color_inner2[0] = col[0], - .color_inner1[1] = col[1], - .color_inner2[1] = col[1], - .color_inner1[2] = col[2], - .color_inner2[2] = col[2], - .color_inner1[3] = col[3], - .color_inner2[3] = col[3], + .color_inner1[0] = filled ? col[0] : 0.0f, + .color_inner1[1] = filled ? col[1] : 0.0f, + .color_inner1[2] = filled ? col[2] : 0.0f, + .color_inner1[3] = filled ? col[3] : 0.0f, + .color_inner2[0] = filled ? col[0] : 0.0f, + .color_inner2[1] = filled ? col[1] : 0.0f, + .color_inner2[2] = filled ? col[2] : 0.0f, + .color_inner2[3] = filled ? col[3] : 0.0f, + .color_outline[0] = col[0], + .color_outline[1] = col[1], + .color_outline[2] = col[2], + .color_outline[3] = col[3], .alpha_discard = 1.0f, }; + /* Exactly the same as UI_draw_roundbox_aa but does not do the legacy transparency. */ - GPUBatch *batch = ui_batch_roundbox_get(filled, false); + /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. + * If it has been scaled, then it's no longer valid. */ + + GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params); + + GPU_blend(true); + GPU_batch_draw(batch); + + GPU_blend(false); } #if 0 @@ -427,32 +447,46 @@ void UI_draw_roundbox_shade_x(bool filled, immEnd(); immUnbindProgram(); #endif - uiWidgetBaseParameters widget_params = { - .recti.xmin = minx, - .recti.ymin = miny, - .recti.xmax = maxx, - .recti.ymax = maxy, + .recti.xmin = minx + U.pixelsize, + .recti.ymin = miny + U.pixelsize, + .recti.xmax = maxx - U.pixelsize, + .recti.ymax = maxy - U.pixelsize, + .rect.xmin = minx, + .rect.ymin = miny, + .rect.xmax = maxx, + .rect.ymax = maxy, .radi = rad, + .rad = rad, .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = min_ff(1.0f, col[0] + shadetop), - .color_inner2[0] = max_ff(0.0f, col[0] + shadedown), - .color_inner1[1] = min_ff(1.0f, col[1] + shadetop), - .color_inner2[1] = max_ff(0.0f, col[1] + shadedown), - .color_inner1[2] = min_ff(1.0f, col[2] + shadetop), - .color_inner2[2] = max_ff(0.0f, col[2] + shadedown), - .color_inner1[3] = 1.0f, - .color_inner2[3] = 1.0f, + .color_inner1[0] = !filled ? 0.0f : min_ff(1.0f, col[0] + shadetop), + .color_inner1[1] = !filled ? 0.0f : min_ff(1.0f, col[1] + shadetop), + .color_inner1[2] = !filled ? 0.0f : min_ff(1.0f, col[2] + shadetop), + .color_inner1[3] = !filled ? 0.0f : 1.0f, + .color_inner2[0] = !filled ? 0.0f : max_ff(0.0f, col[0] + shadedown), + .color_inner2[1] = !filled ? 0.0f : max_ff(0.0f, col[1] + shadedown), + .color_inner2[2] = !filled ? 0.0f : max_ff(0.0f, col[2] + shadedown), + .color_inner2[3] = !filled ? 0.0f : 1.0f, + /* TODO: non-filled box don't have gradients. Just use middle color. */ + .color_outline[0] = clamp_f(col[0] + shadetop + shadedown, 0.0f, 1.0f), + .color_outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f), + .color_outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f), + .color_outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f), + .shade_dir = 1.0f, .alpha_discard = 1.0f, }; - GPUBatch *batch = ui_batch_roundbox_get(filled, false); + GPU_blend(true); + + GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float *)&widget_params); GPU_batch_draw(batch); + + GPU_blend(false); } #if 0 /* unused */ @@ -765,10 +799,8 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region), * * \note This function is to be used with the 2D dashed shader enabled. * - * \param pos: is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attribute. - * \param line_origin: is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attribute. - * - * The next 4 parameters are the offsets for the view, not the zones. + * \param pos: is a #PRIM_FLOAT, 2, #GPU_FETCH_FLOAT vertex attribute. + * \param x1, x2, y1, y2: The offsets for the view, not the zones. */ void UI_draw_safe_areas(uint pos, float x1, @@ -801,7 +833,7 @@ void UI_draw_safe_areas(uint pos, static void draw_scope_end(const rctf *rect, GLint *scissor) { - /* restore scissortest */ + /* Restore scissor test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); GPU_blend_set_func_separate( @@ -2131,7 +2163,19 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, immUnbindProgram(); } -/** Used to draw a curve profile widget. Somewhat similar to ui_draw_but_CURVE */ +/** + * Helper for #ui_draw_but_CURVEPROFILE. Used to tell whether to draw a control point's handles. + */ +static bool point_draw_handles(CurveProfilePoint *point) +{ + return (point->flag & PROF_SELECT && + (ELEM(point->h1, HD_FREE, HD_ALIGN) || ELEM(point->h2, HD_FREE, HD_ALIGN))) || + ELEM(point->flag, PROF_H1_SELECT, PROF_H2_SELECT); +} + +/** + * Draws the curve profile widget. Somewhat similar to ui_draw_but_CURVE. + */ void ui_draw_but_CURVEPROFILE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, @@ -2147,18 +2191,18 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, profile = (CurveProfile *)but->poin; } - /* Calculate offset and zoom */ + /* Calculate offset and zoom. */ float zoomx = (BLI_rcti_size_x(rect) - 2.0f) / BLI_rctf_size_x(&profile->view_rect); float zoomy = (BLI_rcti_size_y(rect) - 2.0f) / BLI_rctf_size_y(&profile->view_rect); float offsx = profile->view_rect.xmin - (1.0f / zoomx); float offsy = profile->view_rect.ymin - (1.0f / zoomy); - /* Exit early if too narrow */ + /* Exit early if too narrow. */ if (zoomx == 0.0f) { return; } - /* Test needed because path can draw outside of boundary */ + /* Test needed because path can draw outside of boundary. */ int scissor[4]; GPU_scissor_get_i(scissor); rcti scissor_new = { @@ -2180,7 +2224,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - /* Backdrop */ + /* Draw the backdrop. */ float color_backdrop[4] = {0, 0, 0, 1}; if (profile->flag & PROF_USE_CLIP) { gl_shaded_color_get_fl((uchar *)wcol->inner, -20, color_backdrop); @@ -2199,33 +2243,33 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } - /* 0.25 step grid */ + /* 0.25 step grid. */ gl_shaded_color((uchar *)wcol->inner, -16); ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f); - /* 1.0 step grid */ + /* 1.0 step grid. */ gl_shaded_color((uchar *)wcol->inner, -24); ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f); - /* Draw the path's fill */ + /* Draw the path's fill. */ if (profile->table == NULL) { - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); } CurveProfilePoint *pts = profile->table; - /* Also add the last points on the right and bottom edges to close off the fill polygon */ + /* Also add the last points on the right and bottom edges to close off the fill polygon. */ bool add_left_tri = profile->view_rect.xmin < 0.0f; bool add_bottom_tri = profile->view_rect.ymin < 0.0f; uint tot_points = (uint)PROF_N_TABLE(profile->path_len) + 1 + add_left_tri + add_bottom_tri; uint tot_triangles = tot_points - 2; - /* Create array of the positions of the table's points */ + /* Create array of the positions of the table's points. */ float(*table_coords)[2] = MEM_mallocN(sizeof(*table_coords) * tot_points, "table x coords"); for (i = 0; i < (uint)PROF_N_TABLE(profile->path_len); - i++) { /* Only add the points from the table here */ + i++) { /* Only add the points from the table here. */ table_coords[i][0] = pts[i].x; table_coords[i][1] = pts[i].y; } if (add_left_tri && add_bottom_tri) { - /* Add left side, bottom left corner, and bottom side points */ + /* Add left side, bottom left corner, and bottom side points. */ table_coords[tot_points - 3][0] = profile->view_rect.xmin; table_coords[tot_points - 3][1] = 1.0f; table_coords[tot_points - 2][0] = profile->view_rect.xmin; @@ -2234,30 +2278,30 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, table_coords[tot_points - 1][1] = profile->view_rect.ymin; } else if (add_left_tri) { - /* Add the left side and bottom left corner points */ + /* Add the left side and bottom left corner points. */ table_coords[tot_points - 2][0] = profile->view_rect.xmin; table_coords[tot_points - 2][1] = 1.0f; table_coords[tot_points - 1][0] = profile->view_rect.xmin; table_coords[tot_points - 1][1] = 0.0f; } else if (add_bottom_tri) { - /* Add the bottom side and bottom left corner points */ + /* Add the bottom side and bottom left corner points. */ table_coords[tot_points - 2][0] = 0.0f; table_coords[tot_points - 2][1] = profile->view_rect.ymin; table_coords[tot_points - 1][0] = 1.0f; table_coords[tot_points - 1][1] = profile->view_rect.ymin; } else { - /* Just add the bottom corner point. Side points would be redundant anyway */ + /* Just add the bottom corner point. Side points would be redundant anyway. */ table_coords[tot_points - 1][0] = 0.0f; table_coords[tot_points - 1][1] = 0.0f; } - /* Calculate the table point indices of the triangles for the profile's fill */ + /* Calculate the table point indices of the triangles for the profile's fill. */ uint(*tri_indices)[3] = MEM_mallocN(sizeof(*tri_indices) * tot_triangles, "return tri indices"); BLI_polyfill_calc(table_coords, tot_points, -1, tri_indices); - /* Draw the triangles for the profile fill */ + /* Draw the triangles for the profile fill. */ immUniformColor3ubvAlpha((const uchar *)wcol->item, 128); GPU_blend(true); GPU_polygon_smooth(false); @@ -2273,7 +2317,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, immEnd(); MEM_freeN(tri_indices); - /* Draw the profile's path so the edge stands out a bit */ + /* Draw the profile's path so the edge stands out a bit. */ tot_points -= (add_left_tri + add_left_tri); GPU_line_width(1.0f); immUniformColor3ubvAlpha((const uchar *)wcol->item, 255); @@ -2285,9 +2329,44 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, immVertex2f(pos, fx, fy); } immEnd(); - immUnbindProgram(); MEM_freeN(table_coords); + /* Draw the handles for the selected control points. */ + pts = profile->path; + tot_points = (uint)profile->path_len; + int selected_free_points = 0; + for (i = 0; i < tot_points; i++) { + if (point_draw_handles(&pts[i])) { + selected_free_points++; + } + } + /* Draw the lines to the handles from the points. */ + if (selected_free_points > 0) { + GPU_line_width(1.0f); + gl_shaded_color((uchar *)wcol->inner, -24); + GPU_line_smooth(true); + immBegin(GPU_PRIM_LINES, selected_free_points * 4); + float ptx, pty; + for (i = 0; i < tot_points; i++) { + if (point_draw_handles(&pts[i])) { + ptx = rect->xmin + zoomx * (pts[i].x - offsx); + pty = rect->ymin + zoomy * (pts[i].y - offsy); + + fx = rect->xmin + zoomx * (pts[i].h1_loc[0] - offsx); + fy = rect->ymin + zoomy * (pts[i].h1_loc[1] - offsy); + immVertex2f(pos, ptx, pty); + immVertex2f(pos, fx, fy); + + fx = rect->xmin + zoomx * (pts[i].h2_loc[0] - offsx); + fy = rect->ymin + zoomy * (pts[i].h2_loc[1] - offsy); + immVertex2f(pos, ptx, pty); + immVertex2f(pos, fx, fy); + } + } + immEnd(); + } + immUnbindProgram(); + /* New GPU instructions for control points and sampled points. */ format = immVertexFormat(); pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -2311,8 +2390,6 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, } /* Draw the control points. */ - pts = profile->path; - tot_points = (uint)profile->path_len; GPU_line_smooth(false); GPU_blend(false); GPU_point_size(max_ff(3.0f, min_ff(UI_DPI_FAC / but->block->aspect * 5.0f, 5.0f))); @@ -2325,6 +2402,28 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, } immEnd(); + /* Draw the handle points. */ + if (selected_free_points > 0) { + GPU_line_smooth(false); + GPU_blend(false); + GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 4.0f, 4.0f))); + immBegin(GPU_PRIM_POINTS, selected_free_points * 2); + for (i = 0; i < tot_points; i++) { + if (point_draw_handles(&pts[i])) { + fx = rect->xmin + zoomx * (pts[i].h1_loc[0] - offsx); + fy = rect->ymin + zoomy * (pts[i].h1_loc[1] - offsy); + immAttr4fv(col, (pts[i].flag & PROF_H1_SELECT) ? color_vert_select : color_vert); + immVertex2f(pos, fx, fy); + + fx = rect->xmin + zoomx * (pts[i].h2_loc[0] - offsx); + fy = rect->ymin + zoomy * (pts[i].h2_loc[1] - offsy); + immAttr4fv(col, (pts[i].flag & PROF_H2_SELECT) ? color_vert_select : color_vert); + immVertex2f(pos, fx, fy); + } + } + immEnd(); + } + /* Draw the sampled points in addition to the control points if they have been created */ pts = profile->segments; tot_points = (uint)profile->segments_len; @@ -2339,7 +2438,6 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, } immEnd(); } - immUnbindProgram(); /* restore scissortest */ @@ -2678,7 +2776,6 @@ void ui_draw_dropshadow( GPU_batch_draw(batch); /* outline emphasis */ - GPU_line_smooth(true); float color[4] = {0.0f, 0.0f, 0.0f, 0.4f}; UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, @@ -2687,7 +2784,6 @@ void ui_draw_dropshadow( rct->ymax + 0.5f, radius + 0.5f, color); - GPU_line_smooth(false); GPU_blend(false); } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 42feda0e1bc..f6bfb492c92 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4872,7 +4872,7 @@ static void ui_numedit_set_active(uiBut *but) /* Don't change the cursor once pressed. */ if ((but->flag & UI_SELECT) == 0) { - if ((but->drawflag & (UI_BUT_ACTIVE_LEFT)) || (but->drawflag & (UI_BUT_ACTIVE_RIGHT))) { + if ((but->drawflag & UI_BUT_ACTIVE_LEFT) || (but->drawflag & UI_BUT_ACTIVE_RIGHT)) { if (data->changed_cursor) { WM_cursor_modal_restore(data->window); data->changed_cursor = false; @@ -6944,7 +6944,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, d[0] = mx - data->dragstartx; d[1] = my - data->dragstarty; - if (len_squared_v2(d) < (3.0f * 3.0f)) { + if (len_squared_v2(d) < (9.0f * U.dpi_fac)) { snap = false; } } @@ -6953,32 +6953,38 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, fy = (my - dragy) / zoomy; if (data->dragsel != -1) { - CurveProfilePoint *point_last = NULL; + float last_x, last_y; const float mval_factor = ui_mouse_scale_warp_factor(shift); bool moved_point = false; /* for ctrl grid, can't use orig coords because of sorting */ fx *= mval_factor; fy *= mval_factor; - /* Move all the points that aren't the last or the first */ - for (a = 1; a < profile->path_len - 1; a++) { - if (pts[a].flag & PROF_SELECT) { - float origx = pts[a].x, origy = pts[a].y; - pts[a].x += fx; - pts[a].y += fy; - if (snap) { - pts[a].x = 0.125f * roundf(8.0f * pts[a].x); - pts[a].y = 0.125f * roundf(8.0f * pts[a].y); + /* Move all selected points. */ + float delta[2] = {fx, fy}; + for (a = 0; a < profile->path_len; a++) { + /* Don't move the last and first control points. */ + if ((pts[a].flag & PROF_SELECT) && (a != 0) && (a != profile->path_len)) { + moved_point |= BKE_curveprofile_move_point(profile, &pts[a], snap, delta); + last_x = pts[a].x; + last_y = pts[a].y; + } + else { + /* Move handles when they're selected but the control point isn't. */ + if (ELEM(pts[a].h2, HD_FREE, HD_ALIGN) && pts[a].flag == PROF_H1_SELECT) { + moved_point |= BKE_curveprofile_move_handle(&pts[a], true, snap, delta); + last_x = pts[a].h1_loc[0]; + last_y = pts[a].h1_loc[1]; } - if (!moved_point && (pts[a].x != origx || pts[a].y != origy)) { - moved_point = true; + if (ELEM(pts[a].h2, HD_FREE, HD_ALIGN) && pts[a].flag == PROF_H2_SELECT) { + moved_point |= BKE_curveprofile_move_handle(&pts[a], false, snap, delta); + last_x = pts[a].h2_loc[0]; + last_y = pts[a].h2_loc[1]; } - - point_last = &pts[a]; } } - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); if (moved_point) { data->draglastx = evtx; @@ -6989,10 +6995,8 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, * but in practice this isnt really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ - data->ungrab_mval[0] = but->rect.xmin + - ((point_last->x - profile->view_rect.xmin) * zoomx); - data->ungrab_mval[1] = but->rect.ymin + - ((point_last->y - profile->view_rect.ymin) * zoomy); + data->ungrab_mval[0] = but->rect.xmin + ((last_x - profile->view_rect.xmin) * zoomx); + data->ungrab_mval[1] = but->rect.ymin + ((last_y - profile->view_rect.ymin) * zoomy); BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval); } #endif @@ -7000,7 +7004,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, data->dragchange = true; /* mark for selection */ } else { - /* clamp for clip */ + /* Clamp the view rect when clipping is on. */ if (profile->flag & PROF_USE_CLIP) { if (profile->view_rect.xmin - fx < profile->clip_rect.xmin) { fx = profile->view_rect.xmin - profile->clip_rect.xmin; @@ -7031,16 +7035,26 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, } /** + * Helper for #ui_do_but_CURVEPROFILE. Used to tell whether to select a control point's handles. + */ +static bool point_draw_handles(CurveProfilePoint *point) +{ + return (point->flag & PROF_SELECT && + (ELEM(point->h1, HD_FREE, HD_ALIGN) || ELEM(point->h2, HD_FREE, HD_ALIGN))) || + ELEM(point->flag, PROF_H1_SELECT, PROF_H2_SELECT); +} + +/** * Interaction for curve profile widget. * \note Uses hardcoded keys rather than the keymap. */ static int ui_do_but_CURVEPROFILE( bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { - int mx, my, i; + CurveProfile *profile = (CurveProfile *)but->poin; + int mx = event->x; + int my = event->y; - mx = event->x; - my = event->y; ui_window_to_block(data->region, block, &mx, &my); /* Move selected control points. */ @@ -7053,12 +7067,10 @@ static int ui_do_but_CURVEPROFILE( return WM_UI_HANDLER_BREAK; } - CurveProfile *profile = (CurveProfile *)but->poin; - /* Delete selected control points. */ if (event->type == EVT_XKEY && event->val == KM_RELEASE) { BKE_curveprofile_remove_by_flag(profile, PROF_SELECT); - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } @@ -7066,76 +7078,94 @@ static int ui_do_but_CURVEPROFILE( /* Selecting, adding, and starting point movements. */ if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE && event->val == KM_PRESS) { - CurveProfilePoint *pts; /* Path or table. */ const float m_xy[2] = {mx, my}; - float dist_min_sq; - int i_selected = -1; if (event->ctrl) { float f_xy[2]; BLI_rctf_transform_pt_v(&profile->view_rect, &but->rect, f_xy, m_xy); BKE_curveprofile_insert(profile, f_xy[0], f_xy[1]); - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_CLIP); } /* Check for selecting of a point by finding closest point in radius. */ - dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius for selecting points. */ - pts = profile->path; - for (i = 0; i < profile->path_len; i++) { + CurveProfilePoint *pts = profile->path; + float dist_min_sq = square_f(U.dpi_fac * 14.0f); /* 14 pixels radius for selecting points. */ + int i_selected = -1; + short selection_type = 0; /* For handle selection. */ + for (int i = 0; i < profile->path_len; i++) { float f_xy[2]; BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[i].x); - const float dist_sq = len_squared_v2v2(m_xy, f_xy); + float dist_sq = len_squared_v2v2(m_xy, f_xy); if (dist_sq < dist_min_sq) { i_selected = i; + selection_type = PROF_SELECT; dist_min_sq = dist_sq; } + + /* Also select handles if the point is selected and it has the right handle type. */ + if (point_draw_handles(&pts[i])) { + if (ELEM(profile->path[i].h1, HD_FREE, HD_ALIGN)) { + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, pts[i].h1_loc); + dist_sq = len_squared_v2v2(m_xy, f_xy); + if (dist_sq < dist_min_sq) { + i_selected = i; + selection_type = PROF_H1_SELECT; + dist_min_sq = dist_sq; + } + } + if (ELEM(profile->path[i].h2, HD_FREE, HD_ALIGN)) { + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, pts[i].h2_loc); + dist_sq = len_squared_v2v2(m_xy, f_xy); + if (dist_sq < dist_min_sq) { + i_selected = i; + selection_type = PROF_H2_SELECT; + dist_min_sq = dist_sq; + } + } + } } - /* Add a point if the click was close to the path but not a control point. */ - if (i_selected == -1) { /* No control point selected. */ + /* Add a point if the click was close to the path but not a control point or handle. */ + if (i_selected == -1) { float f_xy[2], f_xy_prev[2]; - pts = profile->table; - BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[0].x); + CurveProfilePoint *table = profile->table; + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &table[0].x); dist_min_sq = square_f(U.dpi_fac * 8.0f); /* 8 pixel radius from each table point. */ /* Loop through the path's high resolution table and find what's near the click. */ - for (i = 1; i <= PROF_N_TABLE(profile->path_len); i++) { + for (int i = 1; i <= PROF_N_TABLE(profile->path_len); i++) { copy_v2_v2(f_xy_prev, f_xy); - BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &pts[i].x); + BLI_rctf_transform_pt_v(&but->rect, &profile->view_rect, f_xy, &table[i].x); if (dist_squared_to_line_segment_v2(m_xy, f_xy_prev, f_xy) < dist_min_sq) { BLI_rctf_transform_pt_v(&profile->view_rect, &but->rect, f_xy, m_xy); CurveProfilePoint *new_pt = BKE_curveprofile_insert(profile, f_xy[0], f_xy[1]); - BKE_curveprofile_update(profile, false); - - /* reset pts back to the control points. */ - pts = profile->path; + BKE_curveprofile_update(profile, PROF_UPDATE_CLIP); /* Get the index of the newly added point. */ - for (i = 0; i < profile->path_len; i++) { - if (&pts[i] == new_pt) { - i_selected = i; - } - } + i_selected = (int)(new_pt - profile->path); + BLI_assert(i_selected >= 0 && i_selected <= profile->path_len); + selection_type = PROF_SELECT; break; } } } - /* Change the flag for the point(s) if one was selected. */ + /* Change the flag for the point(s) if one was selected or added. */ if (i_selected != -1) { /* Deselect all if this one is deselected, except if we hold shift. */ - if (!event->shift) { - for (i = 0; i < profile->path_len; i++) { - pts[i].flag &= ~PROF_SELECT; - } - pts[i_selected].flag |= PROF_SELECT; + if (event->shift) { + pts[i_selected].flag ^= selection_type; } else { - pts[i_selected].flag ^= PROF_SELECT; + for (int i = 0; i < profile->path_len; i++) { + // pts[i].flag &= ~(PROF_SELECT | PROF_H1_SELECT | PROF_H2_SELECT); + profile->path[i].flag &= ~(PROF_SELECT | PROF_H1_SELECT | PROF_H2_SELECT); + } + profile->path[i_selected].flag |= selection_type; } } else { @@ -7166,19 +7196,13 @@ static int ui_do_but_CURVEPROFILE( else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { /* Finish move. */ if (data->dragsel != -1) { - CurveProfilePoint *pts = profile->path; if (data->dragchange == false) { /* Deselect all, select one. */ - if (!event->shift) { - for (i = 0; i < profile->path_len; i++) { - pts[i].flag &= ~PROF_SELECT; - } - pts[data->dragsel].flag |= PROF_SELECT; - } } else { - BKE_curveprofile_update(profile, true); /* Remove doubles after move. */ + /* Remove doubles, clip after move. */ + BKE_curveprofile_update(profile, PROF_UPDATE_REMOVE_DOUBLES | PROF_UPDATE_CLIP); } } button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -9947,7 +9971,7 @@ static int ui_handle_menu_event(bContext *C, if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) { if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) { /* for root menus, allow clicking to close */ - if (block->flag & (UI_BLOCK_OUT_1)) { + if (block->flag & UI_BLOCK_OUT_1) { menu->menuretval = UI_RETURN_OK; } else { @@ -9955,7 +9979,7 @@ static int ui_handle_menu_event(bContext *C, } } else if (saferct && !BLI_rctf_isect_pt(&saferct->parent, event->x, event->y)) { - if (block->flag & (UI_BLOCK_OUT_1)) { + if (block->flag & UI_BLOCK_OUT_1) { menu->menuretval = UI_RETURN_OK; } else { @@ -10049,7 +10073,7 @@ static int ui_handle_menu_event(bContext *C, /* strict check, and include the parent rect */ if (!menu->dotowards && !saferct) { - if (block->flag & (UI_BLOCK_OUT_1)) { + if (block->flag & UI_BLOCK_OUT_1) { menu->menuretval = UI_RETURN_OK; } else { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index deea3028354..7411639a99f 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -2192,6 +2192,26 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big) return iconid; } +int UI_library_icon_get(const ID *id) +{ + if (ID_IS_LINKED(id)) { + if (id->tag & LIB_TAG_MISSING) { + return ICON_LIBRARY_DATA_BROKEN; + } + else if (id->tag & LIB_TAG_INDIRECT) { + return ICON_LIBRARY_DATA_INDIRECT; + } + else { + return ICON_LIBRARY_DATA_DIRECT; + } + } + else if (ID_IS_OVERRIDE_LIBRARY(id)) { + return ICON_LIBRARY_DATA_OVERRIDE; + } + + return ICON_NONE; +} + int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big) { ID *id = NULL; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6cd990ec2b0..fac78808a9a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -848,6 +848,8 @@ typedef struct uiWidgetBaseParameters { * The absolute value itself is the discard factor. * Initialize value to 1.0.f if you don't want discard */ float alpha_discard; + float tria_type; + float _pad[3]; } uiWidgetBaseParameters; enum { @@ -861,8 +863,7 @@ enum { ROUNDBOX_TRIA_MAX, /* don't use */ }; -struct GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased); -struct GPUBatch *ui_batch_roundbox_widget_get(int tria); +struct GPUBatch *ui_batch_roundbox_widget_get(void); struct GPUBatch *ui_batch_roundbox_shadow_get(void); void ui_draw_anti_tria_rect(const rctf *rect, char dir, const float color[4]); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 6aefef197df..188ff62d923 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5576,6 +5576,7 @@ static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, panel->layout = layout; pt->draw(C, panel); panel->layout = NULL; + BLI_assert(panel->runtime.custom_data_ptr == NULL); MEM_freeN(panel); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 41c89d2d832..924fc6738e1 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -513,7 +513,7 @@ static bool override_type_set_button_poll(bContext *C) UI_context_active_but_prop_get(C, &ptr, &prop, &index); - const int override_status = RNA_property_override_library_status(&ptr, prop, index); + const uint override_status = RNA_property_override_library_status(&ptr, prop, index); return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE)); } @@ -613,7 +613,7 @@ static bool override_remove_button_poll(bContext *C) UI_context_active_but_prop_get(C, &ptr, &prop, &index); - const int override_status = RNA_property_override_library_status(&ptr, prop, index); + const uint override_status = RNA_property_override_library_status(&ptr, prop, index); return (ptr.data && ptr.owner_id && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN)); } @@ -630,11 +630,11 @@ static int override_remove_button_exec(bContext *C, wmOperator *op) UI_context_active_but_prop_get(C, &ptr, &prop, &index); ID *id = ptr.owner_id; - IDOverrideLibraryProperty *oprop = RNA_property_override_property_find(&ptr, prop); + IDOverrideLibraryProperty *oprop = RNA_property_override_property_find(&ptr, prop, &id); BLI_assert(oprop != NULL); BLI_assert(id != NULL && id->override_library != NULL); - const bool is_template = (id->override_library->reference == NULL); + const bool is_template = ID_IS_OVERRIDE_LIBRARY_TEMPLATE(id); /* We need source (i.e. linked data) to restore values of deleted overrides... * If this is an override template, we obviously do not need to restore anything. */ @@ -1309,7 +1309,7 @@ static int editsource_text_edit(bContext *C, printf("%s:%d\n", filepath, line); for (text = bmain->texts.first; text; text = text->id.next) { - if (text->name && BLI_path_cmp(text->name, filepath) == 0) { + if (text->filepath && BLI_path_cmp(text->filepath, filepath) == 0) { break; } } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 55657d7297a..2eeab4efbc7 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -245,20 +245,25 @@ static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_ /********* Functions for instanced panels. ***********/ -static Panel *UI_panel_add_instanced_ex( - ScrArea *area, ARegion *region, ListBase *panels, PanelType *panel_type, int list_index) +static Panel *UI_panel_add_instanced_ex(ScrArea *area, + ARegion *region, + ListBase *panels, + PanelType *panel_type, + int list_index, + PointerRNA *custom_data) { Panel *panel = MEM_callocN(sizeof(Panel), "instanced panel"); panel->type = panel_type; BLI_strncpy(panel->panelname, panel_type->idname, sizeof(panel->panelname)); panel->runtime.list_index = list_index; + panel->runtime.custom_data_ptr = custom_data; /* Add the panel's children too. Although they aren't instanced panels, we can still use this * function to create them, as UI_panel_begin does other things we don't need to do. */ LISTBASE_FOREACH (LinkData *, child, &panel_type->children) { PanelType *child_type = child->data; - UI_panel_add_instanced_ex(area, region, &panel->children, child_type, list_index); + UI_panel_add_instanced_ex(area, region, &panel->children, child_type, list_index, custom_data); } /* Make sure the panel is added to the end of the display-order as well. This is needed for @@ -283,8 +288,12 @@ static Panel *UI_panel_add_instanced_ex( * Called in situations where panels need to be added dynamically rather than having only one panel * corresponding to each PanelType. */ -Panel *UI_panel_add_instanced( - ScrArea *area, ARegion *region, ListBase *panels, char *panel_idname, int list_index) +Panel *UI_panel_add_instanced(ScrArea *area, + ARegion *region, + ListBase *panels, + char *panel_idname, + int list_index, + PointerRNA *custom_data) { ARegionType *region_type = region->type; @@ -296,7 +305,7 @@ Panel *UI_panel_add_instanced( return NULL; } - return UI_panel_add_instanced_ex(area, region, panels, panel_type, list_index); + return UI_panel_add_instanced_ex(area, region, panels, panel_type, list_index, custom_data); } /** @@ -332,7 +341,8 @@ static void panel_free_block(ARegion *region, Panel *panel) } /** - * Free a panel and it's children. + * Free a panel and it's children. Custom data is shared by the panel and its children + * and is freed by #UI_panels_free_instanced. * * \note The only panels that should need to be deleted at runtime are panels with the * #PNL_INSTANCED flag set. @@ -369,6 +379,13 @@ void UI_panels_free_instanced(bContext *C, ARegion *region) if (C != NULL && panel->activedata != NULL) { panel_activate_state(C, panel, PANEL_STATE_EXIT); } + + /* Free panel's custom data. */ + if (panel->runtime.custom_data_ptr != NULL) { + MEM_freeN(panel->runtime.custom_data_ptr); + } + + /* Free the panel and its sub-panels. */ panel_delete(region, ®ion->panels, panel); } } @@ -387,9 +404,19 @@ bool UI_panel_list_matches_data(ARegion *region, ListBase *data, uiListPanelIDFromDataFunc panel_idname_func) { - int data_len = BLI_listbase_count(data); + /* Check for NULL data. */ + int data_len = 0; + Link *data_link = NULL; + if (data == NULL) { + data_len = 0; + data_link = NULL; + } + else { + data_len = BLI_listbase_count(data); + data_link = data->first; + } + int i = 0; - Link *data_link = data->first; LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { if (panel->type != NULL && panel->type->flag & PNL_INSTANCED) { /* The panels were reordered by drag and drop. */ @@ -493,7 +520,7 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr /** * Recursive implementation for #UI_panel_set_expand_from_list_data. * - * \return Whether the closed flag for the panel or any subpanels changed. + * \return Whether the closed flag for the panel or any sub-panels changed. */ static bool panel_set_expand_from_list_data_recursive(Panel *panel, short flag, short *flag_index) { @@ -513,7 +540,7 @@ static bool panel_set_expand_from_list_data_recursive(Panel *panel, short flag, } /** - * Set the expansion of the panel and its subpanels from the flag stored by the list data + * Set the expansion of the panel and its sub-panels from the flag stored by the list data * corresponding to this panel. The flag has expansion stored in each bit in depth first * order. */ @@ -583,6 +610,26 @@ static void set_panels_list_data_expand_flag(const bContext *C, ARegion *region) /****************************** panels ******************************/ +/** + * Set flag state for a panel and its sub-panels. + * + * \return True if this function changed any of the flags, false if it didn't. + */ +static bool panel_set_flag_recursive(Panel *panel, int flag, bool value) +{ + short flag_original = panel->flag; + + SET_FLAG_FROM_TEST(panel->flag, value, flag); + + bool changed = (flag_original != panel->flag); + + LISTBASE_FOREACH (Panel *, child, &panel->children) { + changed |= panel_set_flag_recursive(child, flag, value); + } + + return changed; +} + static void panels_collapse_all(const bContext *C, ScrArea *area, ARegion *region, @@ -980,7 +1027,7 @@ void ui_draw_aligned_panel(uiStyle *style, * can't be dragged. This may be changed in future. */ show_background); const int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK; - const bool draw_box_style = (panel->type && panel->type->flag & (PNL_DRAW_BOX)); + const bool draw_box_style = (panel->type && panel->type->flag & PNL_DRAW_BOX); /* Use the theme for box widgets for box-style panels. */ uiWidgetColors *box_wcol = NULL; @@ -1160,7 +1207,7 @@ void ui_draw_aligned_panel(uiStyle *style, /* Draw panel backdrop if it wasn't already been drawn by the single opaque round box earlier. * Note: Sub-panels blend with panels, so they can't be opaque. */ if (show_background && !(draw_box_style && !is_subpanel)) { - /* Draw the bottom subpanels . */ + /* Draw the bottom sub-panels. */ if (draw_box_style) { if (panel->next) { immUniformThemeColor(panel_col); @@ -1461,11 +1508,6 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co ps->panel->ofsx = 0; ps->panel->ofsy = -get_panel_size_y(ps->panel); ps->panel->ofsx += ps->panel->runtime.region_ofsx; - /* Extra margin if the panel is a box style panel. */ - if (ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX) { - ps->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN; - ps->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN; - } for (a = 0; a < tot - 1; a++, ps++) { psnext = ps + 1; @@ -1475,16 +1517,12 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co bool use_box_next = psnext->panel->type && psnext->panel->type->flag & PNL_DRAW_BOX; psnext->panel->ofsx = ps->panel->ofsx; psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel); + /* Extra margin for box style panels. */ + ps->panel->ofsx += (use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0.0f; if (use_box || use_box_next) { psnext->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN; } - if (use_box && !use_box_next) { - psnext->panel->ofsx -= UI_PANEL_BOX_STYLE_MARGIN; - } - else if (!use_box && use_box_next) { - psnext->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN; - } } else { psnext->panel->ofsx = get_panel_real_ofsx(ps->panel); @@ -1492,6 +1530,10 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co get_panel_size_y(psnext->panel); } } + /* Extra margin for the last panel if it's a box-style panel. */ + if (panelsort[tot - 1].panel->type && panelsort[tot - 1].panel->type->flag & PNL_DRAW_BOX) { + panelsort[tot - 1].panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN; + } /* we interpolate */ done = false; @@ -2017,14 +2059,28 @@ static void ui_handle_panel_header( if (button == 2) { /* close */ ED_region_tag_redraw(region); } - else { /* collapse */ + else { + /* Collapse and expand panels. */ + if (ctrl) { - /* Only collapse all for parent panels. */ + /* For parent panels, collapse all other panels or toggle children. */ if (block->panel->type != NULL && block->panel->type->parent == NULL) { - panels_collapse_all(C, area, region, block->panel); + if (block->panel->flag & PNL_CLOSED || BLI_listbase_is_empty(&block->panel->children)) { + panels_collapse_all(C, area, region, block->panel); - /* reset the view - we don't want to display a view without content */ - UI_view2d_offset(®ion->v2d, 0.0f, 1.0f); + /* Reset the view - we don't want to display a view without content. */ + UI_view2d_offset(®ion->v2d, 0.0f, 1.0f); + } + else { + const int closed_flag = (align == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY; + /* If a panel has sub-panels and it's open, toggle the expansion + * of the sub-panels (based on the expansion of the first subpanel). */ + Panel *first_child = block->panel->children.first; + BLI_assert(first_child != NULL); + panel_set_flag_recursive( + block->panel, closed_flag, (first_child->flag & PNL_CLOSED) == 0); + block->panel->flag |= closed_flag; + } } } @@ -2847,6 +2903,56 @@ int ui_handler_panel_region(bContext *C, return retval; } +static void ui_panel_custom_data_set_recursive(Panel *panel, PointerRNA *custom_data) +{ + panel->runtime.custom_data_ptr = custom_data; + + LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { + ui_panel_custom_data_set_recursive(child_panel, custom_data); + } +} + +void UI_panel_custom_data_set(Panel *panel, PointerRNA *custom_data) +{ + BLI_assert(panel->type != NULL); + + /* Free the old custom data, which should be shared among all of the panel's sub-panels. */ + if (panel->runtime.custom_data_ptr != NULL) { + MEM_freeN(panel->runtime.custom_data_ptr); + } + + ui_panel_custom_data_set_recursive(panel, custom_data); +} + +PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wmEvent *event) +{ + ARegion *region = CTX_wm_region(C); + + Panel *panel = NULL; + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + panel = block->panel; + if (panel == NULL) { + continue; + } + + int mx = event->x; + int my = event->y; + ui_window_to_block(region, block, &mx, &my); + int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my); + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { + break; + } + } + + if (panel == NULL) { + return NULL; + } + + PointerRNA *customdata = panel->runtime.custom_data_ptr; + + return customdata; +} + /**************** window level modal panel interaction **************/ /* note, this is modal handler and should not swallow events for animation */ @@ -2899,24 +3005,6 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } -/** - * Set selection state for a panel and its subpanels. The subpanels need to know they are selected - * too so they can be drawn above their parent when it is dragged. - */ -static void set_panel_selection(Panel *panel, bool value) -{ - if (value) { - panel->flag |= PNL_SELECT; - } - else { - panel->flag &= ~PNL_SELECT; - } - - LISTBASE_FOREACH (Panel *, child, &panel->children) { - set_panel_selection(child, value); - } -} - static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; @@ -2929,6 +3017,8 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS bool was_drag_drop = (data && data->state == PANEL_STATE_DRAG); + /* Set selection state for the panel and its sub-panels, which need to know they are selected + * too so they can be drawn above their parent when it's dragged. */ if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { if (data && data->state != PANEL_STATE_ANIMATION) { /* XXX: @@ -2941,10 +3031,10 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS check_panel_overlap(region, NULL); /* clears */ } - set_panel_selection(panel, false); + panel_set_flag_recursive(panel, PNL_SELECT, false); } else { - set_panel_selection(panel, true); + panel_set_flag_recursive(panel, PNL_SELECT, true); } if (data && data->animtimer) { diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index 3e34b7f3f8a..65f5798bdce 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -184,7 +184,12 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi pup->block->handle = NULL; } - if (pup->but) { + /* Find block minimum width. */ + if (uiLayoutGetUnitsX(pup->layout) != 0.0f) { + /* Use the minimum width from the layout if it's set. */ + minwidth = uiLayoutGetUnitsX(pup->layout) * UI_UNIT_X; + } + else if (pup->but) { /* minimum width to enforece */ if (pup->but->drawstr[0]) { minwidth = BLI_rctf_size_x(&pup->but->rect); @@ -193,7 +198,13 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi /* For buttons with no text, use the minimum (typically icon only). */ minwidth = UI_MENU_WIDTH_MIN; } + } + else { + minwidth = UI_MENU_WIDTH_MIN; + } + /* Find block direction. */ + if (pup->but) { if (pup->block->direction != 0) { /* allow overriding the direction from menu_func */ direction = pup->block->direction; @@ -203,7 +214,6 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi } } else { - minwidth = UI_MENU_WIDTH_MIN; direction = UI_DIR_DOWN; } diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 68be08ef4f8..c88dd1954c9 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -77,6 +77,9 @@ struct uiSearchItems { int *icons; int *states; + /** Is there any item with an icon? */ + bool has_icon; + AutoComplete *autocpl; void *active; }; @@ -122,6 +125,10 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int return true; } + if (iconid) { + items->has_icon = true; + } + /* hijack for finding active item */ if (items->active) { if (poin == items->active) { @@ -562,6 +569,10 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *region) /* widget itself */ if ((search_sep_len == 0) || !(name_sep_test = strstr(data->items.names[a], data->sep_string))) { + if (!icon && data->items.has_icon) { + /* If there is any icon item, make sure all items line up. */ + icon = ICON_BLANK1; + } /* Simple menu item. */ ui_draw_menu_item(&data->fstyle, &rect, name, icon, state, use_sep_char, NULL); diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index b64f080d9cc..9fed98ffda2 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -923,7 +923,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) .style = UI_TIP_STYLE_NORMAL, .color_id = UI_TIP_LC_NORMAL, }); - field->text = BLI_sprintfN(TIP_("Library: %s"), id->lib->name); + field->text = BLI_sprintfN(TIP_("Library: %s"), id->lib->filepath); } } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 1ce1e2950d5..baea948e122 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -361,11 +361,16 @@ static bool id_search_add(const bContext *C, * followed by ID_NAME-2 characters from id->name */ char name_ui[MAX_ID_FULL_NAME_UI]; - BKE_id_full_name_ui_prefix_get(name_ui, id, UI_SEP_CHAR); - int iconid = ui_id_icon_get(C, id, template_ui->preview); bool has_sep_char = (id->lib != NULL); + /* When using previews, the library hint (linked, overridden, missing) is added with a + * character prefix, otherwise we can use a icon. */ + BKE_id_full_name_ui_prefix_get(name_ui, id, template_ui->preview, UI_SEP_CHAR); + if (!template_ui->preview) { + iconid = UI_library_icon_get(id); + } + if (!UI_search_item_add( items, name_ui, id, iconid, has_sep_char ? UI_BUT_HAS_SEP_CHAR : 0)) { return false; @@ -511,6 +516,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) PointerRNA idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); ID *id = idptr.data; int event = POINTER_AS_INT(arg_event); + const char *undo_push_label = NULL; switch (event) { case UI_ID_BROWSE: @@ -531,6 +537,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) id_us_clear_real(id); id_fake_user_clear(id); id->us = 0; + undo_push_label = "Delete Data-Block"; } break; @@ -542,6 +549,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) else { id_us_min(id); } + undo_push_label = "Fake User"; } else { return; @@ -572,15 +580,17 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); + undo_push_label = "Make Local"; } break; case UI_ID_OVERRIDE: - if (id && id->override_library) { + if (id && ID_IS_OVERRIDE_LIBRARY(id)) { BKE_lib_override_library_free(&id->override_library, true); /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); + undo_push_label = "Override Data-Block"; } break; case UI_ID_ALONE: @@ -601,6 +611,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) id_single_user(C, id, &template_ui->ptr, template_ui->prop); DEG_relations_tag_update(bmain); } + undo_push_label = "Make Single User"; } break; #if 0 @@ -608,6 +619,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; #endif } + + if (undo_push_label != NULL) { + ED_undo_push(C, undo_push_label); + } } static const char *template_id_browse_tip(const StructRNA *type) @@ -1823,6 +1838,20 @@ void uiTemplatePathBuilder(uiLayout *layout, * Template for building the panel layout for the active object's modifiers. * \{ */ +/** + * Get the active object or the property region's pinned object. + */ +static Object *get_context_object(const bContext *C) +{ + SpaceProperties *sbuts = CTX_wm_space_properties(C); + if (sbuts != NULL && (sbuts->pinid != NULL) && GS(sbuts->pinid->name) == ID_OB) { + return (Object *)sbuts->pinid; + } + else { + return CTX_data_active_object(C); + } +} + static void modifier_panel_id(void *md_link, char *r_name) { ModifierData *md = (ModifierData *)md_link; @@ -1834,14 +1863,7 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C) ScrArea *sa = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - Object *ob; - SpaceProperties *sbuts = CTX_wm_space_properties(C); - if (sbuts != NULL && (sbuts->pinid != NULL) && GS(sbuts->pinid->name) == ID_OB) { - ob = (Object *)sbuts->pinid; - } - else { - ob = CTX_data_active_object(C); - } + Object *ob = get_context_object(C); ListBase *modifiers = &ob->modifiers; bool panels_match = UI_panel_list_matches_data(region, modifiers, modifier_panel_id); @@ -1851,14 +1873,22 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C) ModifierData *md = modifiers->first; for (int i = 0; md; i++, md = md->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (mti->panelRegister) { - char panel_idname[MAX_NAME]; - modifier_panel_id(md, panel_idname); + if (mti->panelRegister == NULL) { + continue; + } - Panel *new_panel = UI_panel_add_instanced(sa, region, ®ion->panels, panel_idname, i); - if (new_panel != NULL) { - UI_panel_set_expand_from_list_data(C, new_panel); - } + char panel_idname[MAX_NAME]; + modifier_panel_id(md, panel_idname); + + /* Create custom data RNA pointer. */ + PointerRNA *md_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_Modifier, md, md_ptr); + + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, md_ptr); + + if (new_panel != NULL) { + UI_panel_set_expand_from_list_data(C, new_panel); } } } @@ -1868,274 +1898,321 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C) if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) UI_panel_set_expand_from_list_data(C, panel); } + + /* Assuming there's only one group of instanced panels, update the custom data pointers. */ + Panel *panel = region->panels.first; + LISTBASE_FOREACH (ModifierData *, md, modifiers) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + if (mti->panelRegister == NULL) { + continue; + } + + /* Move to the next instanced panel corresponding to the next modifier. */ + while ((panel->type == NULL) || !(panel->type->flag & PNL_INSTANCED)) { + panel = panel->next; + BLI_assert(panel != NULL); /* There shouldn't be fewer panels than modifiers with UIs. */ + } + + PointerRNA *md_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_Modifier, md, md_ptr); + UI_panel_custom_data_set(panel, md_ptr); + + panel = panel->next; + } } } /** \} */ /* -------------------------------------------------------------------- */ -/** \name Grease Pencil Modifier Template +/** \name Constraints Template + * + * Template for building the panel layout for the active object or bone's constraints. * \{ */ -#define ERROR_LIBDATA_MESSAGE TIP_("Can't edit external library data") +/** For building the panel UI for constraints. */ +#define CONSTRAINT_TYPE_PANEL_PREFIX "OBJECT_PT_" +#define CONSTRAINT_BONE_TYPE_PANEL_PREFIX "BONE_PT_" -static uiLayout *gpencil_draw_modifier(uiLayout *layout, Object *ob, GpencilModifierData *md) +/** + * Check if the panel's ID starts with 'BONE', meaning it is a bone constraint. + */ +static bool constraint_panel_is_bone(Panel *panel) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); - PointerRNA ptr; - uiBlock *block; - uiLayout *box, *column, *row, *sub; - uiLayout *result = NULL; - - /* create RNA pointer */ - RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, &ptr); - - column = uiLayoutColumn(layout, true); - uiLayoutSetContextPointer(column, "modifier", &ptr); - - /* rounded header ------------------------------------------------------------------- */ - box = uiLayoutBox(column); - - row = uiLayoutRow(box, false); - block = uiLayoutGetBlock(row); - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - /* Open/Close ................................. */ - uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE); - - /* modifier-type icon */ - uiItemL(row, "", RNA_struct_ui_icon(ptr.type)); - UI_block_emboss_set(block, UI_EMBOSS); + return (panel->panelname[0] == 'B') && (panel->panelname[1] == 'O') && + (panel->panelname[2] == 'N') && (panel->panelname[3] == 'E'); +} - /* modifier name */ - if (mti->isDisabled && mti->isDisabled(md, 0)) { - uiLayoutSetRedAlert(row, true); +/** + * Get the constraints for the active pose bone or the active / pinned object. + */ +static ListBase *get_constraints(const bContext *C, bool use_bone_constraints) +{ + ListBase *constraints = {NULL}; + if (use_bone_constraints) { + bPoseChannel *pose_bone = CTX_data_pointer_get(C, "pose_bone").data; + if (pose_bone != NULL) { + constraints = &pose_bone->constraints; + } } - uiItemR(row, &ptr, "name", 0, "", ICON_NONE); - uiLayoutSetRedAlert(row, false); - - /* mode enabling buttons */ - UI_block_align_begin(block); - uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); - uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE); - - if (mti->flags & eGpencilModifierTypeFlag_SupportsEditmode) { - sub = uiLayoutRow(row, true); - uiLayoutSetActive(sub, false); - uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE); + else { + Object *ob = get_context_object(C); + if (ob != NULL) { + constraints = &ob->constraints; + } } + return constraints; +} - UI_block_align_end(block); - - /* Up/Down + Delete ........................... */ - UI_block_align_begin(block); - uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_gpencil_modifier_move_up"); - uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_gpencil_modifier_move_down"); - UI_block_align_end(block); - - UI_block_emboss_set(block, UI_EMBOSS_NONE); - uiItemO(row, "", ICON_X, "OBJECT_OT_gpencil_modifier_remove"); - UI_block_emboss_set(block, UI_EMBOSS); +/** + * Move a constraint to the index it's moved to after a drag and drop. + */ +static void constraint_reorder(bContext *C, Panel *panel, int new_index) +{ + bool constraint_from_bone = constraint_panel_is_bone(panel); + ListBase *lb = get_constraints(C, constraint_from_bone); - /* modifier settings (under the header) --------------------------------------------------- */ - if (md->mode & eGpencilModifierMode_Expanded) { - /* apply/convert/copy */ - box = uiLayoutBox(column); - row = uiLayoutRow(box, false); + bConstraint *con = BLI_findlink(lb, panel->runtime.list_index); + PointerRNA props_ptr; + wmOperatorType *ot = WM_operatortype_find("CONSTRAINT_OT_move_to_index", false); + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_string_set(&props_ptr, "constraint", con->name); + RNA_int_set(&props_ptr, "index", new_index); + /* Set owner to #EDIT_CONSTRAINT_OWNER_OBJECT or #EDIT_CONSTRAINT_OWNER_BONE. */ + RNA_enum_set(&props_ptr, "owner", constraint_from_bone ? 1 : 0); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); +} - /* only here obdata, the rest of modifiers is ob level */ - UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE); +/** + * Get the expand flag from the active constraint to use for the panel. + */ +static short get_constraint_expand_flag(const bContext *C, Panel *panel) +{ + bool constraint_from_bone = constraint_panel_is_bone(panel); + ListBase *lb = get_constraints(C, constraint_from_bone); - uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); + bConstraint *con = BLI_findlink(lb, panel->runtime.list_index); + return con->ui_expand_flag; +} - sub = uiLayoutRow(row, false); - if (mti->flags & eGpencilModifierTypeFlag_NoApply) { - uiLayoutSetEnabled(sub, false); - } - uiItemEnumO(sub, - "OBJECT_OT_gpencil_modifier_apply", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"), - 0, - "apply_as", - MODIFIER_APPLY_DATA); +/** + * Save the expand flag for the panel and sub-panels to the constraint. + */ +static void set_constraint_expand_flag(const bContext *C, Panel *panel, short expand_flag) +{ + bool constraint_from_bone = constraint_panel_is_bone(panel); + ListBase *lb = get_constraints(C, constraint_from_bone); - UI_block_lock_clear(block); - UI_block_lock_set(block, ob && ID_IS_LINKED(ob), ERROR_LIBDATA_MESSAGE); + bConstraint *con = BLI_findlink(lb, panel->runtime.list_index); + con->ui_expand_flag = expand_flag; +} - uiItemO(row, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), - ICON_NONE, - "OBJECT_OT_gpencil_modifier_copy"); +/** + * Function with void * argument for #uiListPanelIDFromDataFunc. + * + * \note: Constraint panel types are assumed to be named with the struct name field + * concatenated to the defined prefix. + */ +static void object_constraint_panel_id(void *md_link, char *r_name) +{ + bConstraint *con = (bConstraint *)md_link; + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(con->type); - /* result is the layout block inside the box, - * that we return so that modifier settings can be drawn */ - result = uiLayoutColumn(box, false); - block = uiLayoutAbsoluteBlock(box); - } + strcpy(r_name, CONSTRAINT_TYPE_PANEL_PREFIX); + strcat(r_name, cti->structName); +} - /* error messages */ - if (md->error) { - box = uiLayoutBox(column); - row = uiLayoutRow(box, false); - uiItemL(row, md->error, ICON_ERROR); - } +static void bone_constraint_panel_id(void *md_link, char *r_name) +{ + bConstraint *con = (bConstraint *)md_link; + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(con->type); - return result; + strcpy(r_name, CONSTRAINT_BONE_TYPE_PANEL_PREFIX); + strcat(r_name, cti->structName); } -uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +/** + * Check if the constraint panels don't match the data and rebuild the panels if so. + */ +void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_constraints) { - Object *ob; - GpencilModifierData *md, *vmd; - int i; - - /* verify we have valid data */ - if (!RNA_struct_is_a(ptr->type, &RNA_GpencilModifier)) { - RNA_warning("Expected modifier on object"); - return NULL; - } + ScrArea *sa = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); - ob = (Object *)ptr->owner_id; - md = ptr->data; + ListBase *constraints = get_constraints(C, use_bone_constraints); - if (!ob || !(GS(ob->id.name) == ID_OB)) { - RNA_warning("Expected modifier on object"); - return NULL; - } + /* Switch between the bone panel ID function and the object panel ID function. */ + uiListPanelIDFromDataFunc panel_id_func = use_bone_constraints ? bone_constraint_panel_id : + object_constraint_panel_id; - UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE); + bool panels_match = UI_panel_list_matches_data(region, constraints, panel_id_func); - /* find modifier and draw it */ - vmd = ob->greasepencil_modifiers.first; - for (i = 0; vmd; i++, vmd = vmd->next) { - if (md == vmd) { - return gpencil_draw_modifier(layout, ob, md); + if (!panels_match) { + UI_panels_free_instanced(C, region); + bConstraint *con = (constraints == NULL) ? NULL : constraints->first; + for (int i = 0; con; i++, con = con->next) { + char panel_idname[MAX_NAME]; + panel_id_func(con, panel_idname); + + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, NULL); + if (new_panel) { + /* Set the list panel functionality function pointers since we don't do it with + * python. */ + new_panel->type->set_list_data_expand_flag = set_constraint_expand_flag; + new_panel->type->get_list_data_expand_flag = get_constraint_expand_flag; + new_panel->type->reorder = constraint_reorder; + + UI_panel_set_expand_from_list_data(C, new_panel); + } + } + } + else { + /* The expansion might have been changed elsewhere, so we still need to set it. */ + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) + UI_panel_set_expand_from_list_data(C, panel); } } - - return NULL; } +#undef CONSTRAINT_TYPE_PANEL_PREFIX +#undef CONSTRAINT_BONE_TYPE_PANEL_PREFIX + /** \} */ /* -------------------------------------------------------------------- */ -/** \name Grease Pencil Shader FX Template +/** \name Grease Pencil Modifiers Template * \{ */ -static uiLayout *gpencil_draw_shaderfx(uiLayout *layout, Object *ob, ShaderFxData *md) +/** + * Function with void * argument for #uiListPanelIDFromDataFunc. + */ +static void gpencil_modifier_panel_id(void *md_link, char *r_name) { - const ShaderFxTypeInfo *mti = BKE_shaderfx_get_info(md->type); - PointerRNA ptr; - uiBlock *block; - uiLayout *box, *column, *row, *sub; - uiLayout *result = NULL; + ModifierData *md = (ModifierData *)md_link; + BKE_gpencil_modifierType_panel_id(md->type, r_name); +} - /* create RNA pointer */ - RNA_pointer_create(&ob->id, &RNA_ShaderFx, md, &ptr); +void uiTemplateGpencilModifiers(uiLayout *UNUSED(layout), bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + Object *ob = get_context_object(C); + ListBase *modifiers = &ob->greasepencil_modifiers; - column = uiLayoutColumn(layout, true); - uiLayoutSetContextPointer(column, "shaderfx", &ptr); + bool panels_match = UI_panel_list_matches_data(region, modifiers, gpencil_modifier_panel_id); - /* rounded header ------------------------------------------------------------------- */ - box = uiLayoutBox(column); + if (!panels_match) { + UI_panels_free_instanced(C, region); + GpencilModifierData *md = modifiers->first; + for (int i = 0; md; i++, md = md->next) { + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); + if (mti->panelRegister == NULL) { + continue; + } - row = uiLayoutRow(box, false); - block = uiLayoutGetBlock(row); + char panel_idname[MAX_NAME]; + gpencil_modifier_panel_id(md, panel_idname); - UI_block_emboss_set(block, UI_EMBOSS_NONE); - /* Open/Close ................................. */ - uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE); + /* Create custom data RNA pointer. */ + PointerRNA *md_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, md_ptr); - /* shader-type icon */ - uiItemL(row, "", RNA_struct_ui_icon(ptr.type)); - UI_block_emboss_set(block, UI_EMBOSS); + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, md_ptr); - /* effect name */ - if (mti->isDisabled && mti->isDisabled(md, 0)) { - uiLayoutSetRedAlert(row, true); + if (new_panel != NULL) { + UI_panel_set_expand_from_list_data(C, new_panel); + } + } } - uiItemR(row, &ptr, "name", 0, "", ICON_NONE); - uiLayoutSetRedAlert(row, false); - - /* mode enabling buttons */ - UI_block_align_begin(block); - uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); - uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE); + else { + /* The expansion might have been changed elsewhere, so we still need to set it. */ + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) + UI_panel_set_expand_from_list_data(C, panel); + } - if (mti->flags & eShaderFxTypeFlag_SupportsEditmode) { - sub = uiLayoutRow(row, true); - uiLayoutSetActive(sub, false); - uiItemR(sub, &ptr, "show_in_editmode", 0, "", ICON_NONE); - } + /* Assuming there's only one group of instanced panels, update the custom data pointers. */ + Panel *panel = region->panels.first; + LISTBASE_FOREACH (ModifierData *, md, modifiers) { + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); + if (mti->panelRegister == NULL) { + continue; + } - UI_block_align_end(block); + /* Move to the next instanced panel corresponding to the next modifier. */ + while ((panel->type == NULL) || !(panel->type->flag & PNL_INSTANCED)) { + panel = panel->next; + BLI_assert(panel != NULL); /* There shouldn't be fewer panels than modifiers with UIs. */ + } - /* Up/Down + Delete ........................... */ - UI_block_align_begin(block); - uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_shaderfx_move_up"); - uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_shaderfx_move_down"); - UI_block_align_end(block); + PointerRNA *md_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_GpencilModifier, md, md_ptr); + UI_panel_custom_data_set(panel, md_ptr); - UI_block_emboss_set(block, UI_EMBOSS_NONE); - uiItemO(row, "", ICON_X, "OBJECT_OT_shaderfx_remove"); - UI_block_emboss_set(block, UI_EMBOSS); + panel = panel->next; + } + } +} - /* effect settings (under the header) --------------------------------------------------- */ - if (md->mode & eShaderFxMode_Expanded) { - /* apply/convert/copy */ - box = uiLayoutBox(column); - row = uiLayoutRow(box, false); +/** \} */ - /* only here obdata, the rest of effect is ob level */ - UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE); +/** \} */ - /* result is the layout block inside the box, - * that we return so that effect settings can be drawn */ - result = uiLayoutColumn(box, false); - block = uiLayoutAbsoluteBlock(box); - } +#define ERROR_LIBDATA_MESSAGE TIP_("Can't edit external library data") - /* error messages */ - if (md->error) { - box = uiLayoutBox(column); - row = uiLayoutRow(box, false); - uiItemL(row, md->error, ICON_ERROR); - } +/* -------------------------------------------------------------------- */ +/** \name ShaderFx Template + * + * Template for building the panel layout for the active object's grease pencil shader + * effects. + * \{ */ - return result; +/** + * Function with void * argument for #uiListPanelIDFromDataFunc. + */ +static void shaderfx_panel_id(void *fx_v, char *r_idname) +{ + ShaderFxData *fx = (ShaderFxData *)fx_v; + BKE_shaderfxType_panel_id(fx->type, r_idname); } -uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +/** + * Check if the shader effect panels don't match the data and rebuild the panels if so. + */ +void uiTemplateShaderFx(uiLayout *UNUSED(layout), bContext *C) { - Object *ob; - ShaderFxData *fx, *vfx; - int i; - - /* verify we have valid data */ - if (!RNA_struct_is_a(ptr->type, &RNA_ShaderFx)) { - RNA_warning("Expected shader fx on object"); - return NULL; - } + ScrArea *sa = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + Object *ob = get_context_object(C); + ListBase *shaderfx = &ob->shader_fx; - ob = (Object *)ptr->owner_id; - fx = ptr->data; + bool panels_match = UI_panel_list_matches_data(region, shaderfx, shaderfx_panel_id); - if (!ob || !(GS(ob->id.name) == ID_OB)) { - RNA_warning("Expected shader fx on object"); - return NULL; + if (!panels_match) { + UI_panels_free_instanced(C, region); + ShaderFxData *fx = shaderfx->first; + for (int i = 0; fx; i++, fx = fx->next) { + char panel_idname[MAX_NAME]; + shaderfx_panel_id(fx, panel_idname); + + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, NULL); + if (new_panel != NULL) { + UI_panel_set_expand_from_list_data(C, new_panel); + } + } } - - UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE); - - /* find modifier and draw it */ - vfx = ob->shader_fx.first; - for (i = 0; vfx; i++, vfx = vfx->next) { - if (fx == vfx) { - return gpencil_draw_shaderfx(layout, ob, fx); + else { + /* The expansion might have been changed elsewhere, so we still need to set it. */ + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) + UI_panel_set_expand_from_list_data(C, panel); } } - - return NULL; } /** \} */ @@ -2441,38 +2518,25 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Constraint Template +/** \name Constraint Header Template * \{ */ +#define ERROR_LIBDATA_MESSAGE TIP_("Can't edit external library data") + static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v) { ED_object_constraint_active_set(ob_v, con_v); } -/* draw panel showing settings for a constraint */ -static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) +static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *con) { bPoseChannel *pchan = BKE_pose_channel_active(ob); - const bConstraintTypeInfo *cti; uiBlock *block; - uiLayout *result = NULL, *col, *box, *row; + uiLayout *sub; PointerRNA ptr; - char typestr[32]; short proxy_protected, xco = 0, yco = 0; // int rb_col; // UNUSED - /* get constraint typeinfo */ - cti = BKE_constraint_typeinfo_get(con); - if (cti == NULL) { - /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */ - BLI_strncpy(typestr, - (con->type == CONSTRAINT_TYPE_NULL) ? IFACE_("Null") : IFACE_("Unknown"), - sizeof(typestr)); - } - else { - BLI_strncpy(typestr, IFACE_(cti->name), sizeof(typestr)); - } - /* determine whether constraint is proxy protected or not */ if (BKE_constraints_proxylocked_owner(ob, pchan)) { proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0; @@ -2487,36 +2551,23 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr); - col = uiLayoutColumn(layout, true); - uiLayoutSetContextPointer(col, "constraint", &ptr); - - box = uiLayoutBox(col); - row = uiLayoutRow(box, false); - block = uiLayoutGetBlock(box); + uiLayoutSetContextPointer(layout, "constraint", &ptr); - /* Draw constraint header */ + /* Constraint type icon. */ + sub = uiLayoutRow(layout, false); + uiLayoutSetEmboss(sub, false); + uiLayoutSetRedAlert(sub, (con->flag & CONSTRAINT_DISABLE)); + uiItemL(sub, "", RNA_struct_ui_icon(ptr.type)); - /* open/close */ - UI_block_emboss_set(block, UI_EMBOSS_NONE); - uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE); - - /* constraint-type icon */ - uiItemL(row, "", RNA_struct_ui_icon(ptr.type)); UI_block_emboss_set(block, UI_EMBOSS); - if (con->flag & CONSTRAINT_DISABLE) { - uiLayoutSetRedAlert(row, true); - } - if (proxy_protected == 0) { - uiItemR(row, &ptr, "name", 0, "", ICON_NONE); + uiItemR(layout, &ptr, "name", 0, "", ICON_NONE); } else { - uiItemL(row, con->name, ICON_NONE); + uiItemL(layout, con->name, ICON_NONE); } - uiLayoutSetRedAlert(row, false); - /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */ if (proxy_protected) { UI_block_emboss_set(block, UI_EMBOSS_NONE); @@ -2555,54 +2606,20 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) UI_block_emboss_set(block, UI_EMBOSS); } else { - short prev_proxylock, show_upbut, show_downbut; - - /* Up/Down buttons: - * Proxy-constraints are not allowed to occur after local (non-proxy) constraints - * as that poses problems when restoring them, so disable the "up" button where - * it may cause this situation. - * - * Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose. - */ - if (BKE_constraints_proxylocked_owner(ob, pchan)) { - if (con->prev) { - prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1; - } - else { - prev_proxylock = 0; - } - } - else { - prev_proxylock = 0; - } - - show_upbut = ((prev_proxylock == 0) && (con->prev)); - show_downbut = (con->next) ? 1 : 0; - /* enabled */ UI_block_emboss_set(block, UI_EMBOSS_NONE); - uiItemR(row, &ptr, "mute", 0, "", 0); + uiItemR(layout, &ptr, "mute", 0, "", 0); UI_block_emboss_set(block, UI_EMBOSS); - uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); - - /* up/down */ - if (show_upbut || show_downbut) { - UI_block_align_begin(block); - if (show_upbut) { - uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up"); - } - - if (show_downbut) { - uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down"); - } - UI_block_align_end(block); - } + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); /* Close 'button' - emboss calls here disable drawing of 'button' behind X */ UI_block_emboss_set(block, UI_EMBOSS_NONE); - uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete"); + uiItemO(layout, "", ICON_X, "CONSTRAINT_OT_delete"); UI_block_emboss_set(block, UI_EMBOSS); + + /* Some extra padding at the end, so the 'x' icon isn't too close to drag button. */ + uiItemS(layout); } /* Set but-locks for protected settings (magic numbers are used here!) */ @@ -2610,23 +2627,11 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) UI_block_lock_set(block, true, TIP_("Cannot edit Proxy-Protected Constraint")); } - /* Draw constraint data */ - if ((con->flag & CONSTRAINT_EXPAND) == 0) { - (yco) -= 10.5f * UI_UNIT_Y; - } - else { - box = uiLayoutBox(col); - block = uiLayoutAbsoluteBlock(box); - result = box; - } - /* clear any locks set up for proxies/lib-linking */ UI_block_lock_clear(block); - - return result; } -uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) +void uiTemplateConstraintHeader(uiLayout *layout, PointerRNA *ptr) { Object *ob; bConstraint *con; @@ -2634,7 +2639,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) /* verify we have valid data */ if (!RNA_struct_is_a(ptr->type, &RNA_Constraint)) { RNA_warning("Expected constraint on object"); - return NULL; + return; } ob = (Object *)ptr->owner_id; @@ -2642,7 +2647,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) if (!ob || !(GS(ob->id.name) == ID_OB)) { RNA_warning("Expected constraint on object"); - return NULL; + return; } UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE); @@ -2651,11 +2656,11 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) if (con->type == CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = con->data; if (data->flag & CONSTRAINT_IK_TEMP) { - return NULL; + return; } } - return draw_constraint(layout, ob, con); + draw_constraint_header(layout, ob, con); } /** \} */ @@ -4525,7 +4530,7 @@ static void CurveProfile_presets_dofunc(bContext *C, void *profile_v, int event) profile->preset = event; BKE_curveprofile_reset(profile); - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); ED_undo_push(C, "CurveProfile tools"); ED_region_tag_redraw(CTX_wm_region(C)); @@ -4641,7 +4646,7 @@ static void CurveProfile_tools_dofunc(bContext *C, void *profile_v, int event) switch (event) { case UIPROFILE_FUNC_RESET: /* reset */ BKE_curveprofile_reset(profile); - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); break; case UIPROFILE_FUNC_RESET_VIEW: /* reset view to clipping rect */ profile->view_rect = profile->clip_rect; @@ -4707,7 +4712,7 @@ static void CurveProfile_buttons_zoom_in(bContext *C, void *profile_v, void *UNU CurveProfile *profile = profile_v; float d; - /* we allow 20 times zoom */ + /* Allow a 20x zoom. */ if (BLI_rctf_size_x(&profile->view_rect) > 0.04f * BLI_rctf_size_x(&profile->clip_rect)) { d = 0.1154f * BLI_rctf_size_x(&profile->view_rect); profile->view_rect.xmin += d; @@ -4771,7 +4776,7 @@ static void CurveProfile_clipping_toggle(bContext *C, void *cb_v, void *profile_ profile->flag ^= PROF_USE_CLIP; - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); rna_update_cb(C, cb_v, NULL); } @@ -4780,7 +4785,7 @@ static void CurveProfile_buttons_reverse(bContext *C, void *cb_v, void *profile_ CurveProfile *profile = profile_v; BKE_curveprofile_reverse(profile); - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); rna_update_cb(C, cb_v, NULL); } @@ -4789,35 +4794,23 @@ static void CurveProfile_buttons_delete(bContext *C, void *cb_v, void *profile_v CurveProfile *profile = profile_v; BKE_curveprofile_remove_by_flag(profile, SELECT); - BKE_curveprofile_update(profile, false); - - rna_update_cb(C, cb_v, NULL); -} - -static void CurveProfile_buttons_setsharp(bContext *C, void *cb_v, void *profile_v) -{ - CurveProfile *profile = profile_v; - - BKE_curveprofile_selected_handle_set(profile, HD_VECT, HD_VECT); - BKE_curveprofile_update(profile, false); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); rna_update_cb(C, cb_v, NULL); } -static void CurveProfile_buttons_setcurved(bContext *C, void *cb_v, void *profile_v) +static void CurveProfile_buttons_update(bContext *C, void *arg1_v, void *profile_v) { CurveProfile *profile = profile_v; - - BKE_curveprofile_selected_handle_set(profile, HD_AUTO, HD_AUTO); - BKE_curveprofile_update(profile, false); - - rna_update_cb(C, cb_v, NULL); + BKE_curveprofile_update(profile, PROF_UPDATE_REMOVE_DOUBLES | PROF_UPDATE_CLIP); + rna_update_cb(C, arg1_v, NULL); } -static void CurveProfile_buttons_update(bContext *C, void *arg1_v, void *profile_v) +static void CurveProfile_buttons_reset(bContext *C, void *arg1_v, void *profile_v) { CurveProfile *profile = profile_v; - BKE_curveprofile_update(profile, true); + BKE_curveprofile_reset(profile); + BKE_curveprofile_update(profile, PROF_UPDATE_NONE); rna_update_cb(C, arg1_v, NULL); } @@ -4836,7 +4829,7 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp UI_block_emboss_set(block, UI_EMBOSS); - uiLayoutRow(layout, false); + uiLayoutSetPropSep(layout, false); /* Preset selector */ /* There is probably potential to use simpler "uiItemR" functions here, but automatic updating @@ -4845,6 +4838,29 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp block, CurveProfile_buttons_presets, profile, "Preset", 0, 0, UI_UNIT_X, UI_UNIT_X, ""); UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + /* Show a "re-apply" preset button when it has been changed from the preset. */ + if (profile->flag & PROF_DIRTY_PRESET) { + /* Only for dynamic presets. */ + if (ELEM(profile->preset, PROF_PRESET_STEPS, PROF_PRESET_SUPPORTS)) { + bt = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_NONE, + "Apply Preset", + 0, + 0, + UI_UNIT_X, + UI_UNIT_X, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + "Reapply and update the preset, removing changes"); + UI_but_funcN_set(bt, CurveProfile_buttons_reset, MEM_dupallocN(cb), profile); + } + } + row = uiLayoutRow(layout, false); /* (Left aligned) */ @@ -4952,11 +4968,24 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp ""); /* Position sliders for (first) selected point */ + float *selection_x, *selection_y; for (i = 0; i < profile->path_len; i++) { if (profile->path[i].flag & PROF_SELECT) { point = &profile->path[i]; + selection_x = &point->x; + selection_y = &point->y; break; } + else if (profile->path[i].flag & PROF_H1_SELECT) { + point = &profile->path[i]; + selection_x = &point->h1_loc[0]; + selection_y = &point->h1_loc[1]; + } + else if (profile->path[i].flag & PROF_H2_SELECT) { + point = &profile->path[i]; + selection_x = &point->h2_loc[0]; + selection_y = &point->h2_loc[1]; + } } if (i == 0 || i == profile->path_len - 1) { point_last_or_first = true; @@ -4972,46 +5001,19 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp bounds.xmax = bounds.ymax = 1000.0; } - uiLayoutRow(layout, true); - UI_block_funcN_set(block, CurveProfile_buttons_update, MEM_dupallocN(cb), profile); + row = uiLayoutRow(layout, true); - /* Sharp / Smooth */ - bt = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_LINCURVE, - 0, - 0, - UI_UNIT_X, - UI_UNIT_X, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Set the point's handle type to sharp")); - if (point_last_or_first) { - UI_but_flag_enable(bt, UI_BUT_DISABLED); - } - UI_but_funcN_set(bt, CurveProfile_buttons_setsharp, MEM_dupallocN(cb), profile); - bt = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_SMOOTHCURVE, - 0, - 0, - UI_UNIT_X, - UI_UNIT_X, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Set the point's handle type to smooth")); - UI_but_funcN_set(bt, CurveProfile_buttons_setcurved, MEM_dupallocN(cb), profile); - if (point_last_or_first) { - UI_but_flag_enable(bt, UI_BUT_DISABLED); - } + PointerRNA point_ptr; + RNA_pointer_create(ptr->owner_id, &RNA_CurveProfilePoint, point, &point_ptr); + PropertyRNA *prop_handle_type = RNA_struct_find_property(&point_ptr, "handle_type_1"); + uiItemFullR(row, + &point_ptr, + prop_handle_type, + RNA_NO_INDEX, + 0, + UI_ITEM_R_EXPAND | UI_ITEM_R_ICON_ONLY, + "", + ICON_NONE); /* Position */ bt = uiDefButF(block, @@ -5022,16 +5024,16 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &point->x, + selection_x, bounds.xmin, bounds.xmax, 1, 5, ""); + UI_but_funcN_set(bt, CurveProfile_buttons_update, MEM_dupallocN(cb), profile); if (point_last_or_first) { UI_but_flag_enable(bt, UI_BUT_DISABLED); } - bt = uiDefButF(block, UI_BTYPE_NUM, 0, @@ -5040,12 +5042,13 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &point->y, + selection_y, bounds.ymin, bounds.ymax, 1, 5, ""); + UI_but_funcN_set(bt, CurveProfile_buttons_update, MEM_dupallocN(cb), profile); if (point_last_or_first) { UI_but_flag_enable(bt, UI_BUT_DISABLED); } @@ -7271,37 +7274,35 @@ void uiTemplateCacheFile(uiLayout *layout, SpaceProperties *sbuts = CTX_wm_space_properties(C); - uiLayout *row = uiLayoutRow(layout, false); - uiBlock *block = uiLayoutGetBlock(row); - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, ""); - - row = uiLayoutRow(layout, false); - uiLayout *split = uiLayoutSplit(row, 0.0f, false); - row = uiLayoutRow(split, true); + uiLayout *row, *sub, *subsub; - uiItemR(row, &fileptr, "filepath", 0, "", ICON_NONE); - uiItemO(row, "", ICON_FILE_REFRESH, "cachefile.reload"); + uiLayoutSetPropSep(layout, true); - row = uiLayoutRow(layout, false); - uiItemR(row, &fileptr, "is_sequence", 0, "Is Sequence", ICON_NONE); + row = uiLayoutRow(layout, true); + uiItemR(row, &fileptr, "filepath", 0, NULL, ICON_NONE); + sub = uiLayoutRow(row, true); + uiItemO(sub, "", ICON_FILE_REFRESH, "cachefile.reload"); row = uiLayoutRow(layout, false); - uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE); + uiItemR(row, &fileptr, "is_sequence", 0, NULL, ICON_NONE); - row = uiLayoutRow(layout, false); - uiLayoutSetActive(row, RNA_boolean_get(&fileptr, "override_frame")); - uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE); + row = uiLayoutRowWithHeading(layout, true, IFACE_("Override Frame")); + sub = uiLayoutRow(row, true); + uiLayoutSetPropDecorate(sub, false); + uiItemR(sub, &fileptr, "override_frame", 0, "", ICON_NONE); + subsub = uiLayoutRow(sub, true); + uiLayoutSetActive(subsub, RNA_boolean_get(&fileptr, "override_frame")); + uiItemR(subsub, &fileptr, "frame", 0, "", ICON_NONE); + uiItemDecoratorR(row, &fileptr, "frame", 0); row = uiLayoutRow(layout, false); - uiItemR(row, &fileptr, "frame_offset", 0, "Frame Offset", ICON_NONE); + uiItemR(row, &fileptr, "frame_offset", 0, NULL, ICON_NONE); uiLayoutSetActive(row, !RNA_boolean_get(&fileptr, "is_sequence")); - row = uiLayoutRow(layout, false); - uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE); - - row = uiLayoutRow(layout, false); - uiLayoutSetActive(row, (sbuts->mainb == BCONTEXT_CONSTRAINT)); - uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE); + if (sbuts->mainb == BCONTEXT_CONSTRAINT) { + row = uiLayoutRow(layout, false); + uiItemR(row, &fileptr, "scale", 0, IFACE_("Manual Scale"), ICON_NONE); + } /* TODO: unused for now, so no need to expose. */ #if 0 diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 3737b607305..432da3d5dd5 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -45,6 +45,7 @@ #include "RNA_access.h" #include "UI_interface.h" +#include "UI_interface_icons.h" #include "UI_resources.h" #include "WM_api.h" @@ -384,6 +385,7 @@ typedef struct CollItemSearch { char *name; int index; int iconid; + bool is_id; uint has_sep_char : 1; } CollItemSearch; @@ -418,6 +420,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, const bool skip_filter = data->search_but && !data->search_but->changed; char name_buf[UI_MAX_DRAW_STR]; char *name; + bool has_id_icon = false; /* build a temporary list of relevant items first */ RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) { @@ -437,16 +440,20 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, int iconid = ICON_NONE; bool has_sep_char = false; + bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type); - if (itemptr.type && RNA_struct_is_ID(itemptr.type)) { + if (is_id) { iconid = ui_id_icon_get(C, itemptr.data, false); + if (!ELEM(iconid, 0, ICON_BLANK1)) { + has_id_icon = true; + } if (requires_exact_data_name) { name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL); } else { const ID *id = itemptr.data; - BKE_id_full_name_ui_prefix_get(name_buf, id, UI_SEP_CHAR); + BKE_id_full_name_ui_prefix_get(name_buf, itemptr.data, true, UI_SEP_CHAR); BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI, "Name string buffer should be big enough to hold full UI ID name"); name = name_buf; @@ -464,6 +471,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, cis->name = BLI_strdup(name); cis->index = i; cis->iconid = iconid; + cis->is_id = is_id; cis->has_sep_char = has_sep_char; BLI_addtail(items_list, cis); } @@ -480,6 +488,17 @@ void ui_rna_collection_search_update_fn(const struct bContext *C, /* add search items from temporary list */ for (cis = items_list->first; cis; cis = cis->next) { + /* If no item has an own icon to display, libraries can use the library icons rather than the + * name prefix for showing the library status. */ + if (!has_id_icon && cis->is_id) { + cis->iconid = UI_library_icon_get(cis->data); + /* No need to re-allocate, string should be shorter than before (lib status prefix is + * removed). */ + BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR); + BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name)); + strcpy(cis->name, name_buf); + } + if (!UI_search_item_add(items, cis->name, cis->data, diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0498b312618..16a5a13885b 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -393,35 +393,14 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} * * \{ */ -/* offset in triavec[] in shader per type */ -static const int tria_ofs[ROUNDBOX_TRIA_MAX] = { - [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 0, - [ROUNDBOX_TRIA_SCROLL] = 12, - [ROUNDBOX_TRIA_MENU] = 28, - [ROUNDBOX_TRIA_CHECK] = 34, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40, -}; -static const int tria_vcount[ROUNDBOX_TRIA_MAX] = { - [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 6, - [ROUNDBOX_TRIA_SCROLL] = 16, - [ROUNDBOX_TRIA_MENU] = 6, - [ROUNDBOX_TRIA_CHECK] = 6, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3, -}; - static struct { - GPUBatch *roundbox_widget[ROUNDBOX_TRIA_MAX]; - - GPUBatch *roundbox_simple; - GPUBatch *roundbox_simple_aa; - GPUBatch *roundbox_simple_outline; + GPUBatch *roundbox_widget; GPUBatch *roundbox_shadow; + /* TODO remove */ GPUVertFormat format; uint vflag_id; -} g_ui_batch_cache = {{0}}; +} g_ui_batch_cache = {0}; static GPUVertFormat *vflag_format(void) { @@ -436,7 +415,7 @@ static GPUVertFormat *vflag_format(void) #define INNER 0 #define OUTLINE 1 #define EMBOSS 2 -#define NO_AA WIDGET_AA_JITTER +#define NO_AA 0 static void set_roundbox_vertex_data(GPUVertBufRaw *vflag_step, uint32_t d) { @@ -462,176 +441,30 @@ static uint32_t set_roundbox_vertex(GPUVertBufRaw *vflag_step, return *data; } -static uint32_t set_tria_vertex( - GPUVertBufRaw *vflag_step, int tria_type, int tria_v, int tria_id, int jit_v) -{ - uint32_t *data = GPU_vertbuf_raw_step(vflag_step); - if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) { - tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS]; - } - *data = tria_ofs[tria_type] + tria_v; - *data |= jit_v << 6; - *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */ - *data |= 1 << 14; /* is tria vert */ - return *data; -} - -static void roundbox_batch_add_tria(GPUVertBufRaw *vflag_step, int tria, uint32_t last_data) +GPUBatch *ui_batch_roundbox_widget_get(void) { - const int tria_num = - ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2; - /* for each tria */ - for (int t = 0; t < tria_num; t++) { - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - /* restart */ - set_roundbox_vertex_data(vflag_step, last_data); - set_tria_vertex(vflag_step, tria, 0, t, j); - for (int v = 0; v < tria_vcount[tria]; v++) { - last_data = set_tria_vertex(vflag_step, tria, v, t, j); - } - } - } -} - -GPUBatch *ui_batch_roundbox_widget_get(int tria) -{ - if (g_ui_batch_cache.roundbox_widget[tria] == NULL) { - uint32_t last_data; - GPUVertBufRaw vflag_step; + if (g_ui_batch_cache.roundbox_widget == NULL) { GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format()); - int vcount = WIDGET_SIZE_MAX; /* inner */ - vcount += 2; /* restart */ - vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */ - vcount += 2; /* restart */ - vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */ - if (tria) { - vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */ - if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) { - vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */ - } - } - GPU_vertbuf_data_alloc(vbo, vcount); - GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); - /* Inner */ - for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { - for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) { - last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER); - last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER); - } - } - /* restart */ - set_roundbox_vertex_data(&vflag_step, last_data); - set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE); - /* Outlines */ - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - for (int c = 0; c < 4; c++) { - for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { - set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE); - set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE); - } - } - /* Close the loop. */ - set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE); - last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE); - } - /* restart */ - set_roundbox_vertex_data(&vflag_step, last_data); - set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS); - /* Emboss */ - /* go back and forth : avoid degenerate triangle (but beware of backface cull) */ - bool rev = false; - for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) { - for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) { - int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0; - int end = WIDGET_CURVE_RESOLU; - for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) { - set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS); - last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS); - } - } - } - if (tria) { - roundbox_batch_add_tria(&vflag_step, tria, last_data); - } - g_ui_batch_cache.roundbox_widget[tria] = GPU_batch_create_ex( - GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); - gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]); - } - return g_ui_batch_cache.roundbox_widget[tria]; -} -GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased) -{ - GPUBatch **batch = NULL; + GPU_vertbuf_data_alloc(vbo, 12); - if (filled) { - if (antialiased) { - batch = &g_ui_batch_cache.roundbox_simple_aa; - } - else { - batch = &g_ui_batch_cache.roundbox_simple; - } - } - else { - if (antialiased) { - BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */ - } - else { - batch = &g_ui_batch_cache.roundbox_simple_outline; - } - } + GPUIndexBufBuilder ibuf; + GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 6, 12); + /* Widget */ + GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2); + GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3); + /* Trias */ + GPU_indexbuf_add_tri_verts(&ibuf, 4, 5, 6); + GPU_indexbuf_add_tri_verts(&ibuf, 6, 5, 7); - if (*batch == NULL) { - uint32_t last_data; - GPUVertBufRaw vflag_step; - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format()); - int vcount = WIDGET_SIZE_MAX; - vcount += (filled) ? 2 : 0; - vcount *= (antialiased) ? WIDGET_AA_JITTER : 1; - GPU_vertbuf_data_alloc(vbo, vcount); - GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); + GPU_indexbuf_add_tri_verts(&ibuf, 8, 9, 10); + GPU_indexbuf_add_tri_verts(&ibuf, 10, 9, 11); - if (filled) { - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - if (!antialiased) { - j = NO_AA; - } - /* restart */ - set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER); - for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { - for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) { - last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER); - last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER); - } - } - /* restart */ - set_roundbox_vertex_data(&vflag_step, last_data); - if (!antialiased) { - break; - } - } - *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); - } - else { - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - if (!antialiased) { - j = NO_AA; - } - for (int c = 0; c < 4; c++) { - for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { - set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER); - } - } - if (!antialiased) { - break; - } - } - *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO); - } - - gpu_batch_presets_register(*batch); + g_ui_batch_cache.roundbox_widget = GPU_batch_create_ex( + GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&ibuf), GPU_BATCH_OWNS_INDEX | GPU_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget); } - return *batch; + return g_ui_batch_cache.roundbox_widget; } GPUBatch *ui_batch_roundbox_shadow_get(void) @@ -1314,14 +1147,13 @@ static void widgetbase_set_uniform_colors_ubv(uiWidgetBase *wtb, /* keep in sync with shader */ #define MAX_WIDGET_BASE_BATCH 6 -#define MAX_WIDGET_PARAMETERS 11 +#define MAX_WIDGET_PARAMETERS 12 static struct { - GPUBatch *batch; /* Batch type */ uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]; int count; bool enabled; -} g_widget_base_batch = {0}; +} g_widget_base_batch = {{{{0}}}}; void UI_widgetbase_draw_cache_flush(void) { @@ -1332,7 +1164,7 @@ void UI_widgetbase_draw_cache_flush(void) return; } - GPUBatch *batch = g_widget_base_batch.batch; + GPUBatch *batch = ui_batch_roundbox_widget_get(); if (g_widget_base_batch.count == 1) { /* draw single */ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); @@ -1376,31 +1208,15 @@ void UI_widgetbase_draw_cache_end(void) GPU_blend(false); } -static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb) +static void draw_widgetbase_batch(uiWidgetBase *wtb) { + wtb->uniform_params.tria_type = wtb->tria1.type; wtb->uniform_params.tria1_size = wtb->tria1.size; wtb->uniform_params.tria2_size = wtb->tria2.size; copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center); copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center); if (g_widget_base_batch.enabled) { - if (g_widget_base_batch.batch == NULL) { - g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS); - } - - /* draw multi */ - if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] && - batch != g_widget_base_batch.batch) { - /* issue previous calls before changing batch type. */ - UI_widgetbase_draw_cache_flush(); - g_widget_base_batch.batch = batch; - } - - /* No need to change batch if tria is not visible. Just scale it to 0. */ - if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) { - wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0; - } - g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params; g_widget_base_batch.count++; @@ -1412,6 +1228,7 @@ static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb) const float checker_params[3] = { UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f}; /* draw single */ + GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array( batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)&wtb->uniform_params); @@ -1434,8 +1251,6 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, show_alpha_checkers = false; } - GPU_blend(true); - /* backdrop non AA */ if (wtb->draw_inner) { if (wcol->shaded == 0) { @@ -1455,7 +1270,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, outline_col[0] = wcol->outline[0]; outline_col[1] = wcol->outline[1]; outline_col[2] = wcol->outline[2]; - outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER; + outline_col[3] = wcol->outline[3]; /* emboss bottom shadow */ if (wtb->draw_emboss) { @@ -1467,7 +1282,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, tria_col[0] = wcol->item[0]; tria_col[1] = wcol->item[1]; tria_col[2] = wcol->item[2]; - tria_col[3] = (uchar)((float)wcol->item[3] / WIDGET_AA_JITTER); + tria_col[3] = wcol->item[3]; } /* Draw everything in one drawcall */ @@ -1476,11 +1291,10 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, widgetbase_set_uniform_colors_ubv( wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, show_alpha_checkers); - GPUBatch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type); - draw_widgetbase_batch(roundbox_batch, wtb); + GPU_blend(true); + draw_widgetbase_batch(wtb); + GPU_blend(false); } - - GPU_blend(false); } static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol) diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f8419ba3eba..d696c99851b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -113,10 +113,10 @@ BLI_INLINE void clamp_rctf_to_rcti(rcti *dst, const rctf *src) static int view2d_scroll_mapped(int scroll) { if (scroll & V2D_SCROLL_HORIZONTAL_FULLR) { - scroll &= ~(V2D_SCROLL_HORIZONTAL); + scroll &= ~V2D_SCROLL_HORIZONTAL; } if (scroll & V2D_SCROLL_VERTICAL_FULLR) { - scroll &= ~(V2D_SCROLL_VERTICAL); + scroll &= ~V2D_SCROLL_VERTICAL; } return scroll; } @@ -198,7 +198,7 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) } /* horizontal scroller */ - if (scroll & (V2D_SCROLL_BOTTOM)) { + if (scroll & V2D_SCROLL_BOTTOM) { /* on bottom edge of region */ v2d->hor = *mask_scroll; v2d->hor.ymax = scroll_height; @@ -211,7 +211,7 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) /* adjust vertical scroller if there's a horizontal scroller, to leave corner free */ if (scroll & V2D_SCROLL_VERTICAL) { - if (scroll & (V2D_SCROLL_BOTTOM)) { + if (scroll & V2D_SCROLL_BOTTOM) { /* on bottom edge of region */ v2d->vert.ymin = v2d->hor.ymax; } @@ -1408,22 +1408,22 @@ struct View2DScrollers { int vert_min, vert_max; /* vertical scrollbar */ int hor_min, hor_max; /* horizontal scrollbar */ - rcti hor, vert; /* exact size of slider backdrop */ - int horfull, vertfull; /* set if sliders are full, we don't draw them */ + /** Exact size of slider backdrop. */ + rcti hor, vert; + /* set if sliders are full, we don't draw them */ + /* int horfull, vertfull; */ /* UNUSED */ }; /* Calculate relevant scroller properties */ -View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) +void UI_view2d_scrollers_calc(View2D *v2d, + const rcti *mask_custom, + struct View2DScrollers *r_scrollers) { - View2DScrollers *scrollers; rcti vert, hor; float fac1, fac2, totsize, scrollsize; int scroll = view2d_scroll_mapped(v2d->scroll); int smaller; - /* scrollers is allocated here... */ - scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers"); - /* Always update before drawing (for dynamically sized scrollers). */ view2d_masks(v2d, mask_custom); @@ -1452,12 +1452,12 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) vert.xmax -= smaller; } - CLAMP(vert.ymin, vert.ymin, vert.ymax - V2D_SCROLL_HANDLE_SIZE_HOTSPOT); - CLAMP(hor.xmin, hor.xmin, hor.xmax - V2D_SCROLL_HANDLE_SIZE_HOTSPOT); + CLAMP_MAX(vert.ymin, vert.ymax - V2D_SCROLL_HANDLE_SIZE_HOTSPOT); + CLAMP_MAX(hor.xmin, hor.xmax - V2D_SCROLL_HANDLE_SIZE_HOTSPOT); /* store in scrollers, used for drawing */ - scrollers->vert = vert; - scrollers->hor = hor; + r_scrollers->vert = vert; + r_scrollers->hor = hor; /* scroller 'buttons': * - These should always remain within the visible region of the scrollbar @@ -1475,30 +1475,30 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize; if (fac1 <= 0.0f) { - scrollers->hor_min = hor.xmin; + r_scrollers->hor_min = hor.xmin; } else { - scrollers->hor_min = (int)(hor.xmin + (fac1 * scrollsize)); + r_scrollers->hor_min = (int)(hor.xmin + (fac1 * scrollsize)); } fac2 = (v2d->cur.xmax - v2d->tot.xmin) / totsize; if (fac2 >= 1.0f) { - scrollers->hor_max = hor.xmax; + r_scrollers->hor_max = hor.xmax; } else { - scrollers->hor_max = (int)(hor.xmin + (fac2 * scrollsize)); + r_scrollers->hor_max = (int)(hor.xmin + (fac2 * scrollsize)); } /* prevent inverted sliders */ - if (scrollers->hor_min > scrollers->hor_max) { - scrollers->hor_min = scrollers->hor_max; + if (r_scrollers->hor_min > r_scrollers->hor_max) { + r_scrollers->hor_min = r_scrollers->hor_max; } /* prevent sliders from being too small to grab */ - if ((scrollers->hor_max - scrollers->hor_min) < V2D_SCROLL_THUMB_SIZE_MIN) { - scrollers->hor_max = scrollers->hor_min + V2D_SCROLL_THUMB_SIZE_MIN; + if ((r_scrollers->hor_max - r_scrollers->hor_min) < V2D_SCROLL_THUMB_SIZE_MIN) { + r_scrollers->hor_max = r_scrollers->hor_min + V2D_SCROLL_THUMB_SIZE_MIN; - CLAMP(scrollers->hor_max, hor.xmin + V2D_SCROLL_THUMB_SIZE_MIN, hor.xmax); - CLAMP(scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLL_THUMB_SIZE_MIN); + CLAMP(r_scrollers->hor_max, hor.xmin + V2D_SCROLL_THUMB_SIZE_MIN, hor.xmax); + CLAMP(r_scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLL_THUMB_SIZE_MIN); } } @@ -1513,39 +1513,39 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize; if (fac1 <= 0.0f) { - scrollers->vert_min = vert.ymin; + r_scrollers->vert_min = vert.ymin; } else { - scrollers->vert_min = (int)(vert.ymin + (fac1 * scrollsize)); + r_scrollers->vert_min = (int)(vert.ymin + (fac1 * scrollsize)); } fac2 = (v2d->cur.ymax - v2d->tot.ymin) / totsize; if (fac2 >= 1.0f) { - scrollers->vert_max = vert.ymax; + r_scrollers->vert_max = vert.ymax; } else { - scrollers->vert_max = (int)(vert.ymin + (fac2 * scrollsize)); + r_scrollers->vert_max = (int)(vert.ymin + (fac2 * scrollsize)); } /* prevent inverted sliders */ - if (scrollers->vert_min > scrollers->vert_max) { - scrollers->vert_min = scrollers->vert_max; + if (r_scrollers->vert_min > r_scrollers->vert_max) { + r_scrollers->vert_min = r_scrollers->vert_max; } /* prevent sliders from being too small to grab */ - if ((scrollers->vert_max - scrollers->vert_min) < V2D_SCROLL_THUMB_SIZE_MIN) { - scrollers->vert_max = scrollers->vert_min + V2D_SCROLL_THUMB_SIZE_MIN; + if ((r_scrollers->vert_max - r_scrollers->vert_min) < V2D_SCROLL_THUMB_SIZE_MIN) { + r_scrollers->vert_max = r_scrollers->vert_min + V2D_SCROLL_THUMB_SIZE_MIN; - CLAMP(scrollers->vert_max, vert.ymin + V2D_SCROLL_THUMB_SIZE_MIN, vert.ymax); - CLAMP(scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLL_THUMB_SIZE_MIN); + CLAMP(r_scrollers->vert_max, vert.ymin + V2D_SCROLL_THUMB_SIZE_MIN, vert.ymax); + CLAMP(r_scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLL_THUMB_SIZE_MIN); } } - - return scrollers; } /* Draw scrollbars in the given 2d-region */ -void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) +void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom) { + View2DScrollers scrollers; + UI_view2d_scrollers_calc(v2d, mask_custom, &scrollers); bTheme *btheme = UI_GetTheme(); rcti vert, hor; const int scroll = view2d_scroll_mapped(v2d->scroll); @@ -1556,8 +1556,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color); /* make copies of rects for less typing */ - vert = vs->vert; - hor = vs->hor; + vert = scrollers.vert; + hor = scrollers.hor; /* horizontal scrollbar */ if (scroll & V2D_SCROLL_HORIZONTAL) { @@ -1566,8 +1566,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) rcti slider; int state; - slider.xmin = vs->hor_min; - slider.xmax = vs->hor_max; + slider.xmin = scrollers.hor_min; + slider.xmax = scrollers.hor_max; slider.ymin = hor.ymin; slider.ymax = hor.ymax; @@ -1602,8 +1602,8 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) slider.xmin = vert.xmin; slider.xmax = vert.xmax; - slider.ymin = vs->vert_min; - slider.ymax = vs->vert_max; + slider.ymin = scrollers.vert_min; + slider.ymax = scrollers.vert_max; state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0; @@ -1631,12 +1631,6 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) btheme->tui.widget_emboss[3] = emboss_alpha; } -/* free temporary memory used for drawing scrollers */ -void UI_view2d_scrollers_free(View2DScrollers *scrollers) -{ - MEM_freeN(scrollers); -} - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 98bbd7af943..0efb49f42bf 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1922,6 +1922,9 @@ struct View2DScrollers { /* focus bubbles */ int vert_min, vert_max; /* vertical scrollbar */ int hor_min, hor_max; /* horizontal scrollbar */ + + /* These values are written into, even if we don't use them. */ + rcti _hor, _vert; }; /* quick enum for vsm->zone (scroller handles) */ @@ -2011,7 +2014,7 @@ static void scroller_activate_init(bContext *C, const char in_scroller) { v2dScrollerMove *vsm; - View2DScrollers *scrollers; + View2DScrollers scrollers; ARegion *region = CTX_wm_region(C); View2D *v2d = ®ion->v2d; rctf tot_cur_union; @@ -2032,7 +2035,7 @@ static void scroller_activate_init(bContext *C, /* 'zone' depends on where mouse is relative to bubble * - zooming must be allowed on this axis, otherwise, default to pan */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); + UI_view2d_scrollers_calc(v2d, NULL, &scrollers); /* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases * moving the scroll bars has far too little effect and the view can get stuck T31476. */ @@ -2049,15 +2052,15 @@ static void scroller_activate_init(bContext *C, /* get 'zone' (i.e. which part of scroller is activated) */ vsm->zone = mouse_in_scroller_handle( - event->mval[0], v2d->hor.xmin, v2d->hor.xmax, scrollers->hor_min, scrollers->hor_max); + event->mval[0], v2d->hor.xmin, v2d->hor.xmax, scrollers.hor_min, scrollers.hor_max); if ((v2d->keepzoom & V2D_LOCKZOOM_X) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { /* default to scroll, as handles not usable */ vsm->zone = SCROLLHANDLE_BAR; } - vsm->scrollbarwidth = scrollers->hor_max - scrollers->hor_min; - vsm->scrollbar_orig = ((scrollers->hor_max + scrollers->hor_min) / 2) + region->winrct.xmin; + vsm->scrollbarwidth = scrollers.hor_max - scrollers.hor_min; + vsm->scrollbar_orig = ((scrollers.hor_max + scrollers.hor_min) / 2) + region->winrct.xmin; } else { /* vertical scroller - calculate adjustment factor first */ @@ -2069,18 +2072,17 @@ static void scroller_activate_init(bContext *C, /* get 'zone' (i.e. which part of scroller is activated) */ vsm->zone = mouse_in_scroller_handle( - event->mval[1], v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max); + event->mval[1], v2d->vert.ymin, v2d->vert.ymax, scrollers.vert_min, scrollers.vert_max); if ((v2d->keepzoom & V2D_LOCKZOOM_Y) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { /* default to scroll, as handles not usable */ vsm->zone = SCROLLHANDLE_BAR; } - vsm->scrollbarwidth = scrollers->vert_max - scrollers->vert_min; - vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + region->winrct.ymin; + vsm->scrollbarwidth = scrollers.vert_max - scrollers.vert_min; + vsm->scrollbar_orig = ((scrollers.vert_max + scrollers.vert_min) / 2) + region->winrct.ymin; } - UI_view2d_scrollers_free(scrollers); ED_region_tag_redraw_no_rebuild(region); } @@ -2299,8 +2301,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * } /* zone is also inappropriate if scroller is not visible... */ - if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_FULLR))) || - ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_FULLR)))) { + if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_HORIZONTAL_FULLR)) || + ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_VERTICAL_FULLR))) { /* free customdata initialized */ scroller_activate_exit(C, op); diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index fc2c55ffeda..9db1fe31494 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -410,8 +410,11 @@ void WM_OT_alembic_export(wmOperatorType *ot) "Use Subdivision Schema", "Export meshes using Alembic's subdivision schema"); - RNA_def_boolean( - ot->srna, "apply_subdiv", 0, "Apply Subdivision Surface", "Export subdivision surfaces as meshes"); + RNA_def_boolean(ot->srna, + "apply_subdiv", + 0, + "Apply Subdivision Surface", + "Export subdivision surfaces as meshes"); RNA_def_boolean(ot->srna, "curves_as_mesh", @@ -667,6 +670,7 @@ void WM_OT_alembic_import(wmOperatorType *ot) ot->name = "Import Alembic"; ot->description = "Load an Alembic archive"; ot->idname = "WM_OT_alembic_import"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ot->invoke = wm_alembic_import_invoke; ot->exec = wm_alembic_import_exec; diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 9091e7d8afc..c1a4492994a 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -857,6 +857,7 @@ void WM_OT_collada_import(wmOperatorType *ot) ot->name = "Import COLLADA"; ot->description = "Load a Collada file"; ot->idname = "WM_OT_collada_import"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ot->invoke = WM_operator_filesel; ot->exec = wm_collada_import_exec; diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index e94412233ff..d18f5de357f 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -121,7 +121,7 @@ enum { BEV_MODAL_MARK_SHARP_TOGGLE, BEV_MODAL_OUTER_MITER_CHANGE, BEV_MODAL_INNER_MITER_CHANGE, - BEV_MODAL_CUSTOM_PROFILE_TOGGLE, + BEV_MODAL_PROFILE_TYPE_CHANGE, BEV_MODAL_VERTEX_MESH_CHANGE, }; @@ -146,7 +146,7 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) int available_len = sizeof(buf); Scene *sce = CTX_data_scene(C); char offset_str[NUM_STR_REP_LEN]; - const char *mode_str, *omiter_str, *imiter_str, *vmesh_str; + const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str; PropertyRNA *prop; #define WM_MODALKEY(_id) \ @@ -170,6 +170,9 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) prop = RNA_struct_find_property(op->ptr, "offset_type"); RNA_property_enum_name_gettexted( C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str); + prop = RNA_struct_find_property(op->ptr, "profile_type"); + RNA_property_enum_name_gettexted( + C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &profile_type_str); prop = RNA_struct_find_property(op->ptr, "miter_outer"); RNA_property_enum_name_gettexted( C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &omiter_str); @@ -195,7 +198,7 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) "%s: Harden Normals (%s), " "%s: Mark Seam (%s), " "%s: Mark Sharp (%s), " - "%s: Custom Profile (%s), " + "%s: Profile Type (%s), " "%s: Intersection (%s)"), WM_MODALKEY(BEV_MODAL_CONFIRM), WM_MODALKEY(BEV_MODAL_CANCEL), @@ -221,8 +224,8 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_seam")), WM_MODALKEY(BEV_MODAL_MARK_SHARP_TOGGLE), WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_sharp")), - WM_MODALKEY(BEV_MODAL_CUSTOM_PROFILE_TOGGLE), - WM_bool_as_string(RNA_boolean_get(op->ptr, "use_custom_profile")), + WM_MODALKEY(BEV_MODAL_PROFILE_TYPE_CHANGE), + profile_type_str, WM_MODALKEY(BEV_MODAL_VERTEX_MESH_CHANGE), vmesh_str); @@ -327,6 +330,7 @@ static bool edbm_bevel_calc(wmOperator *op) const float offset = get_bevel_offset(op); const int offset_type = RNA_enum_get(op->ptr, "offset_type"); + const int profile_type = RNA_enum_get(op->ptr, "profile_type"); const int segments = RNA_int_get(op->ptr, "segments"); const float profile = RNA_float_get(op->ptr, "profile"); const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only"); @@ -340,7 +344,6 @@ static bool edbm_bevel_calc(wmOperator *op) const int miter_outer = RNA_enum_get(op->ptr, "miter_outer"); const int miter_inner = RNA_enum_get(op->ptr, "miter_inner"); const float spread = RNA_float_get(op->ptr, "spread"); - const bool use_custom_profile = RNA_boolean_get(op->ptr, "use_custom_profile"); const int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method"); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { @@ -364,16 +367,17 @@ static bool edbm_bevel_calc(wmOperator *op) EDBM_op_init(em, &bmop, op, - "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f " - "clamp_overlap=%b material=%i loop_slide=%b mark_seam=%b mark_sharp=%b " - "harden_normals=%b face_strength_mode=%i " - "miter_outer=%i miter_inner=%i spread=%f smoothresh=%f use_custom_profile=%b " - "custom_profile=%p vmesh_method=%i", + "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i " + "profile_type=%i profile=%f clamp_overlap=%b material=%i loop_slide=%b " + "mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i " + "miter_outer=%i miter_inner=%i spread=%f smoothresh=%f custom_profile=%p " + "vmesh_method=%i", BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, + profile_type, profile, clamp_overlap, material, @@ -386,7 +390,6 @@ static bool edbm_bevel_calc(wmOperator *op) miter_inner, spread, me->smoothresh, - use_custom_profile, opdata->custom_profile, vmesh_method); @@ -681,7 +684,7 @@ wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf) 0, "Change inner miter", "Cycle through inner miter kinds"}, - {BEV_MODAL_CUSTOM_PROFILE_TOGGLE, "CUSTOM_PROFILE_TOGGLE", 0, "Toggle custom profile", ""}, + {BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""}, {BEV_MODAL_VERTEX_MESH_CHANGE, "VERTEX_MESH_CHANGE", 0, @@ -892,9 +895,13 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) break; } - case BEV_MODAL_CUSTOM_PROFILE_TOGGLE: { - bool use_custom_profile = RNA_boolean_get(op->ptr, "use_custom_profile"); - RNA_boolean_set(op->ptr, "use_custom_profile", !use_custom_profile); + case BEV_MODAL_PROFILE_TYPE_CHANGE: { + int profile_type = RNA_enum_get(op->ptr, "profile_type"); + profile_type++; + if (profile_type > BEVEL_PROFILE_CUSTOM) { + profile_type = BEVEL_PROFILE_SUPERELLIPSE; + } + RNA_enum_set(op->ptr, "profile_type", profile_type); edbm_bevel_calc(op); edbm_bevel_update_status_text(C, op); handled = true; @@ -938,21 +945,12 @@ static void edbm_bevel_ui(bContext *C, wmOperator *op) RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + int profile_type = RNA_enum_get(&ptr, "profile_type"); + if (RNA_enum_get(&ptr, "offset_type") == BEVEL_AMT_PERCENT) { uiItemR(layout, &ptr, "offset_pct", 0, NULL, ICON_NONE); } else { - switch (RNA_enum_get(&ptr, "offset_type")) { - case BEVEL_AMT_DEPTH: - offset_name = "Depth"; - break; - case BEVEL_AMT_WIDTH: - offset_name = "Width"; - break; - case BEVEL_AMT_OFFSET: - offset_name = "Offset"; - break; - } prop = RNA_struct_find_property(op->ptr, "offset_type"); RNA_property_enum_name_gettexted( C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &offset_name); @@ -972,7 +970,14 @@ static void edbm_bevel_ui(bContext *C, wmOperator *op) uiItemR(col, &ptr, "harden_normals", 0, NULL, ICON_NONE); uiItemR(layout, &ptr, "segments", 0, NULL, ICON_NONE); - uiItemR(layout, &ptr, "profile", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + if (ELEM(profile_type, BEVEL_PROFILE_SUPERELLIPSE, BEVEL_PROFILE_CUSTOM)) { + uiItemR(layout, + &ptr, + "profile", + UI_ITEM_R_SLIDER, + (profile_type == BEVEL_PROFILE_SUPERELLIPSE) ? IFACE_("Shape") : IFACE_("Miter Shape"), + ICON_NONE); + } uiItemR(layout, &ptr, "material", 0, NULL, ICON_NONE); uiItemL(layout, "Miter Type:", ICON_NONE); @@ -990,9 +995,11 @@ static void edbm_bevel_ui(bContext *C, wmOperator *op) row = uiLayoutRow(layout, true); uiItemR(row, &ptr, "vmesh_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, &ptr, "use_custom_profile", 0, NULL, ICON_NONE); - if (RNA_boolean_get(&ptr, "use_custom_profile")) { - /* Get an RNA pointer to ToolSettings to give to the curve profile template code */ + uiItemL(layout, "Profile Type:", ICON_NONE); + row = uiLayoutRow(layout, true); + uiItemR(row, &ptr, "profile_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + if (profile_type == BEVEL_PROFILE_CUSTOM) { + /* Get an RNA pointer to ToolSettings to give to the curve profile template code. */ Scene *scene = CTX_data_scene(C); RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr); uiTemplateCurveProfile(layout, &toolsettings_ptr, "custom_bevel_profile_preset"); @@ -1012,6 +1019,25 @@ void MESH_OT_bevel(wmOperatorType *ot) "Depth", "Amount is perpendicular distance from original edge to bevel face"}, {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"}, + {BEVEL_AMT_ABSOLUTE, + "ABSOLUTE", + 0, + "Absolute", + "Amount is absolute distance along adjacent edge"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem prop_profile_type_items[] = { + {BEVEL_PROFILE_SUPERELLIPSE, + "SUPERELLIPSE", + 0, + "Superellipse", + "The profile can be a concave or convex curve"}, + {BEVEL_PROFILE_CUSTOM, + "CUSTOM", + 0, + "Custom", + "The profile can be any arbitrary path between its endpoints"}, {0, NULL, 0, NULL, NULL}, }; @@ -1068,13 +1094,24 @@ void MESH_OT_bevel(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR_XY | OPTYPE_BLOCKING; /* properties */ - RNA_def_enum( - ot->srna, "offset_type", offset_type_items, 0, "Width Type", "What distance Width measures"); + RNA_def_enum(ot->srna, + "offset_type", + offset_type_items, + 0, + "Width Type", + "The method for determining the size of the bevel"); prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.0, 1e6); RNA_def_property_ui_range(prop, 0.0, 100.0, 1, 3); RNA_def_property_ui_text(prop, "Width", "Bevel amount"); + RNA_def_enum(ot->srna, + "profile_type", + prop_profile_type_items, + 0, + "Profile Type", + "The type of shape used to rebuild a beveled section"); + prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_range(prop, 0.0, 100); RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method"); @@ -1161,12 +1198,6 @@ void MESH_OT_bevel(wmOperatorType *ot) 0.0f, 100.0f); - RNA_def_boolean(ot->srna, - "use_custom_profile", - false, - "Custom Profile", - "Use a custom profile for the bevel"); - RNA_def_enum(ot->srna, "vmesh_method", vmesh_method_items, diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 5f5599b53df..369c7735d20 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1895,12 +1895,12 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, if (!f) { if (kcd->is_interactive) { - /* try to use backbuffer selection method if ray casting failed */ + /* Try to use back-buffer selection method if ray casting failed. */ f = EDBM_face_find_nearest(&kcd->vc, &dist); /* cheat for now; just put in the origin instead * of a true coordinate on the face. - * This just puts a point 1.0f infront of the view. */ + * This just puts a point 1.0f in front of the view. */ add_v3_v3v3(co, origin, ray); } } @@ -1908,8 +1908,10 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, return f; } -/* find the 2d screen space density of vertices within a radius. used to scale snapping - * distance for picking edges/verts.*/ +/** + * Find the 2d screen space density of vertices within a radius. + * Used to scale snapping distance for picking edges/verts. + */ static int knife_sample_screen_density(KnifeTool_OpData *kcd, const float radius) { BMFace *f; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index a0a3d24e49a..2cffb3ecdec 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4161,7 +4161,7 @@ static Base *mesh_separate_tagged( CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE); /* Take into account user preferences for duplicating actions. */ - short dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT); + const eDupli_ID_Flags dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT); base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag); /* normally would call directly after but in this case delay recalc */ @@ -4233,7 +4233,7 @@ static Base *mesh_separate_arrays(Main *bmain, CustomData_bmesh_init_pool(&bm_new->pdata, faces_len, BM_FACE); /* Take into account user preferences for duplicating actions. */ - short dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT); + const eDupli_ID_Flags dupflag = USER_DUP_MESH | (U.dupflag & USER_DUP_ACT); base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag); /* normally would call directly after but in this case delay recalc */ @@ -7240,8 +7240,11 @@ void MESH_OT_wireframe(wmOperatorType *ot) /* use 1 rather then 10 for max else dragging the button moves too far */ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4); RNA_def_float_distance(ot->srna, "offset", 0.01f, 0.0f, 1e4f, "Offset", "", 0.0f, 10.0f); - RNA_def_boolean( - ot->srna, "use_crease", false, "Crease", "Crease hub edges for an improved subdivision surface"); + RNA_def_boolean(ot->srna, + "use_crease", + false, + "Crease", + "Crease hub edges for an improved subdivision surface"); prop = RNA_def_float( ot->srna, "crease_weight", 0.01f, 0.0f, 1e3f, "Crease weight", "", 0.0f, 1.0f); RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 51b699acd63..8fce726eff5 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -121,8 +121,15 @@ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer) CustomData *data; int layer_index, tot, n; - data = mesh_customdata_get_type( - me, (ELEM(type, CD_MLOOPUV, CD_MLOOPCOL)) ? BM_LOOP : BM_FACE, &tot); + char htype = BM_FACE; + if (ELEM(type, CD_MLOOPCOL, CD_MLOOPUV)) { + htype = BM_LOOP; + } + else if (ELEM(type, CD_PROP_COLOR)) { + htype = BM_VERT; + } + + data = mesh_customdata_get_type(me, htype, &tot); layer_index = CustomData_get_layer_index(data, type); n = (layer - &data->layers[layer_index]); BLI_assert(n >= 0 && (n + layer_index) < data->totlayer); @@ -488,6 +495,117 @@ bool ED_mesh_color_remove_named(Mesh *me, const char *name) } } +/*********************** Sculpt Vertex colors operators ************************/ + +/* note: keep in sync with ED_mesh_uv_texture_add */ +int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) +{ + BMEditMesh *em; + int layernum; + + if (me->edit_mesh) { + em = me->edit_mesh; + + layernum = CustomData_number_of_layers(&em->bm->vdata, CD_PROP_COLOR); + if (layernum >= MAX_MCOL) { + return -1; + } + + /* CD_PROP_COLOR */ + BM_data_layer_add_named(em->bm, &em->bm->vdata, CD_PROP_COLOR, name); + /* copy data from active vertex color layer */ + if (layernum && do_init) { + const int layernum_dst = CustomData_get_active_layer(&em->bm->vdata, CD_PROP_COLOR); + BM_data_layer_copy(em->bm, &em->bm->vdata, CD_PROP_COLOR, layernum_dst, layernum); + } + if (active_set || layernum == 0) { + CustomData_set_layer_active(&em->bm->vdata, CD_PROP_COLOR, layernum); + } + } + else { + layernum = CustomData_number_of_layers(&me->vdata, CD_PROP_COLOR); + if (layernum >= MAX_MCOL) { + return -1; + } + + if (CustomData_has_layer(&me->vdata, CD_PROP_COLOR) && do_init) { + MPropCol *color_data = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); + CustomData_add_layer_named( + &me->vdata, CD_PROP_COLOR, CD_DUPLICATE, color_data, me->totvert, name); + } + else { + CustomData_add_layer_named(&me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, me->totvert, name); + } + + if (active_set || layernum == 0) { + CustomData_set_layer_active(&me->vdata, CD_PROP_COLOR, layernum); + } + + BKE_mesh_update_customdata_pointers(me, true); + } + + DEG_id_tag_update(&me->id, 0); + WM_main_add_notifier(NC_GEOM | ND_DATA, me); + + return layernum; +} + +bool ED_mesh_sculpt_color_ensure(struct Mesh *me, const char *name) +{ + BLI_assert(me->edit_mesh == NULL); + + if (me->totvert && !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) { + CustomData_add_layer_named(&me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, me->totvert, name); + BKE_mesh_update_customdata_pointers(me, true); + } + + DEG_id_tag_update(&me->id, 0); + + return (me->mloopcol != NULL); +} + +bool ED_mesh_sculpt_color_remove_index(Mesh *me, const int n) +{ + CustomData *vdata = GET_CD_DATA(me, vdata); + CustomDataLayer *cdl; + int index; + + index = CustomData_get_layer_index_n(vdata, CD_PROP_COLOR, n); + cdl = (index == -1) ? NULL : &vdata->layers[index]; + + if (!cdl) { + return false; + } + + delete_customdata_layer(me, cdl); + DEG_id_tag_update(&me->id, 0); + WM_main_add_notifier(NC_GEOM | ND_DATA, me); + + return true; +} +bool ED_mesh_sculpt_color_remove_active(Mesh *me) +{ + CustomData *vdata = GET_CD_DATA(me, vdata); + const int n = CustomData_get_active_layer(vdata, CD_PROP_COLOR); + if (n != -1) { + return ED_mesh_sculpt_color_remove_index(me, n); + } + else { + return false; + } +} +bool ED_mesh_sculpt_color_remove_named(Mesh *me, const char *name) +{ + CustomData *vdata = GET_CD_DATA(me, vdata); + const int n = CustomData_get_named_layer(vdata, CD_PROP_COLOR, name); + if (n != -1) { + return ED_mesh_sculpt_color_remove_index(me, n); + } + else { + return false; + } +} + /*********************** UV texture operators ************************/ static bool layers_poll(bContext *C) @@ -619,6 +737,62 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/*********************** Sculpt Vertex Color Operators ************************/ + +static int mesh_sculpt_vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + Mesh *me = ob->data; + + if (ED_mesh_sculpt_color_add(me, NULL, true, true) == -1) { + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + +void MESH_OT_sculpt_vertex_color_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Sculpt Vertex Color"; + ot->description = "Add vertex color layer"; + ot->idname = "MESH_OT_sculpt_vertex_color_add"; + + /* api callbacks */ + ot->poll = layers_poll; + ot->exec = mesh_sculpt_vertex_color_add_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mesh_sculpt_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + Mesh *me = ob->data; + + if (!ED_mesh_sculpt_color_remove_active(me)) { + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + +void MESH_OT_sculpt_vertex_color_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Sculpt Vertex Color"; + ot->description = "Remove vertex color layer"; + ot->idname = "MESH_OT_sculpt_vertex_color_remove"; + + /* api callbacks */ + ot->exec = mesh_sculpt_vertex_color_remove_exec; + ot->poll = layers_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* *** CustomData clear functions, we need an operator for each *** */ static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int type) diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 5e70069456b..bebad312454 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -267,6 +267,8 @@ void MESH_OT_uv_texture_add(struct wmOperatorType *ot); void MESH_OT_uv_texture_remove(struct wmOperatorType *ot); void MESH_OT_vertex_color_add(struct wmOperatorType *ot); void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); +void MESH_OT_sculpt_vertex_color_add(struct wmOperatorType *ot); +void MESH_OT_sculpt_vertex_color_remove(struct wmOperatorType *ot); /* no create_mask yet */ void MESH_OT_customdata_mask_clear(struct wmOperatorType *ot); void MESH_OT_customdata_skin_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index c52a5956ac4..ad1e91a57c0 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -155,6 +155,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); WM_operatortype_append(MESH_OT_vertex_color_remove); + WM_operatortype_append(MESH_OT_sculpt_vertex_color_add); + WM_operatortype_append(MESH_OT_sculpt_vertex_color_remove); WM_operatortype_append(MESH_OT_customdata_mask_clear); WM_operatortype_append(MESH_OT_customdata_skin_add); WM_operatortype_append(MESH_OT_customdata_skin_clear); @@ -278,8 +280,8 @@ void ED_operatormacros_mesh(void) RNA_boolean_set(otmacro->ptr, "mirror", false); ot = WM_operatortype_append_macro( - "MESH_OT_extrude_region_dissolve_move_intersect", - "Extrude, Dissolve, Move and Intersect", + "MESH_OT_extrude_manifold", + "Extrude Manifold", "Extrude, dissolves edges whose faces form a flat surface and intersect new edges", OPTYPE_UNDO | OPTYPE_REGISTER); otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region"); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 917bbe61e3d..1bdf2ede22a 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -297,7 +297,7 @@ static void join_mesh_single(Depsgraph *depsgraph, *mpoly_pp += me->totpoly; } -int join_mesh_exec(bContext *C, wmOperator *op) +int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -706,12 +706,14 @@ int join_mesh_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/*********************** JOIN AS SHAPES ***************************/ +/* -------------------------------------------------------------------- */ +/** \name Join as Shapes + * \{ */ /* Append selected meshes vertex locations as shapes of the active mesh, * return 0 if no join is made (error) and 1 of the join is done */ -int join_mesh_shapes_exec(bContext *C, wmOperator *op) +int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -796,6 +798,8 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Mesh Topology Mirror API * \{ */ diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index a25175510cd..094011ebef1 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -58,6 +58,10 @@ #include "mball_intern.h" +/* -------------------------------------------------------------------- */ +/** \name Edit Mode Functions + * \{ */ + /* This function is used to free all MetaElems from MetaBall */ void ED_mball_editmball_free(Object *obedit) { @@ -93,9 +97,36 @@ void ED_mball_editmball_load(Object *UNUSED(obedit)) { } -/* Add metaelem primitive to metaball object (which is in edit mode) */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Selection + * \{ */ + +bool ED_mball_deselect_all_multi(bContext *C) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc, depsgraph); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = BKE_mball_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Meta Primitive Utility + * \{ */ + +/** + * Add meta-element primitive to meta-ball object (which is in edit mode). + */ MetaElem *ED_mball_add_primitive( - bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type) + bContext *UNUSED(C), Object *obedit, bool obedit_is_new, float mat[4][4], float dia, int type) { MetaBall *mball = (MetaBall *)obedit->data; MetaElem *ml; @@ -109,16 +140,28 @@ MetaElem *ED_mball_add_primitive( ml = BKE_mball_element_add(mball, type); ml->rad *= dia; - mball->wiresize *= dia; - mball->rendersize *= dia; + + if (obedit_is_new) { + mball->wiresize *= dia; + mball->rendersize *= dia; + } copy_v3_v3(&ml->x, mat[3]); + /* MB_ELIPSOID works differently (intentional?). Whatever the case, + * on testing this needs to be skipped otherwise it doesn't behave like other types. */ + if (type != MB_ELIPSOID) { + mul_v3_fl(&ml->expx, dia); + } ml->flag |= SELECT; mball->lastelem = ml; return ml; } -/***************************** Select/Deselect operator *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select/Deselect Operator + * \{ */ /* Select or deselect all MetaElements */ static int mball_select_all_exec(bContext *C, wmOperator *op) @@ -175,8 +218,11 @@ void MBALL_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } +/** \} */ + /* -------------------------------------------------------------------- */ -/* Select Similar */ +/** \name Select Similar Operator + * \{ */ enum { SIMMBALL_TYPE = 1, @@ -428,9 +474,12 @@ void MBALL_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.01, 1.0); } -/***************************** Select random operator *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Random Operator + * \{ */ -/* Random metaball selection */ static int select_random_metaelems_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); @@ -494,7 +543,11 @@ void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot) WM_operator_properties_select_random(ot); } -/***************************** Duplicate operator *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Meta-Ball Operator + * \{ */ /* Duplicate selected MetaElements */ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) @@ -546,9 +599,14 @@ void MBALL_OT_duplicate_metaelems(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************************** Delete operator *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Meta-Ball Operator + * + * Delete all selected MetaElems (not MetaBall). + * \{ */ -/* Delete all selected MetaElems (not MetaBall) */ static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -601,9 +659,12 @@ void MBALL_OT_delete_metaelems(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************************** Hide operator *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Meta-Elements Operator + * \{ */ -/* Hide selected MetaElems */ static int hide_metaelems_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -646,9 +707,12 @@ void MBALL_OT_hide_metaelems(wmOperatorType *ot) ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected"); } -/***************************** Unhide operator *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Un-Hide Meta-Elements Operator + * \{ */ -/* Unhide all edited MetaElems */ static int reveal_metaelems_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -689,6 +753,12 @@ void MBALL_OT_reveal_metaelems(wmOperatorType *ot) RNA_def_boolean(ot->srna, "select", true, "Select", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Pick Utility + * \{ */ + /* Select MetaElement with mouse click (user can select radius circle or * stiffness circle) */ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) @@ -740,7 +810,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese continue; } - if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) { + if (metaelem_id != (hitresult & 0xFFFF0000 & ~MBALLSEL_ANY)) { continue; } @@ -831,15 +901,4 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese return false; } -bool ED_mball_deselect_all_multi(bContext *C) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - ViewContext vc; - ED_view3d_viewcontext_init(C, &vc, depsgraph); - uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc.view_layer, vc.v3d, &bases_len); - bool changed_multi = BKE_mball_deselect_all_multi_ex(bases, bases_len); - MEM_freeN(bases); - return changed_multi; -} +/** \} */ diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index fb273cf49a8..953ef8114f9 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -91,8 +91,4 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_NEW_OBJECT_TYPES) - add_definitions(-DWITH_NEW_OBJECT_TYPES) -endif() - blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 8289f52b0c8..8073d87080f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -65,6 +65,7 @@ #include "BKE_effect.h" #include "BKE_font.h" #include "BKE_gpencil_curve.h" +#include "BKE_gpencil_geom.h" #include "BKE_hair.h" #include "BKE_key.h" #include "BKE_lattice.h" @@ -96,6 +97,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -857,7 +860,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) * we want to pass in 1 so other values such as resolution are scaled by 1.0. */ dia = RNA_float_get(op->ptr, "radius") / 2; - ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type")); + ED_mball_add_primitive(C, obedit, newob, mat, dia, RNA_enum_get(op->ptr, "type")); /* userdef */ if (newob && !enter_editmode) { @@ -1508,6 +1511,14 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot) /** \name Add Hair Operator * \{ */ +static bool object_hair_add_poll(bContext *C) +{ + if (!U.experimental.use_new_hair_type) { + return false; + } + return ED_operator_objectmode(C); +} + static int object_hair_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; @@ -1531,7 +1542,7 @@ void OBJECT_OT_hair_add(wmOperatorType *ot) /* api callbacks */ ot->exec = object_hair_add_exec; - ot->poll = ED_operator_objectmode; + ot->poll = object_hair_add_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1545,6 +1556,14 @@ void OBJECT_OT_hair_add(wmOperatorType *ot) /** \name Add Point Cloud Operator * \{ */ +static bool object_pointcloud_add_poll(bContext *C) +{ + if (!U.experimental.use_new_particle_system) { + return false; + } + return ED_operator_objectmode(C); +} + static int object_pointcloud_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; @@ -1568,7 +1587,7 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot) /* api callbacks */ ot->exec = object_pointcloud_add_exec; - ot->poll = ED_operator_objectmode; + ot->poll = object_pointcloud_add_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2129,11 +2148,11 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot) static const EnumPropertyItem convert_target_items[] = { {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""}, {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""}, - {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve", ""}, + {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve/Mesh", ""}, {0, NULL, 0, NULL, NULL}, }; -static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) +static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) { if (ob->runtime.curve_cache == NULL) { /* Force creation. This is normally not needed but on operator @@ -2152,7 +2171,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec } } -static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob) +static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); Curve *curve = ob->data; @@ -2185,17 +2204,22 @@ static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob) } } -static bool convert_poll(bContext *C) +static bool object_convert_poll(bContext *C) { Scene *scene = CTX_data_scene(C); Base *base_act = CTX_data_active_base(C); Object *obact = base_act ? base_act->object : NULL; - return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) && - (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact)); + if (obact == NULL || obact->data == NULL || ID_IS_LINKED(obact) || + ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) { + return false; + } + + return (!ID_IS_LINKED(scene) && (BKE_object_is_in_editmode(obact) == false) && + (base_act->flag & BASE_SELECTED)); } -/* Helper for convert_exec */ +/* Helper for object_convert_exec */ static Base *duplibase_for_convert( Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob) { @@ -2230,7 +2254,7 @@ static Base *duplibase_for_convert( * time we need to duplicate an object to convert it. Even worse, this is not 100% correct, since * we do not yet have duplicated obdata. * However, that is a safe solution for now. Proper, longer-term solution is to refactor - * convert_exec to: + * object_convert_exec to: * - duplicate all data it needs to in a first loop. * - do a single update. * - convert data in a second loop. */ @@ -2248,7 +2272,7 @@ static Base *duplibase_for_convert( return basen; } -static int convert_exec(bContext *C, wmOperator *op) +static int object_convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -2261,9 +2285,16 @@ static int convert_exec(bContext *C, wmOperator *op) Nurb *nu; MetaBall *mb; Mesh *me; - Object *gpencil_ob = NULL; + Object *ob_gpencil = NULL; const short target = RNA_enum_get(op->ptr, "target"); bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); + + const float angle = RNA_float_get(op->ptr, "angle"); + const int thickness = RNA_int_get(op->ptr, "thickness"); + const bool use_seams = RNA_boolean_get(op->ptr, "seams"); + const bool use_faces = RNA_boolean_get(op->ptr, "faces"); + const float offset = RNA_float_get(op->ptr, "offset"); + int a, mballConverted = 0; bool gpencilConverted = false; @@ -2375,6 +2406,54 @@ static int convert_exec(bContext *C, wmOperator *op) ED_rigidbody_object_remove(bmain, scene, newob); } } + else if (ob->type == OB_MESH && target == OB_GPENCIL) { + ob->flag |= OB_DONE; + + /* Create a new grease pencil object and copy transformations. */ + ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; + float loc[3], size[3], rot[3][3], eul[3]; + float matrix[4][4]; + mat4_to_loc_rot_size(loc, rot, size, ob->obmat); + mat3_to_eul(eul, rot); + + ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); + copy_v3_v3(ob_gpencil->loc, loc); + copy_v3_v3(ob_gpencil->rot, eul); + copy_v3_v3(ob_gpencil->scale, size); + unit_m4(matrix); + /* Set object in 3D mode. */ + bGPdata *gpd = (bGPdata *)ob_gpencil->data; + gpd->draw_mode = GP_DRAWMODE_3D; + + BKE_gpencil_convert_mesh(bmain, + depsgraph, + scene, + ob_gpencil, + ob, + angle, + thickness, + offset, + matrix, + 0, + use_seams, + use_faces); + gpencilConverted = true; + + /* Remove unused materials. */ + int actcol = ob_gpencil->actcol; + for (int slot = 1; slot <= ob_gpencil->totcol; slot++) { + while (slot <= ob_gpencil->totcol && + !BKE_object_material_slot_used(ob_gpencil->data, slot)) { + ob_gpencil->actcol = slot; + BKE_object_material_slot_remove(CTX_data_main(C), ob_gpencil); + + if (actcol >= slot) { + actcol--; + } + } + } + ob_gpencil->actcol = actcol; + } else if (ob->type == OB_MESH) { ob->flag |= OB_DONE; @@ -2470,7 +2549,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (target == OB_MESH) { /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ - curvetomesh(bmain, depsgraph, newob); + object_data_convert_curve_to_mesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); } @@ -2495,7 +2574,7 @@ static int convert_exec(bContext *C, wmOperator *op) /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ - curvetomesh(bmain, depsgraph, newob); + object_data_convert_curve_to_mesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); } @@ -2509,10 +2588,10 @@ static int convert_exec(bContext *C, wmOperator *op) * Nurbs Surface are not supported. */ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; - gpencil_ob = ED_gpencil_add_object(C, ob->loc, local_view_bits); - copy_v3_v3(gpencil_ob->rot, ob->rot); - copy_v3_v3(gpencil_ob->scale, ob->scale); - BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true); + ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits); + copy_v3_v3(ob_gpencil->rot, ob->rot); + copy_v3_v3(ob_gpencil->scale, ob->scale); + BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, false, true); gpencilConverted = true; } } @@ -2549,7 +2628,7 @@ static int convert_exec(bContext *C, wmOperator *op) } } - convert_ensure_curve_cache(depsgraph, scene, baseob); + object_data_convert_ensure_curve_cache(depsgraph, scene, baseob); BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data); if (obact->type == OB_MBALL) { @@ -2618,12 +2697,12 @@ static int convert_exec(bContext *C, wmOperator *op) } FOREACH_SCENE_OBJECT_END; } - /* Remove curves converted to Grease Pencil object. */ + /* Remove curves and meshes converted to Grease Pencil object. */ if (gpencilConverted) { - FOREACH_SCENE_OBJECT_BEGIN (scene, ob_curve) { - if (ob_curve->type == OB_CURVE) { - if (ob_curve->flag & OB_DONE) { - ED_object_base_free_and_unlink(bmain, scene, ob_curve); + FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) { + if ((ob_delete->type == OB_CURVE) || (ob_delete->type == OB_MESH)) { + if (ob_delete->flag & OB_DONE) { + ED_object_base_free_and_unlink(bmain, scene, ob_delete); } } } @@ -2652,8 +2731,28 @@ static int convert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void object_convert_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + PointerRNA ptr; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + uiItemR(layout, &ptr, "target", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "keep_original", 0, NULL, ICON_NONE); + + if (RNA_enum_get(&ptr, "target") == OB_GPENCIL) { + uiItemR(layout, &ptr, "thickness", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "offset", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "seams", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "faces", 0, NULL, ICON_NONE); + } +} + void OBJECT_OT_convert(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Convert to"; ot->description = "Convert selected objects to another type"; @@ -2661,8 +2760,9 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* api callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = convert_exec; - ot->poll = convert_poll; + ot->exec = object_convert_exec; + ot->poll = object_convert_poll; + ot->ui = object_convert_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2675,6 +2775,31 @@ void OBJECT_OT_convert(wmOperatorType *ot) 0, "Keep Original", "Keep original objects instead of replacing them"); + + prop = RNA_def_float_rotation(ot->srna, + "angle", + 0, + NULL, + DEG2RADF(0.0f), + DEG2RADF(180.0f), + "Threshold Angle", + "Threshold to determine ends of the strokes", + DEG2RADF(0.0f), + DEG2RADF(180.0f)); + RNA_def_property_float_default(prop, DEG2RADF(70.0f)); + + RNA_def_int(ot->srna, "thickness", 5, 1, 100, "Thickness", "", 1, 100); + RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); + RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); + RNA_def_float_distance(ot->srna, + "offset", + 0.01f, + 0.0, + OBJECT_ADD_SIZE_MAXF, + "Stroke Offset", + "Offset strokes from fill", + 0.0, + 100.00); } /** \} */ @@ -2693,8 +2818,12 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* used below, assumes id.new is correct */ /* leaves selection of base/object unaltered */ /* Does set ID->newid pointers. */ -static Base *object_add_duplicate_internal( - Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag) +static Base *object_add_duplicate_internal(Main *bmain, + Scene *scene, + ViewLayer *view_layer, + Object *ob, + const eDupli_ID_Flags dupflag, + const eLibIDDuplicateFlags duplicate_options) { Base *base, *basen = NULL; Object *obn; @@ -2703,7 +2832,7 @@ static Base *object_add_duplicate_internal( /* nothing? */ } else { - obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag)); + obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)); DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); base = BKE_view_layer_base_find(view_layer, ob); @@ -2742,12 +2871,13 @@ static Base *object_add_duplicate_internal( * note: caller must do DAG_relations_tag_update(bmain); * this is not done automatic since we may duplicate many objects in a batch */ Base *ED_object_add_duplicate( - Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag) + Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag) { Base *basen; Object *ob; - basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag); + basen = object_add_duplicate_internal( + bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS); if (basen == NULL) { return NULL; } @@ -2775,10 +2905,11 @@ static int duplicate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool linked = RNA_boolean_get(op->ptr, "linked"); - int dupflag = (linked) ? 0 : U.dupflag; + const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag); + Base *basen = object_add_duplicate_internal( + bmain, scene, view_layer, base->object, dupflag, 0); /* note that this is safe to do with this context iterator, * the list is made in advance */ @@ -2849,7 +2980,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) * Use for drag & drop. * \{ */ -static int add_named_exec(bContext *C, wmOperator *op) +static int object_add_named_exec(bContext *C, wmOperator *op) { wmWindow *win = CTX_wm_window(C); const wmEvent *event = win ? win->eventstate : NULL; @@ -2859,7 +2990,7 @@ static int add_named_exec(bContext *C, wmOperator *op) Base *basen; Object *ob; const bool linked = RNA_boolean_get(op->ptr, "linked"); - int dupflag = (linked) ? 0 : U.dupflag; + const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; char name[MAX_ID_NAME - 2]; /* find object, create fake base */ @@ -2872,7 +3003,7 @@ static int add_named_exec(bContext *C, wmOperator *op) } /* prepare dupli */ - basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag); + basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag, 0); if (basen == NULL) { BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); @@ -2912,7 +3043,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot) ot->idname = "OBJECT_OT_add_named"; /* api callbacks */ - ot->exec = add_named_exec; + ot->exec = object_add_named_exec; ot->poll = ED_operator_objectmode; /* flags */ @@ -2933,23 +3064,24 @@ void OBJECT_OT_add_named(wmOperatorType *ot) * * \{ */ -static bool join_poll(bContext *C) +static bool object_join_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (!ob || ID_IS_LINKED(ob)) { - return 0; + if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { + return false; } if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL)) { return ED_operator_screenactive(C); } else { - return 0; + return false; } } -static int join_exec(bContext *C, wmOperator *op) +static int object_join_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -2970,13 +3102,13 @@ static int join_exec(bContext *C, wmOperator *op) } if (ob->type == OB_MESH) { - return join_mesh_exec(C, op); + return ED_mesh_join_objects_exec(C, op); } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - return join_curve_exec(C, op); + return ED_curve_join_objects_exec(C, op); } else if (ob->type == OB_ARMATURE) { - return join_armature_exec(C, op); + return ED_armature_join_objects_exec(C, op); } else if (ob->type == OB_GPENCIL) { return ED_gpencil_join_objects_exec(C, op); @@ -2993,8 +3125,8 @@ void OBJECT_OT_join(wmOperatorType *ot) ot->idname = "OBJECT_OT_join"; /* api callbacks */ - ot->exec = join_exec; - ot->poll = join_poll; + ot->exec = object_join_exec; + ot->poll = object_join_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3010,8 +3142,9 @@ static bool join_shapes_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (!ob || ID_IS_LINKED(ob)) { - return 0; + if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { + return false; } /* only meshes supported at the moment */ @@ -3019,7 +3152,7 @@ static bool join_shapes_poll(bContext *C) return ED_operator_screenactive(C); } else { - return 0; + return false; } } @@ -3037,7 +3170,7 @@ static int join_shapes_exec(bContext *C, wmOperator *op) } if (ob->type == OB_MESH) { - return join_mesh_shapes_exec(C, op); + return ED_mesh_shapes_join_objects_exec(C, op); } return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index a2d33ffe413..5746480e3f8 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1557,6 +1557,77 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ +/** \name Move Constraint To Index Operator + * \{ */ + +static int constraint_move_to_index_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, 0); + + int new_index = RNA_int_get(op->ptr, "index"); + if (new_index < 0) { + new_index = 0; + } + + if (con) { + ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL); + int current_index = BLI_findindex(conlist, con); + BLI_assert(current_index >= 0); + + BLI_listbase_link_move(conlist, con, new_index - current_index); + + WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +static int constraint_move_to_index_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + if (edit_constraint_invoke_properties(C, op)) { + return constraint_move_to_index_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void CONSTRAINT_OT_move_to_index(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Move Constraint To Index"; + ot->idname = "CONSTRAINT_OT_move_to_index"; + ot->description = + "Change the constraint's position in the list so it evaluates after the set number of " + "others"; + + /* callbacks */ + ot->exec = constraint_move_to_index_exec; + ot->invoke = constraint_move_to_index_invoke; + ot->poll = edit_constraint_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + edit_constraint_properties(ot); + RNA_def_int(ot->srna, + "index", + 0, + 0, + INT_MAX, + "Index", + "The index to move the constraint to", + 0, + INT_MAX); +} + +/** \} */ + +/* ------------------------------------------------------------------- */ /** \name Clear Pose Constraints Operator * \{ */ diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 274cd31406c..0df33255c34 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -381,7 +381,7 @@ static bool data_transfer_exec_is_object_valid(wmOperator *op, me->id.tag &= ~LIB_TAG_DOIT; return true; } - else if (!ID_IS_LINKED(me)) { + else if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) { /* Do not apply transfer operation more than once. */ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */ BKE_reportf( @@ -446,8 +446,8 @@ static int data_transfer_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - if (reverse_transfer && ID_IS_LINKED(ob_src->data)) { - /* Do not transfer to linked data, not supported. */ + if (reverse_transfer && (ID_IS_LINKED(ob_src->data) || ID_IS_OVERRIDE_LIBRARY(ob_src->data))) { + /* Do not transfer to linked or override data, not supported. */ return OPERATOR_CANCELLED; } @@ -530,7 +530,7 @@ static bool data_transfer_poll(bContext *C) { Object *ob = ED_object_active_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && ob->type == OB_MESH && data); + return (ob != NULL && ob->type == OB_MESH && data != NULL); } /* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */ @@ -786,7 +786,7 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) const bool use_delete = false; /* Never when used from modifier, for now. */ - if (!ob_src) { + if (!ob_src || ID_IS_LINKED(ob_dst) || ID_IS_OVERRIDE_LIBRARY(ob_dst)) { return OPERATOR_CANCELLED; } @@ -854,7 +854,7 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return datalayout_transfer_exec(C, op); } else { diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index d522dcabae3..283aaec85ef 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -600,7 +600,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag { bool ok = false; - if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob)) { + if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } @@ -695,14 +696,10 @@ bool ED_object_editmode_enter(bContext *C, int flag) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob; /* Active layer checked here for view3d, * callers that don't want view context can call the extended version. */ - ob = CTX_data_active_object(C); - if ((ob == NULL) || ID_IS_LINKED(ob)) { - return false; - } + Object *ob = CTX_data_active_object(C); return ED_object_editmode_enter_ex(bmain, scene, ob, flag); } @@ -760,7 +757,8 @@ static bool editmode_toggle_poll(bContext *C) Object *ob = CTX_data_active_object(C); /* covers proxies too */ - if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data)) { + if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { return 0; } @@ -1368,7 +1366,8 @@ static bool shade_poll(bContext *C) Object *obact = OBACT(view_layer); if (obact != NULL) { /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ - if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) { + if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == NULL || + ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) { return false; } } @@ -1771,15 +1770,6 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout const char *name = BKE_collection_ui_name_get(menu->collection); UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP); - uiItemIntO(layout, name, ICON_NONE, menu->ot->idname, "collection_index", menu->index); - uiItemS(layout); - - for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL; - submenu = submenu->next) { - move_to_collection_menus_items(layout, submenu); - } - - uiItemS(layout); WM_operator_properties_create_ptr(&menu->ptr, menu->ot); RNA_int_set(&menu->ptr, "collection_index", menu->index); @@ -1787,6 +1777,15 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout uiItemFullO_ptr( layout, menu->ot, "New Collection", ICON_ADD, menu->ptr.data, WM_OP_INVOKE_DEFAULT, 0, NULL); + + uiItemS(layout); + + uiItemIntO(layout, name, ICON_SCENE_DATA, menu->ot->idname, "collection_index", menu->index); + + for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL; + submenu = submenu->next) { + move_to_collection_menus_items(layout, submenu); + } } static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu) diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c index 147bd3d7871..6e0376358bb 100644 --- a/source/blender/editors/object/object_facemap_ops.c +++ b/source/blender/editors/object/object_facemap_ops.c @@ -171,14 +171,15 @@ static bool face_map_supported_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib); + return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data && + !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); } static bool face_map_supported_edit_mode_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib) { + + if (face_map_supported_poll(C)) { if (ob->mode == OB_MODE_EDIT) { return true; } diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 6d0f53cfa1e..cfdb6fea52d 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -24,6 +24,7 @@ #include <math.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "MEM_guardedalloc.h" @@ -54,6 +55,8 @@ #include "ED_object.h" #include "ED_screen.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -105,23 +108,6 @@ GpencilModifierData *ED_object_gpencil_modifier_add( return new_md; } -/* Return true if the object has a modifier of type 'type' other than - * the modifier pointed to be 'exclude', otherwise returns false. */ -static bool UNUSED_FUNCTION(gpencil_object_has_modifier)(const Object *ob, - const GpencilModifierData *exclude, - GpencilModifierType type) -{ - GpencilModifierData *md; - - for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - if ((md != exclude) && (md->type == type)) { - return true; - } - } - - return false; -} - static bool gpencil_object_modifier_remove(Main *bmain, Object *ob, GpencilModifierData *md, @@ -211,6 +197,40 @@ int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), return 1; } +bool ED_object_gpencil_modifier_move_to_index(ReportList *reports, + Object *ob, + GpencilModifierData *md, + const int index) +{ + BLI_assert(md != NULL); + BLI_assert(index >= 0); + if (index >= BLI_listbase_count(&ob->greasepencil_modifiers)) { + BKE_report(reports, RPT_WARNING, "Cannot move modifier beyond the end of the stack"); + return false; + } + + int md_index = BLI_findindex(&ob->greasepencil_modifiers, md); + BLI_assert(md_index != -1); + if (md_index < index) { + /* Move modifier down in list. */ + for (; md_index < index; md_index++) { + if (!ED_object_gpencil_modifier_move_down(reports, ob, md)) { + break; + } + } + } + else { + /* Move modifier up in list. */ + for (; md_index > index; md_index--) { + if (!ED_object_gpencil_modifier_move_up(reports, ob, md)) { + break; + } + } + } + + return true; +} + static int gpencil_modifier_apply_obdata( ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md) { @@ -428,22 +448,58 @@ static void gpencil_edit_modifier_properties(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -static int gpencil_edit_modifier_invoke_properties(bContext *C, wmOperator *op) +static void gpencil_edit_modifier_report_property(wmOperatorType *ot) { - GpencilModifierData *md; + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "report", false, "Report", "Create a notification after the operation"); + RNA_def_property_flag(prop, PROP_HIDDEN); +} +/** + * \param event: If this isn't NULL, the operator will also look for panels underneath + * the cursor with customdata set to a modifier. + * \param r_retval: This should be used if #event is used in order to to return + * #OPERATOR_PASS_THROUGH to check other operators with the same key set. + */ +static bool gpencil_edit_modifier_invoke_properties(bContext *C, + wmOperator *op, + const wmEvent *event, + int *r_retval) +{ if (RNA_struct_property_is_set(op->ptr, "modifier")) { return true; } - else { - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier); - if (ptr.data) { - md = ptr.data; - RNA_string_set(op->ptr, "modifier", md->name); - return true; + + PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier); + if (ctx_ptr.data != NULL) { + GpencilModifierData *md = ctx_ptr.data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + + /* Check the custom data of panels under the mouse for a modifier. */ + if (event != NULL) { + PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event); + + if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) { + if (RNA_struct_is_a(panel_ptr->type, &RNA_GpencilModifier)) { + GpencilModifierData *md = panel_ptr->data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + else { + BLI_assert(r_retval != NULL); /* We need the return value in this case. */ + if (r_retval != NULL) { + *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED); + } + return false; + } } } + if (r_retval != NULL) { + *r_retval = OPERATOR_CANCELLED; + } return false; } @@ -472,24 +528,35 @@ static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); - if (!md || !ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) { return OPERATOR_CANCELLED; } WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int gpencil_modifier_remove_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int gpencil_modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_remove_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -506,6 +573,7 @@ void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; gpencil_edit_modifier_properties(ot); + gpencil_edit_modifier_report_property(ot); } /************************ move up modifier operator *********************/ @@ -525,15 +593,14 @@ static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int gpencil_modifier_move_up_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int gpencil_modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_move_up_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -569,15 +636,14 @@ static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int gpencil_modifier_move_down_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int gpencil_modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_move_down_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -596,6 +662,59 @@ void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot) gpencil_edit_modifier_properties(ot); } +/* ************************* Move to Index Gpencil Modifier Operator ************************* */ + +static bool gpencil_modifier_move_to_index_poll(bContext *C) +{ + return gpencil_edit_modifier_poll(C); +} + +static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); + int index = RNA_int_get(op->ptr, "index"); + + if (!ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index)) { + return OPERATOR_CANCELLED; + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int gpencil_modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { + return gpencil_modifier_move_to_index_exec(C, op); + } + else { + return retval; + } +} + +void OBJECT_OT_gpencil_modifier_move_to_index(wmOperatorType *ot) +{ + ot->name = "Move Active Modifier to Index"; + ot->idname = "OBJECT_OT_gpencil_modifier_move_to_index"; + ot->description = + "Change the modifier's position in the list so it evaluates after the set number of " + "others"; + + ot->invoke = gpencil_modifier_move_to_index_invoke; + ot->exec = gpencil_modifier_move_to_index_exec; + ot->poll = gpencil_modifier_move_to_index_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); + RNA_def_int( + ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the modifier to", 0, INT_MAX); +} + /************************ apply modifier operator *********************/ static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op) @@ -606,23 +725,36 @@ static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op) GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) { return OPERATOR_CANCELLED; } DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_apply_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -656,6 +788,7 @@ void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot) "Apply as", "How to apply the modifier to the geometry"); gpencil_edit_modifier_properties(ot); + gpencil_edit_modifier_report_property(ot); } /************************ copy modifier operator *********************/ @@ -675,13 +808,14 @@ static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_copy_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index c5a6e38fbcb..afc87c0caba 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -153,7 +153,10 @@ bool edit_modifier_poll_generic(struct bContext *C, const bool is_editmode_allowed); bool edit_modifier_poll(struct bContext *C); void edit_modifier_properties(struct wmOperatorType *ot); -int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op); +bool edit_modifier_invoke_properties(struct bContext *C, + struct wmOperator *op, + const struct wmEvent *event, + int *r_retval); struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type); @@ -190,6 +193,7 @@ void OBJECT_OT_gpencil_modifier_add(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_remove(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_move_up(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_move_down(struct wmOperatorType *ot); +void OBJECT_OT_gpencil_modifier_move_to_index(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_apply(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot); @@ -198,6 +202,7 @@ void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_remove(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_move_up(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_move_down(struct wmOperatorType *ot); +void OBJECT_OT_shaderfx_move_to_index(struct wmOperatorType *ot); /* object_constraint.c */ void OBJECT_OT_constraint_add(struct wmOperatorType *ot); @@ -217,6 +222,7 @@ void POSE_OT_ik_clear(struct wmOperatorType *ot); void CONSTRAINT_OT_delete(struct wmOperatorType *ot); void CONSTRAINT_OT_move_up(struct wmOperatorType *ot); +void CONSTRAINT_OT_move_to_index(struct wmOperatorType *ot); void CONSTRAINT_OT_move_down(struct wmOperatorType *ot); void CONSTRAINT_OT_stretchto_reset(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index c518fd32c7f..5d4476ecb8c 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -116,7 +116,7 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode) case OB_SURF: case OB_FONT: case OB_MBALL: - if (mode & (OB_MODE_EDIT)) { + if (mode & OB_MODE_EDIT) { return true; } break; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index a6c5814e88a..6b0eff5b6e5 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -88,6 +88,8 @@ #include "ED_screen.h" #include "ED_sculpt.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -1037,22 +1039,58 @@ void edit_modifier_properties(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -int edit_modifier_invoke_properties(bContext *C, wmOperator *op) +static void edit_modifier_report_property(wmOperatorType *ot) { - ModifierData *md; + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "report", false, "Report", "Create a notification after the operation"); + RNA_def_property_flag(prop, PROP_HIDDEN); +} +/** + * \param event: If this isn't NULL, the operator will also look for panels underneath + * the cursor with customdata set to a modifier. + * \param r_retval: This should be used if #event is used in order to to return + * #OPERATOR_PASS_THROUGH to check other operators with the same key set. + */ +bool edit_modifier_invoke_properties(bContext *C, + wmOperator *op, + const wmEvent *event, + int *r_retval) +{ if (RNA_struct_property_is_set(op->ptr, "modifier")) { return true; } - else { - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); - if (ptr.data) { - md = ptr.data; - RNA_string_set(op->ptr, "modifier", md->name); - return true; + + PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); + if (ctx_ptr.data != NULL) { + ModifierData *md = ctx_ptr.data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + + /* Check the custom data of panels under the mouse for a modifier. */ + if (event != NULL) { + PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event); + + if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) { + if (RNA_struct_is_a(panel_ptr->type, &RNA_Modifier)) { + ModifierData *md = panel_ptr->data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + else { + BLI_assert(r_retval != NULL); /* We need the return value in this case. */ + if (r_retval != NULL) { + *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED); + } + return false; + } } } + if (r_retval != NULL) { + *r_retval = OPERATOR_CANCELLED; + } return false; } @@ -1085,7 +1123,15 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int mode_orig = ob->mode; - if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_modifier_remove(op->reports, bmain, ob, md)) { return OPERATOR_CANCELLED; } @@ -1099,16 +1145,22 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) } } } + + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_remove_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1125,6 +1177,7 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); + edit_modifier_report_property(ot); } /** \} */ @@ -1148,13 +1201,14 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_move_up_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1194,13 +1248,14 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_move_down_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1246,13 +1301,14 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_move_to_index_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1291,6 +1347,10 @@ static bool modifier_apply_poll(bContext *C) Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C); ModifierData *md = ptr.data; /* May be NULL. */ + if (ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { + CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data"); + return false; + } if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) { CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data"); return false; @@ -1315,7 +1375,15 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } @@ -1323,16 +1391,21 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_apply_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1366,6 +1439,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) "Apply as", "How to apply the modifier to the geometry"); edit_modifier_properties(ot); + edit_modifier_report_property(ot); } /** \} */ @@ -1396,7 +1470,7 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return modifier_convert_exec(C, op); } else { @@ -1440,13 +1514,14 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_copy_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1501,7 +1576,7 @@ static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_higher_levels_delete_exec(C, op); } else { @@ -1579,7 +1654,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_subdivide_exec(C, op); } else { @@ -1656,7 +1731,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_reshape_exec(C, op); } else { @@ -1720,7 +1795,7 @@ static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEv Mesh *me = ob->data; char path[FILE_MAX]; - if (!edit_modifier_invoke_properties(C, op)) { + if (!edit_modifier_invoke_properties(C, op, NULL, NULL)) { return OPERATOR_CANCELLED; } @@ -1837,7 +1912,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op) static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_base_apply_exec(C, op); } else { @@ -1891,7 +1966,7 @@ static int multires_unsubdivide_exec(bContext *C, wmOperator *op) static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_unsubdivide_exec(C, op); } else { @@ -1949,7 +2024,7 @@ static int multires_rebuild_subdiv_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_rebuild_subdiv_exec(C, op); } else { @@ -1999,8 +2074,9 @@ static bool skin_poll(bContext *C) static bool skin_edit_poll(bContext *C) { - return (CTX_data_edit_object(C) && - edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true)); + Object *ob = CTX_data_edit_object(C); + return (ob != NULL && edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true) && + !ID_IS_OVERRIDE_LIBRARY(ob) && !ID_IS_OVERRIDE_LIBRARY(ob->data)); } static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset) @@ -2327,7 +2403,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return skin_armature_create_exec(C, op); } else { @@ -2406,7 +2482,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return correctivesmooth_bind_exec(C, op); } else { @@ -2483,7 +2559,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return meshdeform_bind_exec(C, op); } else { @@ -2539,7 +2615,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op) static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return explode_refresh_exec(C, op); } else { @@ -2743,7 +2819,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return ocean_bake_exec(C, op); } else { @@ -2822,7 +2898,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return laplaciandeform_bind_exec(C, op); } else { @@ -2891,7 +2967,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return surfacedeform_bind_exec(C, op); } else { diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 05f1ced8615..e28bbb3fb1c 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -109,10 +109,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_light_add); WM_operatortype_append(OBJECT_OT_camera_add); WM_operatortype_append(OBJECT_OT_speaker_add); -#ifdef WITH_NEW_OBJECT_TYPES WM_operatortype_append(OBJECT_OT_hair_add); WM_operatortype_append(OBJECT_OT_pointcloud_add); -#endif WM_operatortype_append(OBJECT_OT_volume_add); WM_operatortype_append(OBJECT_OT_volume_import); WM_operatortype_append(OBJECT_OT_add); @@ -152,6 +150,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_gpencil_modifier_remove); WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_up); WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_down); + WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_to_index); WM_operatortype_append(OBJECT_OT_gpencil_modifier_apply); WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy); @@ -160,6 +159,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_shaderfx_remove); WM_operatortype_append(OBJECT_OT_shaderfx_move_up); WM_operatortype_append(OBJECT_OT_shaderfx_move_down); + WM_operatortype_append(OBJECT_OT_shaderfx_move_to_index); WM_operatortype_append(OBJECT_OT_correctivesmooth_bind); WM_operatortype_append(OBJECT_OT_meshdeform_bind); @@ -179,6 +179,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(CONSTRAINT_OT_delete); WM_operatortype_append(CONSTRAINT_OT_move_up); WM_operatortype_append(CONSTRAINT_OT_move_down); + WM_operatortype_append(CONSTRAINT_OT_move_to_index); WM_operatortype_append(CONSTRAINT_OT_stretchto_reset); WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset); WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fd2fcb11635..509b70f849e 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -33,6 +33,7 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_gpencil_types.h" +#include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" @@ -68,6 +69,7 @@ #include "BKE_gpencil.h" #include "BKE_hair.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_lattice.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -1771,7 +1773,10 @@ static Collection *single_object_users_collection(Main *bmain, /* Generate new copies for objects in given collection and all its children, * and optionally also copy collections themselves. */ if (copy_collections && !is_master_collection) { - collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection)); + Collection *collection_new; + BKE_id_copy(bmain, &collection->id, (ID **)&collection_new); + id_us_min(&collection_new->id); + collection = ID_NEW_SET(collection, collection_new); } /* We do not remap to new objects here, this is done in separate step. */ @@ -2246,47 +2251,66 @@ void OBJECT_OT_make_local(wmOperatorType *ot) /** \name Make Library Override Operator * \{ */ -static void make_override_library_tag_object(Object *obact, Object *ob) +static bool make_override_hierarchy_recursive_tag(Main *bmain, ID *id) { - if (ob == obact) { - return; + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); + + /* This way we won't process again that ID should we encounter it again through another + * relationship hierarchy. + * Note that this does not free any memory from relations, so we can still use the entries. + */ + BKE_main_relations_ID_remove(bmain, id); + + for (; entry != NULL; entry = entry->next) { + /* We only consider IDs from the same library. */ + if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { + if (make_override_hierarchy_recursive_tag(bmain, *entry->id_pointer)) { + id->tag |= LIB_TAG_DOIT; + } + } } - if (!ID_IS_LINKED(ob)) { - return; + return (id->tag & LIB_TAG_DOIT) != 0; +} + +static int make_override_tag_ids_cb(LibraryIDLinkCallbackData *cb_data) +{ + if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) { + return IDWALK_RET_STOP_RECURSION; } - /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full - * 'automatic', generic handling of all this, - * will probably require adding some override-aware stuff to library_query code... */ + ID *id_root = cb_data->user_data; + Library *library_root = id_root->lib; + ID *id = *cb_data->id_pointer; + ID *id_owner = cb_data->id_owner; - if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) { - for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) { - if (md->type == eModifierType_Armature) { - ArmatureModifierData *amd = (ArmatureModifierData *)md; - if (amd->object == obact) { - ob->id.tag |= LIB_TAG_DOIT; - break; - } - } - } + BLI_assert(id_owner == cb_data->id_self); + + if (ELEM(id, NULL, id_owner)) { + return IDWALK_RET_NOP; } - else if (ob->parent == obact) { - ob->id.tag |= LIB_TAG_DOIT; + + BLI_assert(id->lib != NULL); + BLI_assert(id_owner->lib == library_root); + + if (id->tag & LIB_TAG_DOIT) { + /* Already processed, but maybe not with the same chain of dependency, so we need to check that + * one nonetheless. */ + return IDWALK_RET_STOP_RECURSION; } - if (ob->id.tag & LIB_TAG_DOIT) { - printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name); + if (id->lib != library_root) { + /* We do not override data-blocks from other libraries, nor do we process them. */ + return IDWALK_RET_STOP_RECURSION; } -} -static void make_override_library_tag_collections(Collection *collection) -{ - collection->id.tag |= LIB_TAG_DOIT; - for (CollectionChild *coll_child = collection->children.first; coll_child != NULL; - coll_child = coll_child->next) { - make_override_library_tag_collections(coll_child->collection); + /* We tag all collections and objects for override. And we also tag all other data-blocks which + * would user one of those. */ + if (ELEM(GS(id->name), ID_OB, ID_GR)) { + id->tag |= LIB_TAG_DOIT; } + + return IDWALK_RET_NOP; } /* Set the object to override. */ @@ -2335,6 +2359,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Object *obact = CTX_data_active_object(C); + ID *id_root = NULL; bool success = false; @@ -2348,111 +2373,156 @@ static int make_override_library_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + id_root = &obact->instance_collection->id; + } + else if (!ID_IS_OVERRIDABLE_LIBRARY(obact)) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Active object '%s' is not overridable", + obact->id.name + 2); + return OPERATOR_CANCELLED; + } + /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ + else { + id_root = &obact->id; + } - Object *obcollection = obact; - Collection *collection = obcollection->instance_collection; + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection); - Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object")); - obact = base->object; + /* Tag all collections and objects, as well as other IDs using them. */ + id_root->tag |= LIB_TAG_DOIT; - /* First, we make a library override of the linked collection itself, and all its children. */ - make_override_library_tag_collections(collection); + BKE_main_relations_create(bmain, 0); - /* Then, we make library override of the whole set of objects in the Collection. */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { - ob->id.tag |= LIB_TAG_DOIT; - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - - /* Then, we remove (untag) bone shape objects, you shall never want to override those - * (hopefully)... */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { - if (ob->type == OB_ARMATURE && ob->pose != NULL) { - for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { - if (pchan->custom != NULL) { - pchan->custom->id.tag &= ~LIB_TAG_DOIT; - } + BKE_library_foreach_ID_link( + bmain, id_root, make_override_tag_ids_cb, id_root, IDWALK_READONLY | IDWALK_RECURSE); + + /* Then, we remove (untag) bone shape objects, you shall never want to override those + * (hopefully)... */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & LIB_TAG_DOIT)) { + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { + if (pchan->custom != NULL) { + pchan->custom->id.tag &= ~LIB_TAG_DOIT; } } } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } - success = BKE_lib_override_library_create_from_tag(bmain); + /* The we tag all intermediary data-blocks in-between to overridden ones (e.g. if a shapekey has + * a driver using an armature object's bone, we need to override the shapekey/obdata, the objects + * using them, etc.) */ + make_override_hierarchy_recursive_tag(bmain, id_root); + + BKE_main_relations_free(bmain); + + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->tag & LIB_TAG_DOIT && id->lib != NULL) { + printf("ID %s tagged for override\n", id->name); + } + } + FOREACH_MAIN_ID_END; - /* Instantiate our newly overridden objects in scene, if not yet done. */ + success = BKE_lib_override_library_create_from_tag(bmain); + + if (success) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Collection *new_collection = (Collection *)collection->id.newid; - BKE_collection_add_from_object(bmain, scene, obcollection, new_collection); + BKE_main_collection_sync(bmain); + + switch (GS(id_root->name)) { + case ID_GR: { + Collection *collection_new = ((Collection *)id_root->newid); + BKE_collection_add_from_object(bmain, scene, obact, collection_new); + + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { + if (ob_new != NULL && ob_new->id.override_library != NULL) { + Base *base; + if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { + BKE_collection_object_add_from(bmain, scene, obact, ob_new); + base = BKE_view_layer_base_find(view_layer, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + } - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) { - if (new_ob != NULL && new_ob->id.override_library != NULL) { - if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) { - BKE_collection_object_add_from(bmain, scene, obcollection, new_ob); - base = BKE_view_layer_base_find(view_layer, new_ob); - DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + if (ob_new == (Object *)obact->id.newid) { + /* TODO: is setting active needed? */ + BKE_view_layer_base_select_and_set_active(view_layer, base); + } + } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + break; + } + case ID_OB: { + BKE_collection_object_add_from(bmain, scene, obact, ((Object *)id_root->newid)); + break; + } + default: + BLI_assert(0); + } - if (new_ob == (Object *)obact->id.newid) { - /* TODO: is setting active needed? */ - BKE_view_layer_base_select_and_set_active(view_layer, base); + /* We need to ensure all new overrides of objects are properly instantiated. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + Object *ob_new = (Object *)ob->id.newid; + if (ob_new != NULL) { + BLI_assert(ob_new->id.override_library != NULL && + ob_new->id.override_library->reference == &ob->id); + + Collection *default_instantiating_collection = NULL; + Base *base; + if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { + if (default_instantiating_collection == NULL) { + switch (GS(id_root->name)) { + case ID_GR: { + default_instantiating_collection = BKE_collection_add( + bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); + break; + } + case ID_OB: { + /* Add the new container collection to one of the collections instantiating the + * root object, or scene's master collection if none found. */ + Object *ob_root = (Object *)id_root; + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, ob_root) && + BKE_view_layer_has_collection(view_layer, collection)) { + default_instantiating_collection = BKE_collection_add( + bmain, collection, "OVERRIDE_HIDDEN"); + } + } + if (default_instantiating_collection == NULL) { + default_instantiating_collection = BKE_collection_add( + bmain, scene->master_collection, "OVERRIDE_HIDDEN"); + } + break; + } + default: + BLI_assert(0); + } + /* Hide the collection from viewport and render. */ + default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | + COLLECTION_RESTRICT_RENDER; + } + + BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } - /* We still want to store all objects' current override status (i.e. change of parent). */ - BKE_lib_override_library_operations_create(bmain, &new_ob->id, true); } } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ - ED_object_base_free_and_unlink(bmain, scene, obcollection); - - /* Also, we'd likely want to lock by default things like - * transformations of implicitly overridden objects? */ - - DEG_id_tag_update(&scene->id, 0); - - /* Cleanup. */ - BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - } - else if (!ID_IS_OVERRIDABLE_LIBRARY(obact)) { - BKE_reportf(op->reports, - RPT_ERROR_INVALID_INPUT, - "Active object '%s' is not overridable", - obact->id.name + 2); - return OPERATOR_CANCELLED; - } - /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ - else if (obact->type == OB_ARMATURE) { - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - - obact->id.tag |= LIB_TAG_DOIT; - - for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) { - make_override_library_tag_object(obact, ob); + if (id_root != &obact->id) { + ED_object_base_free_and_unlink(bmain, scene, obact); } - - success = BKE_lib_override_library_create_from_tag(bmain); - - /* Also, we'd likely want to lock by default things like - * transformations of implicitly overridden objects? */ - - /* Cleanup. */ - BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - } - /* TODO: probably more cases where we want to do automated smart things in the future! */ - else { - /* For now, remapp all local usages of linked ID to local override one here. */ - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true); - success = (BKE_lib_override_library_create_from_id(bmain, &obact->id, true) != NULL); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } + /* Cleanup. */ + BKE_main_id_clear_newpoins(bmain); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_WINDOW, NULL); return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 1d7920b9991..664d4219686 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -100,7 +100,12 @@ static bool object_remesh_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (ob == NULL) { + if (ob == NULL || ob->data == NULL) { + return false; + } + + if (ID_IS_LINKED(ob) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { + CTX_wm_operator_poll_msg_set(C, "The remesher cannot worked on linked or override data"); return false; } @@ -174,6 +179,11 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) BKE_remesh_reproject_sculpt_face_sets(new_mesh, mesh); } + if (mesh->flag & ME_REMESH_REPROJECT_VERTEX_COLORS) { + BKE_mesh_runtime_clear_geometry(mesh); + BKE_remesh_reproject_vertex_paint(new_mesh, mesh); + } + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) { @@ -521,7 +531,9 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Project the selected face in the previous step of the Bounding Box. */ for (int i = 0; i < 4; i++) { - ED_view3d_project(ar, cd->preview_plane[i], preview_plane_proj[i]); + float preview_plane_world_space[3]; + mul_v3_m4v3(preview_plane_world_space, active_object->obmat, cd->preview_plane[i]); + ED_view3d_project(ar, preview_plane_world_space, preview_plane_proj[i]); } /* Get the initial X and Y axis of the basis from the edges of the Bounding Box face. */ @@ -569,7 +581,9 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev copy_v3_v3(cd->text_mat[3], text_pos); /* Scale the text. */ - const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos); + float text_pos_word_space[3]; + mul_v3_m4v3(text_pos_word_space, active_object->obmat, text_pos); + const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos_word_space); scale_m4_fl(scale_mat, pixelsize * 0.5f); mul_m4_m4_post(cd->text_mat, scale_mat); diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index 5db4a5a4f57..d9f37b8e38b 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -200,6 +200,40 @@ int ED_object_shaderfx_move_down(ReportList *UNUSED(reports), Object *ob, Shader return 1; } +bool ED_object_shaderfx_move_to_index(ReportList *reports, + Object *ob, + ShaderFxData *fx, + const int index) +{ + BLI_assert(fx != NULL); + BLI_assert(index >= 0); + if (index >= BLI_listbase_count(&ob->shader_fx)) { + BKE_report(reports, RPT_WARNING, "Cannot move effect beyond the end of the stack"); + return false; + } + + int fx_index = BLI_findindex(&ob->shader_fx, fx); + BLI_assert(fx_index != -1); + if (fx_index < index) { + /* Move shaderfx down in list. */ + for (; fx_index < index; fx_index++) { + if (!ED_object_shaderfx_move_down(reports, ob, fx)) { + break; + } + } + } + else { + /* Move shaderfx up in list. */ + for (; fx_index > index; fx_index--) { + if (!ED_object_shaderfx_move_up(reports, ob, fx)) { + break; + } + } + } + + return true; +} + /************************ add effect operator *********************/ static int shaderfx_add_exec(bContext *C, wmOperator *op) @@ -391,8 +425,8 @@ static int shaderfx_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UN void OBJECT_OT_shaderfx_remove(wmOperatorType *ot) { - ot->name = "Remove Grease Pencil Modifier"; - ot->description = "Remove a shaderfx from the active grease pencil object"; + ot->name = "Remove Grease Pencil Effect"; + ot->description = "Remove a effect from the active grease pencil object"; ot->idname = "OBJECT_OT_shaderfx_remove"; ot->invoke = shaderfx_remove_invoke; @@ -433,8 +467,8 @@ static int shaderfx_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *U void OBJECT_OT_shaderfx_move_up(wmOperatorType *ot) { - ot->name = "Move Up Modifier"; - ot->description = "Move shaderfx up in the stack"; + ot->name = "Move Up Effect"; + ot->description = "Move effect up in the stack"; ot->idname = "OBJECT_OT_shaderfx_move_up"; ot->invoke = shaderfx_move_up_invoke; @@ -475,8 +509,8 @@ static int shaderfx_move_down_invoke(bContext *C, wmOperator *op, const wmEvent void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot) { - ot->name = "Move Down Modifier"; - ot->description = "Move shaderfx down in the stack"; + ot->name = "Move Down Effect"; + ot->description = "Move effect down in the stack"; ot->idname = "OBJECT_OT_shaderfx_move_down"; ot->invoke = shaderfx_move_down_invoke; @@ -487,3 +521,55 @@ void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_shaderfx_properties(ot); } + +/************************ move shaderfx to index operator *********************/ + +static bool shaderfx_move_to_index_poll(bContext *C) +{ + return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0); +} + +static int shaderfx_move_to_index_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); + int index = RNA_int_get(op->ptr, "index"); + + if (!fx || !ED_object_shaderfx_move_to_index(op->reports, ob, fx, index)) { + return OPERATOR_CANCELLED; + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int shaderfx_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (edit_shaderfx_invoke_properties(C, op)) { + return shaderfx_move_to_index_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_shaderfx_move_to_index(wmOperatorType *ot) +{ + ot->name = "Move Effect to Index"; + ot->idname = "OBJECT_OT_shaderfx_move_to_index"; + ot->description = + "Change the effect's position in the list so it evaluates after the set number of " + "others"; + + ot->invoke = shaderfx_move_to_index_invoke; + ot->exec = shaderfx_move_to_index_exec; + ot->poll = shaderfx_move_to_index_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_shaderfx_properties(ot); + RNA_def_int( + ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the effect to", 0, INT_MAX); +} diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 26d33bbc375..71778f92349 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -216,40 +216,38 @@ static bool object_shape_key_mirror( /********************** shape key operators *********************/ -static bool shape_key_mode_poll(bContext *C) +static bool shape_key_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT); + + return (ob != NULL && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && data != NULL && + !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); } -static bool shape_key_mode_exists_poll(bContext *C) +static bool shape_key_mode_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - /* same as shape_key_mode_poll */ - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT) && - /* check a keyblock exists */ - (BKE_keyblock_from_object(ob) != NULL); + return (shape_key_poll(C) && ob->mode != OB_MODE_EDIT); } -static bool shape_key_move_poll(bContext *C) +static bool shape_key_mode_exists_poll(bContext *C) { - /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */ Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - Key *key = BKE_key_from_object(ob); - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT && - key && key->totkey > 1); + return (shape_key_mode_poll(C) && + /* check a keyblock exists */ + (BKE_keyblock_from_object(ob) != NULL)); } -static bool shape_key_poll(bContext *C) +static bool shape_key_move_poll(bContext *C) { + /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */ Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)); + Key *key = BKE_key_from_object(ob); + + return (shape_key_mode_poll(C) && key != NULL && key->totkey > 1); } static int shape_key_add_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 132b530455e..161611d59c9 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1098,15 +1098,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) mul_m4_v3(obedit->imat, cent); } else { - if (around == V3D_AROUND_CENTER_MEDIAN) { - if (em->bm->totvert) { - const float total_div = 1.0f / (float)em->bm->totvert; - BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - madd_v3_v3fl(cent, eve->co, total_div); - } - } - } - else { + if (around == V3D_AROUND_CENTER_BOUNDS) { float min[3], max[3]; INIT_MINMAX(min, max); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -1114,6 +1106,14 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } mid_v3_v3v3(cent, min, max); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + if (em->bm->totvert) { + const float total_div = 1.0f / (float)em->bm->totvert; + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + madd_v3_v3fl(cent, eve->co, total_div); + } + } + } } BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -1211,12 +1211,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) { BKE_mesh_center_of_volume(me, cent); } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_mesh_center_median(me, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_mesh_center_bounds(me, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mesh_center_median(me, cent); + } negate_v3_v3(cent_neg, cent); BKE_mesh_translate(me, cent_neg, 1); @@ -1231,12 +1231,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_curve_center_median(cu, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_curve_center_bounds(cu, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_curve_center_median(cu, cent); + } /* don't allow Z change if curve is 2D */ if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { @@ -1324,12 +1324,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_mball_center_median(mb, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_mball_center_bounds(mb, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mball_center_median(mb, cent); + } negate_v3_v3(cent_neg, cent); BKE_mball_translate(mb, cent_neg); @@ -1351,12 +1351,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_lattice_center_median(lt, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_lattice_center_bounds(lt, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_lattice_center_median(lt, cent); + } negate_v3_v3(cent_neg, cent); BKE_lattice_translate(lt, cent_neg, 1); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index fb79cfb910e..7ca2a89f61d 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -77,7 +77,10 @@ #include "object_intern.h" -/************************ Exported Functions **********************/ +/* -------------------------------------------------------------------- */ +/** \name Public Utility Functions + * \{ */ + static bool vertex_group_use_vert_sel(Object *ob) { if (ob->mode == OB_MODE_EDIT) { @@ -682,7 +685,11 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) MEM_freeN((void *)vgroup_validmap); } -/***********************Start weight transfer (WT)*********************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shared Weight Transfer Operator Properties + * \{ */ static const EnumPropertyItem WT_vertex_group_select_item[] = { {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"}, @@ -779,7 +786,15 @@ static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_act ot->prop = prop; } -/***********************End weight transfer (WT)***********************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name High Level Vertex Group Add/Remove + * + * Wrap lower level `BKE` functions. + * + * \note that operations on many vertices should use #ED_vgroup_parray_alloc. + * \{ */ /* for Mesh in Object mode */ /* allows editmode for Lattice */ @@ -976,7 +991,11 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1; } -/********************** Operator Implementations *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Function Implementations + * \{ */ /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) @@ -2634,48 +2653,49 @@ static void vgroup_assign_verts(Object *ob, const float weight) } } -/********************** vertex group operators *********************/ +/** \} */ -static bool vertex_group_poll(bContext *C) +/* -------------------------------------------------------------------- */ +/** \name Shared Operator Poll Functions + * \{ */ + +static bool vertex_group_supported_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && - OB_TYPE_SUPPORT_VGROUP(ob->type) && ob->defbase.first); + return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && + !ID_IS_OVERRIDE_LIBRARY(ob) && data && !ID_IS_LINKED(data) && + !ID_IS_OVERRIDE_LIBRARY(data)); } -static bool vertex_group_supported_poll(bContext *C) +static bool vertex_group_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && data && - !ID_IS_LINKED(data)); + + return (vertex_group_supported_poll(C) && ob->defbase.first); } static bool vertex_group_mesh_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->type == OB_MESH && - ob->defbase.first); + return (vertex_group_poll(C) && ob->type == OB_MESH); } static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data)); + + return (vertex_group_supported_poll(C) && ob->type == OB_MESH); } static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { - return 0; + if (!vertex_group_supported_poll(C)) { + return false; } return BKE_object_is_in_editmode_vgroup(ob); @@ -2687,9 +2707,8 @@ static bool vertex_group_vert_poll_ex(bContext *C, const short ob_type_flag) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { + if (!vertex_group_supported_poll(C)) { return false; } @@ -2747,14 +2766,13 @@ static bool vertex_group_mesh_vert_select_poll(bContext *C) static bool vertex_group_vert_select_unlocked_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { - return 0; + if (!vertex_group_supported_poll(C)) { + return false; } if (!(BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) { - return 0; + return false; } if (ob->actdef != 0) { @@ -2763,26 +2781,31 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) return !(dg->flag & DG_LOCK_WEIGHT); } } - return 1; + return true; } static bool vertex_group_vert_select_mesh_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { - return 0; + if (!vertex_group_supported_poll(C)) { + return false; } /* only difference to #vertex_group_vert_select_poll */ if (ob->type != OB_MESH) { - return 0; + return false; } return (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Add Operator + * \{ */ + static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -2811,6 +2834,12 @@ void OBJECT_OT_vertex_group_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Remove Operator + * \{ */ + static int vertex_group_remove_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -2858,6 +2887,12 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Assign Operator + * \{ */ + static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op)) { ToolSettings *ts = CTX_data_tool_settings(C); @@ -2888,6 +2923,12 @@ void OBJECT_OT_vertex_group_assign(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Assign New Operator + * \{ */ + /* NOTE: just a wrapper around vertex_group_assign_exec(), except we add these to a new group */ static int vertex_group_assign_new_exec(bContext *C, wmOperator *op) { @@ -2917,6 +2958,12 @@ void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Remove From Operator + * \{ */ + static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) { const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups"); @@ -2968,6 +3015,12 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Select Operator + * \{ */ + static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -2998,6 +3051,12 @@ void OBJECT_OT_vertex_group_select(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Deselect Operator + * \{ */ + static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -3037,6 +3096,12 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy Operator + * \{ */ + void OBJECT_OT_vertex_group_copy(wmOperatorType *ot) { /* identifiers */ @@ -3074,6 +3139,12 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Levels Operator + * \{ */ + void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) { /* identifiers */ @@ -3115,6 +3186,12 @@ static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize Operator + * \{ */ + void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot) { /* identifiers */ @@ -3158,6 +3235,12 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize All Operator + * \{ */ + void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) { /* identifiers */ @@ -3182,6 +3265,12 @@ void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) "Keep the values of the active group while normalizing others"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Fix Position Operator + * \{ */ + static int vertex_group_fix_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -3259,6 +3348,12 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot) 1.f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Lock Operator + * \{ */ + static int vertex_group_lock_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -3361,6 +3456,12 @@ void OBJECT_OT_vertex_group_lock(wmOperatorType *ot) "Apply the action based on vertex group selection"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Invert Operator + * \{ */ + static int vertex_group_invert_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3410,6 +3511,12 @@ void OBJECT_OT_vertex_group_invert(wmOperatorType *ot) "Remove verts from groups that have zero weight after inverting"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Invert Operator + * \{ */ + static int vertex_group_smooth_exec(bContext *C, wmOperator *op) { const float fac = RNA_float_get(op->ptr, "factor"); @@ -3482,6 +3589,12 @@ void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot) 1.0f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Clean Operator + * \{ */ + static int vertex_group_clean_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3535,6 +3648,12 @@ void OBJECT_OT_vertex_group_clean(wmOperatorType *ot) "Keep verts assigned to at least one group when cleaning"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Quantize Operator + * \{ */ + static int vertex_group_quantize_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3574,6 +3693,12 @@ void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot) RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Limit Total Operator + * \{ */ + static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3625,6 +3750,12 @@ void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot) RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Mirror Operator + * \{ */ + static int vertex_group_mirror_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3677,6 +3808,12 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) "Use topology based mirroring (for when both sides of mesh have matching, unique topology)"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy to Linked Operator + * \{ */ + static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); @@ -3720,6 +3857,12 @@ void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy to Selected Operator + * \{ */ + static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) { Object *obact = ED_object_context(C); @@ -3768,6 +3911,12 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Set Active Operator + * \{ */ + static int set_active_group_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3836,6 +3985,12 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot) ot->prop = prop; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Sort Operator + * \{ */ + /* creates the name_array parameter for vgroup_do_remap, call this before fiddling * with the order of vgroups then call vgroup_do_remap after */ static char *vgroup_init_remap(Object *ob) @@ -4030,6 +4185,12 @@ void OBJECT_OT_vertex_group_sort(wmOperatorType *ot) RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Move Operator + * \{ */ + static int vgroup_move_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -4089,6 +4250,12 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot) "Direction to move the active vertex group towards"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Weight Paste Operator + * \{ */ + static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) { MDeformVert *dvert_act; @@ -4218,6 +4385,12 @@ void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Weight Delete Operator + * \{ */ + static int vertex_weight_delete_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -4262,6 +4435,12 @@ void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Set Active by Weight Operator + * \{ */ + static int vertex_weight_set_active_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -4303,6 +4482,12 @@ void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize Active Vertex Operator + * \{ */ + static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -4338,6 +4523,12 @@ void OBJECT_OT_vertex_weight_normalize_active_vertex(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy Weights from Active Operator + * \{ */ + static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -4366,3 +4557,5 @@ void OBJECT_OT_vertex_weight_copy(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index ef5ed806c1e..457c8ba30e6 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4103,7 +4103,7 @@ static void brush_add_count_iter(void *__restrict iter_data_v, BrushAddCountIterTLSData *tls = tls_v->userdata_chunk; const int number = iter_data->number; const short size = iter_data->size; - const short size2 = size * size; + const int size2 = size * size; float dmx, dmy; if (number > 1) { dmx = size; diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 8524870c15e..8f6b5aa8bc3 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -270,31 +270,31 @@ static void fluid_bake_sequence(FluidJob *job) *(job->do_update) = true; } - /* Get current pause frame (pointer) - depending on bake type */ + /* Get current pause frame (pointer) - depending on bake type. */ pause_frame = job->pause_frame; - /* Set frame to start point (depending on current pause frame value) */ + /* Set frame to start point (depending on current pause frame value). */ is_first_frame = ((*pause_frame) == 0); frame = is_first_frame ? mds->cache_frame_start : (*pause_frame); - /* Save orig frame and update scene frame */ + /* Save orig frame and update scene frame. */ orig_frame = CFRA; CFRA = frame; - /* Loop through selected frames */ + /* Loop through selected frames. */ for (; frame <= mds->cache_frame_end; frame++) { const float progress = (frame - mds->cache_frame_start) / (float)frames; - /* Keep track of pause frame - needed to init future loop */ + /* Keep track of pause frame - needed to init future loop. */ (*pause_frame) = frame; - /* If user requested stop, quit baking */ + /* If user requested stop, quit baking. */ if (G.is_break) { job->success = 0; return; } - /* Update progress bar */ + /* Update progress bar. */ if (job->do_update) { *(job->do_update) = true; } @@ -304,17 +304,17 @@ static void fluid_bake_sequence(FluidJob *job) CFRA = frame; - /* Update animation system */ + /* Update animation system. */ ED_update_for_newframe(job->bmain, job->depsgraph); - /* If user requested stop, quit baking */ + /* If user requested stop, quit baking. */ if (G.is_break) { job->success = 0; return; } } - /* Restore frame position that we were on before bake */ + /* Restore frame position that we were on before bake. */ CFRA = orig_frame; } @@ -355,9 +355,9 @@ static void fluid_bake_endjob(void *customdata) WM_set_locked_interface(G_MAIN->wm.first, false); /* Bake was successful: - * Report for ended bake and how long it took */ + * Report for ended bake and how long it took. */ if (job->success) { - /* Show bake info */ + /* Show bake info. */ WM_reportf( RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start); } @@ -365,7 +365,7 @@ static void fluid_bake_endjob(void *customdata) if (mds->error[0] != '\0') { WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error); } - else { /* User canceled the bake */ + else { /* User canceled the bake. */ WM_reportf(RPT_WARNING, "Fluid: %s canceled!", job->name); } } diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 700a94e4f93..5bd56baf41e 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -132,7 +132,7 @@ static void ptcache_job_endjob(void *customdata) WM_set_locked_interface(job->wm, false); WM_main_add_notifier(NC_SCENE | ND_FRAME, scene); - WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob); + WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.owner_id); } static void ptcache_free_bake(PointCache *cache) diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 10f69f3fe9d..7d0ad42c703 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -178,7 +178,7 @@ void ED_render_engine_area_exit(Main *bmain, ScrArea *area) } } -void ED_render_engine_changed(Main *bmain) +void ED_render_engine_changed(Main *bmain, const bool update_scene_data) { /* on changing the render engine type, clear all running render engines */ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { @@ -198,7 +198,7 @@ void ED_render_engine_changed(Main *bmain) update_ctx.view_layer = view_layer; ED_render_id_flush_update(&update_ctx, &scene->id); } - if (scene->nodetree) { + if (scene->nodetree && update_scene_data) { ntreeCompositUpdateRLayers(scene->nodetree); } } diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c index c32bb69db4e..a1fa5e2d655 100644 --- a/source/blender/editors/scene/scene_edit.c +++ b/source/blender/editors/scene/scene_edit.c @@ -122,7 +122,7 @@ void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer) DEG_graph_relations_update(depsgraph, bmain, scene, layer); DEG_on_visible_update(bmain, false); - ED_render_engine_changed(bmain); + ED_render_engine_changed(bmain, false); ED_update_for_newframe(bmain, depsgraph); } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c04122edd36..a182dd662af 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -646,7 +646,7 @@ void ED_region_tag_redraw(ARegion *region) void ED_region_tag_redraw_cursor(ARegion *region) { if (region) { - region->do_draw_overlay = RGN_DRAW; + region->do_draw_paintcursor = RGN_DRAW; } } @@ -1145,7 +1145,7 @@ static void region_overlap_fix(ScrArea *area, ARegion *region) /* find overlapping previous region on same place */ for (ar1 = region->prev; ar1; ar1 = ar1->prev) { - if (ar1->flag & (RGN_FLAG_HIDDEN)) { + if (ar1->flag & RGN_FLAG_HIDDEN) { continue; } @@ -1194,7 +1194,7 @@ static void region_overlap_fix(ScrArea *area, ARegion *region) /* At this point, 'region' is in its final position and still open. * Make a final check it does not overlap any previous 'other side' region. */ for (ar1 = region->prev; ar1; ar1 = ar1->prev) { - if (ar1->flag & (RGN_FLAG_HIDDEN)) { + if (ar1->flag & RGN_FLAG_HIDDEN) { continue; } if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) { @@ -1556,7 +1556,14 @@ static void region_rect_recursive( /* Tag for redraw if size changes. */ if (region->winx != prev_winx || region->winy != prev_winy) { - ED_region_tag_redraw(region); + /* 3D View needs a full rebuild in case a progressive render runs. Rest can live with + * no-rebuild (e.g. Outliner) */ + if (area->spacetype == SPACE_VIEW3D) { + ED_region_tag_redraw(region); + } + else { + ED_region_tag_redraw_no_rebuild(region); + } } /* Clear, initialize on demand. */ @@ -2348,9 +2355,9 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[]) /** * Builds the panel layout for the input \a panel or type \a pt. * - * \param panel The panel to draw. Can be null, in which case a panel with the type of \a pt will - * be created. - * \param unique_panel_str A unique identifier for the name of the \a uiBlock associated with the + * \param panel: The panel to draw. Can be null, + * in which case a panel with the type of \a pt will be created. + * \param unique_panel_str: A unique identifier for the name of the \a uiBlock associated with the * panel. Used when the panel is an instanced panel so a unique identifier is needed to find the * correct old \a uiBlock, and NULL otherwise. */ @@ -2566,16 +2573,16 @@ void ED_region_panels_layout_ex(const bContext *C, /* only allow scrolling in vertical direction */ v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y; v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X); - v2d->scroll &= ~(V2D_SCROLL_BOTTOM); - v2d->scroll |= (V2D_SCROLL_RIGHT); + v2d->scroll &= ~V2D_SCROLL_BOTTOM; + v2d->scroll |= V2D_SCROLL_RIGHT; } else { /* for now, allow scrolling in both directions (since layouts are optimized for vertical, * they often don't fit in horizontal layout) */ v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y); - v2d->scroll |= (V2D_SCROLL_BOTTOM); - v2d->scroll &= ~(V2D_SCROLL_RIGHT); + v2d->scroll |= V2D_SCROLL_BOTTOM; + v2d->scroll &= ~V2D_SCROLL_RIGHT; } /* collect categories */ @@ -2788,9 +2795,7 @@ void ED_region_panels_draw(const bContext *C, ARegion *region) mask_buf.xmax -= UI_PANEL_CATEGORY_MARGIN_WIDTH; mask = &mask_buf; } - View2DScrollers *scrollers = UI_view2d_scrollers_calc(v2d, mask); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, mask); } void ED_region_panels_ex( diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 6f004238522..b6f210d7f13 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1331,6 +1331,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const oldscreen->animtimer = NULL; ED_screen_change(C, screen); + ED_area_tag_refresh(fullsa); BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index b2243f2ccb9..5de8ccd404d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -366,19 +366,20 @@ bool ED_operator_object_active_editable_mesh(bContext *C) { Object *ob = ED_object_active_context(C); return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_MESH) && - !ID_IS_LINKED(ob->data)); + !ID_IS_LINKED(ob->data) && !ID_IS_OVERRIDE_LIBRARY(ob->data)); } bool ED_operator_object_active_editable_font(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_FONT)); + return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_FONT) && + !ID_IS_LINKED(ob->data) && !ID_IS_OVERRIDE_LIBRARY(ob->data)); } bool ED_operator_editable_mesh(bContext *C) { Mesh *mesh = ED_mesh_context(C); - return (mesh != NULL) && !ID_IS_LINKED(mesh); + return (mesh != NULL) && !ID_IS_LINKED(mesh) && !ID_IS_OVERRIDE_LIBRARY(mesh); } bool ED_operator_editmesh(bContext *C) @@ -1761,7 +1762,7 @@ static void area_move_apply_do(const bContext *C, screen->do_refresh = true; redraw_all = true; } - ED_area_tag_redraw(area); + ED_area_tag_redraw_no_rebuild(area); } } if (redraw_all) { @@ -4273,68 +4274,67 @@ static void SCREEN_OT_region_context_menu(wmOperatorType *ot) * * Animation Step. * \{ */ +static bool screen_animation_region_supports_time_follow(eSpace_Type spacetype, + eRegionType regiontype) +{ + return (regiontype == RGN_TYPE_WINDOW && + ELEM(spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) || + (spacetype == SPACE_CLIP && regiontype == RGN_TYPE_PREVIEW); +} -static int match_region_with_redraws(int spacetype, - int regiontype, - int redraws, - bool from_anim_edit) +static bool match_region_with_redraws(const ScrArea *area, + eRegionType regiontype, + eScreen_Redraws_Flag redraws, + bool from_anim_edit) { + const eSpace_Type spacetype = area->spacetype; if (regiontype == RGN_TYPE_WINDOW) { switch (spacetype) { case SPACE_VIEW3D: if ((redraws & TIME_ALL_3D_WIN) || from_anim_edit) { - return 1; + return true; } break; case SPACE_GRAPH: case SPACE_NLA: if ((redraws & TIME_ALL_ANIM_WIN) || from_anim_edit) { - return 1; + return true; } break; case SPACE_ACTION: /* if only 1 window or 3d windows, we do timeline too * NOTE: Now we do action editor in all these cases, since timeline is here. */ if ((redraws & (TIME_ALL_ANIM_WIN | TIME_REGION | TIME_ALL_3D_WIN)) || from_anim_edit) { - return 1; + return true; } break; case SPACE_PROPERTIES: if (redraws & TIME_ALL_BUTS_WIN) { - return 1; + return true; } break; case SPACE_SEQ: if ((redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN)) || from_anim_edit) { - return 1; + return true; } break; case SPACE_NODE: - if (redraws & (TIME_NODES)) { - return 1; + if (redraws & TIME_NODES) { + return true; } break; case SPACE_IMAGE: if ((redraws & TIME_ALL_IMAGE_WIN) || from_anim_edit) { - return 1; + return true; } break; case SPACE_CLIP: if ((redraws & TIME_CLIPS) || from_anim_edit) { - return 1; + return true; } break; - } - } - else if (regiontype == RGN_TYPE_CHANNELS) { - switch (spacetype) { - case SPACE_GRAPH: - case SPACE_ACTION: - case SPACE_NLA: - if (redraws & TIME_ALL_ANIM_WIN) { - return 1; - } + default: break; } } @@ -4345,30 +4345,68 @@ static int match_region_with_redraws(int spacetype, * during playback, so asking people to enable special option * for this is a bit tricky, so add exception here for refreshing * Properties Editor for SpaceClip always */ - return 1; + return true; } if (redraws & TIME_ALL_BUTS_WIN) { - return 1; + return true; } } - else if (ELEM(regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { + else if (regiontype == RGN_TYPE_HEADER) { if (spacetype == SPACE_ACTION) { - return 1; + /* The timeline shows the current frame in the header. Other headers + * don't need to be updated. */ + SpaceAction *saction = (SpaceAction *)area->spacedata.first; + return saction->mode == SACTCONT_TIMELINE; } } else if (regiontype == RGN_TYPE_PREVIEW) { switch (spacetype) { case SPACE_SEQ: if (redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN)) { - return 1; + return true; } break; case SPACE_CLIP: - return 1; + return true; + default: + break; } } - return 0; + return false; +} + +static void screen_animation_region_tag_redraw(ScrArea *area, + ARegion *region, + const Scene *scene, + eScreen_Redraws_Flag redraws) +{ + /* Do follow time here if editor type supports it */ + if ((redraws & TIME_FOLLOW) && + (screen_animation_region_supports_time_follow(area->spacetype, region->regiontype))) { + float w = BLI_rctf_size_x(®ion->v2d.cur); + if (scene->r.cfra < region->v2d.cur.xmin) { + region->v2d.cur.xmax = scene->r.cfra; + region->v2d.cur.xmin = region->v2d.cur.xmax - w; + ED_region_tag_redraw(region); + return; + } + else if (scene->r.cfra > region->v2d.cur.xmax) { + region->v2d.cur.xmin = scene->r.cfra; + region->v2d.cur.xmax = region->v2d.cur.xmin + w; + ED_region_tag_redraw(region); + return; + } + } + + /* No need to do a full redraw as the current frame indicator is only updated. + * We do need to redraw when this area is in full screen as no other areas + * will be tagged for redrawing. */ + if ((region->regiontype == RGN_TYPE_WINDOW) && + (ELEM(area->spacetype, SPACE_GRAPH, SPACE_NLA, SPACE_ACTION, SPACE_SEQ)) && !area->full) { + return; + } + ED_region_tag_redraw(region); } //#define PROFILE_AUDIO_SYNCH @@ -4409,7 +4447,8 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } if (scene_eval == NULL) { - /* Happens when undo/redo system is used during playback, nothing meaningful we can do here. + /* Happens when undo/redo system is used during playback, nothing meaningful we can do + * here. */ } else if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) { @@ -4549,28 +4588,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv redraw = true; } else if (match_region_with_redraws( - area->spacetype, region->regiontype, sad->redraws, sad->from_anim_edit)) { + area, region->regiontype, sad->redraws, sad->from_anim_edit)) { redraw = true; } if (redraw) { - ED_region_tag_redraw(region); - /* do follow here if editor type supports it */ - if ((sad->redraws & TIME_FOLLOW)) { - if ((region->regiontype == RGN_TYPE_WINDOW && - ELEM(area->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) || - (area->spacetype == SPACE_CLIP && region->regiontype == RGN_TYPE_PREVIEW)) { - float w = BLI_rctf_size_x(®ion->v2d.cur); - if (scene->r.cfra < region->v2d.cur.xmin) { - region->v2d.cur.xmax = scene->r.cfra; - region->v2d.cur.xmin = region->v2d.cur.xmax - w; - } - else if (scene->r.cfra > region->v2d.cur.xmax) { - region->v2d.cur.xmin = scene->r.cfra; - region->v2d.cur.xmax = region->v2d.cur.xmin + w; - } - } - } + screen_animation_region_tag_redraw(area, region, scene, sad->redraws); } } } diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c index 7ce92bc3e4d..0af81e0db21 100644 --- a/source/blender/editors/screen/workspace_layout_edit.c +++ b/source/blender/editors/screen/workspace_layout_edit.c @@ -38,7 +38,7 @@ #include "screen_intern.h" /** - * Empty screen, with 1 dummy area without spacedata. Uses window size. + * Empty screen, with 1 dummy area without space-data. Uses window size. */ WorkSpaceLayout *ED_workspace_layout_add(Main *bmain, WorkSpace *workspace, diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index b8754953741..ed87d524627 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -64,10 +64,12 @@ set(SRC sculpt_detail.c sculpt_dyntopo.c sculpt_face_set.c + sculpt_filter_color.c sculpt_filter_mask.c sculpt_filter_mesh.c sculpt_mask_expand.c sculpt_multiplane_scrape.c + sculpt_paint_color.c sculpt_pose.c sculpt_smooth.c sculpt_transform.c diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 4222a466a7b..1291de04634 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1441,7 +1441,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) * cursor won't be tagged to update, so always initialize the preview chain if it is * null before drawing it. */ if (update_previews || !ss->pose_ik_chain_preview) { - BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false); + BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false, false); /* Free the previous pose brush preview. */ if (ss->pose_ik_chain_preview) { diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 08af3bdd16c..7f64fdf3501 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1301,7 +1301,7 @@ static bool brush_colors_flip_poll(bContext *C) else { Object *ob = CTX_data_active_object(C); if (ob != NULL) { - if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) { + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_SCULPT)) { return true; } } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 5e3204b6d5a..dfb8f03fa6e 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -811,7 +811,7 @@ static bool project_paint_PickColor( } /** - * Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusion test) + * Check if 'pt' is in front of the 3 verts on the Z axis (used for screen-space occlusion test) * \return * - `0`: no occlusion * - `-1`: no occlusion but 2D intersection is true @@ -836,7 +836,7 @@ static int project_paint_occlude_ptv(const float pt[3], } /* From here on we know there IS an intersection */ - /* if ALL of the verts are infront of us then we know it intersects ? */ + /* if ALL of the verts are in front of us then we know it intersects ? */ if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) { return 1; } diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index c32e496f4f5..6e0402fc6e0 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -146,12 +146,11 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) PBVHNode **nodes; int totnode; bool multires; - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; mode = RNA_enum_get(op->ptr, "mode"); value = RNA_float_get(op->ptr, "value"); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); @@ -169,7 +168,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings); if (multires) { @@ -313,7 +312,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti * /* Transform the clip planes in object space. */ ED_view3d_clipping_calc(&bb, clip_planes, vc->region, vc->obact, rect); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); @@ -344,7 +343,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti * }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings); if (nodes) { @@ -500,7 +499,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) ED_view3d_clipping_calc(&bb, clip_planes, vc.region, vc.obact, &data.rect); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); @@ -533,7 +532,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) data.task_data.value = value; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings); if (nodes) { diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 0f54d5e0821..191ae1da343 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -304,7 +304,10 @@ static bool palette_extract_img_poll(bContext *C) { SpaceLink *sl = CTX_wm_space_data(C); if ((sl != NULL) && (sl->spacetype == SPACE_IMAGE)) { - return true; + SpaceImage *sima = CTX_wm_space_image(C); + Image *image = sima->image; + ImageUser iuser = sima->iuser; + return BKE_image_has_ibuf(image, &iuser); } return false; @@ -326,16 +329,16 @@ static int palette_extract_img_exec(bContext *C, wmOperator *op) ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); - if (ibuf->rect) { + if (ibuf && ibuf->rect) { /* Extract all colors. */ + const int range = (int)pow(10.0f, threshold); for (int row = 0; row < ibuf->y; row++) { for (int col = 0; col < ibuf->x; col++) { float color[4]; IMB_sampleImageAtLocation(ibuf, (float)col, (float)row, false, color); - const float range = pow(10.0f, threshold); - color[0] = truncf(color[0] * range) / range; - color[1] = truncf(color[1] * range) / range; - color[2] = truncf(color[2] * range) / range; + for (int i = 0; i < 3; i++) { + color[i] = truncf(color[i] * range) / range; + } uint key = rgb_to_cpack(color[0], color[1], color[2]); if (!BLI_ghash_haskey(color_table, POINTER_FROM_INT(key))) { @@ -360,6 +363,8 @@ static int palette_extract_img_exec(bContext *C, wmOperator *op) static void PALETTE_OT_extract_from_image(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Extract Palette from Image"; ot->idname = "PALETTE_OT_extract_from_image"; @@ -373,7 +378,8 @@ static void PALETTE_OT_extract_from_image(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, "threshold", 1, 1, 4, "Threshold", "", 1, 4); + prop = RNA_def_int(ot->srna, "threshold", 1, 1, 1, "Threshold", "", 1, 1); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /* Sort Palette color by Hue and Saturation. */ diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 2c6f708d82a..447d5373a48 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -909,7 +909,7 @@ PaintStroke *paint_stroke_new(bContext *C, stroke->zoom_2d = max_ff(zoomx, zoomy); if (stroke->stroke_mode == BRUSH_STROKE_INVERT) { - if (br->flag & (BRUSH_CURVE)) { + if (br->flag & BRUSH_CURVE) { RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL); } } @@ -1467,8 +1467,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) } else if (first_modal || /* regular dabs */ - (!(br->flag & (BRUSH_AIRBRUSH)) && - (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) || + (!(br->flag & BRUSH_AIRBRUSH) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) || /* airbrush */ ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer)) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 6de54b3ae6a..7ac778630ac 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1101,12 +1101,12 @@ static void vertex_paint_init_session(Depsgraph *depsgraph, BLI_assert(ob->sculpt == NULL); ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = object_mode; - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); } static void vertex_paint_init_stroke(Depsgraph *depsgraph, Object *ob) { - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); } static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) @@ -1425,10 +1425,10 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) } } - /* Weightpaint works by overriding colors in mesh, - * so need to make sure we recalc on enter and + /* Weight-paint works by overriding colors in mesh, + * so need to make sure we recalculate on enter and * exit (exit needs doing regardless because we - * should redeform). + * should re-deform). */ DEG_id_tag_update(&me->id, 0); @@ -2171,7 +2171,7 @@ static void calculate_average_weight(SculptThreadedTaskData *data, data->custom_data = accum; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (data->sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings); uint accum_len = 0; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 75c88047914..fb7ae4d017d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -30,6 +30,7 @@ #include "BLI_gsqueue.h" #include "BLI_hash.h" #include "BLI_math.h" +#include "BLI_math_color_blend.h" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -73,6 +74,8 @@ #include "DEG_depsgraph.h" +#include "IMB_colormanagement.h" + #include "WM_api.h" #include "WM_message.h" #include "WM_toolsystem.h" @@ -153,6 +156,21 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, int index) return NULL; } +const float *SCULPT_vertex_color_get(SculptSession *ss, int index) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + if (ss->vcol) { + return ss->vcol[index].color; + } + break; + case PBVH_BMESH: + case PBVH_GRIDS: + break; + } + return NULL; +} + void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]) { switch (BKE_pbvh_type(ss->pbvh)) { @@ -180,6 +198,23 @@ void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]) } } +static const float *sculpt_vertex_persistent_co_get(SculptSession *ss, int index) +{ + if (ss->persistent_base) { + return ss->persistent_base[index].co; + } + return SCULPT_vertex_co_get(ss, index); +} + +static void sculpt_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3]) +{ + if (ss->persistent_base) { + copy_v3_v3(no, ss->persistent_base[index].no); + return; + } + SCULPT_vertex_normal_get(ss, index, no); +} + float SCULPT_vertex_mask_get(SculptSession *ss, int index) { BMVert *v; @@ -633,6 +668,13 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, } } } + + if (ss->fake_neighbors.use_fake_neighbors) { + BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL); + if (ss->fake_neighbors.fake_neighbor_index[index] != FAKE_NEIGHBOR_NONE) { + sculpt_vertex_neighbor_add(iter, ss->fake_neighbors.fake_neighbor_index[index]); + } + } } static void sculpt_vertex_neighbors_get_grids(SculptSession *ss, @@ -665,6 +707,13 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss, neighbors.coords[i].y * key->grid_size + neighbors.coords[i].x); } + if (ss->fake_neighbors.use_fake_neighbors) { + BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL); + if (ss->fake_neighbors.fake_neighbor_index[index] != FAKE_NEIGHBOR_NONE) { + sculpt_vertex_neighbor_add(iter, ss->fake_neighbors.fake_neighbor_index[index]); + } + } + if (neighbors.coords != neighbors.coords_fixed) { MEM_freeN(neighbors.coords); } @@ -821,7 +870,7 @@ int SCULPT_nearest_vertex_get( nvtd.nearest_vertex_distance_squared = FLT_MAX; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); settings.func_reduce = nearest_vertex_get_reduce; settings.userdata_chunk = &nvtd; settings.userdata_chunk_size = sizeof(NearestVertexTLSData); @@ -998,6 +1047,8 @@ static bool sculpt_tool_is_proxy_used(const char sculpt_tool) SCULPT_TOOL_LAYER, SCULPT_TOOL_POSE, SCULPT_TOOL_CLOTH, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_SMEAR, SCULPT_TOOL_DRAW_FACE_SETS); } @@ -1045,9 +1096,7 @@ typedef enum StrokeFlags { /* Initialize a SculptOrigVertData for accessing original vertex data; * handles BMesh, mesh, and multires. */ -static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data, - Object *ob, - SculptUndoNode *unode) +void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, SculptUndoNode *unode) { SculptSession *ss = ob->sculpt; BMesh *bm = ss->bm; @@ -1062,6 +1111,7 @@ static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data, data->coords = data->unode->co; data->normals = data->unode->no; data->vmasks = data->unode->mask; + data->colors = data->unode->col; } } @@ -1071,7 +1121,7 @@ void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode * { SculptUndoNode *unode; unode = SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS); - sculpt_orig_vert_data_unode_init(data, ob, unode); + SCULPT_orig_vert_data_unode_init(data, ob, unode); } /* Update a SculptOrigVertData for a particular vertex from the PBVH @@ -1087,6 +1137,9 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter orig_data->no = orig_data->normals[iter->i]; } } + else if (orig_data->unode->type == SCULPT_UNDO_COLOR) { + orig_data->col = orig_data->colors[iter->i]; + } else if (orig_data->unode->type == SCULPT_UNDO_MASK) { if (orig_data->bm_log) { orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert); @@ -1247,7 +1300,7 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, PBVHVertexIter vd; SculptOrigVertData orig_data; - sculpt_orig_vert_data_unode_init(&orig_data, data->ob, unode); + SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -1265,6 +1318,9 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, else if (orig_data.unode->type == SCULPT_UNDO_MASK) { *vd.mask = orig_data.mask; } + else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { + copy_v4_v4(vd.col, orig_data.col); + } if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -1288,7 +1344,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) /** * Disable OpenMP when dynamic-topology is enabled. Otherwise, new entries might be inserted by - * #sculpt_undo_push_node() into the GHash used internally by #BM_log_original_vert_co() + * #SCULPT_undo_push_node() into the #GHash used internally by #BM_log_original_vert_co() * by a different thread. See T33787. */ SculptThreadedTaskData data = { .sd = sd, @@ -1298,9 +1354,11 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode); + BKE_pbvh_parallel_range_settings(&settings, true && !ss->bm, totnode); BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); + BKE_pbvh_node_color_buffer_free(ss->pbvh); + MEM_SAFE_FREE(nodes); } @@ -1478,6 +1536,9 @@ bool SCULPT_brush_test_cube(SculptBrushTest *test, { float side = M_SQRT1_2; float local_co[3]; + float i_local[4][4]; + + invert_m4_m4(i_local, local); if (sculpt_brush_test_clipping(test, co)) { return false; @@ -1924,7 +1985,7 @@ static void calc_area_center( AreaNormalCenterTLSData anctd = {{{0}}}; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); @@ -1953,8 +2014,7 @@ void SCULPT_calc_area_normal( Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3]) { const Brush *brush = BKE_paint_brush(&sd->paint); - bool use_threading = (sd->flags & SCULPT_USE_OPENMP); - SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, use_threading, r_area_no); + SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, r_area_no); } /* Expose 'calc_area_normal' externally. */ @@ -2024,7 +2084,7 @@ static void calc_area_normal_and_center( AreaNormalCenterTLSData anctd = {{{0}}}; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); @@ -2116,6 +2176,11 @@ static float brush_strength(const Sculpt *sd, return alpha * pressure * overlap * feather; case SCULPT_TOOL_SLIDE_RELAX: return alpha * pressure * overlap * feather * 2.0f; + case SCULPT_TOOL_PAINT: + final_pressure = pressure * pressure; + return final_pressure * overlap * feather; + case SCULPT_TOOL_SMEAR: + return pressure * overlap * feather; case SCULPT_TOOL_CLAY_STRIPS: /* Clay Strips needs less strength to compensate the curve. */ final_pressure = powf(pressure, 1.5f); @@ -2577,11 +2642,6 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob) } } -/* Note: uses after-struct allocated mem to store actual cache... */ -typedef struct SculptDoBrushSmoothGridDataChunk { - size_t tmpgrid_size; -} SculptDoBrushSmoothGridDataChunk; - typedef struct { SculptSession *ss; const float *ray_start; @@ -2689,7 +2749,7 @@ static void bmesh_topology_rake( .strength = factor, }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); } @@ -2746,7 +2806,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); } @@ -2834,7 +2894,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); } @@ -2911,7 +2971,7 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); } @@ -3098,7 +3158,7 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); if (ss->cache->alt_smooth) { for (int i = 0; i < 4; i++) { BLI_task_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings); @@ -3308,7 +3368,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); } @@ -3422,7 +3482,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); } @@ -3495,7 +3555,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); } @@ -3604,7 +3664,7 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); } @@ -3811,7 +3871,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); } @@ -3933,7 +3993,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); } @@ -4006,7 +4066,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); } @@ -4080,7 +4140,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); } @@ -4093,7 +4153,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, Sculpt *sd = data->sd; const Brush *brush = data->brush; - const bool use_persistent_base = ss->layer_base && brush->flag & BRUSH_PERSISTENT; + const bool use_persistent_base = ss->persistent_base && brush->flag & BRUSH_PERSISTENT; PBVHVertexIter vd; SculptOrigVertData orig_data; @@ -4123,7 +4183,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, const int vi = vd.index; float *disp_factor; if (use_persistent_base) { - disp_factor = &ss->layer_base[vi].disp; + disp_factor = &ss->persistent_base[vi].disp; } else { disp_factor = &ss->cache->layer_displacement_factor[vi]; @@ -4153,9 +4213,9 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, float normal[3]; if (use_persistent_base) { - copy_v3_v3(normal, ss->layer_base[vi].no); + sculpt_vertex_persistent_normal_get(ss, vi, normal); mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, ss->layer_base[vi].co, normal, *disp_factor); + madd_v3_v3v3fl(final_co, sculpt_vertex_persistent_co_get(ss, vi), normal, *disp_factor); } else { normal_short_to_float_v3(normal, orig_data.no); @@ -4196,7 +4256,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); } @@ -4263,7 +4323,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); } @@ -4388,7 +4448,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); } @@ -4539,7 +4599,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) ClaySampleData csd = {{0}}; TaskParallelSettings sample_settings; - BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&sample_settings, true, totnode); sample_settings.func_reduce = calc_clay_surface_reduce; sample_settings.userdata_chunk = &csd; sample_settings.userdata_chunk_size = sizeof(ClaySampleData); @@ -4570,7 +4630,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); } @@ -4677,6 +4737,17 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t mul_v3_fl(temp, displace); add_v3_v3(area_co, temp); + /* Clay Strips uses a cube test with falloff in the XY axis (not in Z) and a plane to deform the + * vertices. When in Add mode, vertices that are below the plane and inside the cube are move + * towards the plane. In this situation, there may be cases where a vertex is outside the cube + * but below the plane, so won't be deformed, causing artifacts. In order to prevent these + * artifacts, this displaces the test cube space in relation to the plane in order to + * deform more vertices that may be below it. */ + /* The 0.7 and 1.25 factors are arbitrary and don't have any relation between them, they were set + * by doing multiple tests using the default "Clay Strips" brush preset. */ + float area_co_displaced[3]; + madd_v3_v3v3fl(area_co_displaced, area_co, area_no, -radius * 0.7f); + /* Init brush local space matrix. */ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry); mat[0][3] = 0.0f; @@ -4684,13 +4755,19 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t mat[1][3] = 0.0f; copy_v3_v3(mat[2], area_no); mat[2][3] = 0.0f; - copy_v3_v3(mat[3], ss->cache->location); + copy_v3_v3(mat[3], area_co_displaced); mat[3][3] = 1.0f; normalize_m4(mat); /* Scale brush local space matrix. */ scale_m4_fl(scale, ss->cache->radius); mul_m4_m4m4(tmat, mat, scale); + + /* Deform the local space in Z to scale the test cube. As the test cube does not have falloff in + * Z this does not produce artifacts in the falloff cube and allows to deform extra vertices + * during big deformation while keeping the surface as uniform as possible. */ + mul_v3_fl(tmat[2], 1.25f); + invert_m4_m4(mat, tmat); SculptThreadedTaskData data = { @@ -4704,7 +4781,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); } @@ -4798,7 +4875,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); } @@ -4891,7 +4968,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); } @@ -5064,7 +5141,7 @@ static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings); } @@ -5136,7 +5213,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); } @@ -5255,23 +5332,23 @@ static void do_brush_action_task_cb(void *__restrict userdata, /* Face Sets modifications do a single undo push */ if (data->brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) { + BKE_pbvh_node_mark_redraw(data->nodes[n]); /* Draw face sets in smooth mode moves the vertices. */ if (ss->cache->alt_smooth) { SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); BKE_pbvh_node_mark_update(data->nodes[n]); } } - else { - SCULPT_undo_push_node(data->ob, - data->nodes[n], - data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : - SCULPT_UNDO_COORDS); - } - - if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) { + else if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) { + SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_MASK); BKE_pbvh_node_mark_update_mask(data->nodes[n]); } + else if (ELEM(data->brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) { + SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR); + BKE_pbvh_node_mark_update_color(data->nodes[n]); + } else { + SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS); BKE_pbvh_node_mark_update(data->nodes[n]); } } @@ -5282,7 +5359,17 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe int totnode; PBVHNode **nodes; - /* Build a list of all nodes that are potentially within the brush's area of influence. */ + /* Check for unsupported features. */ + PBVHType type = BKE_pbvh_type(ss->pbvh); + if (brush->sculpt_tool == SCULPT_TOOL_PAINT && type != PBVH_FACES) { + return; + } + + if (brush->sculpt_tool == SCULPT_TOOL_SMEAR && type != PBVH_FACES) { + return; + } + + /* Build a list of all nodes that are potentially within the brush's area of influence */ /* These brushes need to update all nodes as they are not constrained by the brush radius */ /* Elastic deform needs all nodes to avoid artifacts as the effect of the brush is not @@ -5322,7 +5409,14 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe * and the number of nodes under the brush influence. */ if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0 && !ss->cache->alt_smooth) { - SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_FACE_SETS); + + /* Dyntopo does not support Face Sets data, so it can't store/restore it from undo. */ + /* TODO (pablodp606): This check should be done in the undo code and not here, but the rest of + * the sculpt code is not checking for unsupported undo types that may return a null node. */ + if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) { + SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_FACE_SETS); + } + if (ss->cache->invert) { /* When inverting the brush, pick the paint face mask ID from the mesh. */ ss->cache->paint_face_set = SCULPT_active_face_set_get(ss); @@ -5345,7 +5439,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); if (sculpt_brush_needs_normal(ss, brush)) { @@ -5464,6 +5558,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe case SCULPT_TOOL_DRAW_FACE_SETS: SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); break; + case SCULPT_TOOL_PAINT: + SCULPT_do_paint_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMEAR: + SCULPT_do_smear_brush(sd, ob, nodes, totnode); + break; } if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && @@ -5602,7 +5702,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); } @@ -5690,7 +5790,7 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings); if (vertCos) { @@ -5991,6 +6091,10 @@ static const char *sculpt_tool_name(Sculpt *sd) return "Cloth Brush"; case SCULPT_TOOL_DRAW_FACE_SETS: return "Draw Face Sets"; + case SCULPT_TOOL_PAINT: + return "Paint Brush"; + case SCULPT_TOOL_SMEAR: + return "Smear Brush"; } return "Sculpting"; @@ -6005,6 +6109,7 @@ void SCULPT_cache_free(StrokeCache *cache) MEM_SAFE_FREE(cache->dial); MEM_SAFE_FREE(cache->surface_smooth_laplacian_disp); MEM_SAFE_FREE(cache->layer_displacement_factor); + MEM_SAFE_FREE(cache->prev_colors); if (cache->pose_ik_chain) { SCULPT_pose_ik_chain_free(cache->pose_ik_chain); @@ -6119,7 +6224,11 @@ static void sculpt_update_cache_invariants( cache->saved_mask_brush_tool = brush->mask_tool; brush->mask_tool = BRUSH_MASK_SMOOTH; } - else if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SLIDE_RELAX, SCULPT_TOOL_DRAW_FACE_SETS)) { + else if (ELEM(brush->sculpt_tool, + SCULPT_TOOL_SLIDE_RELAX, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_SMEAR)) { /* Do nothing, this tool has its own smooth mode. */ } else { @@ -6266,6 +6375,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru int tool = brush->sculpt_tool; if (ELEM(tool, + SCULPT_TOOL_PAINT, SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM, SCULPT_TOOL_CLOTH, @@ -6519,7 +6629,7 @@ static bool sculpt_needs_connectivity_info(const Sculpt *sd, ((brush->sculpt_tool == SCULPT_TOOL_MASK) && (brush->mask_tool == BRUSH_MASK_SMOOTH)) || (brush->sculpt_tool == SCULPT_TOOL_POSE) || (brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) || - (brush->sculpt_tool == SCULPT_TOOL_CLOTH) || + (brush->sculpt_tool == SCULPT_TOOL_CLOTH) || (brush->sculpt_tool == SCULPT_TOOL_SMEAR) || (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS)); } @@ -6533,7 +6643,7 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *b if (ss->shapekey_active || ss->deform_modifiers_active || (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, false, false); } } @@ -6877,7 +6987,7 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) SculptSession *ss = CTX_data_active_object(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); int mode = RNA_enum_get(op->ptr, "mode"); - bool is_smooth; + bool is_smooth, needs_colors; bool need_mask = false; if (brush->sculpt_tool == SCULPT_TOOL_MASK) { @@ -6892,7 +7002,8 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) sculpt_brush_init_tex(scene, sd, ss); is_smooth = sculpt_needs_connectivity_info(sd, brush, ss, mode); - BKE_sculpt_update_object_for_edit(depsgraph, ob, is_smooth, need_mask); + needs_colors = ELEM(brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR); + BKE_sculpt_update_object_for_edit(depsgraph, ob, is_smooth, need_mask, needs_colors); } static void sculpt_restore_mesh(Sculpt *sd, Object *ob) @@ -7035,12 +7146,19 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up if (update_flags & SCULPT_UPDATE_COORDS) { BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateOriginalBB); + + /* Coordinates were modified, so fake neighbors are not longer valid. */ + SCULPT_fake_neighbors_free(ob); } if (update_flags & SCULPT_UPDATE_MASK) { BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask); } + if (update_flags & SCULPT_UPDATE_COLOR) { + BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateColor); + } + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { BKE_pbvh_bmesh_after_stroke(ss->pbvh); } @@ -7155,6 +7273,9 @@ static void sculpt_stroke_update_step(bContext *C, if (brush->sculpt_tool == SCULPT_TOOL_MASK) { SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK); } + else if (ELEM(brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) { + SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR); + } else { SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS); } @@ -7192,7 +7313,11 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str if (brush->sculpt_tool == SCULPT_TOOL_MASK) { brush->mask_tool = ss->cache->saved_mask_brush_tool; } - else if (ELEM(brush->sculpt_tool, SCULPT_TOOL_SLIDE_RELAX, SCULPT_TOOL_DRAW_FACE_SETS)) { + else if (ELEM(brush->sculpt_tool, + SCULPT_TOOL_SLIDE_RELAX, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_SMEAR)) { /* Do nothing. */ } else { @@ -7208,6 +7333,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str SCULPT_automasking_end(ob); } + BKE_pbvh_node_color_buffer_free(ss->pbvh); SCULPT_cache_free(ss->cache); ss->cache = NULL; @@ -7346,18 +7472,18 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op)) if (ss) { SCULPT_vertex_random_access_init(ss); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); - MEM_SAFE_FREE(ss->layer_base); + MEM_SAFE_FREE(ss->persistent_base); const int totvert = SCULPT_vertex_count_get(ss); - ss->layer_base = MEM_mallocN(sizeof(SculptLayerPersistentBase) * totvert, - "layer persistent base"); + ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, + "layer persistent base"); for (int i = 0; i < totvert; i++) { - copy_v3_v3(ss->layer_base[i].co, SCULPT_vertex_co_get(ss, i)); - SCULPT_vertex_normal_get(ss, i, ss->layer_base[i].no); - ss->layer_base[i].disp = 0.0f; + copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); + SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); + ss->persistent_base[i].disp = 0.0f; } } @@ -7548,7 +7674,7 @@ static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob) ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = OB_MODE_SCULPT; - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); /* Here we can detect geometry that was just added to Sculpt Mode as it has the * SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */ @@ -7834,7 +7960,7 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float return; } - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); if (!ss->pmap) { return; @@ -7886,6 +8012,417 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float ss->preview_vert_index_count = totpoints; } +static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_active_object(C); + + ID *data; + data = ob->data; + if (data && ID_IS_LINKED(data)) { + return OPERATOR_CANCELLED; + } + + if (ob->type != OB_MESH) { + return OPERATOR_CANCELLED; + } + + Mesh *mesh = ob->data; + + const int mloopcol_layer_n = CustomData_get_active_layer(&mesh->ldata, CD_MLOOPCOL); + if (mloopcol_layer_n == -1) { + return OPERATOR_CANCELLED; + } + MLoopCol *loopcols = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPCOL, mloopcol_layer_n); + + const int MPropCol_layer_n = CustomData_get_active_layer(&mesh->vdata, CD_PROP_COLOR); + if (MPropCol_layer_n == -1) { + return OPERATOR_CANCELLED; + } + MPropCol *vertcols = CustomData_get_layer_n(&mesh->vdata, CD_PROP_COLOR, MPropCol_layer_n); + + MLoop *loops = CustomData_get_layer(&mesh->ldata, CD_MLOOP); + MPoly *polys = CustomData_get_layer(&mesh->pdata, CD_MPOLY); + + for (int i = 0; i < mesh->totpoly; i++) { + MPoly *c_poly = &polys[i]; + for (int j = 0; j < c_poly->totloop; j++) { + int loop_index = c_poly->loopstart + j; + MLoop *c_loop = &loops[c_poly->loopstart + j]; + loopcols[loop_index].r = (char)(vertcols[c_loop->v].color[0] * 255); + loopcols[loop_index].g = (char)(vertcols[c_loop->v].color[1] * 255); + loopcols[loop_index].b = (char)(vertcols[c_loop->v].color[2] * 255); + loopcols[loop_index].a = (char)(vertcols[c_loop->v].color[3] * 255); + } + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + return OPERATOR_FINISHED; +} + +static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Sculpt Vertex Color to Vertex Color"; + ot->description = "Copy the Sculpt Vertex Color to a regular color layer"; + ot->idname = "SCULPT_OT_vertex_to_loop_colors"; + + /* api callbacks */ + ot->poll = SCULPT_mode_poll; + ot->exec = vertex_to_loop_colors_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int loop_to_vertex_colors_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_active_object(C); + + ID *data; + data = ob->data; + if (data && ID_IS_LINKED(data)) { + return OPERATOR_CANCELLED; + } + + if (ob->type != OB_MESH) { + return OPERATOR_CANCELLED; + } + + Mesh *mesh = ob->data; + + const int mloopcol_layer_n = CustomData_get_active_layer(&mesh->ldata, CD_MLOOPCOL); + if (mloopcol_layer_n == -1) { + return OPERATOR_CANCELLED; + } + MLoopCol *loopcols = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPCOL, mloopcol_layer_n); + + const int MPropCol_layer_n = CustomData_get_active_layer(&mesh->vdata, CD_PROP_COLOR); + if (MPropCol_layer_n == -1) { + return OPERATOR_CANCELLED; + } + MPropCol *vertcols = CustomData_get_layer_n(&mesh->vdata, CD_PROP_COLOR, MPropCol_layer_n); + + MLoop *loops = CustomData_get_layer(&mesh->ldata, CD_MLOOP); + MPoly *polys = CustomData_get_layer(&mesh->pdata, CD_MPOLY); + + for (int i = 0; i < mesh->totpoly; i++) { + MPoly *c_poly = &polys[i]; + for (int j = 0; j < c_poly->totloop; j++) { + int loop_index = c_poly->loopstart + j; + MLoop *c_loop = &loops[c_poly->loopstart + j]; + vertcols[c_loop->v].color[0] = (loopcols[loop_index].r / 255.0f); + vertcols[c_loop->v].color[1] = (loopcols[loop_index].g / 255.0f); + vertcols[c_loop->v].color[2] = (loopcols[loop_index].b / 255.0f); + vertcols[c_loop->v].color[3] = (loopcols[loop_index].a / 255.0f); + } + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + return OPERATOR_FINISHED; +} + +static void SCULPT_OT_loop_to_vertex_colors(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Vertex Color to Sculpt Vertex Color"; + ot->description = "Copy the active loop color layer to the vertex color"; + ot->idname = "SCULPT_OT_loop_to_vertex_colors"; + + /* api callbacks */ + ot->poll = SCULPT_mode_poll; + ot->exec = loop_to_vertex_colors_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int sculpt_sample_color_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(e)) +{ + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + int active_vertex = SCULPT_active_vertex_get(ss); + const float *active_vertex_color = SCULPT_vertex_color_get(ss, active_vertex); + if (!active_vertex_color) { + return OPERATOR_CANCELLED; + } + + float color_srgb[3]; + copy_v3_v3(color_srgb, active_vertex_color); + IMB_colormanagement_scene_linear_to_srgb_v3(color_srgb); + BKE_brush_color_set(scene, brush, color_srgb); + BKE_brush_alpha_set(scene, brush, active_vertex_color[3]); + + WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush); + + return OPERATOR_FINISHED; +} + +static void SCULPT_OT_sample_color(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Sample color"; + ot->idname = "SCULPT_OT_sample_color"; + ot->description = "Sample the vertex color of the active vertex"; + + /* api callbacks */ + ot->invoke = sculpt_sample_color_invoke; + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER; +} + +/* Fake Neighbors. */ +/* This allows the sculpt tools to work on meshes with multiple connected components as they had + * only one connected component. When initialized and enabled, the sculpt API will return extra + * connectivity neighbors that are not in the real mesh. These neighbors are calculated for each + * vertex using the minimun distance to a vertex that is in a different connected component. */ + +/* The fake neighbors first need to be ensured to be initialized. + * After that tools which needs fake neighbors functionality need to + * temporarily enable it: + * + * void my_awesome_sculpt_tool() { + * SCULPT_fake_neighbors_ensure(sd, object, brush->disconnected_distance_max); + * SCULPT_fake_neighbors_enable(ob); + * + * ... Logic of the tool ... + * SCULPT_fake_neighbors_disable(ob); + * } + * + * Such approach allows to keep all the connectivity information ready for reuse + * (withouy having lag prior to every stroke), but also makes it so the affect + * is localized to a specific brushes and tools only. */ + +enum { + SCULPT_TOPOLOGY_ID_NONE, + SCULPT_TOPOLOGY_ID_DEFAULT, +}; + +static int SCULPT_vertex_get_connected_component(SculptSession *ss, int index) +{ + if (ss->vertex_info.connected_component) { + return ss->vertex_info.connected_component[index]; + } + return SCULPT_TOPOLOGY_ID_DEFAULT; +} + +static void SCULPT_fake_neighbor_init(SculptSession *ss, const float max_dist) +{ + const int totvert = SCULPT_vertex_count_get(ss); + ss->fake_neighbors.fake_neighbor_index = MEM_malloc_arrayN( + totvert, sizeof(int), "fake neighbor"); + for (int i = 0; i < totvert; i++) { + ss->fake_neighbors.fake_neighbor_index[i] = FAKE_NEIGHBOR_NONE; + } + + ss->fake_neighbors.current_max_distance = max_dist; +} + +static void SCULPT_fake_neighbor_add(SculptSession *ss, int v_index_a, int v_index_b) +{ + if (ss->fake_neighbors.fake_neighbor_index[v_index_a] == FAKE_NEIGHBOR_NONE) { + ss->fake_neighbors.fake_neighbor_index[v_index_a] = v_index_b; + ss->fake_neighbors.fake_neighbor_index[v_index_b] = v_index_a; + } +} + +static void sculpt_pose_fake_neighbors_free(SculptSession *ss) +{ + MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index); +} + +typedef struct NearestVertexFakeNeighborTLSData { + int nearest_vertex_index; + float nearest_vertex_distance_squared; + int current_topology_id; +} NearestVertexFakeNeighborTLSData; + +static void do_fake_neighbor_search_task_cb(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + NearestVertexFakeNeighborTLSData *nvtd = tls->userdata_chunk; + PBVHVertexIter vd; + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + int vd_topology_id = SCULPT_vertex_get_connected_component(ss, vd.index); + if (vd_topology_id != nvtd->current_topology_id && + ss->fake_neighbors.fake_neighbor_index[vd.index] == FAKE_NEIGHBOR_NONE) { + float distance_squared = len_squared_v3v3(vd.co, data->nearest_vertex_search_co); + if (distance_squared < nvtd->nearest_vertex_distance_squared && + distance_squared < data->max_distance_squared) { + nvtd->nearest_vertex_index = vd.index; + nvtd->nearest_vertex_distance_squared = distance_squared; + } + } + } + BKE_pbvh_vertex_iter_end; +} + +static void fake_neighbor_search_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) +{ + NearestVertexFakeNeighborTLSData *join = chunk_join; + NearestVertexFakeNeighborTLSData *nvtd = chunk; + if (join->nearest_vertex_index == -1) { + join->nearest_vertex_index = nvtd->nearest_vertex_index; + join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; + } + else if (nvtd->nearest_vertex_distance_squared < join->nearest_vertex_distance_squared) { + join->nearest_vertex_index = nvtd->nearest_vertex_index; + join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared; + } +} + +static int SCULPT_fake_neighbor_search(Sculpt *sd, Object *ob, const int index, float max_distance) +{ + SculptSession *ss = ob->sculpt; + PBVHNode **nodes = NULL; + int totnode; + SculptSearchSphereData data = { + .ss = ss, + .sd = sd, + .radius_squared = max_distance * max_distance, + .original = false, + .center = SCULPT_vertex_co_get(ss, index), + }; + BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode); + + if (totnode == 0) { + return -1; + } + + SculptThreadedTaskData task_data = { + .sd = sd, + .ob = ob, + .nodes = nodes, + .max_distance_squared = max_distance * max_distance, + }; + + copy_v3_v3(task_data.nearest_vertex_search_co, SCULPT_vertex_co_get(ss, index)); + + NearestVertexFakeNeighborTLSData nvtd; + nvtd.nearest_vertex_index = -1; + nvtd.nearest_vertex_distance_squared = FLT_MAX; + nvtd.current_topology_id = SCULPT_vertex_get_connected_component(ss, index); + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + settings.func_reduce = fake_neighbor_search_reduce; + settings.userdata_chunk = &nvtd; + settings.userdata_chunk_size = sizeof(NearestVertexFakeNeighborTLSData); + BLI_task_parallel_range(0, totnode, &task_data, do_fake_neighbor_search_task_cb, &settings); + + MEM_SAFE_FREE(nodes); + + return nvtd.nearest_vertex_index; +} + +typedef struct SculptTopologyIDFloodFillData { + int next_id; +} SculptTopologyIDFloodFillData; + +static bool SCULPT_connected_components_floodfill_cb( + SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata) +{ + SculptTopologyIDFloodFillData *data = userdata; + ss->vertex_info.connected_component[from_v] = data->next_id; + ss->vertex_info.connected_component[to_v] = data->next_id; + return true; +} + +static void sculpt_connected_components_ensure(Object *ob) +{ + SculptSession *ss = ob->sculpt; + + /* Topology IDs already initialized. They only need to be recalculated when the PBVH is rebuild. + */ + if (ss->vertex_info.connected_component) { + return; + } + + const int totvert = SCULPT_vertex_count_get(ss); + ss->vertex_info.connected_component = MEM_malloc_arrayN(totvert, sizeof(int), "topology ID"); + + for (int i = 0; i < totvert; i++) { + ss->vertex_info.connected_component[i] = SCULPT_TOPOLOGY_ID_NONE; + } + + int next_id = 0; + for (int i = 0; i < totvert; i++) { + if (ss->vertex_info.connected_component[i] == SCULPT_TOPOLOGY_ID_NONE) { + SculptFloodFill flood; + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_initial(&flood, i); + SculptTopologyIDFloodFillData data; + data.next_id = next_id; + SCULPT_floodfill_execute(ss, &flood, SCULPT_connected_components_floodfill_cb, &data); + SCULPT_floodfill_free(&flood); + next_id++; + } + } +} + +void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist) +{ + SculptSession *ss = ob->sculpt; + const int totvert = SCULPT_vertex_count_get(ss); + + /* Fake neighbors were already initialized with the same distance, so no need to be recalculated. + */ + if (ss->fake_neighbors.fake_neighbor_index && + ss->fake_neighbors.current_max_distance == max_dist) { + return; + } + + sculpt_connected_components_ensure(ob); + SCULPT_fake_neighbor_init(ss, max_dist); + + for (int i = 0; i < totvert; i++) { + const int from_v = i; + + /* This vertex does not have a fake neighbor yet, seach one for it. */ + if (ss->fake_neighbors.fake_neighbor_index[from_v] == FAKE_NEIGHBOR_NONE) { + const int to_v = SCULPT_fake_neighbor_search(sd, ob, from_v, max_dist); + if (to_v != -1) { + /* Add the fake neighbor if available. */ + SCULPT_fake_neighbor_add(ss, from_v, to_v); + } + } + } +} + +void SCULPT_fake_neighbors_enable(Object *ob) +{ + SculptSession *ss = ob->sculpt; + BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL); + ss->fake_neighbors.use_fake_neighbors = true; +} + +void SCULPT_fake_neighbors_disable(Object *ob) +{ + SculptSession *ss = ob->sculpt; + BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL); + ss->fake_neighbors.use_fake_neighbors = false; +} + +void SCULPT_fake_neighbors_free(Object *ob) +{ + SculptSession *ss = ob->sculpt; + sculpt_pose_fake_neighbors_free(ss); +} + void ED_operatortypes_sculpt(void) { WM_operatortype_append(SCULPT_OT_brush_stroke); @@ -7908,4 +8445,8 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_face_sets_init); WM_operatortype_append(SCULPT_OT_cloth_filter); WM_operatortype_append(SCULPT_OT_face_sets_edit); + WM_operatortype_append(SCULPT_OT_sample_color); + WM_operatortype_append(SCULPT_OT_loop_to_vertex_colors); + WM_operatortype_append(SCULPT_OT_vertex_to_loop_colors); + WM_operatortype_append(SCULPT_OT_color_filter); } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 7776af11a77..c821685e8b1 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -25,7 +25,7 @@ #include "BLI_blenlib.h" #include "BLI_dial_2d.h" -#include "BLI_ghash.h" +#include "BLI_edgehash.h" #include "BLI_gsqueue.h" #include "BLI_hash.h" #include "BLI_math.h" @@ -106,25 +106,11 @@ #define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024 #define CLOTH_SIMULATION_TIME_STEP 0.01f -static void cloth_brush_constraint_key_get(int r_key[2], const int v1, const int v2) -{ - if (v1 < v2) { - r_key[0] = v1; - r_key[1] = v2; - } - else { - r_key[0] = v2; - r_key[1] = v1; - } -} - static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_sim, const int v1, const int v2) { - int constraint[2]; - cloth_brush_constraint_key_get(constraint, v1, v2); - return BLI_gset_haskey(cloth_sim->created_length_constraints, constraint); + return BLI_edgeset_haskey(cloth_sim->created_length_constraints, v1, v2); } static void cloth_brush_add_length_constraint(SculptSession *ss, @@ -149,9 +135,7 @@ static void cloth_brush_add_length_constraint(SculptSession *ss, } /* Add the constraint to the GSet to avoid creating it again. */ - int constraint[2]; - cloth_brush_constraint_key_get(constraint, v1, v2); - BLI_gset_add(cloth_sim->created_length_constraints, constraint); + BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2); } static void do_cloth_brush_build_constraints_task_cb_ex( @@ -472,8 +456,7 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, false, totnode); - cloth_sim->created_length_constraints = BLI_gset_new( - BLI_ghashutil_inthash_v2_p, BLI_ghashutil_inthash_v2_cmp, "created length constraints"); + cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints"); SculptThreadedTaskData build_constraints_data = { .sd = sd, @@ -487,7 +470,7 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, BLI_task_parallel_range( 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings); - BLI_gset_free(cloth_sim->created_length_constraints, NULL); + BLI_edgeset_free(cloth_sim->created_length_constraints); } static void cloth_brush_satisfy_constraints(SculptSession *ss, @@ -564,7 +547,7 @@ static void cloth_brush_do_simulation_step( }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range( 0, totnode, &solve_simulation_data, do_cloth_brush_solve_simulation_task_cb_ex, &settings); } @@ -639,7 +622,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod } TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range( 0, totnode, &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings); } @@ -873,7 +856,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent SCULPT_vertex_random_access_init(ss); - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); const int totverts = SCULPT_vertex_count_get(ss); for (int i = 0; i < totverts; i++) { @@ -889,8 +872,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings( - &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings); @@ -922,10 +904,10 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_vertex_random_access_init(ss); /* Needs mask data to be available as it is used when solving the constraints. */ - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); SCULPT_undo_push_begin("Cloth filter"); - SCULPT_filter_cache_init(ob, sd); + SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS); const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass"); const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping"); diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index f071deaa219..463233fd6fb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -181,7 +181,7 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my) /* Update the active vertex. */ float mouse[2] = {mx, my}; SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); /* Average the edge length of the connected edges to the active vertex. */ int active_vertex = SCULPT_active_vertex_get(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 7bb54366204..031b4f8731d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -203,7 +203,7 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); if (ss->cache->alt_smooth) { for (int i = 0; i < 4; i++) { BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); @@ -269,7 +269,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED, false); const int tot_vert = SCULPT_vertex_count_get(ss); float threshold = 0.5f; @@ -630,7 +630,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; @@ -787,7 +787,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); const int tot_vert = SCULPT_vertex_count_get(ss); const int mode = RNA_enum_get(op->ptr, "mode"); @@ -1083,7 +1083,7 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven return OPERATOR_CANCELLED; } - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c new file mode 100644 index 00000000000..5f7805af347 --- /dev/null +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -0,0 +1,323 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edsculpt + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_hash.h" +#include "BLI_math.h" +#include "BLI_math_color_blend.h" +#include "BLI_task.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_brush.h" +#include "BKE_colortools.h" +#include "BKE_context.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_pbvh.h" +#include "BKE_scene.h" + +#include "IMB_colormanagement.h" + +#include "DEG_depsgraph.h" + +#include "WM_api.h" +#include "WM_message.h" +#include "WM_toolsystem.h" +#include "WM_types.h" + +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_sculpt.h" +#include "paint_intern.h" +#include "sculpt_intern.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_interface.h" + +#include "bmesh.h" + +#include <math.h> +#include <stdlib.h> + +typedef enum eSculptColorFilterTypes { + COLOR_FILTER_FILL, + COLOR_FILTER_HUE, + COLOR_FILTER_SATURATION, + COLOR_FILTER_VALUE, + COLOR_FILTER_BRIGHTNESS, + COLOR_FILTER_CONTRAST, + COLOR_FILTER_RED, + COLOR_FILTER_GREEN, + COLOR_FILTER_BLUE, + COLOR_FILTER_SMOOTH, +} eSculptColorFilterTypes; + +EnumPropertyItem prop_color_filter_types[] = { + {COLOR_FILTER_FILL, "FILL", 0, "Fill", "Fill with a specific color"}, + {COLOR_FILTER_HUE, "HUE", 0, "Hue", "Change hue"}, + {COLOR_FILTER_SATURATION, "SATURATION", 0, "Saturation", "Change saturation"}, + {COLOR_FILTER_VALUE, "VALUE", 0, "Value", "Change value"}, + + {COLOR_FILTER_BRIGHTNESS, "BRIGTHNESS", 0, "Brightness", "Change brightness"}, + {COLOR_FILTER_CONTRAST, "CONTRAST", 0, "Contrast", "Change contrast"}, + + {COLOR_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth colors"}, + + {COLOR_FILTER_RED, "RED", 0, "Red", "Change red channel"}, + {COLOR_FILTER_GREEN, "GREEN", 0, "Green", "Change green channel"}, + {COLOR_FILTER_BLUE, "BLUE", 0, "Blue", "Change blue channel"}, + {0, NULL, 0, NULL, NULL}, +}; + +static void color_filter_task_cb(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + + const int mode = data->filter_type; + + SculptOrigVertData orig_data; + SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); + + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SCULPT_orig_vert_data_update(&orig_data, &vd); + float orig_color[3], final_color[4], hsv_color[3]; + int hue; + float brightness, contrast, gain, delta, offset; + float fade = vd.mask ? *vd.mask : 0.0f; + fade = 1.0f - fade; + fade *= data->filter_strength; + + copy_v3_v3(orig_color, orig_data.col); + + switch (mode) { + case COLOR_FILTER_FILL: { + float fill_color_rgba[4]; + copy_v3_v3(fill_color_rgba, data->filter_fill_color); + fill_color_rgba[3] = 1.0f; + CLAMP(fade, 0.0f, 1.0f); + mul_v4_fl(fill_color_rgba, fade); + blend_color_mix_float(final_color, orig_data.col, fill_color_rgba); + break; + } + case COLOR_FILTER_HUE: + rgb_to_hsv_v(orig_color, hsv_color); + hue = hsv_color[0] + fade; + hsv_color[0] = fabs((hsv_color[0] + fade) - hue); + hsv_to_rgb_v(hsv_color, final_color); + break; + case COLOR_FILTER_SATURATION: + rgb_to_hsv_v(orig_color, hsv_color); + hsv_color[1] = hsv_color[1] + fade; + CLAMP(hsv_color[1], 0.0f, 1.0f); + hsv_to_rgb_v(hsv_color, final_color); + break; + case COLOR_FILTER_VALUE: + rgb_to_hsv_v(orig_color, hsv_color); + hsv_color[2] = hsv_color[2] + fade; + CLAMP(hsv_color[2], 0.0f, 1.0f); + hsv_to_rgb_v(hsv_color, final_color); + break; + case COLOR_FILTER_RED: + orig_color[0] = orig_color[0] + fade; + CLAMP(orig_color[0], 0.0f, 1.0f); + copy_v3_v3(final_color, orig_color); + break; + case COLOR_FILTER_GREEN: + orig_color[1] = orig_color[1] + fade; + CLAMP(orig_color[1], 0.0f, 1.0f); + copy_v3_v3(final_color, orig_color); + break; + case COLOR_FILTER_BLUE: + orig_color[2] = orig_color[2] + fade; + CLAMP(orig_color[2], 0.0f, 1.0f); + copy_v3_v3(final_color, orig_color); + break; + case COLOR_FILTER_BRIGHTNESS: + CLAMP(fade, -1.0f, 1.0f); + brightness = fade; + contrast = 0; + delta = contrast / 2.0f; + gain = 1.0f - delta * 2.0f; + delta *= -1; + offset = gain * (brightness + delta); + for (int i = 0; i < 3; i++) { + final_color[i] = gain * orig_color[i] + offset; + CLAMP(final_color[i], 0.0f, 1.0f); + } + break; + case COLOR_FILTER_CONTRAST: + CLAMP(fade, -1.0f, 1.0f); + brightness = 0; + contrast = fade; + delta = contrast / 2.0f; + gain = 1.0f - delta * 2.0f; + if (contrast > 0) { + gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON); + offset = gain * (brightness - delta); + } + else { + delta *= -1; + offset = gain * (brightness + delta); + } + for (int i = 0; i < 3; i++) { + final_color[i] = gain * orig_color[i] + offset; + CLAMP(final_color[i], 0.0f, 1.0f); + } + break; + case COLOR_FILTER_SMOOTH: { + CLAMP(fade, -1.0f, 1.0f); + float smooth_color[4]; + SCULPT_neighbor_color_average(ss, smooth_color, vd.index); + blend_color_interpolate_float(final_color, vd.col, smooth_color, fade); + break; + } + } + + copy_v3_v3(vd.col, final_color); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + BKE_pbvh_vertex_iter_end; + BKE_pbvh_node_mark_update_color(data->nodes[n]); +} + +static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + const int mode = RNA_enum_get(op->ptr, "type"); + float filter_strength = RNA_float_get(op->ptr, "strength"); + + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + SCULPT_undo_push_end(); + SCULPT_filter_cache_free(ss); + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR); + return OPERATOR_FINISHED; + } + + if (event->type != MOUSEMOVE) { + return OPERATOR_RUNNING_MODAL; + } + + float len = event->prevclickx - event->mval[0]; + filter_strength = filter_strength * -len * 0.001f; + + float fill_color[3]; + RNA_float_get_array(op->ptr, "fill_color", fill_color); + IMB_colormanagement_srgb_to_scene_linear_v3(fill_color); + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .nodes = ss->filter_cache->nodes, + .filter_type = mode, + .filter_strength = filter_strength, + .filter_fill_color = fill_color, + }; + + TaskParallelSettings settings; + BLI_parallel_range_settings_defaults(&settings); + + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, color_filter_task_cb, &settings); + + SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR); + + return OPERATOR_RUNNING_MODAL; +} + +static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + Object *ob = CTX_data_active_object(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + SculptSession *ss = ob->sculpt; + int mode = RNA_enum_get(op->ptr, "type"); + PBVH *pbvh = ob->sculpt->pbvh; + + /* Disable for multires and dyntopo for now */ + if (!ss->pbvh) { + return OPERATOR_CANCELLED; + } + if (BKE_pbvh_type(pbvh) != PBVH_FACES) { + return OPERATOR_CANCELLED; + } + + if (!ss->vcol) { + return OPERATOR_CANCELLED; + } + + SCULPT_undo_push_begin("color filter"); + + bool needs_pmap = mode == COLOR_FILTER_SMOOTH; + BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, true); + + if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) { + return OPERATOR_CANCELLED; + } + + SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COLOR); + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; +} + +void SCULPT_OT_color_filter(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Filter color"; + ot->idname = "SCULPT_OT_color_filter"; + ot->description = "Applies a filter to modify the current sculpt vertex colors"; + + /* api callbacks */ + ot->invoke = sculpt_color_filter_invoke; + ot->modal = sculpt_color_filter_modal; + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* rna */ + RNA_def_enum(ot->srna, "type", prop_color_filter_types, COLOR_FILTER_HUE, "Filter type", ""); + RNA_def_float( + ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f); + + PropertyRNA *prop = RNA_def_float_color( + ot->srna, "fill_color", 3, NULL, 0.0f, FLT_MAX, "Fill Color", "fill color", 0.0f, 1.0f); + RNA_def_property_subtype(prop, PROP_COLOR_GAMMA); +} diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index d2a683461a7..83145f5600f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -202,7 +202,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) int totnode; int filter_type = RNA_enum_get(op->ptr, "filter_type"); - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); SCULPT_vertex_random_access_init(ss); @@ -247,7 +247,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) { @@ -276,7 +276,7 @@ void SCULPT_mask_filter_smooth_apply( for (int i = 0; i < smooth_iterations; i++) { TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); } } @@ -432,7 +432,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) Sculpt *sd = CTX_data_tool_settings(C)->sculpt; int totnode; - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); SCULPT_vertex_random_access_init(ss); @@ -459,7 +459,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); settings.func_reduce = dirty_mask_compute_range_reduce; settings.userdata_chunk = ⦥ diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index fd0f67f040a..494588d0996 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -70,10 +70,10 @@ static void filter_cache_init_task_cb(void *__restrict userdata, SculptThreadedTaskData *data = userdata; PBVHNode *node = data->nodes[i]; - SCULPT_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS); + SCULPT_undo_push_node(data->ob, node, data->filter_undo_type); } -void SCULPT_filter_cache_init(Object *ob, Sculpt *sd) +void SCULPT_filter_cache_init(Object *ob, Sculpt *sd, const int undo_type) { SculptSession *ss = ob->sculpt; PBVH *pbvh = ob->sculpt->pbvh; @@ -110,11 +110,11 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd) .sd = sd, .ob = ob, .nodes = ss->filter_cache->nodes, + .filter_undo_type = undo_type, }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings( - &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings); } @@ -475,7 +475,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * SCULPT_vertex_random_access_init(ss); bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); - BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false); SculptThreadedTaskData data = { .sd = sd, @@ -486,8 +486,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings( - &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { @@ -542,7 +541,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_vertex_random_access_init(ss); bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); - BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false); const int totvert = SCULPT_vertex_count_get(ss); if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) { @@ -551,7 +550,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_undo_push_begin("Mesh filter"); - SCULPT_filter_cache_init(ob, sd); + SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS); if (use_face_sets) { ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 0e27658e848..c981f89ada7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -27,6 +27,7 @@ #include "DNA_brush_types.h" #include "DNA_key_types.h" #include "DNA_listBase.h" +#include "DNA_meshdata_types.h" #include "DNA_vec_types.h" #include "BLI_bitmap.h" @@ -56,6 +57,7 @@ typedef enum SculptUpdateType { SCULPT_UPDATE_COORDS = 1 << 0, SCULPT_UPDATE_MASK = 1 << 1, SCULPT_UPDATE_VISIBILITY = 1 << 2, + SCULPT_UPDATE_COLOR = 1 << 3, } SculptUpdateType; void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags); @@ -92,6 +94,7 @@ int SCULPT_vertex_count_get(struct SculptSession *ss); const float *SCULPT_vertex_co_get(struct SculptSession *ss, int index); void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]); float SCULPT_vertex_mask_get(struct SculptSession *ss, int index); +const float *SCULPT_vertex_color_get(SculptSession *ss, int index); #define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256 typedef struct SculptVertexNeighborIter { @@ -145,6 +148,15 @@ void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3]); bool SCULPT_vertex_is_boundary(SculptSession *ss, const int index); +/* Fake Neighbors */ + +#define FAKE_NEIGHBOR_NONE -1 + +void SCULPT_fake_neighbors_ensure(struct Sculpt *sd, Object *ob, const float max_dist); +void SCULPT_fake_neighbors_enable(Object *ob); +void SCULPT_fake_neighbors_disable(Object *ob); +void SCULPT_fake_neighbors_free(struct Object *ob); + /* Sculpt Visibility API */ void SCULPT_vertex_visible_set(SculptSession *ss, int index, bool visible); @@ -179,15 +191,20 @@ typedef struct { float (*coords)[3]; short (*normals)[3]; const float *vmasks; + float (*colors)[4]; /* Original coordinate, normal, and mask. */ const float *co; const short *no; float mask; + const float *col; } SculptOrigVertData; void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node); void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter); +void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, + Object *ob, + struct SculptUndoNode *unode); /* Utils. */ void SCULPT_calc_brush_plane(struct Sculpt *sd, @@ -305,7 +322,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, float *automask_factor); /* Filters. */ -void SCULPT_filter_cache_init(Object *ob, Sculpt *sd); +void SCULPT_filter_cache_init(Object *ob, Sculpt *sd, const int undo_type); void SCULPT_filter_cache_free(SculptSession *ss); void SCULPT_mask_filter_smooth_apply( @@ -374,6 +391,12 @@ void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, /* Draw Face Sets Brush. */ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); +/* Paint Brush. */ +void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); + +/* Smear Brush. */ +void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); + /* Smooth Brush. */ void SCULPT_neighbor_average(SculptSession *ss, float avg[3], uint vert); @@ -383,6 +406,7 @@ void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], struct void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index); float SCULPT_neighbor_mask_average(SculptSession *ss, int index); +void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index); void SCULPT_smooth(Sculpt *sd, Object *ob, @@ -427,6 +451,7 @@ typedef enum { SCULPT_UNDO_DYNTOPO_SYMMETRIZE, SCULPT_UNDO_GEOMETRY, SCULPT_UNDO_FACE_SETS, + SCULPT_UNDO_COLOR, } SculptUndoType; /* Storage of geometry for the undo node. @@ -457,6 +482,7 @@ typedef struct SculptUndoNode { float (*co)[3]; float (*orig_co)[3]; short (*no)[3]; + float (*col)[4]; float *mask; int totvert; @@ -556,6 +582,7 @@ typedef struct SculptThreadedTaskData { int filter_type; float filter_strength; + float *filter_fill_color; bool use_area_cos; bool use_area_nos; @@ -568,6 +595,8 @@ typedef struct SculptThreadedTaskData { bool any_vertex_sampled; + float *wet_mix_sampled_color; + float *prev_mask; float *pose_factor; @@ -601,6 +630,7 @@ typedef struct SculptThreadedTaskData { bool dirty_mask_dirty_only; int face_set; + int filter_undo_type; ThreadMutex mutex; @@ -720,6 +750,8 @@ typedef struct StrokeCache { float bstrength; float normal_weight; /* from brush (with optional override) */ + float (*prev_colors)[4]; + /* The rest is temporary storage that isn't saved as a property */ bool first_time; /* Beginning of stroke may do some things special */ @@ -813,6 +845,9 @@ typedef struct StrokeCache { float stroke_local_mat[4][4]; float multiplane_scrape_angle; + float wet_mix_prev_color[4]; + float density_seed; + rcti previous_r; /* previous redraw rectangle */ rcti current_r; /* current redraw rectangle */ @@ -901,6 +936,9 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot); /* Cloth Filter. */ void SCULPT_OT_cloth_filter(struct wmOperatorType *ot); +/* Color Filter. */ +void SCULPT_OT_color_filter(struct wmOperatorType *ot); + /* Mask filter and Dirty Mask. */ void SCULPT_OT_mask_filter(struct wmOperatorType *ot); void SCULPT_OT_dirty_mask(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index cbb198e14a3..60483cc168d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -206,7 +206,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * (event->type == EVT_PADENTER && event->val == KM_PRESS)) { /* Smooth iterations. */ - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); const int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations"); SCULPT_mask_filter_smooth_apply( sd, ob, ss->filter_cache->nodes, ss->filter_cache->totnode, smooth_iterations); @@ -289,8 +289,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"), }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings( - &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); ss->filter_cache->mask_update_current_it = mask_expand_update_it; } @@ -365,7 +364,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); int vertex_count = SCULPT_vertex_count_get(ss); @@ -459,8 +458,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"), }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings( - &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); const char *status_str = TIP_( diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c index f3327706102..503f9429a50 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c @@ -304,7 +304,7 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, MultiplaneScrapeSampleData mssd = {{{0}}}; TaskParallelSettings sample_settings; - BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&sample_settings, true, totnode); sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce; sample_settings.userdata_chunk = &mssd; sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData); @@ -395,7 +395,7 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no); TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings); } diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c new file mode 100644 index 00000000000..9b38def6b7b --- /dev/null +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -0,0 +1,477 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edsculpt + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_hash.h" +#include "BLI_math.h" +#include "BLI_math_color_blend.h" +#include "BLI_task.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_brush.h" +#include "BKE_colortools.h" +#include "BKE_context.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_pbvh.h" +#include "BKE_scene.h" + +#include "DEG_depsgraph.h" + +#include "IMB_colormanagement.h" + +#include "WM_api.h" +#include "WM_message.h" +#include "WM_toolsystem.h" +#include "WM_types.h" + +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_sculpt.h" +#include "paint_intern.h" +#include "sculpt_intern.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "UI_interface.h" + +#include "IMB_imbuf.h" + +#include "bmesh.h" + +#include <math.h> +#include <stdlib.h> + +static void do_color_smooth_task_cb_exec(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + const float bstrength = ss->cache->bstrength; + + PBVHVertexIter vd; + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float smooth_color[4]; + SCULPT_neighbor_color_average(ss, smooth_color, vd.index); + blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + } + BKE_pbvh_vertex_iter_end; +} + +static void do_paint_brush_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + const float bstrength = fabsf(ss->cache->bstrength); + + PBVHVertexIter vd; + PBVHColorBufferNode *color_buffer; + + SculptOrigVertData orig_data; + SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); + + color_buffer = BKE_pbvh_node_color_buffer_get(data->nodes[n]); + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + + float brush_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + copy_v3_v3(brush_color, BKE_brush_color_get(ss->scene, brush)); + IMB_colormanagement_srgb_to_scene_linear_v3(brush_color); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SCULPT_orig_vert_data_update(&orig_data, &vd); + + bool affect_vertex = false; + float distance_to_stroke_location = 0.0f; + if (brush->tip_roundness < 1.0f) { + affect_vertex = SCULPT_brush_test_cube(&test, vd.co, data->mat, brush->tip_roundness); + distance_to_stroke_location = ss->cache->radius * test.dist; + } + else { + affect_vertex = sculpt_brush_test_sq_fn(&test, vd.co); + distance_to_stroke_location = sqrtf(test.dist); + } + + if (affect_vertex) { + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + distance_to_stroke_location, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Density. */ + float noise = 1.0f; + const float density = brush->density; + if (density < 1.0f) { + const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); + if (hash_noise > density) { + noise = density * hash_noise; + fade = fade * noise; + } + } + + /* Brush paint color, brush test falloff and flow. */ + float paint_color[4]; + float wet_mix_color[4]; + float buffer_color[4]; + + mul_v4_v4fl(paint_color, brush_color, fade * brush->flow); + mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * brush->flow); + + /* Interpolate with the wet_mix color for wet paint mixing. */ + blend_color_interpolate_float(paint_color, paint_color, wet_mix_color, brush->wet_mix); + blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); + + /* Final mix over the original color using brush alpha. */ + mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + + IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); + } + CLAMP4(vd.col, 0.0f, 1.0f); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + BKE_pbvh_vertex_iter_end; +} + +typedef struct SampleWetPaintTLSData { + int tot_samples; + float color[4]; +} SampleWetPaintTLSData; + +static void do_sample_wet_paint_task_cb(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + SampleWetPaintTLSData *swptd = tls->userdata_chunk; + PBVHVertexIter vd; + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + add_v4_v4(swptd->color, vd.col); + swptd->tot_samples++; + } + } + BKE_pbvh_vertex_iter_end; +} + +static void sample_wet_paint_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) +{ + SampleWetPaintTLSData *join = chunk_join; + SampleWetPaintTLSData *swptd = chunk; + + join->tot_samples += swptd->tot_samples; + add_v4_v4(join->color, swptd->color); +} + +void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + + if (!ss->vcol) { + return; + } + + if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) { + ss->cache->density_seed = BLI_hash_int_01(ss->cache->location[0] * 1000); + return; + } + + BKE_curvemapping_initialize(brush->curve); + + float area_no[3]; + float mat[4][4]; + float scale[4][4]; + float tmat[4][4]; + + /* If the brush is round the tip does not need to be aligned to the surface, so this saves a + * whole iteration over the affected nodes. */ + if (brush->tip_roundness < 1.0f) { + SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no); + + cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry); + mat[0][3] = 0; + cross_v3_v3v3(mat[1], area_no, mat[0]); + mat[1][3] = 0; + copy_v3_v3(mat[2], area_no); + mat[2][3] = 0; + copy_v3_v3(mat[3], ss->cache->location); + mat[3][3] = 1; + normalize_m4(mat); + + scale_m4_fl(scale, ss->cache->radius); + mul_m4_m4m4(tmat, mat, scale); + mul_v3_fl(tmat[1], brush->tip_scale_x); + invert_m4_m4(mat, tmat); + if (is_zero_m4(mat)) { + return; + } + } + + /* Smooth colors mode. */ + if (ss->cache->alt_smooth) { + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + .mat = mat, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, do_color_smooth_task_cb_exec, &settings); + return; + } + + /* Regular Paint mode. */ + + /* Wet paint color sampling. */ + float wet_color[4] = {0.0f}; + if (brush->wet_mix > 0.0f) { + SculptThreadedTaskData task_data = { + .sd = sd, + .ob = ob, + .nodes = nodes, + .brush = brush, + }; + + SampleWetPaintTLSData swptd; + swptd.tot_samples = 0; + zero_v4(swptd.color); + + TaskParallelSettings settings_sample; + BKE_pbvh_parallel_range_settings(&settings_sample, true, totnode); + settings_sample.func_reduce = sample_wet_paint_reduce; + settings_sample.userdata_chunk = &swptd; + settings_sample.userdata_chunk_size = sizeof(SampleWetPaintTLSData); + BLI_task_parallel_range(0, totnode, &task_data, do_sample_wet_paint_task_cb, &settings_sample); + + if (swptd.tot_samples > 0 && is_finite_v4(swptd.color)) { + copy_v4_v4(wet_color, swptd.color); + mul_v4_fl(wet_color, 1.0f / (float)swptd.tot_samples); + CLAMP4(wet_color, 0.0f, 1.0f); + + if (ss->cache->first_time) { + copy_v4_v4(ss->cache->wet_mix_prev_color, wet_color); + } + blend_color_interpolate_float( + wet_color, wet_color, ss->cache->wet_mix_prev_color, brush->wet_persistence); + copy_v4_v4(ss->cache->wet_mix_prev_color, wet_color); + CLAMP4(ss->cache->wet_mix_prev_color, 0.0f, 1.0f); + } + } + + /* Threaded loop over nodes. */ + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + .wet_mix_sampled_color = wet_color, + .mat = mat, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, do_paint_brush_task_cb_ex, &settings); +} + +static void do_smear_brush_task_cb_exec(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + const float bstrength = ss->cache->bstrength; + + PBVHVertexIter vd; + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float current_disp[3]; + float current_disp_norm[3]; + float interp_color[4]; + copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); + + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + const float *neighbor_color = ss->cache->prev_colors[ni.index]; + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { + const float color_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + float color_mix[4]; + copy_v4_v4(color_mix, neighbor_color); + mul_v4_fl(color_mix, color_interp * fade); + blend_color_mix_float(interp_color, interp_color, color_mix); + } + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + } + BKE_pbvh_vertex_iter_end; +} + +static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + copy_v4_v4(ss->cache->prev_colors[vd.index], SCULPT_vertex_color_get(ss, vd.index)); + } + BKE_pbvh_vertex_iter_end; +} + +void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + + if (!ss->vcol) { + return; + } + + const int totvert = SCULPT_vertex_count_get(ss); + + if (ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0) { + if (!ss->cache->prev_colors) { + ss->cache->prev_colors = MEM_callocN(sizeof(float) * 4 * totvert, "prev colors"); + for (int i = 0; i < totvert; i++) { + copy_v4_v4(ss->cache->prev_colors[i], SCULPT_vertex_color_get(ss, i)); + } + } + } + + BKE_curvemapping_initialize(brush->curve); + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + + /* Smooth colors mode. */ + if (ss->cache->alt_smooth) { + BLI_task_parallel_range(0, totnode, &data, do_color_smooth_task_cb_exec, &settings); + } + else { + /* Smear mode. */ + BLI_task_parallel_range(0, totnode, &data, do_smear_store_prev_colors_task_cb_exec, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smear_brush_task_cb_exec, &settings); + } +} diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index a4a87051e03..c9e2b7318d6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -293,7 +293,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, PoseGrowFactorTLSData gftd; gftd.pos_count = 0; zero_v3(gftd.pos_avg); - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); settings.func_reduce = pose_brush_grow_factor_reduce; settings.userdata_chunk = &gftd; settings.userdata_chunk_size = sizeof(PoseGrowFactorTLSData); @@ -937,18 +937,32 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, const float initial_location[3], const float radius) { + SculptPoseIKChain *ik_chain = NULL; + + const bool use_fake_neighbors = !(br->flag2 & BRUSH_USE_CONNECTED_ONLY); + + if (use_fake_neighbors) { + SCULPT_fake_neighbors_ensure(sd, ob, br->disconnected_distance_max); + SCULPT_fake_neighbors_enable(ob); + } + switch (br->pose_origin_type) { case BRUSH_POSE_ORIGIN_TOPOLOGY: - return pose_ik_chain_init_topology(sd, ob, ss, br, initial_location, radius); + ik_chain = pose_ik_chain_init_topology(sd, ob, ss, br, initial_location, radius); break; case BRUSH_POSE_ORIGIN_FACE_SETS: - return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius); + ik_chain = pose_ik_chain_init_face_sets(sd, ob, ss, br, radius); break; case BRUSH_POSE_ORIGIN_FACE_SETS_FK: return pose_ik_chain_init_face_sets_fk(sd, ob, ss, radius, initial_location); break; } - return NULL; + + if (use_fake_neighbors) { + SCULPT_fake_neighbors_disable(ob); + } + + return ik_chain; } void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br) @@ -975,7 +989,7 @@ void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights; for (int i = 0; i < br->pose_smooth_iterations; i++) { TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); } } @@ -1198,7 +1212,7 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 17451cb40ae..aa82ae1d7ad 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -226,6 +226,26 @@ float SCULPT_neighbor_mask_average(SculptSession *ss, int index) } } +void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index) +{ + float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + int total = 0; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { + add_v4_v4(avg, SCULPT_vertex_color_get(ss, ni.index)); + total++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + if (total > 0) { + mul_v4_v4fl(result, avg, 1.0f / (float)total); + } + else { + copy_v4_v4(result, SCULPT_vertex_color_get(ss, index)); + } +} + static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) @@ -433,7 +453,7 @@ void SCULPT_smooth(Sculpt *sd, }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); switch (type) { case PBVH_GRIDS: @@ -525,10 +545,15 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( { SCULPT_orig_vert_data_update(&orig_data, &vd); if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = - bstrength * - SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); float disp[3]; SCULPT_surface_smooth_laplacian_step(ss, @@ -566,10 +591,15 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = - bstrength * - SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); SCULPT_surface_smooth_displace_step( ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); } @@ -598,7 +628,7 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); for (int i = 0; i < brush->surface_smooth_iterations; i++) { BLI_task_parallel_range( 0, totnode, &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings); diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index 59a4695ce18..f616817c330 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -71,12 +71,12 @@ void ED_sculpt_init_transform(struct bContext *C) copy_v4_v4(ss->init_pivot_rot, ss->pivot_rot); SCULPT_undo_push_begin("Transform"); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); ss->pivot_rot[3] = 1.0f; SCULPT_vertex_random_access_init(ss); - SCULPT_filter_cache_init(ob, sd); + SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS); } static void sculpt_transform_task_cb(void *__restrict userdata, @@ -127,7 +127,7 @@ void ED_sculpt_update_modal_transform(struct bContext *C) const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; SCULPT_vertex_random_access_init(ss); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); SculptThreadedTaskData data = { .sd = sd, @@ -178,8 +178,7 @@ void ED_sculpt_update_modal_transform(struct bContext *C) } TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings( - &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings); @@ -253,7 +252,7 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op) int mode = RNA_enum_get(op->ptr, "mode"); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false); /* Pivot to center. */ if (mode == SCULPT_PIVOT_POSITION_ORIGIN) { diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index d21552efafe..6ede631eb11 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -205,7 +205,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt if (kb) { ob->shapenr = BLI_findindex(&key->block, kb) + 1; - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); } else { @@ -326,6 +326,29 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode) return true; } +static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + SculptSession *ss = ob->sculpt; + MVert *mvert; + MPropCol *vcol; + int *index, i; + + if (unode->maxvert) { + /* regular mesh restore */ + index = unode->index; + mvert = ss->mvert; + vcol = ss->vcol; + + for (i = 0; i < unode->totvert; i++) { + copy_v4_v4(vcol[index[i]].color, unode->col[i]); + mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; + } + } + return true; +} + static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -394,10 +417,7 @@ static void sculpt_undo_bmesh_restore_generic_task_cb( BKE_pbvh_node_mark_redraw(nodes[n]); } -static void sculpt_undo_bmesh_restore_generic(bContext *C, - SculptUndoNode *unode, - Object *ob, - SculptSession *ss) +static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob, SculptSession *ss) { if (unode->applied) { BM_log_undo(ss->bm, ss->bm_log); @@ -411,12 +431,11 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C, if (unode->type == SCULPT_UNDO_MASK) { int totnode; PBVHNode **nodes; - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + BKE_pbvh_parallel_range_settings(&settings, true, totnode); BLI_task_parallel_range( 0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings); @@ -588,7 +607,7 @@ static int sculpt_undo_bmesh_restore(bContext *C, return true; default: if (ss->bm_log) { - sculpt_undo_bmesh_restore_generic(C, unode, ob, ss); + sculpt_undo_bmesh_restore_generic(unode, ob, ss); return true; } break; @@ -633,7 +652,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase rebuild = true; BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild); - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, need_mask); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, need_mask, false); SCULPT_visibility_sync_all_face_sets_to_vertices(ss); @@ -659,7 +678,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase * ensure object is updated after the node is handled. */ const SculptUndoNode *first_unode = (const SculptUndoNode *)lb->first; if (first_unode->type != SCULPT_UNDO_GEOMETRY) { - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask, false); } if (sculpt_undo_bmesh_restore(C, lb->first, ob, ss)) { @@ -712,10 +731,15 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase break; case SCULPT_UNDO_FACE_SETS: break; + case SCULPT_UNDO_COLOR: + if (sculpt_undo_restore_color(C, unode)) { + update = true; + } + break; case SCULPT_UNDO_GEOMETRY: sculpt_undo_geometry_restore(unode, ob); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, need_mask, false); break; case SCULPT_UNDO_DYNTOPO_BEGIN: @@ -998,6 +1022,12 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt usculpt->undo_size += (sizeof(float) * sizeof(int)) * allvert; break; + case SCULPT_UNDO_COLOR: + unode->col = MEM_callocN(sizeof(MPropCol) * allvert, "SculptUndoNode.col"); + + usculpt->undo_size += (sizeof(MPropCol) * sizeof(int)) * allvert; + + break; case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: @@ -1083,6 +1113,18 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode) BKE_pbvh_vertex_iter_end; } +static void sculpt_undo_store_color(Object *ob, SculptUndoNode *unode) +{ + SculptSession *ss = ob->sculpt; + PBVHVertexIter vd; + + BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL) + { + copy_v4_v4(unode->col[vd.i], vd.col); + } + BKE_pbvh_vertex_iter_end; +} + static SculptUndoNodeGeometry *sculpt_undo_geometry_get(SculptUndoNode *unode) { if (!unode->geometry_original.is_initialized) { @@ -1203,6 +1245,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: case SCULPT_UNDO_GEOMETRY: case SCULPT_UNDO_FACE_SETS: + case SCULPT_UNDO_COLOR: break; } } @@ -1272,6 +1315,9 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType case SCULPT_UNDO_MASK: sculpt_undo_store_mask(ob, unode); break; + case SCULPT_UNDO_COLOR: + sculpt_undo_store_color(ob, unode); + break; case SCULPT_UNDO_DYNTOPO_BEGIN: case SCULPT_UNDO_DYNTOPO_END: case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 81ac8a16d8a..2e52f3aa8a8 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -771,7 +771,7 @@ static int sound_pack_exec(bContext *C, wmOperator *op) } sound->packedfile = BKE_packedfile_new( - op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id)); + op->reports, sound->filepath, ID_BLEND_PATH(bmain, &sound->id)); BKE_sound_load(bmain, sound); return OPERATOR_FINISHED; @@ -847,7 +847,8 @@ static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE "AutoPack is enabled, so image will be packed again on file save"); } - unpack_menu(C, "SOUND_OT_unpack", sound->id.name + 2, sound->name, "sounds", sound->packedfile); + unpack_menu( + C, "SOUND_OT_unpack", sound->id.name + 2, sound->filepath, "sounds", sound->packedfile); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index b390e4b56d6..aa784800be0 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -800,10 +800,17 @@ static void insert_gpencil_keys(bAnimContext *ac, short mode) add_frame_mode = GP_GETFRAME_ADD_NEW; } - /* insert gp frames */ + /* Insert gp frames. */ + bGPdata *gpd_old = NULL; for (ale = anim_data.first; ale; ale = ale->next) { + bGPdata *gpd = (bGPdata *)ale->id; bGPDlayer *gpl = (bGPDlayer *)ale->data; BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode); + /* Check if the gpd changes to tag only once. */ + if (gpd != gpd_old) { + BKE_gpencil_tag(gpd); + gpd_old = gpd; + } } ANIM_animdata_update(ac, &anim_data); @@ -839,6 +846,9 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) } /* set notifier that keyframes have changed */ + if (ac.datatype == ANIMCONT_GPENCIL) { + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); return OPERATOR_FINISHED; @@ -888,7 +898,7 @@ static void duplicate_action_keys(bAnimContext *ac) duplicate_fcurve_keys((FCurve *)ale->key_data); } else if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_frames_duplicate((bGPDlayer *)ale->data); + ED_gpencil_layer_frames_duplicate((bGPDlayer *)ale->data); } else if (ale->type == ANIMTYPE_MASKLAYER) { ED_masklayer_frames_duplicate((MaskLayer *)ale->data); @@ -964,7 +974,7 @@ static bool delete_action_keys(bAnimContext *ac) bool changed = false; if (ale->type == ANIMTYPE_GPLAYER) { - changed = ED_gplayer_frames_delete((bGPDlayer *)ale->data); + changed = ED_gpencil_layer_frames_delete((bGPDlayer *)ale->data); } else if (ale->type == ANIMTYPE_MASKLAYER) { changed = ED_masklayer_frames_delete((MaskLayer *)ale->data); @@ -1539,7 +1549,7 @@ static void setkeytype_gpencil_keys(bAnimContext *ac, short mode) /* loop through each layer */ for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_frames_keytype_set(ale->data, mode); + ED_gpencil_layer_frames_keytype_set(ale->data, mode); ale->update |= ANIM_UPDATE_DEPS; } } @@ -1740,7 +1750,7 @@ static void snap_action_keys(bAnimContext *ac, short mode) AnimData *adt = ANIM_nla_mapping_get(ac, ale); if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_snap_frames(ale->data, ac->scene, mode); + ED_gpencil_layer_snap_frames(ale->data, ac->scene, mode); } else if (ale->type == ANIMTYPE_MASKLAYER) { ED_masklayer_snap_frames(ale->data, ac->scene, mode); @@ -1870,7 +1880,7 @@ static void mirror_action_keys(bAnimContext *ac, short mode) AnimData *adt = ANIM_nla_mapping_get(ac, ale); if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_mirror_frames(ale->data, ac->scene, mode); + ED_gpencil_layer_mirror_frames(ale->data, ac->scene, mode); } else if (ale->type == ANIMTYPE_MASKLAYER) { /* TODO */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index bbb68f632fb..f40b792269b 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -270,7 +270,7 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) if (test) { for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { - if (ED_gplayer_frame_select_check(ale->data)) { + if (ED_gpencil_layer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } @@ -296,7 +296,7 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) /* Now set the flags */ for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_frame_select_set(ale->data, sel); + ED_gpencil_layer_frame_select_set(ale->data, sel); ale->update |= ANIM_UPDATE_DEPS; } else if (ale->type == ANIMTYPE_MASKLAYER) { @@ -405,14 +405,14 @@ static void box_select_elem( bGPdata *gpd = ale->data; bGPDlayer *gpl; for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - ED_gplayer_frames_select_box(gpl, xmin, xmax, data->selectmode); + ED_gpencil_layer_frames_select_box(gpl, xmin, xmax, data->selectmode); } ale->update |= ANIM_UPDATE_DEPS; break; } #endif case ANIMTYPE_GPLAYER: { - ED_gplayer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode); + ED_gpencil_layer_frames_select_box(ale->data, xmin, xmax, sel_data->selectmode); ale->update |= ANIM_UPDATE_DEPS; break; } @@ -641,13 +641,13 @@ static void region_select_elem(RegionSelectData *sel_data, bAnimListElem *ale, b bGPdata *gpd = ale->data; bGPDlayer *gpl; for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - ED_gplayer_frames_select_region(&rdata->ked, ale->data, rdata->mode, rdata->selectmode); + ED_gpencil_layer_frames_select_region(&rdata->ked, ale->data, rdata->mode, rdata->selectmode); } break; } #endif case ANIMTYPE_GPLAYER: { - ED_gplayer_frames_select_region( + ED_gpencil_layer_frames_select_region( &sel_data->ked, ale->data, sel_data->mode, sel_data->selectmode); ale->update |= ANIM_UPDATE_DEPS; break; @@ -972,7 +972,7 @@ static void markers_selectkeys_between(bAnimContext *ac) ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_frames_select_box(ale->data, min, max, SELECT_ADD); + ED_gpencil_layer_frames_select_box(ale->data, min, max, SELECT_ADD); ale->update |= ANIM_UPDATE_DEPS; } else if (ale->type == ANIMTYPE_MASKLAYER) { @@ -1008,7 +1008,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { - ED_gplayer_make_cfra_list(ale->data, &ked.list, 1); + ED_gpencil_layer_make_cfra_list(ale->data, &ked.list, 1); } } else { @@ -1385,7 +1385,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else if (ale->type == ANIMTYPE_GPLAYER) { - ED_gplayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode); + ED_gpencil_layer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode); ale->update |= ANIM_UPDATE_DEPS; } else if (ale->type == ANIMTYPE_MASKLAYER) { diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index e92ea906237..079cee290ae 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -128,7 +128,7 @@ static SpaceLink *action_new(const ScrArea *area, const Scene *scene) region->v2d.minzoom = 0.01f; region->v2d.maxzoom = 50; region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); - region->v2d.scroll |= (V2D_SCROLL_RIGHT); + region->v2d.scroll |= V2D_SCROLL_RIGHT; region->v2d.keepzoom = V2D_LOCKZOOM_Y; region->v2d.keepofs = V2D_KEEPOFS_Y; region->v2d.align = V2D_ALIGN_NO_POS_Y; @@ -181,10 +181,14 @@ static void action_main_region_draw(const bContext *C, ARegion *region) Object *obact = CTX_data_active_object(C); bAnimContext ac; View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; short marker_flag = 0; short cfra_flag = 0; + UI_view2d_view_ortho(v2d); + if (saction->flag & SACTION_DRAWTIME) { + cfra_flag |= DRAWCFRA_UNIT_SECONDS; + } + /* clear and setup matrix */ UI_ThemeClearColor(TH_BACK); GPU_clear(GPU_COLOR_BIT); @@ -204,12 +208,6 @@ static void action_main_region_draw(const bContext *C, ARegion *region) draw_channel_strips(&ac, saction, region); } - /* current frame */ - if (saction->flag & SACTION_DRAWTIME) { - cfra_flag |= DRAWCFRA_UNIT_SECONDS; - } - ANIM_draw_cfra(C, v2d, cfra_flag); - /* markers */ UI_view2d_view_orthoSpecial(region, v2d, 1); @@ -238,11 +236,20 @@ static void action_main_region_draw(const bContext *C, ARegion *region) /* scrubbing region */ ED_time_scrub_draw(region, scene, saction->flag & SACTION_DRAWTIME, true); +} + +static void action_main_region_draw_overlay(const bContext *C, ARegion *region) +{ + /* draw entirely, view changes should be handled here */ + const SpaceAction *saction = CTX_wm_space_action(C); + const Scene *scene = CTX_data_scene(C); + View2D *v2d = ®ion->v2d; + + /* scrubbing region */ + ED_time_scrub_draw_current_frame(region, scene, saction->flag & SACTION_DRAWTIME, true); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } /* add handlers, stuff you only do once or on area/region changes */ @@ -874,6 +881,7 @@ void ED_spacetype_action(void) art->regionid = RGN_TYPE_WINDOW; art->init = action_main_region_init; art->draw = action_main_region_draw; + art->draw_overlay = action_main_region_draw_overlay; art->listener = action_main_region_listener; art->message_subscribe = saction_main_region_message_subscribe; art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index c3b7d65689f..25ff6bbd098 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -54,8 +54,4 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() -if(WITH_NEW_OBJECT_TYPES) - add_definitions(-DWITH_NEW_OBJECT_TYPES) -endif() - blender_add_lib(bf_editor_space_buttons "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 7e6088bc3cc..ba618083620 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -251,14 +251,12 @@ static int buttons_context_path_data(ButsContextPath *path, int type) else if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) { return 1; } -#ifdef WITH_NEW_OBJECT_TYPES else if (RNA_struct_is_a(ptr->type, &RNA_Hair) && (type == -1 || type == OB_HAIR)) { return 1; } else if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && (type == -1 || type == OB_POINTCLOUD)) { return 1; } -#endif else if (RNA_struct_is_a(ptr->type, &RNA_Volume) && (type == -1 || type == OB_VOLUME)) { return 1; } @@ -796,10 +794,8 @@ const char *buttons_context_dir[] = { "line_style", "collection", "gpencil", -#ifdef WITH_NEW_OBJECT_TYPES "hair", "pointcloud", -#endif "volume", NULL, }; @@ -878,7 +874,6 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_LightProbe); return 1; } -#ifdef WITH_NEW_OBJECT_TYPES else if (CTX_data_equals(member, "hair")) { set_pointer_type(path, result, &RNA_Hair); return 1; @@ -887,7 +882,6 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_PointCloud); return 1; } -#endif else if (CTX_data_equals(member, "volume")) { set_pointer_type(path, result, &RNA_Volume); return 1; diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 187334a5c34..71b86996989 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -30,10 +30,10 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_gpencil_modifier.h" /* Types for registering panels. */ #include "BKE_modifier.h" #include "BKE_screen.h" - -#include "DNA_modifier_types.h" +#include "BKE_shader_fx.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -643,6 +643,21 @@ void ED_spacetype_buttons(void) mti->panelRegister(art); } } + for (int i = 0; i < NUM_GREASEPENCIL_MODIFIER_TYPES; i++) { + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(i); + if (mti != NULL && mti->panelRegister != NULL) { + mti->panelRegister(art); + } + } + for (int i = 0; i < NUM_SHADER_FX_TYPES; i++) { + if (i == eShaderFxType_Light_deprecated) { + continue; + } + const ShaderFxTypeInfo *fxti = BKE_shaderfx_get_info(i); + if (fxti != NULL && fxti->panelRegister != NULL) { + fxti->panelRegister(art); + } + } /* regions: header */ art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region"); diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 84ab5e6524b..c3aca95910b 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -118,7 +118,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *region, Scene *scene) MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingDopesheetChannel *channel; float strip[4], selected_strip[4]; - float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); + float height = (dopesheet->tot_channel * CHANNEL_STEP) + CHANNEL_HEIGHT; uint keyframe_len = 0; @@ -305,7 +305,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *region) MovieTracking *tracking = &clip->tracking; MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; - int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); + int height = (dopesheet->tot_channel * CHANNEL_STEP) + CHANNEL_HEIGHT; if (height > BLI_rcti_size_y(&v2d->mask)) { /* don't use totrect set, as the width stays the same diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 984aa0a63ad..22707b97afa 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -283,7 +283,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event) } if (clip) { - BLI_strncpy(path, clip->name, sizeof(path)); + BLI_strncpy(path, clip->filepath, sizeof(path)); BLI_path_abs(path, CTX_data_main(C)->name); BLI_path_parent_dir(path); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a68e06951f7..54da00a132d 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -96,7 +96,7 @@ static void init_preview_region(const Scene *scene, region->v2d.minzoom = 0.01f; region->v2d.maxzoom = 50; region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); - region->v2d.scroll |= (V2D_SCROLL_RIGHT); + region->v2d.scroll |= V2D_SCROLL_RIGHT; region->v2d.keepzoom = V2D_LOCKZOOM_Y; region->v2d.keepofs = V2D_KEEPOFS_Y; region->v2d.align = V2D_ALIGN_NO_POS_Y; @@ -1045,7 +1045,6 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *region) static void graph_region_draw(const bContext *C, ARegion *region) { View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; SpaceClip *sc = CTX_wm_space_clip(C); Scene *scene = CTX_data_scene(C); short cfra_flag = 0; @@ -1076,9 +1075,7 @@ static void graph_region_draw(const bContext *C, ARegion *region) ED_time_scrub_draw(region, scene, sc->flag & SC_SHOW_SECONDS, true); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); /* scale indicators */ { @@ -1095,7 +1092,6 @@ static void dopesheet_region_draw(const bContext *C, ARegion *region) SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; short cfra_flag = 0; if (clip) { @@ -1127,9 +1123,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *region) ED_time_scrub_draw(region, scene, sc->flag & SC_SHOW_SECONDS, true); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } static void clip_preview_region_draw(const bContext *C, ARegion *region) diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index d8c097cad37..3c62aeb1759 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -70,7 +70,7 @@ static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(s region->regiontype = RGN_TYPE_WINDOW; /* keep in sync with info */ - region->v2d.scroll |= (V2D_SCROLL_RIGHT); + region->v2d.scroll |= V2D_SCROLL_RIGHT; region->v2d.align |= V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y; /* align bottom left */ region->v2d.keepofs |= V2D_LOCKOFS_X; region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT); @@ -208,7 +208,6 @@ static void console_main_region_draw(const bContext *C, ARegion *region) /* draw entirely, view changes should be handled here */ SpaceConsole *sc = CTX_wm_space_console(C); View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; if (BLI_listbase_is_empty(&sc->scrollback)) { WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL); @@ -230,9 +229,7 @@ static void console_main_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } static void console_operatortypes(void) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index d8d7ef01a2e..f60ef2b6aed 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2740,7 +2740,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist) } else { char relname[FILE_MAX + (MAX_ID_NAME - 2) + 3]; - BLI_snprintf(relname, sizeof(relname), "%s | %s", id->lib->name, id->name + 2); + BLI_snprintf(relname, sizeof(relname), "%s | %s", id->lib->filepath, id->name + 2); files->entry->relpath = BLI_strdup(relname); } // files->type |= S_IFREG; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 21b705cbb44..56f3fd08bae 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -449,7 +449,6 @@ static void file_main_region_draw(const bContext *C, ARegion *region) FileSelectParams *params = ED_fileselect_get_params(sfile); View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; float col[3]; /* Needed, because filelist is not initialized on loading */ @@ -509,9 +508,7 @@ static void file_main_region_draw(const bContext *C, ARegion *region) /* scrollers */ rcti view_rect; ED_fileselect_layout_maskrect(sfile->layout, v2d, &view_rect); - scrollers = UI_view2d_scrollers_calc(v2d, &view_rect); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, &view_rect); } static void file_operatortypes(void) diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index b9c7c529620..052e089942c 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -200,9 +200,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) Scene *scene = CTX_data_scene(C); bAnimContext ac; View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; float col[3]; - short cfra_flag = 0; /* clear and setup matrix */ UI_GetThemeColor3fv(TH_BACK, col); @@ -284,14 +282,6 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) immUnbindProgram(); } - if (sipo->mode != SIPO_MODE_DRIVERS) { - /* current frame */ - if (sipo->flag & SIPO_DRAWTIME) { - cfra_flag |= DRAWCFRA_UNIT_SECONDS; - } - ANIM_draw_cfra(C, v2d, cfra_flag); - } - /* markers */ if (sipo->mode != SIPO_MODE_DRIVERS) { UI_view2d_view_orthoSpecial(region, v2d, 1); @@ -316,12 +306,22 @@ static void graph_main_region_draw(const bContext *C, ARegion *region) /* time-scrubbing */ ED_time_scrub_draw(region, scene, display_seconds, false); +} + +static void graph_main_region_draw_overlay(const bContext *C, ARegion *region) +{ + /* draw entirely, view changes should be handled here */ + const SpaceGraph *sipo = CTX_wm_space_graph(C); + const Scene *scene = CTX_data_scene(C); + const bool draw_vert_line = sipo->mode != SIPO_MODE_DRIVERS; + View2D *v2d = ®ion->v2d; + + /* scrubbing region */ + ED_time_scrub_draw_current_frame(region, scene, sipo->flag & SIPO_DRAWTIME, draw_vert_line); /* scrollers */ // FIXME: args for scrollers depend on the type of data being shown... - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); /* scale numbers */ { @@ -358,7 +358,6 @@ static void graph_channel_region_draw(const bContext *C, ARegion *region) { bAnimContext ac; View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; float col[3]; /* clear and setup matrix */ @@ -380,9 +379,7 @@ static void graph_channel_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } /* add handlers, stuff you only do once or on area/region changes */ @@ -859,6 +856,7 @@ void ED_spacetype_ipo(void) art->regionid = RGN_TYPE_WINDOW; art->init = graph_main_region_init; art->draw = graph_main_region_draw; + art->draw_overlay = graph_main_region_draw_overlay; art->listener = graph_region_listener; art->message_subscribe = graph_region_message_subscribe; art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index c9f2ec38354..cb0fdcf23ca 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -191,7 +191,7 @@ int ED_space_image_get_display_channel_mask(ImBuf *ibuf) result &= ~(SI_USE_ALPHA | SI_SHOW_ALPHA); } if (!zbuf) { - result &= ~(SI_SHOW_ZBUF); + result &= ~SI_SHOW_ZBUF; } if (!color) { result &= ~(SI_SHOW_R | SI_SHOW_G | SI_SHOW_B); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 8cb85ce9800..f71c92b4c1f 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1237,7 +1237,7 @@ static Image *image_open_single(Main *bmain, if (!exists) { /* only image path after save, never ibuf */ if (is_relative_path) { - BLI_path_rel(ima->name, relbase); + BLI_path_rel(ima->filepath, relbase); } /* handle multiview images */ @@ -1417,7 +1417,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED( } if (ima) { - path = ima->name; + path = ima->filepath; } if (RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -1577,7 +1577,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filepath", str); /* we cant do much if the str is longer then FILE_MAX :/ */ - BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)); + BLI_strncpy(sima->image->filepath, str, sizeof(sima->image->filepath)); if (sima->image->source == IMA_SRC_GENERATED) { sima->image->source = IMA_SRC_FILE; @@ -1614,10 +1614,10 @@ static int image_replace_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS } if (!RNA_struct_property_is_set(op->ptr, "relative_path")) { - RNA_boolean_set(op->ptr, "relative_path", BLI_path_is_rel(sima->image->name)); + RNA_boolean_set(op->ptr, "relative_path", BLI_path_is_rel(sima->image->filepath)); } - image_filesel(C, op, sima->image->name); + image_filesel(C, op, sima->image->filepath); return OPERATOR_RUNNING_MODAL; } @@ -1777,7 +1777,7 @@ static int image_save_options_init(Main *bmain, /* append UDIM numbering if not present */ if (ima->source == IMA_SRC_TILED && - (BLI_path_sequence_decode(ima->name, NULL, NULL, NULL) != 1001)) { + (BLI_path_sequence_decode(ima->filepath, NULL, NULL, NULL) != 1001)) { int len = strlen(opts->filepath); STR_CONCAT(opts->filepath, len, ".1001"); } @@ -2301,7 +2301,7 @@ static bool image_should_be_saved(Image *ima, bool *is_format_writable) static bool image_has_valid_path(Image *ima) { - return strchr(ima->name, '\\') || strchr(ima->name, '/'); + return strchr(ima->filepath, '\\') || strchr(ima->filepath, '/'); } bool ED_image_should_save_modified(const Main *bmain) @@ -2336,7 +2336,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports) RPT_WARNING, "Packed library image can't be saved: \"%s\" from \"%s\"", ima->id.name + 2, - ima->id.lib->name); + ima->id.lib->filepath); } } else if (!is_format_writable) { @@ -2348,19 +2348,21 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports) else { if (image_has_valid_path(ima)) { num_saveable_images++; - if (BLI_gset_haskey(unique_paths, ima->name)) { + if (BLI_gset_haskey(unique_paths, ima->filepath)) { BKE_reportf(reports, RPT_WARNING, "Multiple images can't be saved to an identical path: \"%s\"", - ima->name); + ima->filepath); } else { - BLI_gset_insert(unique_paths, BLI_strdup(ima->name)); + BLI_gset_insert(unique_paths, BLI_strdup(ima->filepath)); } } else { - BKE_reportf( - reports, RPT_WARNING, "Image can't be saved, no valid file path: \"%s\"", ima->name); + BKE_reportf(reports, + RPT_WARNING, + "Image can't be saved, no valid file path: \"%s\"", + ima->filepath); } } } @@ -3044,7 +3046,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE unpack_menu(C, "IMAGE_OT_unpack", ima->id.name + 2, - ima->name, + ima->filepath, "textures", BKE_image_has_packedfile(ima) ? ((ImagePackedFile *)ima->packedfiles.first)->packedfile : diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 04df0f0d4f0..836830916ed 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -77,7 +77,7 @@ static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen region->regiontype = RGN_TYPE_WINDOW; /* keep in sync with console */ - region->v2d.scroll |= (V2D_SCROLL_RIGHT); + region->v2d.scroll |= V2D_SCROLL_RIGHT; region->v2d.align |= V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y; /* align bottom left */ region->v2d.keepofs |= V2D_LOCKOFS_X; region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT); @@ -139,7 +139,6 @@ static void info_main_region_draw(const bContext *C, ARegion *region) /* draw entirely, view changes should be handled here */ SpaceInfo *sinfo = CTX_wm_space_info(C); View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; /* clear and setup matrix */ UI_ThemeClearColor(TH_BACK); @@ -161,9 +160,7 @@ static void info_main_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } static void info_operatortypes(void) diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 307b6d9bc21..d0d9f2f57bb 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -407,7 +407,7 @@ static void nla_panel_properties(const bContext *C, Panel *panel) uiItemR(row, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? /* settings */ - column = uiLayoutColumnWithHeading(layout, true, "Playback"); + column = uiLayoutColumnWithHeading(layout, true, IFACE_("Playback")); row = uiLayoutRow(column, true); uiLayoutSetActive(row, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || @@ -446,7 +446,7 @@ static void nla_panel_actclip(const bContext *C, Panel *panel) uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Frame Start"), ICON_NONE); uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End"), ICON_NONE); - row = uiLayoutRowWithHeading(layout, false, "Sync Length"); + row = uiLayoutRowWithHeading(layout, false, IFACE_("Sync Length")); uiItemR(row, &strip_ptr, "use_sync_length", 0, "", ICON_NONE); uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length"); diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index f060693d9f4..b09536e0621 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -120,7 +120,7 @@ static SpaceLink *nla_new(const ScrArea *area, const Scene *scene) region->v2d.minzoom = 0.01f; region->v2d.maxzoom = 50; region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); - region->v2d.scroll |= (V2D_SCROLL_RIGHT); + region->v2d.scroll |= V2D_SCROLL_RIGHT; region->v2d.keepzoom = V2D_LOCKZOOM_Y; region->v2d.keepofs = V2D_KEEPOFS_Y; region->v2d.align = V2D_ALIGN_NO_POS_Y; @@ -191,7 +191,6 @@ static void nla_channel_region_draw(const bContext *C, ARegion *region) { bAnimContext ac; View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; /* clear and setup matrix */ UI_ThemeClearColor(TH_BACK); @@ -211,9 +210,7 @@ static void nla_channel_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } /* add handlers, stuff you only do once or on area/region changes */ @@ -237,7 +234,6 @@ static void nla_main_region_draw(const bContext *C, ARegion *region) Scene *scene = CTX_data_scene(C); bAnimContext ac; View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; short cfra_flag = 0; /* clear and setup matrix */ @@ -263,13 +259,10 @@ static void nla_main_region_draw(const bContext *C, ARegion *region) UI_view2d_text_cache_draw(region); } - UI_view2d_view_ortho(v2d); - /* current frame */ if (snla->flag & SNLA_DRAWTIME) { cfra_flag |= DRAWCFRA_UNIT_SECONDS; } - ANIM_draw_cfra(C, v2d, cfra_flag); /* markers */ UI_view2d_view_orthoSpecial(region, v2d, 1); @@ -290,11 +283,20 @@ static void nla_main_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); ED_time_scrub_draw(region, scene, snla->flag & SNLA_DRAWTIME, true); +} + +static void nla_main_region_draw_overlay(const bContext *C, ARegion *region) +{ + /* draw entirely, view changes should be handled here */ + const SpaceNla *snla = CTX_wm_space_nla(C); + const Scene *scene = CTX_data_scene(C); + View2D *v2d = ®ion->v2d; + + /* scrubbing region */ + ED_time_scrub_draw_current_frame(region, scene, snla->flag & SNLA_DRAWTIME, true); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } /* add handlers, stuff you only do once or on area/region changes */ @@ -620,6 +622,7 @@ void ED_spacetype_nla(void) art->regionid = RGN_TYPE_WINDOW; art->init = nla_main_region_init; art->draw = nla_main_region_draw; + art->draw_overlay = nla_main_region_draw_overlay; art->listener = nla_main_region_listener; art->message_subscribe = nla_main_region_message_subscribe; art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 4e21cdc9d16..f8c30f9a688 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -75,10 +75,6 @@ if(WITH_OPENIMAGEDENOISE) add_definitions(-DWITH_OPENIMAGEDENOISE) endif() -if (WITH_NEW_SIMULATION_TYPE) - add_definitions(-DWITH_NEW_SIMULATION_TYPE) -endif() - add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 01ac3a80871..234ca5d5ce6 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -849,12 +849,35 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "sky_type", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); - if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) { + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_PREETHAM) { + uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); + } + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_HOSEK) { + uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); uiItemR(layout, ptr, "ground_albedo", DEFAULT_FLAGS, NULL, ICON_NONE); } + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NISHITA) { + uiItemR(layout, ptr, "sun_disc", DEFAULT_FLAGS, NULL, 0); + + if (RNA_boolean_get(ptr, "sun_disc")) { + uiItemR(layout, ptr, "sun_size", DEFAULT_FLAGS, NULL, ICON_NONE); + } + + uiLayout *col; + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "sun_elevation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sun_rotation", DEFAULT_FLAGS, NULL, ICON_NONE); + + uiItemR(layout, ptr, "altitude", DEFAULT_FLAGS, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "air_density", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "dust_density", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "ozone_density", DEFAULT_FLAGS, NULL, ICON_NONE); + } } static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -991,7 +1014,14 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - uiItemPointerR(layout, ptr, "layer_name", &dataptr, "vertex_colors", "", ICON_GROUP_VCOL); + + if (RNA_collection_length(&dataptr, "sculpt_vertex_colors")) { + uiItemPointerR( + layout, ptr, "layer_name", &dataptr, "sculpt_vertex_colors", "", ICON_GROUP_VCOL); + } + else { + uiItemPointerR(layout, ptr, "layer_name", &dataptr, "vertex_colors", "", ICON_GROUP_VCOL); + } } else { uiItemL(layout, "No mesh in active object.", ICON_ERROR); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index bd8950c5085..c3823d8eb27 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1323,7 +1323,7 @@ static void node_draw_basis(const bContext *C, UI_BTYPE_LABEL, 0, showname, - (int)(rct->xmin + (NODE_MARGIN_X)), + (int)(rct->xmin + NODE_MARGIN_X), (int)(rct->ymax - NODE_DY), (short)(iconofs - rct->xmin - 18.0f), (short)NODE_DY, @@ -1772,7 +1772,6 @@ static void draw_group_overlay(const bContext *C, ARegion *region) void drawnodespace(const bContext *C, ARegion *region) { wmWindow *win = CTX_wm_window(C); - View2DScrollers *scrollers; SpaceNode *snode = CTX_wm_space_node(C); View2D *v2d = ®ion->v2d; @@ -1921,7 +1920,5 @@ void drawnodespace(const bContext *C, ARegion *region) draw_tree_path(snode); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index ac58ec1e636..11d87148713 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1428,11 +1428,15 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op)) Scene *sce = CTX_data_scene(C); bNode *node; + /* This is actually a test whether scene is used by the compositor or not. + * All the nodes are using same render result, so there is no need to do + * anything smart about check how exactly scene is used. */ for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->id == (ID *)sce && node->need_exec) { + if (node->id == (ID *)sce) { break; } } + if (node) { ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1); diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index f339d11b842..562aa6b078c 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -936,11 +936,10 @@ static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, bool free; const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free); for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) { -#ifndef WITH_NEW_SIMULATION_TYPE - if (STREQ(item_iter->identifier, "SimulationNodeTree")) { + if (!U.experimental.use_new_particle_system && + STREQ(item_iter->identifier, "SimulationNodeTree")) { continue; } -#endif RNA_enum_item_add(item, totitem, item_iter); } if (free) { diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 82ff9e06194..131491fcc40 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -581,7 +581,8 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op) "it won't be linked to any view layer"); } - BKE_collection_duplicate(bmain, parent, collection, true, true, !linked); + const eDupli_ID_Flags dupli_flags = USER_DUP_OBJECT | (linked ? 0 : U.dupflag); + BKE_collection_duplicate(bmain, parent, collection, dupli_flags, 0); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C)); diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index c2c9f3a5bfb..70a628eead0 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -907,6 +907,9 @@ static int outliner_item_drag_drop_invoke(bContext *C, return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } + /* Scroll view when dragging near edges */ + WM_operator_name_call(C, "VIEW2D_OT_edge_pan", WM_OP_INVOKE_DEFAULT, NULL); + wmDrag *drag = WM_event_start_drag(C, data.icon, WM_DRAG_ID, NULL, 0.0, WM_DRAG_NOP); if (ELEM(GS(data.drag_id->name), ID_OB, ID_GR)) { diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 9a9bd610322..5eee97e3fee 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -709,9 +709,9 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) Library *lib = (Library *)tselem->id; char expanded[FILE_MAX]; - BKE_library_filepath_set(bmain, lib, lib->name); + BKE_library_filepath_set(bmain, lib, lib->filepath); - BLI_strncpy(expanded, lib->name, sizeof(expanded)); + BLI_strncpy(expanded, lib->filepath, sizeof(expanded)); BLI_path_abs(expanded, BKE_main_blendfile_path(bmain)); if (!BLI_exists(expanded)) { BKE_reportf(CTX_wm_reports(C), @@ -1657,7 +1657,6 @@ static void outliner_draw_userbuts(uiBlock *block, uiBut *bt; ID *id = tselem->id; const char *tip = NULL; - int icon = ICON_NONE; char buf[16] = ""; int but_flag = UI_BUT_DRAG_LOCK; @@ -1683,18 +1682,16 @@ static void outliner_draw_userbuts(uiBlock *block, UI_but_flag_enable(bt, but_flag); if (id->flag & LIB_FAKEUSER) { - icon = ICON_FILE_TICK; tip = TIP_("Data-block will be retained using a fake user"); } else { - icon = ICON_X; tip = TIP_("Data-block has no users and will be deleted"); } bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, LIB_FAKEUSER, 1, - icon, + ICON_FAKE_USER_OFF, (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS), te->ys, UI_UNIT_X, @@ -1707,25 +1704,6 @@ static void outliner_draw_userbuts(uiBlock *block, tip); UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL); UI_but_flag_enable(bt, but_flag); - - bt = uiDefButBitS(block, - UI_BTYPE_ICON_TOGGLE, - LIB_FAKEUSER, - 1, - (id->flag & LIB_FAKEUSER) ? "F" : " ", - (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_FAKEUSER), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &id->flag, - 0, - 0, - 0, - 0, - TIP_("Data-block has a 'fake' user which will keep it in the file " - "even if nothing else uses it")); - UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL); - UI_but_flag_enable(bt, but_flag); } } @@ -1864,7 +1842,7 @@ static void outliner_buttons(const bContext *C, len = sizeof(((ModifierData *)0)->name); } else if (tselem->id && GS(tselem->id->name) == ID_LI) { - len = sizeof(((Library *)0)->name); + len = sizeof(((Library *)0)->filepath); } else { len = MAX_ID_NAME - 2; @@ -2288,6 +2266,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) data.icon = ICON_MATERIAL_DATA; break; case TSE_POSEGRP_BASE: + case TSE_POSEGRP: data.icon = ICON_GROUP_BONE; break; case TSE_SEQUENCE: @@ -2702,7 +2681,7 @@ static void tselem_draw_icon(uiBlock *block, 0.0, 1.0, alpha, - (data.drag_id && ID_IS_LINKED(data.drag_id)) ? data.drag_id->lib->name : ""); + (data.drag_id && ID_IS_LINKED(data.drag_id)) ? data.drag_id->lib->filepath : ""); } } @@ -3129,18 +3108,13 @@ static void outliner_draw_tree_element(bContext *C, offsx += 2 * ufac; } - if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) { - if (tselem->id->tag & LIB_TAG_MISSING) { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, - (float)*starty + 2 * ufac, - ICON_LIBRARY_DATA_BROKEN, - alpha_fac); - } - else if (tselem->id->tag & LIB_TAG_INDIRECT) { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, - (float)*starty + 2 * ufac, - ICON_LIBRARY_DATA_INDIRECT, - alpha_fac); + if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) || + ((tselem->type == TSE_RNA_STRUCT) && RNA_struct_is_ID(te->rnaptr.type))) { + const BIFIconID lib_icon = UI_library_icon_get(tselem->id); + if (lib_icon != ICON_NONE) { + UI_icon_draw_alpha( + (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, lib_icon, alpha_fac); + offsx += UI_UNIT_X + 4 * ufac; } else { UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, @@ -3171,13 +3145,6 @@ static void outliner_draw_tree_element(bContext *C, } offsx += UI_UNIT_X + 4 * ufac; } - else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_OVERRIDE_LIBRARY(tselem->id)) { - UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, - (float)*starty + 2 * ufac, - ICON_LIBRARY_DATA_OVERRIDE, - alpha_fac); - offsx += UI_UNIT_X + 4 * ufac; - } GPU_blend(false); /* name */ diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 3db75d9288b..bee8b28e658 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -191,7 +191,14 @@ static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEv /* Only toggle openclose on the same level as the first clicked element */ if (te->xs == data->x_location) { outliner_item_openclose(te, data->open, false); - ED_region_tag_redraw(region); + + /* Avoid rebuild if possible. */ + if (outliner_element_needs_rebuild_on_open_change(TREESTORE(te))) { + ED_region_tag_redraw(region); + } + else { + ED_region_tag_redraw_no_rebuild(region); + } } } @@ -231,7 +238,13 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1))); outliner_item_openclose(te, open, toggle_all); - ED_region_tag_redraw(region); + /* Avoid rebuild if possible. */ + if (outliner_element_needs_rebuild_on_open_change(TREESTORE(te))) { + ED_region_tag_redraw(region); + } + else { + ED_region_tag_redraw_no_rebuild(region); + } /* Only toggle once for single click toggling */ if (event->type == LEFTMOUSE) { @@ -532,7 +545,7 @@ static int outliner_id_delete_invoke_do(bContext *C, BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Cannot delete indirectly linked library '%s'", - ((Library *)tselem->id)->filepath); + ((Library *)tselem->id)->filepath_abs); return OPERATOR_CANCELLED; } id_delete(C, reports, te, tselem); @@ -898,12 +911,13 @@ static int lib_relocate( Library *lib = (Library *)tselem->id; char dir[FILE_MAXDIR], filename[FILE_MAX]; - BLI_split_dirfile(lib->filepath, dir, filename, sizeof(dir), sizeof(filename)); + BLI_split_dirfile(lib->filepath_abs, dir, filename, sizeof(dir), sizeof(filename)); - printf("%s, %s\n", tselem->id->name, lib->filepath); + printf("%s, %s\n", tselem->id->name, lib->filepath_abs); - /* We assume if both paths in lib are not the same then lib->name was relative... */ - RNA_boolean_set(&op_props, "relative_path", BLI_path_cmp(lib->filepath, lib->name) != 0); + /* We assume if both paths in lib are not the same then `lib->filepath` was relative. */ + RNA_boolean_set( + &op_props, "relative_path", BLI_path_cmp(lib->filepath_abs, lib->filepath) != 0); RNA_string_set(&op_props, "directory", dir); RNA_string_set(&op_props, "filename", filename); @@ -930,7 +944,7 @@ static int outliner_lib_relocate_invoke_do( BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Cannot relocate indirectly linked library '%s'", - ((Library *)tselem->id)->filepath); + ((Library *)tselem->id)->filepath_abs); return OPERATOR_CANCELLED; } else { diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index f2b64bc2a4b..b590eb75407 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -163,8 +163,7 @@ typedef enum { #define OL_Y_OFFSET 2 #define OL_TOG_USER_BUTS_USERS (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH) -#define OL_TOG_USER_BUTS_STATUS (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH) -#define OL_TOG_USER_BUTS_FAKEUSER (UI_UNIT_X + V2D_SCROLL_WIDTH) +#define OL_TOG_USER_BUTS_STATUS (UI_UNIT_X + V2D_SCROLL_WIDTH) #define OL_RNA_COLX (UI_UNIT_X * 15) #define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f) @@ -216,6 +215,16 @@ typedef struct TreeViewContext { Object *ob_pose; } TreeViewContext; +typedef enum TreeItemSelectAction { + OL_ITEM_DESELECT = 0, /* Deselect the item */ + OL_ITEM_SELECT = (1 << 0), /* Select the item */ + OL_ITEM_SELECT_DATA = (1 << 1), /* Select object data */ + OL_ITEM_ACTIVATE = (1 << 2), /* Activate the item */ + OL_ITEM_EXTEND = (1 << 3), /* Extend the current selection */ + OL_ITEM_RECURSIVE = (1 << 4), /* Select recursively */ + OL_ITEM_TOGGLE_MODE = (1 << 5) /* Temporary */ +} TreeItemSelectAction; + /* outliner_tree.c ----------------------------------------------- */ void outliner_free_tree(ListBase *tree); @@ -228,6 +237,8 @@ void outliner_build_tree(struct Main *mainvar, struct SpaceOutliner *soops, struct ARegion *region); +bool outliner_element_needs_rebuild_on_open_change(const TreeStoreElem *tselem); + typedef struct IDsSelectedData { struct ListBase selected_array; } IDsSelectedData; @@ -266,21 +277,16 @@ eOLDrawState tree_element_active(struct bContext *C, const eOLSetState set, const bool handle_all_types); -void outliner_item_do_activate_from_tree_element( - struct bContext *C, TreeElement *te, TreeStoreElem *tselem, bool extend, bool recursive); - -void outliner_item_select(struct SpaceOutliner *soops, - const struct TreeElement *te, - const bool extend, - const bool toggle); +void outliner_item_select(struct bContext *C, + struct SpaceOutliner *soops, + struct TreeElement *te, + const short select_flag); void outliner_object_mode_toggle(struct bContext *C, Scene *scene, ViewLayer *view_layer, Base *base); -void outliner_element_activate(struct SpaceOutliner *soops, struct TreeStoreElem *tselem); - bool outliner_item_is_co_over_name_icons(const TreeElement *te, float view_co_x); bool outliner_item_is_co_within_close_toggle(const TreeElement *te, float view_co_x); @@ -495,6 +501,7 @@ TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *outliner_find_id(struct SpaceOutliner *soops, ListBase *lb, const struct ID *id); TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan); TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone); +TreeElement *outliner_search_back_te(TreeElement *te, short idcode); struct ID *outliner_search_back(TreeElement *te, short idcode); bool outliner_tree_traverse(const SpaceOutliner *soops, ListBase *tree, diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index fa8422573ab..8a408a41897 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -111,7 +111,7 @@ static bool do_outliner_activate_common(bContext *C, * If extend is used, we try to have the other compatible selected objects in the new mode as well. * Otherwise only the new object will be active, selected and in the edit mode. */ -static void do_outliner_activate_obdata( +static void do_outliner_item_editmode_toggle( bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend) { Main *bmain = CTX_data_main(C); @@ -159,7 +159,7 @@ static void do_outliner_activate_obdata( } } -static void do_outliner_activate_pose( +static void do_outliner_item_posemode_toggle( bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend) { Main *bmain = CTX_data_main(C); @@ -214,10 +214,42 @@ void outliner_object_mode_toggle(bContext *C, Scene *scene, ViewLayer *view_laye { Object *obact = OBACT(view_layer); if (obact->mode & OB_MODE_EDIT) { - do_outliner_activate_obdata(C, scene, view_layer, base, true); + do_outliner_item_editmode_toggle(C, scene, view_layer, base, true); } else if (obact->mode & OB_MODE_POSE) { - do_outliner_activate_pose(C, scene, view_layer, base, true); + do_outliner_item_posemode_toggle(C, scene, view_layer, base, true); + } +} + +/* Toggle the item's interaction mode if supported */ +static void outliner_item_mode_toggle(bContext *C, + TreeViewContext *tvc, + TreeElement *te, + const bool extend) +{ + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->type == 0) { + if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) { + Object *ob = (Object *)outliner_search_back(te, ID_OB); + if ((ob != NULL) && (ob->data == tselem->id)) { + Base *base = BKE_view_layer_base_find(tvc->view_layer, ob); + if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) { + do_outliner_item_editmode_toggle(C, tvc->scene, tvc->view_layer, base, extend); + } + } + } + else if (ELEM(te->idcode, ID_GD)) { + /* set grease pencil to object mode */ + WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); + } + } + else if (tselem->type == TSE_POSE_BASE) { + Object *ob = (Object *)tselem->id; + Base *base = BKE_view_layer_base_find(tvc->view_layer, ob); + if (base != NULL) { + do_outliner_item_posemode_toggle(C, tvc->scene, tvc->view_layer, base, extend); + } } } @@ -302,28 +334,32 @@ static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_p static eOLDrawState tree_element_set_active_object(bContext *C, Scene *scene, ViewLayer *view_layer, - SpaceOutliner *soops, + SpaceOutliner *UNUSED(soops), TreeElement *te, const eOLSetState set, bool recursive) { TreeStoreElem *tselem = TREESTORE(te); TreeStoreElem *parent_tselem = NULL; + TreeElement *parent_te = NULL; Scene *sce; Base *base; Object *ob = NULL; - TreeElement *te_ob = NULL; /* if id is not object, we search back */ - if (te->idcode == ID_OB) { + if (tselem->type == 0 && te->idcode == ID_OB) { ob = (Object *)tselem->id; } else { - ob = (Object *)outliner_search_back(te, ID_OB); - - /* Don't return when activating children of the previous active object. */ - if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) { - return OL_DRAWSEL_NONE; + parent_te = outliner_search_back_te(te, ID_OB); + if (parent_te) { + parent_tselem = TREESTORE(parent_te); + ob = (Object *)parent_tselem->id; + + /* Don't return when activating children of the previous active object. */ + if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) { + return OL_DRAWSEL_NONE; + } } } if (ob == NULL) { @@ -356,11 +392,6 @@ static eOLDrawState tree_element_set_active_object(bContext *C, } } - te_ob = outliner_find_id(soops, &soops->tree, (ID *)ob); - if (te_ob != NULL && te_ob != te) { - parent_tselem = TREESTORE(te_ob); - } - if (base) { if (set == OL_SETSEL_EXTEND) { /* swap select */ @@ -863,8 +894,8 @@ static eOLDrawState tree_element_active_text(bContext *UNUSED(C), return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_pose(bContext *C, - Scene *scene, +static eOLDrawState tree_element_active_pose(bContext *UNUSED(C), + Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, @@ -879,7 +910,6 @@ static eOLDrawState tree_element_active_pose(bContext *C, } if (set != OL_SETSEL_NONE) { - do_outliner_activate_pose(C, scene, view_layer, base, (set == OL_SETSEL_EXTEND)); } else { if (ob->mode & OB_MODE_POSE) { @@ -1113,13 +1143,6 @@ eOLDrawState tree_element_type_active(bContext *C, /* ================================================ */ -/* Activate a tree store element and set the walk navigation start element */ -void outliner_element_activate(SpaceOutliner *soops, TreeStoreElem *tselem) -{ - outliner_flag_set(&soops->tree, TSE_ACTIVE | TSE_ACTIVE_WALK, false); - tselem->flag |= TSE_ACTIVE | TSE_ACTIVE_WALK; -} - /** * Action when clicking to activate an item (typically under the mouse cursor), * but don't do any cursor intersection checks. @@ -1133,9 +1156,8 @@ static void do_outliner_item_activate_tree_element(bContext *C, TreeStoreElem *tselem, const bool extend, const bool recursive, - const bool is_over_name_icons) + const bool do_activate_data) { - bool do_activate_data = soops->flag & SO_SYNC_SELECT || is_over_name_icons; /* Always makes active object, except for some specific types. */ if (ELEM(tselem->type, TSE_SEQUENCE, @@ -1153,7 +1175,6 @@ static void do_outliner_item_activate_tree_element(bContext *C, /* Support pose mode toggle, keeping the active object as is. */ } else if (do_activate_data) { - /* Only activate when synced selection is enabled */ tree_element_set_active_object(C, tvc->scene, tvc->view_layer, @@ -1164,9 +1185,6 @@ static void do_outliner_item_activate_tree_element(bContext *C, recursive && tselem->type == 0); } - /* Mark as active in the outliner */ - outliner_element_activate(soops, tselem); - if (tselem->type == 0) { // the lib blocks if (do_activate_data == false) { /* Only select in outliner. */ @@ -1216,19 +1234,6 @@ static void do_outliner_item_activate_tree_element(bContext *C, DEG_id_tag_update(&tvc->scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, tvc->scene); } - else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) { - Object *ob = (Object *)outliner_search_back(te, ID_OB); - if ((ob != NULL) && (ob->data == tselem->id)) { - Base *base = BKE_view_layer_base_find(tvc->view_layer, ob); - if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) { - do_outliner_activate_obdata(C, tvc->scene, tvc->view_layer, base, extend); - } - } - } - else if (ELEM(te->idcode, ID_GD)) { - /* set grease pencil to object mode */ - WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); - } else { // rest of types tree_element_active(C, tvc, soops, te, OL_SETSEL_NORMAL, false); } @@ -1239,23 +1244,49 @@ static void do_outliner_item_activate_tree_element(bContext *C, } } -/** - * \param extend: Don't deselect other items, only modify \a te. - * \param toggle: Select \a te when not selected, deselect when selected. - */ -void outliner_item_select(SpaceOutliner *soops, - const TreeElement *te, - const bool extend, - const bool toggle) +/* Select the item using the set flags */ +void outliner_item_select(bContext *C, + SpaceOutliner *soops, + TreeElement *te, + const short select_flag) { TreeStoreElem *tselem = TREESTORE(te); - const short new_flag = (toggle && (tselem->flag & TSE_ACTIVE)) ? (tselem->flag ^ TSE_SELECTED) : - (tselem->flag | TSE_SELECTED); + const bool activate = select_flag & OL_ITEM_ACTIVATE; + const bool extend = select_flag & OL_ITEM_EXTEND; + const bool activate_data = select_flag & OL_ITEM_SELECT_DATA; - if (extend == false) { - outliner_flag_set(&soops->tree, TSE_SELECTED, false); + /* Clear previous active when activating and clear selection when not extending selection */ + const short clear_flag = (activate ? TSE_ACTIVE : 0) | (extend ? 0 : TSE_SELECTED); + if (clear_flag) { + outliner_flag_set(&soops->tree, clear_flag, false); + } + + if (select_flag & OL_ITEM_SELECT) { + tselem->flag |= TSE_SELECTED; + } + else { + tselem->flag &= ~TSE_SELECTED; + } + + if (activate) { + TreeViewContext tvc; + outliner_viewcontext_init(C, &tvc); + + tselem->flag |= TSE_ACTIVE; + do_outliner_item_activate_tree_element(C, + &tvc, + soops, + te, + tselem, + extend, + select_flag & OL_ITEM_RECURSIVE, + activate_data || soops->flag & SO_SYNC_SELECT); + + /* Mode toggle on data activate for now, but move later */ + if (select_flag & OL_ITEM_TOGGLE_MODE) { + outliner_item_mode_toggle(C, &tvc, te, extend); + } } - tselem->flag = new_flag; } static bool do_outliner_range_select_recursive(ListBase *lb, @@ -1298,8 +1329,7 @@ static void do_outliner_range_select(bContext *C, /* If no active element exists, activate the element under the cursor */ if (!active) { - outliner_item_select(soops, cursor, false, false); - outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false); + outliner_item_select(C, soops, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE); return; } @@ -1312,14 +1342,13 @@ static void do_outliner_range_select(bContext *C, /* Select active if under cursor */ if (active == cursor) { - TREESTORE(cursor)->flag |= TSE_SELECTED; + outliner_item_select(C, soops, cursor, OL_ITEM_SELECT); return; } - /* If active is not selected, select the element under the cursor */ + /* If active is not selected or visible, select and activate the element under the cursor */ if (!active_selected || !outliner_is_element_visible(active)) { - outliner_item_select(soops, cursor, false, false); - outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false); + outliner_item_select(C, soops, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE); return; } @@ -1334,23 +1363,6 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops, } /** - * A version of #outliner_item_do_activate_from_cursor that takes the tree element directly. - * and doesn't depend on the pointer position. - * - * This allows us to simulate clicking on an item without dealing with the mouse cursor. - */ -void outliner_item_do_activate_from_tree_element( - bContext *C, TreeElement *te, TreeStoreElem *tselem, bool extend, bool recursive) -{ - SpaceOutliner *soops = CTX_wm_space_outliner(C); - - TreeViewContext tvc; - outliner_viewcontext_init(C, &tvc); - - do_outliner_item_activate_tree_element(C, &tvc, soops, te, tselem, extend, recursive, false); -} - -/** * Action to run when clicking in the outliner, * * May expend/collapse branches or activate items. @@ -1402,14 +1414,17 @@ static int outliner_item_do_activate_from_cursor(bContext *C, do_outliner_range_select(C, soops, activate_te, extend); } else { - TreeViewContext tvc; - outliner_viewcontext_init(C, &tvc); - const bool is_over_name_icons = outliner_item_is_co_over_name_icons(activate_te, view_mval[0]); - outliner_item_select(soops, activate_te, extend, extend); - do_outliner_item_activate_tree_element( - C, &tvc, soops, activate_te, activate_tselem, extend, false, is_over_name_icons); + /* Always select unless already active and selected */ + const bool select = !extend || !(activate_tselem->flag & TSE_ACTIVE && + activate_tselem->flag & TSE_SELECTED); + + const short select_flag = OL_ITEM_ACTIVATE | (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | + (is_over_name_icons ? OL_ITEM_SELECT_DATA : 0) | + (extend ? OL_ITEM_EXTEND : 0) | OL_ITEM_TOGGLE_MODE; + + outliner_item_select(C, soops, activate_te, select_flag); } changed = true; @@ -1468,23 +1483,19 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) /* **************** Box Select Tool ****************** */ static void outliner_item_box_select( - SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select) + bContext *C, SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select) { TreeStoreElem *tselem = TREESTORE(te); if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) { - if (select) { - tselem->flag |= TSE_SELECTED; - } - else { - tselem->flag &= ~TSE_SELECTED; - } + outliner_item_select( + C, soops, te, (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | OL_ITEM_EXTEND); } /* Look at its children. */ if (TSELEM_OPEN(tselem, soops)) { for (te = te->subtree.first; te; te = te->next) { - outliner_item_box_select(soops, scene, rectf, te, select); + outliner_item_box_select(C, soops, scene, rectf, te, select); } } } @@ -1506,7 +1517,7 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); LISTBASE_FOREACH (TreeElement *, te, &soops->tree) { - outliner_item_box_select(soops, scene, &rectf, te, select); + outliner_item_box_select(C, soops, scene, &rectf, te, select); } DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); @@ -1587,17 +1598,17 @@ static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *soops, } /* Find previous visible element in the tree */ -static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *walk_element) +static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *te) { - if (walk_element->prev) { - walk_element = outliner_find_rightmost_visible_child(soops, walk_element->prev); + if (te->prev) { + te = outliner_find_rightmost_visible_child(soops, te->prev); } - else if (walk_element->parent) { + else if (te->parent) { /* Use parent if at beginning of list */ - walk_element = walk_element->parent; + te = te->parent; } - return walk_element; + return te; } /* Recursively search up the tree until a successor to a given element is found */ @@ -1618,98 +1629,78 @@ static TreeElement *outliner_element_find_successor_in_parents(TreeElement *te) } /* Find next visible element in the tree */ -static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *walk_element) +static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *te) { - TreeStoreElem *tselem = TREESTORE(walk_element); + TreeStoreElem *tselem = TREESTORE(te); - if (TSELEM_OPEN(tselem, soops) && walk_element->subtree.first) { - walk_element = walk_element->subtree.first; + if (TSELEM_OPEN(tselem, soops) && te->subtree.first) { + te = te->subtree.first; } - else if (walk_element->next) { - walk_element = walk_element->next; + else if (te->next) { + te = te->next; } else { - walk_element = outliner_element_find_successor_in_parents(walk_element); + te = outliner_element_find_successor_in_parents(te); } - return walk_element; + return te; } static TreeElement *do_outliner_select_walk(SpaceOutliner *soops, - TreeElement *walk_element, + TreeElement *te, const int direction, const bool extend, const bool toggle_all) { - TreeStoreElem *tselem = TREESTORE(walk_element); - - if (!extend) { - outliner_flag_set(&soops->tree, TSE_SELECTED, false); - } - tselem->flag &= ~TSE_ACTIVE_WALK; + TreeStoreElem *tselem = TREESTORE(te); switch (direction) { case UI_SELECT_WALK_UP: - walk_element = outliner_find_previous_element(soops, walk_element); + te = outliner_find_previous_element(soops, te); break; case UI_SELECT_WALK_DOWN: - walk_element = outliner_find_next_element(soops, walk_element); + te = outliner_find_next_element(soops, te); break; case UI_SELECT_WALK_LEFT: - outliner_item_openclose(walk_element, false, toggle_all); + outliner_item_openclose(te, false, toggle_all); break; case UI_SELECT_WALK_RIGHT: - outliner_item_openclose(walk_element, true, toggle_all); + outliner_item_openclose(te, true, toggle_all); break; } - TreeStoreElem *tselem_new = TREESTORE(walk_element); - /* If new element is already selected, deselect the previous element */ + TreeStoreElem *tselem_new = TREESTORE(te); if (extend) { tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) : (tselem->flag | TSE_SELECTED); } - tselem_new->flag |= TSE_SELECTED | TSE_ACTIVE_WALK; - - return walk_element; + return te; } -/* Find walk select element, or set it if it does not exist. - * Changed is set to true if walk element is found, false if it was set */ +/* Find the active element to walk from, or set one if none exists. + * Changed is set to true if the active element is found, or false if it was set */ static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *changed) { - TreeElement *walk_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE_WALK); - + TreeElement *active_te = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE); *changed = false; - /* If no walk element exists, start from active */ - if (!walk_element) { - TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE); - - /* If no active element exists, use the first element in the tree */ - if (!active_element) { - walk_element = soops->tree.first; - } - else { - walk_element = active_element; - } - + /* If no active element exists, use the first element in the tree */ + if (!active_te) { + active_te = soops->tree.first; *changed = true; } - /* If walk element is not visible, set that element's first visible parent as walk element */ - if (!outliner_is_element_visible(walk_element)) { - TREESTORE(walk_element)->flag &= ~TSE_ACTIVE_WALK; - - while (!outliner_is_element_visible(walk_element)) { - walk_element = walk_element->parent; + /* If the active element is not visible, activate the first visible parent element */ + if (!outliner_is_element_visible(active_te)) { + while (!outliner_is_element_visible(active_te)) { + active_te = active_te->parent; } *changed = true; } - return walk_element; + return active_te; } /* Scroll the outliner when the walk element reaches the top or bottom boundary */ @@ -1738,18 +1729,18 @@ static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEven const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all"); bool changed; - TreeElement *walk_element = find_walk_select_start_element(soops, &changed); + TreeElement *active_te = find_walk_select_start_element(soops, &changed); - /* If finding the starting walk select element did not move the element, proceed to walk */ + /* If finding the active element did not modify the selection, proceed to walk */ if (!changed) { - walk_element = do_outliner_select_walk(soops, walk_element, direction, extend, toggle_all); - } - else { - TREESTORE(walk_element)->flag |= TSE_SELECTED | TSE_ACTIVE_WALK; + active_te = do_outliner_select_walk(soops, active_te, direction, extend, toggle_all); } + outliner_item_select( + C, soops, active_te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | (extend ? OL_ITEM_EXTEND : 0)); + /* Scroll outliner to focus on walk element */ - outliner_walk_scroll(region, walk_element); + outliner_walk_scroll(region, active_te); ED_outliner_select_sync_from_outliner(C, soops); ED_region_tag_redraw(region); diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c index 852773d3979..a4be4062746 100644 --- a/source/blender/editors/space_outliner/outliner_sync.c +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -392,7 +392,6 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *soops) } static void outliner_select_sync_from_object(ViewLayer *view_layer, - SpaceOutliner *soops, Object *obact, TreeElement *te, TreeStoreElem *tselem) @@ -403,7 +402,7 @@ static void outliner_select_sync_from_object(ViewLayer *view_layer, const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0); if (base && (ob == obact)) { - outliner_element_activate(soops, tselem); + tselem->flag |= TSE_ACTIVE; } else { tselem->flag &= ~TSE_ACTIVE; @@ -417,15 +416,14 @@ static void outliner_select_sync_from_object(ViewLayer *view_layer, } } -static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops, - EditBone *ebone_active, +static void outliner_select_sync_from_edit_bone(EditBone *ebone_active, TreeElement *te, TreeStoreElem *tselem) { EditBone *ebone = (EditBone *)te->directdata; if (ebone == ebone_active) { - outliner_element_activate(soops, tselem); + tselem->flag |= TSE_ACTIVE; } else { tselem->flag &= ~TSE_ACTIVE; @@ -439,8 +437,7 @@ static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops, } } -static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops, - bPoseChannel *pchan_active, +static void outliner_select_sync_from_pose_bone(bPoseChannel *pchan_active, TreeElement *te, TreeStoreElem *tselem) { @@ -448,7 +445,7 @@ static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops, Bone *bone = pchan->bone; if (pchan == pchan_active) { - outliner_element_activate(soops, tselem); + tselem->flag |= TSE_ACTIVE; } else { tselem->flag &= ~TSE_ACTIVE; @@ -462,14 +459,12 @@ static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops, } } -static void outliner_select_sync_from_sequence(SpaceOutliner *soops, - Sequence *sequence_active, - TreeStoreElem *tselem) +static void outliner_select_sync_from_sequence(Sequence *sequence_active, TreeStoreElem *tselem) { Sequence *seq = (Sequence *)tselem->id; if (seq == sequence_active) { - outliner_element_activate(soops, tselem); + tselem->flag |= TSE_ACTIVE; } else { tselem->flag &= ~TSE_ACTIVE; @@ -506,26 +501,26 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer, if (tselem->type == 0 && te->idcode == ID_OB) { if (sync_types->object) { - outliner_select_sync_from_object(view_layer, soops, active_data->object, te, tselem); + outliner_select_sync_from_object(view_layer, active_data->object, te, tselem); } } else if (tselem->type == TSE_EBONE) { if (sync_types->edit_bone) { - outliner_select_sync_from_edit_bone(soops, active_data->edit_bone, te, tselem); + outliner_select_sync_from_edit_bone(active_data->edit_bone, te, tselem); } } else if (tselem->type == TSE_POSE_CHANNEL) { if (sync_types->pose_bone) { - outliner_select_sync_from_pose_bone(soops, active_data->pose_channel, te, tselem); + outliner_select_sync_from_pose_bone(active_data->pose_channel, te, tselem); } } else if (tselem->type == TSE_SEQUENCE) { if (sync_types->sequence) { - outliner_select_sync_from_sequence(soops, active_data->sequence, tselem); + outliner_select_sync_from_sequence(active_data->sequence, tselem); } } else { - tselem->flag &= ~TSE_SELECTED; + tselem->flag &= ~(TSE_SELECTED | TSE_ACTIVE); } /* Sync subtree elements */ diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index b4c5dd8813a..51b919cd0dc 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -44,6 +44,7 @@ #include "DNA_world_types.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "BKE_anim_data.h" @@ -573,8 +574,7 @@ static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1) SpaceOutliner *soops = CTX_wm_space_outliner(C); TreeElement *te = (TreeElement *)element; - outliner_item_select(soops, te, false, false); - outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false); + outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE); ED_outliner_select_sync_from_outliner(C, soops); } @@ -664,12 +664,13 @@ static void object_select_hierarchy_cb(bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, + TreeStoreElem *UNUSED(tselem), void *UNUSED(user_data)) { /* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item. * it's especially confusing when multiple items are selected since some toggle on/off. */ - outliner_item_do_activate_from_tree_element(C, te, tselem, false, true); + SpaceOutliner *soops = CTX_wm_space_outliner(C); + outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | OL_ITEM_RECURSIVE); } static void object_deselect_cb(bContext *C, @@ -689,12 +690,8 @@ static void object_deselect_cb(bContext *C, } } -static void outliner_object_delete(bContext *C, - ReportList *reports, - Scene *scene, - TreeStoreElem *tselem) +static void outliner_object_delete_fn(bContext *C, ReportList *reports, Scene *scene, Object *ob) { - Object *ob = (Object *)tselem->id; if (ob) { Main *bmain = CTX_data_main(C); if (ob->id.tag & LIB_TAG_INDIRECT) { @@ -862,7 +859,6 @@ void outliner_do_object_operation_ex(bContext *C, bool select_recurse) { TreeElement *te; - for (te = lb->first; te; te = te->next) { TreeStoreElem *tselem = TREESTORE(te); bool select_handled = false; @@ -1177,82 +1173,6 @@ static void outliner_do_data_operation( } } -static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base) -{ - Base *child_base, *base_next; - Object *parent; - ViewLayer *view_layer = CTX_data_view_layer(C); - - if (!base) { - return NULL; - } - - for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) { - base_next = child_base->next; - for (parent = child_base->object->parent; parent && (parent != base->object); - parent = parent->parent) { - /* pass */ - } - if (parent) { - base_next = outline_delete_hierarchy(C, reports, scene, child_base); - } - } - - base_next = base->next; - - Main *bmain = CTX_data_main(C); - if (base->object->id.tag & LIB_TAG_INDIRECT) { - BKE_reportf(reports, - RPT_WARNING, - "Cannot delete indirectly linked object '%s'", - base->object->id.name + 2); - return base_next; - } - else if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) { - BKE_reportf(reports, - RPT_WARNING, - "Cannot delete object '%s' from scene '%s', indirectly used objects need at least " - "one user", - base->object->id.name + 2, - scene->id.name + 2); - return base_next; - } - ED_object_base_free_and_unlink(CTX_data_main(C), scene, base->object); - return base_next; -} - -static void object_delete_hierarchy_cb(bContext *C, - ReportList *reports, - Scene *scene, - TreeElement *te, - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *UNUSED(user_data)) -{ - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = (Base *)te->directdata; - Object *obedit = CTX_data_edit_object(C); - - if (!base) { - base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id); - } - if (base) { - /* Check also library later. */ - for (; obedit && (obedit != base->object); obedit = obedit->parent) { - /* pass */ - } - if (obedit == base->object) { - ED_object_editmode_exit(C, EM_FREEDATA); - } - - outline_delete_hierarchy(C, reports, scene, base); - } - - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); -} - static Base *outline_batch_delete_hierarchy( ReportList *reports, Main *bmain, ViewLayer *view_layer, Scene *scene, Base *base) { @@ -1305,21 +1225,16 @@ static Base *outline_batch_delete_hierarchy( return base_next; } -static void object_batch_delete_hierarchy_cb(bContext *C, +static void object_batch_delete_hierarchy_fn(bContext *C, ReportList *reports, Scene *scene, - TreeElement *te, - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *UNUSED(user_data)) + Object *ob) { ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = (Base *)te->directdata; Object *obedit = CTX_data_edit_object(C); - if (!base) { - base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id); - } + Base *base = BKE_view_layer_base_find(view_layer, ob); + if (base) { /* Check also library later. */ for (; obedit && (obedit != base->object); obedit = obedit->parent) { @@ -1343,7 +1258,6 @@ enum { OL_OP_SELECT = 1, OL_OP_DESELECT, OL_OP_SELECT_HIERARCHY, - OL_OP_DELETE_HIERARCHY, OL_OP_REMAP, OL_OP_LOCALIZED, /* disabled, see below */ OL_OP_TOGVIS, @@ -1358,7 +1272,6 @@ static const EnumPropertyItem prop_object_op_types[] = { {OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""}, {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""}, {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""}, - {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""}, {OL_OP_REMAP, "REMAP", 0, @@ -1372,7 +1285,6 @@ static const EnumPropertyItem prop_object_op_types[] = { static int outliner_object_operation_exec(bContext *C, wmOperator *op) { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); wmWindow *win = CTX_wm_window(C); @@ -1413,43 +1325,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) str = "Deselect Objects"; selection_changed = true; } - else if (event == OL_OP_DELETE_HIERARCHY) { - ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *basact_prev = BASACT(view_layer); - - /* Keeping old 'safe and slow' code for a bit (new one enabled on 28/01/2019). */ - if (G.debug_value == 666) { - outliner_do_object_operation_ex( - C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false); - } - else { - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - - outliner_do_object_operation_ex(C, - op->reports, - scene, - soops, - &soops->tree, - object_batch_delete_hierarchy_cb, - NULL, - false); - - BKE_id_multi_tagged_delete(bmain); - } - - /* XXX: See outliner_delete_exec comment below. */ - outliner_cleanup_tree(soops); - - DEG_relations_tag_update(bmain); - str = "Delete Object Hierarchy"; - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - if (basact_prev != BASACT(view_layer)) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); - } - selection_changed = true; - } else if (event == OL_OP_REMAP) { outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth trick @@ -1513,22 +1388,38 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot) /** \name Delete Object/Collection Operator * \{ */ -static void outliner_objects_delete( - bContext *C, Scene *scene, SpaceOutliner *soops, ReportList *reports, ListBase *lb) +typedef void (*OutlinerDeleteFunc)(bContext *C, ReportList *reports, Scene *scene, Object *ob); + +static void outliner_do_object_delete(bContext *C, + ReportList *reports, + Scene *scene, + GSet *objects_to_delete, + OutlinerDeleteFunc delete_fn) { - LISTBASE_FOREACH (TreeElement *, te, lb) { - TreeStoreElem *tselem = TREESTORE(te); + GSetIterator objects_to_delete_iter; + GSET_ITER (objects_to_delete_iter, objects_to_delete) { + Object *ob = (Object *)BLI_gsetIterator_getKey(&objects_to_delete_iter); - if (tselem->flag & TSE_SELECTED) { - if (tselem->type == 0 && te->idcode == ID_OB) { - outliner_object_delete(C, reports, scene, tselem); - } - } + delete_fn(C, reports, scene, ob); + } +} - if (TSELEM_OPEN(tselem, soops)) { - outliner_objects_delete(C, scene, soops, reports, &te->subtree); - } +static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void *customdata) +{ + GSet *objects_to_delete = (GSet *)customdata; + TreeStoreElem *tselem = TREESTORE(te); + + if (outliner_is_collection_tree_element(te)) { + return TRAVERSE_CONTINUE; } + + if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) { + return TRAVERSE_SKIP_CHILDS; + } + + BLI_gset_add(objects_to_delete, tselem->id); + + return TRAVERSE_CONTINUE; } static int outliner_delete_exec(bContext *C, wmOperator *op) @@ -1537,12 +1428,32 @@ static int outliner_delete_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); struct wmMsgBus *mbus = CTX_wm_message_bus(C); - ViewLayer *view_layer = CTX_data_view_layer(C); const Base *basact_prev = BASACT(view_layer); - outliner_collection_delete(C, bmain, scene, op->reports, false); - outliner_objects_delete(C, scene, soops, op->reports, &soops->tree); + const bool delete_hierarchy = RNA_boolean_get(op->ptr, "hierarchy"); + + /* Get selected objects skipping duplicates to prevent deleting objects linked to multiple + * collections twice */ + GSet *objects_to_delete = BLI_gset_ptr_new(__func__); + outliner_tree_traverse( + soops, &soops->tree, 0, TSE_SELECTED, outliner_find_objects_to_delete, objects_to_delete); + + if (delete_hierarchy) { + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + outliner_do_object_delete( + C, op->reports, scene, objects_to_delete, object_batch_delete_hierarchy_fn); + + BKE_id_multi_tagged_delete(bmain); + } + else { + outliner_do_object_delete(C, op->reports, scene, objects_to_delete, outliner_object_delete_fn); + } + + BLI_gset_free(objects_to_delete, NULL); + + outliner_collection_delete(C, bmain, scene, op->reports, delete_hierarchy); /* Tree management normally happens from draw_outliner(), but when * you're clicking too fast on Delete object from context menu in @@ -1579,6 +1490,11 @@ void OUTLINER_OT_delete(wmOperatorType *ot) /* flags */ ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index d6efe683673..bc272431e3a 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -235,6 +235,17 @@ static TreeElement *outliner_add_element( /* -------------------------------------------------------- */ +/** + * Check if an element type needs a full rebuild if the open/collapsed state changes. + * These element types don't add children if collapsed. + * + * This current check isn't great really. A per element-type flag would be preferable. + */ +bool outliner_element_needs_rebuild_on_open_change(const TreeStoreElem *tselem) +{ + return ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_KEYMAP); +} + /* special handling of hierarchical non-lib data */ static void outliner_add_bone( SpaceOutliner *soops, ListBase *lb, ID *id, Bone *curBone, TreeElement *parent, int *a) @@ -538,7 +549,7 @@ static void outliner_add_id_contents(SpaceOutliner *soops, /* expand specific data always */ switch (GS(id->name)) { case ID_LI: { - te->name = ((Library *)id)->name; + te->name = ((Library *)id)->filepath; break; } case ID_SCE: { @@ -786,8 +797,13 @@ static void outliner_add_id_contents(SpaceOutliner *soops, } } -// TODO: this function needs to be split up! It's getting a bit too large... -// Note: "ID" is not always a real ID +/** + * TODO: this function needs to be split up! It's getting a bit too large... + * + * \note: "ID" is not always a real ID + * \note: If child items are only added to the tree if the item is open, the TSE_ type _must_ be + * added to #outliner_element_needs_rebuild_on_open_change(). + */ static TreeElement *outliner_add_element( SpaceOutliner *soops, ListBase *lb, void *idv, TreeElement *parent, short type, short index) { @@ -854,7 +870,7 @@ static TreeElement *outliner_add_element( else { /* do here too, for blend file viewer, own ID_LI then shows file name */ if (GS(id->name) == ID_LI) { - te->name = ((Library *)id)->name; + te->name = ((Library *)id)->filepath; } else { te->name = id->name + 2; // default, can be overridden by Library or non-ID data @@ -2340,8 +2356,10 @@ void outliner_build_tree( for (lib = mainvar->libraries.first; lib; lib = lib->id.next) { ten = outliner_add_library_contents(mainvar, soops, &soops->tree, lib); - BLI_assert(ten != NULL); - lib->id.newid = (ID *)ten; + /* NULL-check matters, due to filtering there may not be a new element. */ + if (ten) { + lib->id.newid = (ID *)ten; + } } /* make hierarchy */ ten = soops->tree.first; diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index a058c30cef2..a120718e36b 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -84,12 +84,24 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops, /* co_y is inside this element */ return te_iter; } - else if (TSELEM_OPEN(te_iter->store_elem, soops)) { - /* co_y is lower than current element, possibly inside children */ - TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y); - if (te_sub) { - return te_sub; - } + + if (BLI_listbase_is_empty(&te_iter->subtree) || !TSELEM_OPEN(TREESTORE(te_iter), soops)) { + /* No need for recursion. */ + continue; + } + + /* If the coordinate is lower than the next element, we can continue with that one and skip + * recursion too. */ + const TreeElement *te_next = te_iter->next; + if (te_next && (view_co_y < (te_next->ys + UI_UNIT_Y))) { + continue; + } + + /* co_y is lower than current element (but not lower than the next one), possibly inside + * children */ + TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y); + if (te_sub) { + return te_sub; } } } @@ -256,7 +268,7 @@ TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone) return NULL; } -ID *outliner_search_back(TreeElement *te, short idcode) +TreeElement *outliner_search_back_te(TreeElement *te, short idcode) { TreeStoreElem *tselem; te = te->parent; @@ -264,13 +276,26 @@ ID *outliner_search_back(TreeElement *te, short idcode) while (te) { tselem = TREESTORE(te); if (tselem->type == 0 && te->idcode == idcode) { - return tselem->id; + return te; } te = te->parent; } return NULL; } +ID *outliner_search_back(TreeElement *te, short idcode) +{ + TreeElement *search_te; + TreeStoreElem *tselem; + + search_te = outliner_search_back_te(te, idcode); + if (search_te) { + tselem = TREESTORE(search_te); + return tselem->id; + } + return NULL; +} + /** * Iterate over all tree elements (pre-order traversal), executing \a func callback for * each tree element matching the optional filters. diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 9450136b6a6..aa1663dff01 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -84,7 +84,6 @@ static void outliner_main_region_init(wmWindowManager *wm, ARegion *region) static void outliner_main_region_draw(const bContext *C, ARegion *region) { View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; /* clear */ UI_ThemeClearColor(TH_BACK); @@ -96,9 +95,7 @@ static void outliner_main_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); /* scrollers */ - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); + UI_view2d_scrollers_draw(v2d, NULL); } static void outliner_main_region_free(ARegion *UNUSED(region)) @@ -215,7 +212,7 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), } break; case NC_SCREEN: - if (ELEM(wmn->data, ND_LAYER)) { + if (ELEM(wmn->data, ND_LAYOUTDELETE, ND_LAYER)) { ED_region_tag_redraw(region); } break; @@ -398,7 +395,7 @@ static void outliner_deactivate(struct ScrArea *area) /* Remove hover highlights */ SpaceOutliner *soops = area->spacedata.first; outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false); - ED_region_tag_redraw(BKE_area_find_region_type(area, RGN_TYPE_WINDOW)); + ED_region_tag_redraw_no_rebuild(BKE_area_find_region_type(area, RGN_TYPE_WINDOW)); } /* only called once, from space_api/spacetypes.c */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 1f06ab68516..1af552680a3 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -697,7 +697,8 @@ static void draw_seq_text(View2D *v2d, str_len = 0; } else if (seq->sound) { - str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d", name, seq->sound->name, seq->len); + str_len = BLI_snprintf( + str, sizeof(str), "%s: %s | %d", name, seq->sound->filepath, seq->len); } else { str_len = BLI_snprintf(str, sizeof(str), "%s | %d", name, seq->len); @@ -2257,7 +2258,6 @@ void draw_timeline_seq(const bContext *C, ARegion *region) Editing *ed = BKE_sequencer_editing_get(scene, false); SpaceSeq *sseq = CTX_wm_space_seq(C); View2D *v2d = ®ion->v2d; - View2DScrollers *scrollers; short cfra_flag = 0; float col[3]; @@ -2299,9 +2299,6 @@ void draw_timeline_seq(const bContext *C, ARegion *region) cfra_flag |= DRAWCFRA_UNIT_SECONDS; } - /* Draw the current frame indicator. */ - ANIM_draw_cfra(C, v2d, cfra_flag); - /* Draw overlap frame frame indicator. */ if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? @@ -2345,9 +2342,6 @@ void draw_timeline_seq(const bContext *C, ARegion *region) ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); UI_view2d_view_restore(C); ED_time_scrub_draw(region, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); - scrollers = UI_view2d_scrollers_calc(v2d, NULL); - UI_view2d_scrollers_draw(v2d, scrollers); - UI_view2d_scrollers_free(scrollers); /* Draw channel numbers. */ { @@ -2357,3 +2351,13 @@ void draw_timeline_seq(const bContext *C, ARegion *region) UI_view2d_draw_scale_y__block(region, v2d, &rect, TH_SCROLL_TEXT); } } + +void draw_timeline_seq_display(const bContext *C, ARegion *region) +{ + const Scene *scene = CTX_data_scene(C); + const SpaceSeq *sseq = CTX_wm_space_seq(C); + View2D *v2d = ®ion->v2d; + + ED_time_scrub_draw_current_frame(region, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); + UI_view2d_scrollers_draw(v2d, NULL); +} diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 9311cbed265..f74a4eae3bb 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -673,6 +673,14 @@ int seq_effect_find_selected(Scene *scene, *r_selseq2 = seq2; *r_selseq3 = seq3; + /* TODO(Richard): This function needs some refactoring, this is just quick hack for T73828. */ + if (BKE_sequence_effect_get_num_inputs(type) < 3) { + *r_selseq3 = NULL; + } + if (BKE_sequence_effect_get_num_inputs(type) < 2) { + *r_selseq2 = NULL; + } + return 1; } @@ -1403,14 +1411,21 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene); } } - else if (seq->type & SEQ_TYPE_EFFECT) { + } + + /* Recalculate bounds of effect strips. */ + for (seq = ed->seqbasep->first; seq; seq = seq->next) { + if (seq->type & SEQ_TYPE_EFFECT) { if (seq->seq1 && (seq->seq1->flag & SELECT)) { + BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); BKE_sequence_calc(scene, seq); } else if (seq->seq2 && (seq->seq2->flag & SELECT)) { + BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); BKE_sequence_calc(scene, seq); } else if (seq->seq3 && (seq->seq3->flag & SELECT)) { + BKE_sequencer_offset_animdata(scene, seq, (snap_frame - seq->startdisp)); BKE_sequence_calc(scene, seq); } } @@ -2218,6 +2233,11 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) Sequence *seq1, *seq2, *seq3, *last_seq = BKE_sequencer_active_get(scene); const char *error_msg; + if (BKE_sequence_effect_get_num_inputs(last_seq->type) != 0) { + BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: strip has no inputs"); + return OPERATOR_CANCELLED; + } + if (!seq_effect_find_selected( scene, last_seq, last_seq->type, &seq1, &seq2, &seq3, &error_msg)) { BKE_report(op->reports, RPT_ERROR, error_msg); @@ -3433,6 +3453,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op)) * on the actual data-blocks. */ BKE_sequencer_base_clipboard_pointers_restore(&seqbase_clipboard, bmain); BKE_sequence_base_dupli_recursive(scene, scene, &nseqbase, &seqbase_clipboard, 0, 0); + BKE_sequencer_base_clipboard_pointers_store(bmain, &seqbase_clipboard); iseq_first = nseqbase.first; @@ -3451,6 +3472,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op)) } DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); ED_outliner_select_sync_from_sequence_tag(C); @@ -3925,7 +3947,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) } char filepath[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filepath); - BLI_strncpy(sound->name, filepath, sizeof(sound->name)); + BLI_strncpy(sound->filepath, filepath, sizeof(sound->filepath)); BKE_sound_load(bmain, sound); } else { diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 12533dbc74f..fee07e8941d 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -43,6 +43,7 @@ struct wmOperator; /* sequencer_draw.c */ void draw_timeline_seq(const struct bContext *C, struct ARegion *region); +void draw_timeline_seq_display(const struct bContext *C, struct ARegion *region); void sequencer_draw_preview(const struct bContext *C, struct Scene *scene, struct ARegion *region, diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 2686edd58a5..85b70354ab3 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -409,32 +409,15 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) /* Select left, right or overlapping the current frame. */ if (side_of_frame) { /* Use different logic for this. */ - float x; if (extend == false) { ED_sequencer_deselect_all(scene); } - /* 10px margin around current frame to select under the current frame with mouse. */ - float margin = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask) * 10; - x = UI_view2d_region_to_view_x(v2d, mval[0]); - if (x >= CFRA - margin && x <= CFRA + margin) { - x = CFRA; - } + const float x = UI_view2d_region_to_view_x(v2d, mval[0]); SEQP_BEGIN (ed, seq) { - bool test = false; - /* FIXME(campbell): this functionality is only in the sequencer, - * either we should support this for all timeline views or remove it. */ - if ((x == CFRA) && (seq->startdisp <= CFRA) && (seq->enddisp >= CFRA)) { - /* Select overlapping the current frame. */ - test = true; - } - else if ((x < CFRA && seq->enddisp <= CFRA) || (x > CFRA && seq->startdisp >= CFRA)) { + if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) { /* Select left or right. */ - test = true; - } - - if (test) { seq->flag |= SELECT; recurs_sel_seq(seq); } @@ -1023,7 +1006,6 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op) void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot) { static const EnumPropertyItem sequencer_select_left_right_types[] = { - {0, "OVERLAP", 0, "Overlap", "Select overlapping the current frame"}, {-1, "LEFT", 0, "Left", "Select to the left of the current frame"}, {1, "RIGHT", 0, "Right", "Select to the right of the current frame"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index f52cfdd34c0..368f9c1af19 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -521,6 +521,12 @@ static void sequencer_main_region_draw(const bContext *C, ARegion *region) draw_timeline_seq(C, region); } +/* Strip editing timeline. */ +static void sequencer_main_region_draw_overlay(const bContext *C, ARegion *region) +{ + draw_timeline_seq_display(C, region); +} + static void sequencer_main_region_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(area), ARegion *region, @@ -865,6 +871,7 @@ void ED_spacetype_sequencer(void) art->regionid = RGN_TYPE_WINDOW; art->init = sequencer_main_region_init; art->draw = sequencer_main_region_draw; + art->draw_overlay = sequencer_main_region_draw_overlay; art->listener = sequencer_main_region_listener; art->message_subscribe = sequencer_main_region_message_subscribe; art->keymapflag = ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index e50b25de412..c0343900f8b 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -85,7 +85,7 @@ static void test_line_start(char c, bool *r_last_state) /** * This function converts the indentation tabs from a buffer to spaces. - * \param buf: A pointer to a cstring. + * \param in_buf: A pointer to a cstring. * \param tab_size: The size, in spaces, of the tab character. */ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size) @@ -370,7 +370,7 @@ static int text_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e { Main *bmain = CTX_data_main(C); Text *text = CTX_data_edit_text(C); - const char *path = (text && text->name) ? text->name : BKE_main_blendfile_path(bmain); + const char *path = (text && text->filepath) ? text->filepath : BKE_main_blendfile_path(bmain); if (RNA_struct_property_is_set(op->ptr, "filepath")) { return text_open_exec(C, op); @@ -428,6 +428,13 @@ static int text_reload_exec(bContext *C, wmOperator *op) const int orig_curl = BLI_findindex(&text->lines, text->curl); const int orig_curc = text->curc; + /* Don't make this part of 'poll', since 'Alt-R' will type 'R', + * if poll checks for the filename. */ + if (text->filepath == NULL) { + BKE_report(op->reports, RPT_ERROR, "This text has not been saved"); + return OPERATOR_CANCELLED; + } + if (!BKE_text_reload(text)) { BKE_report(op->reports, RPT_ERROR, "Could not reopen file"); return OPERATOR_CANCELLED; @@ -536,10 +543,7 @@ static int text_make_internal_exec(bContext *C, wmOperator *UNUSED(op)) text->flags |= TXT_ISMEM | TXT_ISDIRTY; - if (text->name) { - MEM_freeN(text->name); - text->name = NULL; - } + MEM_SAFE_FREE(text->filepath); text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); @@ -576,7 +580,7 @@ static bool text_save_poll(bContext *C) return 0; } - return (text->name != NULL && !(text->flags & TXT_ISMEM)); + return (text->filepath != NULL && !(text->flags & TXT_ISMEM)); } static void txt_write_file(Main *bmain, Text *text, ReportList *reports) @@ -586,7 +590,7 @@ static void txt_write_file(Main *bmain, Text *text, ReportList *reports) BLI_stat_t st; char filepath[FILE_MAX]; - BLI_strncpy(filepath, text->name, FILE_MAX); + BLI_strncpy(filepath, text->filepath, FILE_MAX); BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); fp = BLI_fopen(filepath, "w"); @@ -669,10 +673,10 @@ static int text_save_as_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filepath", str); - if (text->name) { - MEM_freeN(text->name); + if (text->filepath) { + MEM_freeN(text->filepath); } - text->name = BLI_strdup(str); + text->filepath = BLI_strdup(str); text->flags &= ~TXT_ISMEM; txt_write_file(bmain, text, op->reports); @@ -693,8 +697,8 @@ static int text_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE return text_save_as_exec(C, op); } - if (text->name) { - str = text->name; + if (text->filepath) { + str = text->filepath; } else if (text->flags & TXT_ISMEM) { str = text->id.name + 2; @@ -3621,9 +3625,57 @@ void TEXT_OT_find(wmOperatorType *ot) /** \name Replace Operator * \{ */ +static int text_replace_all(bContext *C) +{ + SpaceText *st = CTX_wm_space_text(C); + Text *text = st->text; + const int flags = st->flags; + int found = 0; + + if (!st->findstr[0]) { + return OPERATOR_CANCELLED; + } + + const int orig_curl = BLI_findindex(&text->lines, text->curl); + const int orig_curc = text->curc; + bool has_sel = txt_has_sel(text); + + txt_move_toline(text, 0, false); + + found = txt_find_string(text, st->findstr, 0, flags & ST_MATCH_CASE); + if (found) { + ED_text_undo_push_init(C); + + do { + txt_insert_buf(text, st->replacestr); + if (text->curl && text->curl->format) { + MEM_freeN(text->curl->format); + text->curl->format = NULL; + } + found = txt_find_string(text, st->findstr, 0, flags & ST_MATCH_CASE); + } while (found); + + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_drawcache_tag_update(CTX_wm_space_text(C), 1); + } + else { + /* Restore position */ + txt_move_to(text, orig_curl, orig_curc, has_sel); + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + static int text_replace_exec(bContext *C, wmOperator *op) { - return text_find_and_replace(C, op, TEXT_REPLACE); + bool replace_all = RNA_boolean_get(op->ptr, "all"); + if (replace_all) { + return text_replace_all(C); + } + else { + return text_find_and_replace(C, op, TEXT_REPLACE); + } } void TEXT_OT_replace(wmOperatorType *ot) @@ -3639,6 +3691,11 @@ void TEXT_OT_replace(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, "all", false, "Replace all", "Replace all occurrences"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index daa3f641404..aeabe68c2d0 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -182,7 +182,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph copy_qt_qt(vctrl->rot_backup, rv3d->viewquat); copy_v3_v3(vctrl->ofs_backup, rv3d->ofs); - /* the dist defines a vector that is infront of the offset + /* The dist defines a vector that is in front of the offset * to rotate the view about. * this is no good for fly mode because we * want to rotate about the viewers center. diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index fac378ae104..b3165c9fc78 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2376,7 +2376,7 @@ void ED_view3d_datamask(const bContext *C, { if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) { r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - r_cddata_masks->vmask |= CD_MASK_ORCO; + r_cddata_masks->vmask |= CD_MASK_ORCO | CD_MASK_PROP_COLOR; } else if (v3d->shading.type == OB_SOLID) { if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) { @@ -2384,6 +2384,7 @@ void ED_view3d_datamask(const bContext *C, } if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) { r_cddata_masks->lmask |= CD_MASK_MLOOPCOL; + r_cddata_masks->vmask |= CD_MASK_ORCO | CD_MASK_PROP_COLOR; } } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index edd75d8e561..3c3dea1509d 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4988,7 +4988,7 @@ void ED_view3d_cursor3d_position(bContext *C, ED_view3d_calc_zfac(rv3d, cursor_co, &flip); - /* reset the depth based on the view offset (we _know_ the offset is infront of us) */ + /* Reset the depth based on the view offset (we _know_ the offset is in front of us). */ if (flip) { negate_v3_v3(cursor_co, rv3d->ofs); /* re initialize, no need to check flip again */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 06d1a033a0d..506969443fd 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -55,6 +55,10 @@ #include "view3d_intern.h" /* own include */ +/* -------------------------------------------------------------------- */ +/** \name Modal Key-map + * \{ */ + /* NOTE: these defines are saved in keymap files, * do not change values but just add new ones */ enum { @@ -138,6 +142,12 @@ void fly_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Fly Structs + * \{ */ + typedef struct FlyInfo { /* context stuff */ RegionView3D *rv3d; @@ -205,6 +215,12 @@ typedef struct FlyInfo { } FlyInfo; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Fly Drawing + * \{ */ + /* prototypes */ #ifdef WITH_INPUT_NDOF static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm); @@ -278,6 +294,12 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(regio immUnbindProgram(); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Fly Logic + * \{ */ + /* FlyInfo->state */ enum { FLY_RUNNING = 0, @@ -1034,6 +1056,12 @@ static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm) } #endif /* WITH_INPUT_NDOF */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Fly Operator + * \{ */ + static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -1128,3 +1156,5 @@ void VIEW3D_OT_fly(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_BLOCKING; } + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 829d793333e..f2e42cd1725 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -209,7 +209,7 @@ static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C) PointerRNA meshptr; RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr); - if (ob->mode & (OB_MODE_TEXTURE_PAINT)) { + if (ob->mode & OB_MODE_TEXTURE_PAINT) { uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); } else { diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index f2b78bc2aaf..131fbbc02ee 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -936,6 +936,8 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve RNA_float_set_array(&op_props, "rotation", rotation); RNA_float_set_array(&op_props, "location", location); RNA_float_set_array(&op_props, "scale", scale); + /* Always use default size here. */ + RNA_float_set(&op_props, "size", 2.0f); WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); WM_operator_properties_free(&op_props); } diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 3a0f0f468fc..f4ec9a22520 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -557,9 +557,9 @@ void ED_view3d_win_to_3d(const View3D *v3d, copy_v3_v3(ray_origin, rv3d->viewinv[3]); ED_view3d_win_to_vector(region, mval, ray_direction); - /* note, we could use isect_line_plane_v3() - * however we want the intersection to be infront of the view no matter what, - * so apply the unsigned factor instead */ + /* Note: we could use #isect_line_plane_v3() + * however we want the intersection to be in front of the view no matter what, + * so apply the unsigned factor instead. */ plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]); isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 1bdb8268c23..9e235d72f26 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -3007,7 +3007,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO continue; } - if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) { + if (metaelem_id != (hitresult & 0xFFFF0000 & ~MBALLSEL_ANY)) { continue; } diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 437c0dd4035..91b2971585d 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -850,12 +850,12 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]) return false; } - if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) { - mul_v3_fl(centroid, 1.0f / (float)count); - copy_v3_v3(cursor, centroid); + if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) { + mid_v3_v3v3(cursor, min, max); } else { - mid_v3_v3v3(cursor, min, max); + mul_v3_fl(centroid, 1.0f / (float)count); + copy_v3_v3(cursor, centroid); } return true; } diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 377e8c58ba3..15d6a43d105 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -94,7 +94,7 @@ bool ED_view3d_has_workbench_in_texture_color(const Scene *scene, if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) { return true; } - if (ob->mode == OB_MODE_TEXTURE_PAINT) { + if (ob && ob->mode == OB_MODE_TEXTURE_PAINT) { return true; } } diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 7aefd173953..50fa573423a 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -65,6 +65,10 @@ /* ensure the target position is one we can reach, see: T45771 */ #define USE_PIXELSIZE_NATIVE_SUPPORT +/* -------------------------------------------------------------------- */ +/** \name Modal Key-map + * \{ */ + /* NOTE: these defines are saved in keymap files, * do not change values but just add new ones */ enum { @@ -173,6 +177,12 @@ void walk_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Walk Structs + * \{ */ + typedef struct WalkTeleport { eWalkTeleportState state; float duration; /* from user preferences */ @@ -283,6 +293,12 @@ typedef struct WalkInfo { } WalkInfo; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Walk Drawing + * \{ */ + /* prototypes */ #ifdef WITH_INPUT_NDOF static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm); @@ -340,6 +356,12 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *region, voi immUnbindProgram(); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Walk Logic + * \{ */ + static void walk_navigation_mode_set(WalkInfo *walk, eWalkMethod mode) { if (mode == WALK_MODE_FREE) { @@ -1343,7 +1365,12 @@ static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm) } #endif /* WITH_INPUT_NDOF */ -/****** walk operator ******/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Walk Operator + * \{ */ + static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -1438,3 +1465,5 @@ void VIEW3D_OT_walk(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_BLOCKING; } + +/** \} */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index b02b1814c67..eb60273fc79 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -526,8 +526,11 @@ static void viewRedrawPost(bContext *C, TransInfo *t) } /* redraw UV editor */ - if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) && - (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ? + UVCALC_TRANSFORM_CORRECT_SLIDE : + UVCALC_TRANSFORM_CORRECT; + + if ((t->data_type == TC_MESH_VERTS) && (t->settings->uvcalc_flag & uvcalc_correct_flag)) { WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } @@ -1591,17 +1594,24 @@ static void drawTransformPixel(const struct bContext *C, ARegion *region, void * void saveTransform(bContext *C, TransInfo *t, wmOperator *op) { ToolSettings *ts = CTX_data_tool_settings(C); - int proportional = 0; PropertyRNA *prop; if (!(t->con.mode & CON_APPLY) && (t->flag & T_MODAL) && ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE)) { /* When redoing these modes the first time, it's more convenient to save - * the Global orientation. */ - mul_m3_v3(t->spacemtx, t->values_final); - unit_m3(t->spacemtx); + * in the Global orientation. */ + if (t->mode == TFM_TRANSLATION) { + mul_m3_v3(t->spacemtx, t->values_final); + } + else { + float tmat[3][3], sizemat[3][3]; + size_to_mat3(sizemat, t->values_final); + mul_m3_m3m3(tmat, t->spacemtx, sizemat); + mat3_to_size(t->values_final, tmat); + } BLI_assert(t->orient_curr == 0); + unit_m3(t->spacemtx); t->orient[0].type = V3D_ORIENT_GLOBAL; } @@ -1619,15 +1629,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } + bool use_prop_edit = false; + int prop_edit_flag = 0; if (t->flag & T_PROP_EDIT_ALL) { if (t->flag & T_PROP_EDIT) { - proportional |= PROP_EDIT_USE; + use_prop_edit = true; } if (t->flag & T_PROP_CONNECTED) { - proportional |= PROP_EDIT_CONNECTED; + prop_edit_flag |= PROP_EDIT_CONNECTED; } if (t->flag & T_PROP_PROJECTED) { - proportional |= PROP_EDIT_PROJECTED; + prop_edit_flag |= PROP_EDIT_PROJECTED; } } @@ -1639,20 +1651,27 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (!(t->options & CTX_NO_PET)) { if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) && !RNA_property_is_set(op->ptr, prop)) { + const Object *obact = OBACT(t->view_layer); + if (t->spacetype == SPACE_GRAPH) { - ts->proportional_fcurve = proportional; + ts->proportional_fcurve = use_prop_edit; } else if (t->spacetype == SPACE_ACTION) { - ts->proportional_action = proportional; - } - else if (t->obedit_type != -1) { - ts->proportional_edit = proportional; + ts->proportional_action = use_prop_edit; } else if (t->options & CTX_MASK) { - ts->proportional_mask = proportional != 0; + ts->proportional_mask = use_prop_edit; } - else if ((t->options & CTX_CURSOR) == 0) { - ts->proportional_objects = proportional != 0; + else if (obact && obact->mode == OB_MODE_OBJECT) { + ts->proportional_objects = use_prop_edit; + } + else { + if (use_prop_edit) { + ts->proportional_edit |= PROP_EDIT_USE; + } + else { + ts->proportional_edit &= ~PROP_EDIT_USE; + } } } @@ -1685,9 +1704,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) { - RNA_property_boolean_set(op->ptr, prop, proportional & PROP_EDIT_USE); - RNA_boolean_set(op->ptr, "use_proportional_connected", proportional & PROP_EDIT_CONNECTED); - RNA_boolean_set(op->ptr, "use_proportional_projected", proportional & PROP_EDIT_PROJECTED); + RNA_property_boolean_set(op->ptr, prop, use_prop_edit); + RNA_boolean_set(op->ptr, "use_proportional_connected", prop_edit_flag & PROP_EDIT_CONNECTED); + RNA_boolean_set(op->ptr, "use_proportional_projected", prop_edit_flag & PROP_EDIT_PROJECTED); RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode); RNA_float_set(op->ptr, "proportional_size", t->prop_size); } @@ -1768,7 +1787,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) { RNA_property_boolean_set( - op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0); + op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0); } } @@ -1819,6 +1838,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve int options = 0; PropertyRNA *prop; + mode = transform_mode_really_used(C, mode); + t->context = C; /* added initialize, for external calls to set stuff in TransInfo, like undo string */ diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 838c1880881..66b90eb159f 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -79,6 +79,27 @@ static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3]) } /* ************************** CONSTRAINTS ************************* */ +#define CONSTRAIN_EPSILON 0.0001f + +static void constraint_plane_calc(TransInfo *t, float r_plane[4]) +{ + const float *constraint_vector[2]; + int n = 0; + for (int i = 0; i < 3; i++) { + if (t->con.mode & (CON_AXIS0 << i)) { + constraint_vector[n++] = t->spacemtx[i]; + if (n == 2) { + break; + } + } + } + BLI_assert(n == 2); + + cross_v3_v3v3(r_plane, constraint_vector[0], constraint_vector[1]); + normalize_v3(r_plane); + r_plane[3] = -dot_v3v3(r_plane, t->center_global); +} + static void constraintValuesFinal(TransInfo *t, float vec[3]) { int mode = t->con.mode; @@ -297,32 +318,83 @@ static void axisProjection(const TransInfo *t, } /** - * Return true if the 2x axis are both aligned when projected into the view. - * In this case, we can't usefully project the cursor onto the plane. + * Snap to the intersection between the edge direction and the constraint plane. */ -static bool isPlaneProjectionViewAligned(const TransInfo *t) +static void constraint_snap_plane_to_edge(const TransInfo *t, const float plane[4], float r_out[3]) { - const float eps = 0.001f; - const float *constraint_vector[2]; - int n = 0; - for (int i = 0; i < 3; i++) { - if (t->con.mode & (CON_AXIS0 << i)) { - constraint_vector[n++] = t->spacemtx[i]; - if (n == 2) { - break; - } - } + float lambda; + const float *edge_snap_point = t->tsnap.snapPoint; + const float *edge_dir = t->tsnap.snapNormal; + bool is_aligned = fabsf(dot_v3v3(edge_dir, plane)) < CONSTRAIN_EPSILON; + if (!is_aligned && isect_ray_plane_v3(edge_snap_point, edge_dir, plane, &lambda, false)) { + madd_v3_v3v3fl(r_out, edge_snap_point, edge_dir, lambda); + sub_v3_v3(r_out, t->tsnap.snapTarget); } - BLI_assert(n == 2); +} + +/** + * Snap to the nearest point between the snap point and the line that + * intersects the face plane with the constraint plane. + */ +static void constraint_snap_plane_to_face(const TransInfo *t, const float plane[4], float r_out[3]) +{ + float face_plane[4], isect_orig[3], isect_dir[3]; + const float *face_snap_point = t->tsnap.snapPoint; + const float *face_normal = t->tsnap.snapNormal; + plane_from_point_normal_v3(face_plane, face_snap_point, face_normal); + bool is_aligned = fabsf(dot_v3v3(plane, face_plane)) > (1.0f - CONSTRAIN_EPSILON); + if (!is_aligned && isect_plane_plane_v3(plane, face_plane, isect_orig, isect_dir)) { + closest_to_ray_v3(r_out, face_snap_point, isect_orig, isect_dir); + sub_v3_v3(r_out, t->tsnap.snapTarget); + } +} - float view_to_plane[3], plane_normal[3]; +/** + * Snap to the nearest point on the axis to the edge/line element. + */ +void transform_constraint_snap_axis_to_edge(const TransInfo *t, + const float axis[3], + float r_out[3]) +{ + float lambda; + const float *edge_snap_point = t->tsnap.snapPoint; + const float *edge_dir = t->tsnap.snapNormal; + bool is_aligned = fabsf(dot_v3v3(axis, edge_dir)) > (1.0f - CONSTRAIN_EPSILON); + if (!is_aligned && + isect_ray_ray_v3(t->tsnap.snapTarget, axis, edge_snap_point, edge_dir, &lambda, NULL)) { + mul_v3_v3fl(r_out, axis, lambda); + } +} - getViewVector(t, t->center_global, view_to_plane); +/** + * Snap to the intersection of the axis and the plane defined by the face. + */ +void transform_constraint_snap_axis_to_face(const TransInfo *t, + const float axis[3], + float r_out[3]) +{ + float lambda; + float face_plane[4]; + const float *face_snap_point = t->tsnap.snapPoint; + const float *face_normal = t->tsnap.snapNormal; + plane_from_point_normal_v3(face_plane, face_snap_point, face_normal); + bool is_aligned = fabsf(dot_v3v3(axis, face_plane)) < CONSTRAIN_EPSILON; + if (!is_aligned && isect_ray_plane_v3(t->tsnap.snapTarget, axis, face_plane, &lambda, false)) { + mul_v3_v3fl(r_out, axis, lambda); + } +} - cross_v3_v3v3(plane_normal, constraint_vector[0], constraint_vector[1]); - normalize_v3(plane_normal); +/** + * Return true if the 2x axis are both aligned when projected into the view. + * In this case, we can't usefully project the cursor onto the plane. + */ +static bool isPlaneProjectionViewAligned(const TransInfo *t, float plane[4]) +{ + const float eps = 0.001f; + float view_to_plane[3]; + getViewVector(t, t->center_global, view_to_plane); - float factor = dot_v3v3(plane_normal, view_to_plane); + float factor = dot_v3v3(plane, view_to_plane); return fabsf(factor) < eps; } @@ -361,14 +433,31 @@ static void applyAxisConstraintVec( copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { mul_m3_v3(t->con.pmtx, out); + bool is_snap_to_edge = false, is_snap_to_face = false; + if (activeSnap(t)) { + is_snap_to_edge = (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) != 0; + is_snap_to_face = (t->tsnap.snapElem & SCE_SNAP_MODE_FACE) != 0; + } - // With snap, a projection is alright, no need to correct for view alignment - if (!validSnap(t)) { + /* With snap points, a projection is alright, no adjustments needed. */ + if (!validSnap(t) || is_snap_to_edge || is_snap_to_face) { const int dims = getConstraintSpaceDimension(t); if (dims == 2) { if (!is_zero_v3(out)) { - if (!isPlaneProjectionViewAligned(t)) { - planeProjection(t, in, out); + float plane[4]; + constraint_plane_calc(t, plane); + + if (is_snap_to_edge) { + constraint_snap_plane_to_edge(t, plane, out); + } + else if (is_snap_to_face) { + constraint_snap_plane_to_face(t, plane, out); + } + else { + /* View alignment correction. */ + if (!isPlaneProjectionViewAligned(t, plane)) { + planeProjection(t, in, out); + } } } } @@ -384,7 +473,17 @@ static void applyAxisConstraintVec( else if (t->con.mode & CON_AXIS2) { copy_v3_v3(c, t->spacemtx[2]); } - axisProjection(t, c, in, out); + + if (is_snap_to_edge) { + transform_constraint_snap_axis_to_edge(t, c, out); + } + else if (is_snap_to_face) { + transform_constraint_snap_axis_to_face(t, c, out); + } + else { + /* View alignment correction. */ + axisProjection(t, c, in, out); + } } } postConstraintChecks(t, out); @@ -779,12 +878,21 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformThemeColor(TH_GRID); + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + + float viewport[4]; + GPU_viewport_size_get_f(viewport); + GPU_blend(true); + + immUniform2fv("viewportSize", &viewport[2]); + immUniform1f("lineWidth", 3.0f * U.pixelsize); + + immUniformThemeColorShadeAlpha(TH_GRID, -20, 255); + imm_drawcircball(t->center_global, t->prop_size, imat, pos); - GPU_logic_op_invert_set(true); + immUniform1f("lineWidth", 1.0f * U.pixelsize); + immUniformThemeColorShadeAlpha(TH_GRID, 20, 255); imm_drawcircball(t->center_global, t->prop_size, imat, pos); - GPU_logic_op_invert_set(false); immUnbindProgram(); diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index c41b9361ca4..282060af2c3 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -27,6 +27,12 @@ struct TransInfo; void constraintNumInput(TransInfo *t, float vec[3]); +void transform_constraint_snap_axis_to_edge(const TransInfo *t, + const float axis[3], + float r_out[3]); +void transform_constraint_snap_axis_to_face(const TransInfo *t, + const float axis[3], + float r_out[3]); void setConstraint(TransInfo *t, int mode, const char text[]); void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]); void setLocalConstraint(TransInfo *t, int mode, const char text[]); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 064057990e0..5d1fd1543df 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -774,7 +774,7 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) bConstraint *con; /* loop through constraints, checking if there's one of the mentioned - * constraints needing special crazyspace corrections + * constraints needing special crazy-space corrections */ if (list) { for (con = list->first; con; con = con->next) { @@ -1148,21 +1148,6 @@ void createTransData(bContext *C, TransInfo *t) } t->flag |= T_OBJECT; - - /* Check if we're transforming the camera from the camera */ - if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - View3D *v3d = t->view; - RegionView3D *rv3d = t->region->regiondata; - if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) { - /* we could have a flag to easily check an object is being transformed */ - if (v3d->camera->id.tag & LIB_TAG_DOIT) { - t->flag |= T_CAMERA; - } - } - else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) { - t->flag |= T_CAMERA; - } - } convert_type = TC_OBJECT; } @@ -1175,6 +1160,7 @@ void createTransData(bContext *C, TransInfo *t) break; case TC_POSE: createTransPose(t); + /* Disable PET, its not usable in pose mode yet [#32444] */ init_prop_edit = false; break; case TC_ARMATURE_VERTS: @@ -1224,6 +1210,20 @@ void createTransData(bContext *C, TransInfo *t) break; case TC_OBJECT: createTransObject(C, t); + /* Check if we're transforming the camera from the camera */ + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + View3D *v3d = t->view; + RegionView3D *rv3d = t->region->regiondata; + if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) { + /* we could have a flag to easily check an object is being transformed */ + if (v3d->camera->id.tag & LIB_TAG_DOIT) { + t->flag |= T_CAMERA; + } + } + else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) { + t->flag |= T_CAMERA; + } + } break; case TC_OBJECT_TEXSPACE: createTransTexspace(t); @@ -1292,18 +1292,9 @@ void createTransData(bContext *C, TransInfo *t) * and are still added into transform data. */ sort_trans_data_selected_first(t); } - } - - /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */ - if (t->mode == TFM_BONESIZE) { - t->flag &= ~(T_EDIT | T_POINTS); - t->flag |= T_POSE; - t->obedit_type = -1; - t->data_type = TC_NONE; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - tc->poseobj = tc->obedit; - tc->obedit = NULL; + if (!init_prop_edit) { + t->flag &= ~T_PROP_EDIT_ALL; } } diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index a94bd609d94..f7eea286983 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -47,7 +47,7 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize); void clipUVData(TransInfo *t); /* transform_convert_mesh.c */ -void trans_mesh_customdata_correction_init(TransInfo *t, struct TransDataContainer *tc); +void trans_mesh_customdata_correction_init(TransInfo *t); /* transform_convert_sequencer.c */ int transform_convert_sequencer_get_snap_bound(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 75b51b3d2c4..f721ed0b866 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -553,8 +553,7 @@ static void pose_mirror_info_init(PoseInitData_Mirror *pid, /** \name Convert Armature * \{ */ -static void add_pose_transdata( - TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td) +static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td) { Bone *bone = pchan->bone; float pmat[3][3], omat[3][3]; @@ -667,20 +666,16 @@ static void add_pose_transdata( mul_m3_m3m3(td->axismtx, omat, pmat); normalize_m3(td->axismtx); - if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) { - bArmature *arm = tc->poseobj->data; - - if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) { - td->loc = NULL; - td->val = &bone->dist; - td->ival = bone->dist; - } - else { - // abusive storage of scale in the loc pointer :) - td->loc = &bone->xwidth; - copy_v3_v3(td->iloc, td->loc); - td->val = NULL; - } + if (t->mode == TFM_BONE_ENVELOPE_DIST) { + td->loc = NULL; + td->val = &bone->dist; + td->ival = bone->dist; + } + else if (t->mode == TFM_BONESIZE) { + // abusive storage of scale in the loc pointer :) + td->loc = &bone->xwidth; + copy_v3_v3(td->iloc, td->loc); + td->val = NULL; } /* in this case we can do target-less IK grabbing */ @@ -836,7 +831,7 @@ void createTransPose(TransInfo *t) td = tc->data; LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { if (pchan->bone->flag & BONE_TRANSFORM) { - add_pose_transdata(t, pchan, ob, tc, td); + add_pose_transdata(t, pchan, ob, td); td++; } } @@ -862,8 +857,6 @@ void createTransPose(TransInfo *t) } t->flag |= T_POSE; - /* disable PET, its not usable in pose mode yet [#32444] */ - t->flag &= ~T_PROP_EDIT_ALL; } void createTransArmatureVerts(TransInfo *t) @@ -988,7 +981,7 @@ void createTransArmatureVerts(TransInfo *t) } else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) { if (ebo->flag & BONE_SELECTED) { - if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) { + if (t->mode == TFM_BONE_ENVELOPE_DIST) { td->loc = NULL; td->val = &ebo->dist; td->ival = ebo->dist; diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 6c03f86f883..37e37072ed7 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -87,7 +87,7 @@ void createTransCurveVerts(TransInfo *t) t->data_len_all = 0; - /* Count control points (one per bez-triple) if any number of handles are selected. + /* Count control points (one per #BezTriple) if any number of handles are selected. * Needed for #transform_around_single_fallback_ex. */ int data_len_all_pt = 0; diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c index 66c27bca207..6f34c49bdac 100644 --- a/source/blender/editors/transform/transform_convert_mask.c +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -149,7 +149,7 @@ static void MaskPointToTransData(Scene *scene, /* CV coords are scaled by aspects. this is needed for rotations and * proportional editing to be consistent with the stretched CV coords - * that are displayed. this also means that for display and numinput, + * that are displayed. this also means that for display and number-input, * and when the CV coords are flushed, these are converted each time */ mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]); td2d->loc[0] *= asp[0]; diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 27ddad262f7..1c286415ea6 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -50,10 +50,11 @@ /* Own include. */ #include "transform_convert.h" -/* Used for both mirror epsilon and TD_MIRROR_EDGE_ */ -#define TRANSFORM_MAXDIST_MIRROR 0.00002f +/* -------------------------------------------------------------------- */ +/** \name Island Creation + * + * \{ */ -/* when transforming islands */ struct TransIslandData { float (*center)[3]; float (*axismtx)[3][3]; @@ -61,8 +62,186 @@ struct TransIslandData { int *island_vert_map; }; +static void editmesh_islands_info_calc(BMEditMesh *em, + const bool calc_single_islands, + const bool calc_island_center, + const bool calc_island_axismtx, + struct TransIslandData *r_island_data) +{ + BMesh *bm = em->bm; + char htype; + char itype; + int i; + + /* group vars */ + float(*center)[3] = NULL; + float(*axismtx)[3][3] = NULL; + int *groups_array; + int(*group_index)[2]; + int group_tot; + void **ele_array; + + int *vert_map; + + if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__); + group_tot = BM_mesh_calc_edge_groups( + bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT); + + htype = BM_EDGE; + itype = BM_VERTS_OF_EDGE; + } + else { /* (bm->selectmode & SCE_SELECT_FACE) */ + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); + group_tot = BM_mesh_calc_face_groups( + bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT); + + htype = BM_FACE; + itype = BM_VERTS_OF_FACE; + } + + if (calc_island_center) { + center = MEM_mallocN(sizeof(*center) * group_tot, __func__); + } + + if (calc_island_axismtx) { + axismtx = MEM_mallocN(sizeof(*axismtx) * group_tot, __func__); + } + + vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__); + /* we shouldn't need this, but with incorrect selection flushing + * its possible we have a selected vertex that's not in a face, + * for now best not crash in that case. */ + copy_vn_i(vert_map, bm->totvert, -1); + + BM_mesh_elem_table_ensure(bm, htype); + ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + /* may be an edge OR a face array */ + for (i = 0; i < group_tot; i++) { + BMEditSelection ese = {NULL}; + + const int fg_sta = group_index[i][0]; + const int fg_len = group_index[i][1]; + float co[3], no[3], tangent[3]; + int j; + + zero_v3(co); + zero_v3(no); + zero_v3(tangent); + + ese.htype = htype; + + /* loop on each face or edge in this group: + * - assign r_vert_map + * - calculate (co, no) + */ + for (j = 0; j < fg_len; j++) { + ese.ele = ele_array[groups_array[fg_sta + j]]; + + if (center) { + float tmp_co[3]; + BM_editselection_center(&ese, tmp_co); + add_v3_v3(co, tmp_co); + } + + if (axismtx) { + float tmp_no[3], tmp_tangent[3]; + BM_editselection_normal(&ese, tmp_no); + BM_editselection_plane(&ese, tmp_tangent); + add_v3_v3(no, tmp_no); + add_v3_v3(tangent, tmp_tangent); + } + + { + /* setup vertex map */ + BMIter iter; + BMVert *v; + + /* connected edge-verts */ + BM_ITER_ELEM (v, &iter, ese.ele, itype) { + vert_map[BM_elem_index_get(v)] = i; + } + } + } + + if (center) { + mul_v3_v3fl(center[i], co, 1.0f / (float)fg_len); + } + + if (axismtx) { + if (createSpaceNormalTangent(axismtx[i], no, tangent)) { + /* pass */ + } + else { + if (normalize_v3(no) != 0.0f) { + axis_dominant_v3_to_m3(axismtx[i], no); + invert_m3(axismtx[i]); + } + else { + unit_m3(axismtx[i]); + } + } + } + } + + MEM_freeN(groups_array); + MEM_freeN(group_index); + + /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */ + if (calc_single_islands) { + BMIter viter; + BMVert *v; + int group_tot_single = 0; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + group_tot_single += 1; + } + } + + if (group_tot_single != 0) { + if (center) { + center = MEM_reallocN(center, sizeof(*center) * (group_tot + group_tot_single)); + } + if (axismtx) { + axismtx = MEM_reallocN(axismtx, sizeof(*axismtx) * (group_tot + group_tot_single)); + } + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + vert_map[i] = group_tot; + if (center) { + copy_v3_v3(center[group_tot], v->co); + } + if (axismtx) { + if (is_zero_v3(v->no) != 0.0f) { + axis_dominant_v3_to_m3(axismtx[group_tot], v->no); + invert_m3(axismtx[group_tot]); + } + else { + unit_m3(axismtx[group_tot]); + } + } + + group_tot += 1; + } + } + } + } + + r_island_data->axismtx = axismtx; + r_island_data->center = center; + r_island_data->island_tot = group_tot; + r_island_data->island_vert_map = vert_map; +} + +/** \} */ + /* -------------------------------------------------------------------- */ -/** \name Edit Mesh Verts Transform Creation +/** \name Connectivity Distance for Proportional Editing * * \{ */ @@ -243,171 +422,25 @@ static void editmesh_set_connectivity_distance(BMesh *bm, } } -static void editmesh_islands_info_calc(BMEditMesh *em, - const bool calc_single_islands, - const bool calc_island_axismtx, - struct TransIslandData *r_island_data) -{ - BMesh *bm = em->bm; - char htype; - char itype; - int i; - - /* group vars */ - float(*center)[3]; - float(*axismtx)[3][3] = NULL; - int *groups_array; - int(*group_index)[2]; - int group_tot; - void **ele_array; - - int *vert_map; - - if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { - groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__); - group_tot = BM_mesh_calc_edge_groups( - bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT); - - htype = BM_EDGE; - itype = BM_VERTS_OF_EDGE; - } - else { /* (bm->selectmode & SCE_SELECT_FACE) */ - groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); - group_tot = BM_mesh_calc_face_groups( - bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT); - - htype = BM_FACE; - itype = BM_VERTS_OF_FACE; - } - - center = MEM_mallocN(sizeof(*center) * group_tot, __func__); - - if (calc_island_axismtx) { - axismtx = MEM_mallocN(sizeof(*axismtx) * group_tot, __func__); - } - - vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__); - /* we shouldn't need this, but with incorrect selection flushing - * its possible we have a selected vertex that's not in a face, - * for now best not crash in that case. */ - copy_vn_i(vert_map, bm->totvert, -1); - - BM_mesh_elem_table_ensure(bm, htype); - ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable; - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - /* may be an edge OR a face array */ - for (i = 0; i < group_tot; i++) { - BMEditSelection ese = {NULL}; - - const int fg_sta = group_index[i][0]; - const int fg_len = group_index[i][1]; - float co[3], no[3], tangent[3]; - int j; - - zero_v3(co); - zero_v3(no); - zero_v3(tangent); - - ese.htype = htype; - - /* loop on each face or edge in this group: - * - assign r_vert_map - * - calculate (co, no) - */ - for (j = 0; j < fg_len; j++) { - float tmp_co[3], tmp_no[3], tmp_tangent[3]; - - ese.ele = ele_array[groups_array[fg_sta + j]]; - - BM_editselection_center(&ese, tmp_co); - add_v3_v3(co, tmp_co); - - if (axismtx) { - BM_editselection_normal(&ese, tmp_no); - BM_editselection_plane(&ese, tmp_tangent); - add_v3_v3(no, tmp_no); - add_v3_v3(tangent, tmp_tangent); - } - - { - /* setup vertex map */ - BMIter iter; - BMVert *v; - - /* connected edge-verts */ - BM_ITER_ELEM (v, &iter, ese.ele, itype) { - vert_map[BM_elem_index_get(v)] = i; - } - } - } - - mul_v3_v3fl(center[i], co, 1.0f / (float)fg_len); - - if (axismtx) { - if (createSpaceNormalTangent(axismtx[i], no, tangent)) { - /* pass */ - } - else { - if (normalize_v3(no) != 0.0f) { - axis_dominant_v3_to_m3(axismtx[i], no); - invert_m3(axismtx[i]); - } - else { - unit_m3(axismtx[i]); - } - } - } - } - - MEM_freeN(groups_array); - MEM_freeN(group_index); - - /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */ - if (calc_single_islands) { - BMIter viter; - BMVert *v; - int group_tot_single = 0; - - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { - group_tot_single += 1; - } - } - - if (group_tot_single != 0) { - center = MEM_reallocN(center, sizeof(*center) * (group_tot + group_tot_single)); - if (axismtx) { - axismtx = MEM_reallocN(axismtx, sizeof(*axismtx) * (group_tot + group_tot_single)); - } +/** \} */ - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { - vert_map[i] = group_tot; - copy_v3_v3(center[group_tot], v->co); +/* -------------------------------------------------------------------- */ +/** \name TransDataMirror Creation + * + * \{ */ - if (axismtx) { - if (is_zero_v3(v->no) != 0.0f) { - axis_dominant_v3_to_m3(axismtx[group_tot], v->no); - invert_m3(axismtx[group_tot]); - } - else { - unit_m3(axismtx[group_tot]); - } - } +/* Used for both mirror epsilon and TD_MIRROR_EDGE_ */ +#define TRANSFORM_MAXDIST_MIRROR 0.00002f - group_tot += 1; - } - } - } - } +struct MirrorDataVert { + int index; + int flag; +}; - r_island_data->axismtx = axismtx; - r_island_data->center = center; - r_island_data->island_tot = group_tot; - r_island_data->island_vert_map = vert_map; -} +struct TransMirrorData { + struct MirrorDataVert *vert_map; + int mirror_elem_len; +}; static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon) { @@ -423,172 +456,124 @@ static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const fl return true; } -static TransDataMirror *editmesh_mirror_data_calc(BMEditMesh *em, - bool use_select, - const bool use_topology, - const bool mirror_axis[3], - int *r_mirror_data_len, - BLI_bitmap **r_mirror_bitmap) +static void editmesh_mirror_data_calc(BMEditMesh *em, + const bool use_select, + const bool use_topology, + const bool mirror_axis[3], + struct TransMirrorData *r_mirror_data) { - BMesh *bm = em->bm; - int *index[3] = {NULL}; - int i; - - bool test_selected_only = use_select && (mirror_axis[0] + mirror_axis[1] + mirror_axis[2]) == 1; - for (i = 0; i < 3; i++) { - if (mirror_axis[i]) { - index[i] = MEM_mallocN(bm->totvert * sizeof(int), __func__); - EDBM_verts_mirror_cache_begin_ex( - em, i, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[i]); - } - } + struct MirrorDataVert *vert_map; + BMesh *bm = em->bm; BMVert *eve; BMIter iter; + int i, flag, totvert = bm->totvert; - int quadrant[3]; - { - float select_sum[3] = {0}; - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - continue; - } - if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - add_v3_v3(select_sum, eve->co); - } - } - - for (i = 0; i < 3; i++) { - if (mirror_axis[i]) { - quadrant[i] = select_sum[i] >= 0.0f ? 1 : -1; - } - else { - quadrant[i] = 0; - } - } - } + vert_map = MEM_mallocN(totvert * sizeof(*vert_map), __func__); - /* Tag only elements that will be transformed within the quadrant. */ + float select_sum[3] = {0}; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + vert_map[i] = (struct MirrorDataVert){-1, 0}; if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { continue; } - if ((!use_select || BM_elem_flag_test(eve, BM_ELEM_SELECT)) && - is_in_quadrant_v3(eve->co, quadrant, TRANSFORM_MAXDIST_MIRROR)) { - BM_elem_flag_enable(eve, BM_ELEM_TAG); - BM_elem_index_set(eve, i); + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + add_v3_v3(select_sum, eve->co); + } + } + + /* Tag only elements that will be transformed within the quadrant. */ + int quadrant[3]; + for (int a = 0; a < 3; a++) { + if (mirror_axis[a]) { + quadrant[a] = select_sum[a] >= 0.0f ? 1 : -1; } else { - BM_elem_flag_disable(eve, BM_ELEM_TAG); - BM_elem_index_set(eve, -1); + quadrant[a] = 0; } } + uint mirror_elem_len = 0; + int *index[3] = {NULL, NULL, NULL}; + bool test_selected_only = use_select && (mirror_axis[0] + mirror_axis[1] + mirror_axis[2]) == 1; for (int a = 0; a < 3; a++) { - int *index_iter = index[a]; - if (index_iter == NULL) { + if (!mirror_axis[a]) { continue; } + + index[a] = MEM_mallocN(totvert * sizeof(*index[a]), __func__); + EDBM_verts_mirror_cache_begin_ex( + em, a, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]); + + flag = TD_MIRROR_X << a; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + int i_mirr = index[a][i]; + if (i_mirr < 0) { + continue; + } if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { continue; } - if (test_selected_only && !BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (use_select && !BM_elem_flag_test(eve, BM_ELEM_SELECT)) { continue; } - int elem_index = BM_elem_index_get(eve); - if (elem_index != -1) { - int i_mirr = index_iter[i]; - if (i_mirr >= 0) { - BMVert *vmir = BM_vert_at_index(bm, i_mirr); - BM_elem_index_set(vmir, elem_index); - - /* The slot of this element in the index array no longer needs to be read. - * Use to set the mirror sign. */ - if (index[0] && a > 0) { - index[0][i_mirr] = index[0][i]; - } - if (index[1] && a > 1) { - index[1][i_mirr] = index[1][i]; - } - /* Use -2 to differ from -1, but both can work. */ - index_iter[i_mirr] = -2; - } + if (!is_in_quadrant_v3(eve->co, quadrant, TRANSFORM_MAXDIST_MIRROR)) { + continue; } - } - } - /* Count mirror elements. */ - uint mirror_elem_len = 0; - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN | BM_ELEM_TAG)) { - /* Not a mirror element. */ - BM_elem_index_set(eve, -1); - continue; - } - int elem_index = BM_elem_index_get(eve); - if (elem_index != -1) { + vert_map[i_mirr] = (struct MirrorDataVert){i, flag}; mirror_elem_len++; } } - TransDataMirror *td_mirror_iter, *td_mirror = NULL; - if (mirror_elem_len != 0) { - td_mirror = MEM_mallocN(mirror_elem_len * sizeof(*td_mirror), __func__); - td_mirror_iter = &td_mirror[0]; - - *r_mirror_bitmap = BLI_BITMAP_NEW(bm->totvert, __func__); - - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - int elem_index = BM_elem_index_get(eve); - if (elem_index != -1) { - BMVert *v_src = BM_vert_at_index(bm, elem_index); + if (mirror_elem_len) { + for (int a = 0; a < 3; a++) { + if (!mirror_axis[a]) { + continue; + } - int flag = 0; - if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - flag |= TD_SELECTED; - } - if (index[0] && index[0][i] == -2) { - flag |= TD_MIRROR_X; - } - if (index[1] && index[1][i] == -2) { - flag |= TD_MIRROR_Y; + flag = TD_MIRROR_X << a; + for (i = 0; i < totvert; i++) { + int i_mirr = index[a][i]; + if (i_mirr < 0) { + continue; } - if (index[2] && index[2][i] == -2) { - flag |= TD_MIRROR_Z; + if (vert_map[i].index != -1 && !(vert_map[i].flag & flag)) { + if (vert_map[i_mirr].index == -1) { + mirror_elem_len++; + } + vert_map[i_mirr].index = vert_map[i].index; + vert_map[i_mirr].flag |= vert_map[i].flag | flag; } - - td_mirror_iter->extra = eve; - td_mirror_iter->loc = eve->co; - copy_v3_v3(td_mirror_iter->iloc, eve->co); - td_mirror_iter->flag = flag; - td_mirror_iter->loc_src = v_src->co; - /** `center` will be set in the main createTransEditVerts loop. - * copy_v3_v3(td_mirror_iter->center, eve->co); */ - - td_mirror_iter++; - - BLI_BITMAP_ENABLE(*r_mirror_bitmap, i); } } } + else { + MEM_freeN(vert_map); + vert_map = NULL; + } MEM_SAFE_FREE(index[0]); MEM_SAFE_FREE(index[1]); MEM_SAFE_FREE(index[2]); - bm->elem_index_dirty |= BM_VERT; - *r_mirror_data_len = mirror_elem_len; - return td_mirror; + r_mirror_data->vert_map = vert_map; + r_mirror_data->mirror_elem_len = mirror_elem_len; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh Verts Transform Creation + * + * \{ */ + static void transdata_center_get(const struct TransIslandData *island_data, const int island_index, - const bool no_island_center, const float iloc[3], float r_center[3]) { - if (island_index != -1 && !no_island_center) { + if (island_data->center && island_index != -1) { copy_v3_v3(r_center, island_data->center[island_index]); } else { @@ -604,8 +589,7 @@ static void VertsToTransData(TransInfo *t, BMVert *eve, float *bweight, const struct TransIslandData *island_data, - const int island_index, - const bool no_island_center) + const int island_index) { float *no, _no[3]; BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0); @@ -626,7 +610,7 @@ static void VertsToTransData(TransInfo *t, no = eve->no; } - transdata_center_get(island_data, island_index, no_island_center, td->iloc, td->center); + transdata_center_get(island_data, island_index, td->iloc, td->center); if ((island_index != -1) && island_data->axismtx) { copy_m3_m3(td->axismtx, island_data->axismtx[island_index]); @@ -676,31 +660,12 @@ void createTransEditVerts(TransInfo *t) BMesh *bm = em->bm; BMVert *eve; BMIter iter; - float(*mappedcos)[3] = NULL, (*quats)[4] = NULL; - float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; - float *dists = NULL; + float mtx[3][3], smtx[3][3]; int a; const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; - int cd_vert_bweight_offset = -1; struct TransIslandData island_data = {NULL}; - - /* Snap rotation along normal needs a common axis for whole islands, - * otherwise one get random crazy results, see T59104. - * However, we do not want to use the island center for the pivot/translation reference. */ - const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) && - /* There is not guarantee that snapping - * is initialized yet at this point... */ - (usingSnappingNormal(t) || - (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) && - (t->around != V3D_AROUND_LOCAL_ORIGINS)); - /* Even for translation this is needed because of island-orientation, see: T51651. */ - const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate; - /* Original index of our connected vertex when connected distances are calculated. - * Optional, allocate if needed. */ - int *dists_index = NULL; - - BLI_bitmap *mirror_bitmap = NULL; + struct TransMirrorData mirror_data = {NULL}; /** * Quick check if we can transform. @@ -711,20 +676,7 @@ void createTransEditVerts(TransInfo *t) /* Support other objects using PET to adjust these, unless connected is enabled. */ if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) { - goto cleanup; - } - - if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT); - cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - } - - if (tc->use_mirror_axis_any) { - bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; - bool use_select = (t->flag & T_PROP_EDIT) == 0; - bool mirror_axis[3] = {tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z}; - tc->data_mirror = editmesh_mirror_data_calc( - em, use_select, use_topology, mirror_axis, &tc->data_mirror_len, &mirror_bitmap); + continue; } int data_len = 0; @@ -734,44 +686,41 @@ void createTransEditVerts(TransInfo *t) data_len++; } } - - if (data_len == 0) { - goto cleanup; - } - - /* allocating scratch arrays */ - if (prop_mode & T_PROP_CONNECTED) { - dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__); - if (is_island_center) { - dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__); - } - } } else { data_len = bm->totvertsel; } - if (mirror_bitmap) { - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { - if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - if (BLI_BITMAP_TEST(mirror_bitmap, a)) { - data_len--; - } - } - } + if (data_len == 0) { + continue; } - BLI_assert(data_len != 0); + /* Snap rotation along normal needs a common axis for whole islands, + * otherwise one get random crazy results, see T59104. + * However, we do not want to use the island center for the pivot/translation reference. */ + const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) && + /* There is not guarantee that snapping + * is initialized yet at this point... */ + (usingSnappingNormal(t) || + (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) && + (t->around != V3D_AROUND_LOCAL_ORIGINS)); - tc->data_len = data_len; - tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"); - if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { - /* warning, this is overkill, we only need 2 extra floats, - * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill - * since we may not use the 'alt' transform mode to maintain shell thickness, - * but with generic transform code its hard to lazy init vars */ - tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), - "TransObData ext"); + /* Even for translation this is needed because of island-orientation, see: T51651. */ + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate; + if (is_island_center) { + /* In this specific case, near-by vertices will need to know + * the island of the nearest connected vertex. */ + const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + const bool calc_island_center = !is_snap_rotate; + /* The island axismtx is only necessary in some modes. + * TODO(Germano): Extend the list to exclude other modes. */ + const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN); + + editmesh_islands_info_calc( + em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data); } copy_m3_m4(mtx, tc->obedit->obmat); @@ -779,26 +728,58 @@ void createTransEditVerts(TransInfo *t) * matrix inversion still works and we can still moving along the other */ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + float *dists = NULL; if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__); + } editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index); } - if (is_island_center) { - /* In this specific case, near-by vertices will need to know - * the island of the nearest connected vertex. */ - const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) && - (t->around == V3D_AROUND_LOCAL_ORIGINS) && - (em->selectmode & SCE_SELECT_VERTEX)); + /* Create TransDataMirror. */ + if (tc->use_mirror_axis_any) { + bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; + bool use_select = (t->flag & T_PROP_EDIT) == 0; + bool mirror_axis[3] = {tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z}; + editmesh_mirror_data_calc(em, use_select, use_topology, mirror_axis, &mirror_data); - /* The island axismtx is only necessary in some modes. - * TODO(Germano): Extend the list to exclude other modes. */ - const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN); + if (mirror_data.vert_map) { + tc->data_mirror_len = mirror_data.mirror_elem_len; + tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror), + __func__); + + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { + if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (mirror_data.vert_map[a].index != -1) { + data_len--; + } + } + } + } + } - editmesh_islands_info_calc(em, calc_single_islands, calc_island_axismtx, &island_data); + /* Create TransData. */ + BLI_assert(data_len >= 1); + tc->data_len = data_len; + tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)"); + if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { + /* warning, this is overkill, we only need 2 extra floats, + * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill + * since we may not use the 'alt' transform mode to maintain shell thickness, + * but with generic transform code its hard to lazy init vars */ + tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), + "TransObData ext"); } /* detect CrazySpace [tm] */ + float(*quats)[4] = NULL; + float(*defmats)[3][3] = NULL; if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) { + float(*defcos)[3] = NULL; int totleft = -1; if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) { BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); @@ -813,16 +794,17 @@ void createTransEditVerts(TransInfo *t) t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos); } - /* if we still have more modifiers, also do crazyspace - * correction with quats, relative to the coordinates after - * the modifiers that support deform matrices (defcos) */ + /* If we still have more modifiers, also do crazy-space + * correction with \a quats, relative to the coordinates after + * the modifiers that support deform matrices \a defcos. */ -#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */ +#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */ if ((totleft > 0) || (totleft == -1)) #else if (totleft > 0) #endif { + float(*mappedcos)[3] = NULL; mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, tc->obedit); quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats"); BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode); @@ -836,6 +818,12 @@ void createTransEditVerts(TransInfo *t) } } + int cd_vert_bweight_offset = -1; + if (t->mode == TFM_BWEIGHT) { + BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT); + cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + } + TransData *tob = tc->data; TransDataMirror *td_mirror = tc->data_mirror; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { @@ -849,9 +837,20 @@ void createTransEditVerts(TransInfo *t) island_index = island_data.island_vert_map[connected_index]; } - if (mirror_bitmap && BLI_BITMAP_TEST(mirror_bitmap, a)) { - transdata_center_get( - &island_data, island_index, is_snap_rotate, td_mirror->iloc, td_mirror->center); + if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) { + int elem_index = mirror_data.vert_map[a].index; + BMVert *v_src = BM_vert_at_index(bm, elem_index); + + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + mirror_data.vert_map[a].flag |= TD_SELECTED; + } + + td_mirror->extra = eve; + td_mirror->loc = eve->co; + copy_v3_v3(td_mirror->iloc, eve->co); + td_mirror->flag = mirror_data.vert_map[a].flag; + td_mirror->loc_src = v_src->co; + transdata_center_get(&island_data, island_index, td_mirror->iloc, td_mirror->center); td_mirror++; } @@ -862,8 +861,7 @@ void createTransEditVerts(TransInfo *t) /* Do not use the island center in case we are using islands * only to get axis for snap/rotate to normal... */ - VertsToTransData( - t, tob, tx, em, eve, bweight, &island_data, island_index, is_snap_rotate); + VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index); if (tx) { tx++; } @@ -933,17 +931,15 @@ void createTransEditVerts(TransInfo *t) if (island_data.center) { MEM_freeN(island_data.center); } - if (island_data.axismtx) { MEM_freeN(island_data.axismtx); } - if (island_data.island_vert_map) { MEM_freeN(island_data.island_vert_map); } - - cleanup: - /* crazy space free */ + if (mirror_data.vert_map) { + MEM_freeN(mirror_data.vert_map); + } if (quats) { MEM_freeN(quats); } @@ -956,9 +952,6 @@ void createTransEditVerts(TransInfo *t) if (dists_index) { MEM_freeN(dists_index); } - if (mirror_bitmap) { - MEM_freeN(mirror_bitmap); - } } } @@ -1075,99 +1068,118 @@ static void create_trans_vert_customdata_layer(BMVert *v, BLI_ghash_insert(tcld->origverts, v, r_tcld_vert); } -void trans_mesh_customdata_correction_init(TransInfo *t, TransDataContainer *tc) +static void trans_mesh_customdata_correction_init_container(TransInfo *t, TransDataContainer *tc) { if (tc->custom.type.data) { /* Custom data correction has initiated before. */ BLI_assert(tc->custom.type.free_cb == trans_mesh_customdata_free_cb); return; } - int i; + + if (!ELEM(t->mode, + TFM_TRANSLATION, + TFM_ROTATION, + TFM_RESIZE, + TFM_TOSPHERE, + TFM_SHEAR, + TFM_BEND, + TFM_SHRINKFATTEN, + TFM_TRACKBALL, + TFM_PUSHPULL, + TFM_ALIGN)) { + /* Currently only modes that change the position of vertices are supported. */ + return; + } BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; - bool use_origfaces; - int cd_loop_mdisp_offset; - { - const bool has_layer_math = CustomData_has_math(&bm->ldata); - cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) && - /* don't do this at all for non-basis shape keys, too easy to - * accidentally break uv maps or vertex colors then */ - (bm->shapenr <= 1) && (has_layer_math || (cd_loop_mdisp_offset != -1))) { - use_origfaces = true; - } - else { - use_origfaces = false; - cd_loop_mdisp_offset = -1; - } + if (bm->shapenr > 1) { + /* Don't do this at all for non-basis shape keys, too easy to + * accidentally break uv maps or vertex colors then */ + /* create copies of faces for customdata projection. */ + return; } - if (use_origfaces) { - /* create copies of faces for customdata projection */ - bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - - struct GHash *origfaces = BLI_ghash_ptr_new(__func__); - struct BMesh *bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default, - &((struct BMeshCreateParams){ - .use_toolflags = false, - })); - - /* we need to have matching customdata */ - BM_mesh_copy_init_customdata(bm_origfaces, bm, NULL); - - int *layer_math_map = NULL; - int layer_index_dst = 0; - { - /* TODO: We don't need `sod->layer_math_map` when there are no loops linked - * to one of the sliding vertices. */ - if (CustomData_has_math(&bm->ldata)) { - /* over alloc, only 'math' layers are indexed */ - layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__); - for (i = 0; i < bm->ldata.totlayer; i++) { - if (CustomData_layer_has_math(&bm->ldata, i)) { - layer_math_map[layer_index_dst++] = i; - } + const bool has_layer_math = CustomData_has_math(&bm->ldata); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + if (!has_layer_math && (cd_loop_mdisp_offset == -1)) { + return; + } + + bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + + struct GHash *origfaces = BLI_ghash_ptr_new(__func__); + struct BMesh *bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default, + &((struct BMeshCreateParams){ + .use_toolflags = false, + })); + + /* we need to have matching customdata */ + BM_mesh_copy_init_customdata(bm_origfaces, bm, NULL); + + int *layer_math_map = NULL; + int layer_math_map_len = 0; + { + /* TODO: We don't need `sod->layer_math_map` when there are no loops linked + * to one of the sliding vertices. */ + if (has_layer_math) { + /* over alloc, only 'math' layers are indexed */ + layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__); + for (int i = 0; i < bm->ldata.totlayer; i++) { + if (CustomData_layer_has_math(&bm->ldata, i)) { + layer_math_map[layer_math_map_len++] = i; } - BLI_assert(layer_index_dst != 0); } + BLI_assert(layer_math_map_len != 0); } + } - struct TransCustomDataLayer *tcld; - tc->custom.type.data = tcld = MEM_mallocN(sizeof(*tcld), __func__); - tc->custom.type.free_cb = trans_mesh_customdata_free_cb; - - tcld->bm = bm; - tcld->origfaces = origfaces; - tcld->bm_origfaces = bm_origfaces; - tcld->cd_loop_mdisp_offset = cd_loop_mdisp_offset; - tcld->layer_math_map = layer_math_map; - tcld->layer_math_map_num = layer_index_dst; - tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + struct TransCustomDataLayer *tcld = MEM_mallocN(sizeof(*tcld), __func__); + int data_len = tc->data_len + tc->data_mirror_len; - int data_len = tc->data_len + tc->data_mirror_len; - struct GHash *origverts = BLI_ghash_ptr_new_ex(__func__, data_len); - tcld->origverts = origverts; + tcld->bm = bm; + tcld->origfaces = origfaces; + tcld->bm_origfaces = bm_origfaces; + tcld->cd_loop_mdisp_offset = cd_loop_mdisp_offset; + tcld->layer_math_map = layer_math_map; + tcld->layer_math_map_num = layer_math_map_len; + tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + tcld->origverts = BLI_ghash_ptr_new_ex(__func__, data_len); + tcld->data = BLI_memarena_alloc(tcld->arena, data_len * sizeof(*tcld->data)); + tcld->data_len = data_len; - struct TransCustomDataLayerVert *tcld_vert, *tcld_vert_iter; - tcld_vert = BLI_memarena_alloc(tcld->arena, data_len * sizeof(*tcld_vert)); - tcld_vert_iter = &tcld_vert[0]; + { + /* Setup Verts. */ + struct TransCustomDataLayerVert *tcld_vert_iter = &tcld->data[0]; - TransData *tob; - for (i = tc->data_len, tob = tc->data; i--; tob++, tcld_vert_iter++) { + TransData *tob = tc->data; + for (int i = tc->data_len; i--; tob++, tcld_vert_iter++) { BMVert *v = tob->extra; create_trans_vert_customdata_layer(v, tcld, tcld_vert_iter); } TransDataMirror *td_mirror = tc->data_mirror; - for (i = tc->data_mirror_len; i--; td_mirror++, tcld_vert_iter++) { + for (int i = tc->data_mirror_len; i--; td_mirror++, tcld_vert_iter++) { BMVert *v = td_mirror->extra; create_trans_vert_customdata_layer(v, tcld, tcld_vert_iter); } + } + + tc->custom.type.data = tcld; + tc->custom.type.free_cb = trans_mesh_customdata_free_cb; +} + +void trans_mesh_customdata_correction_init(TransInfo *t) +{ + const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ? + UVCALC_TRANSFORM_CORRECT_SLIDE : + UVCALC_TRANSFORM_CORRECT; - tcld->data = tcld_vert; - tcld->data_len = data_len; + if (t->settings->uvcalc_flag & uvcalc_correct_flag) { + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + trans_mesh_customdata_correction_init_container(t, tc); + } } } @@ -1187,19 +1199,17 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa BMesh *bm = tcld->bm; BMVert *v = tcld_vert->v; const float *co_orig_3d = tcld_vert->co_orig_3d; - struct LinkNode **cd_loop_groups = tcld_vert->cd_loop_groups; BMIter liter; int j, l_num; float *loop_weights; const bool is_moved = (len_squared_v3v3(v->co, co_orig_3d) > FLT_EPSILON); - const bool do_loop_weight = tcld->layer_math_map_num && is_moved; - const bool do_loop_mdisps = is_final && is_moved && (tcld->cd_loop_mdisp_offset != -1); + const bool do_loop_weight = is_moved && tcld->layer_math_map_num; const float *v_proj_axis = v->no; /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */ float v_proj[3][3]; - if (do_loop_weight || do_loop_mdisps) { + if (do_loop_weight) { project_plane_normalized_v3_v3v3(v_proj[1], co_orig_3d, v_proj_axis); } @@ -1264,6 +1274,7 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa } } + struct LinkNode **cd_loop_groups = tcld_vert->cd_loop_groups; if (tcld->layer_math_map_num && cd_loop_groups) { if (do_loop_weight) { for (j = 0; j < tcld->layer_math_map_num; j++) { @@ -1283,6 +1294,7 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa * Interpolate from every other loop (not ideal) * However values will only be taken from loops which overlap other mdisps. * */ + const bool do_loop_mdisps = is_moved && is_final && (tcld->cd_loop_mdisp_offset != -1); if (do_loop_mdisps) { float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num); BMLoop *l; @@ -1386,13 +1398,9 @@ void recalcData_mesh(TransInfo *t) } } - if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - trans_mesh_customdata_correction_apply(tc, false); - } - } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { + trans_mesh_customdata_correction_apply(tc, false); + DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); EDBM_mesh_normals_update(em); @@ -1408,18 +1416,9 @@ void recalcData_mesh(TransInfo *t) void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) { const bool canceled = (t->state == TRANS_CANCEL); + const bool use_automerge = !canceled && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0; - if (canceled) { - /* Exception, edge slide transformed UVs too. */ - if (t->mode == TFM_EDGE_SLIDE) { - doEdgeSlide(t, 0.0f); - } - else if (t->mode == TFM_VERT_SLIDE) { - doVertSlide(t, 0.0f); - } - } - - if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + if (TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.type.data != NULL) { /* Handle multires re-projection, done * on transform completion since it's * really slow -joeedh. */ @@ -1428,10 +1427,8 @@ void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) } } - bool use_automerge = !canceled && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0; if (use_automerge) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; char hflag; diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h index bc95fdad59c..48ed9ecf34b 100644 --- a/source/blender/editors/transform/transform_data.h +++ b/source/blender/editors/transform/transform_data.h @@ -88,8 +88,8 @@ typedef struct TransDataExtension { * It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */ float l_smtx[3][3]; /** The rotscale matrix of pose bone, to allow using snap-align in translation mode, - * when td->mtx is the loc pose bone matrix (and hence can't be used to apply - * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */ + * when #TransData.mtx is the loc pose bone matrix (and hence can't be used to apply + * rotation in some cases, namely when a bone is in "No-Local" or "Hinge" mode)... */ float r_mtx[3][3]; /** Inverse of previous one. */ float r_smtx[3][3]; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 78c47014d62..cce6ef1f3bd 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -131,21 +131,6 @@ void resetTransRestrictions(TransInfo *t) t->flag &= ~T_ALL_RESTRICTIONS; } -static int initTransInfo_edit_pet_to_flag(const int proportional) -{ - int flag = 0; - if (proportional & PROP_EDIT_USE) { - flag |= T_PROP_EDIT; - } - if (proportional & PROP_EDIT_CONNECTED) { - flag |= T_PROP_CONNECTED; - } - if (proportional & PROP_EDIT_PROJECTED) { - flag |= T_PROP_PROJECTED; - } - return flag; -} - void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object **objects, @@ -390,15 +375,15 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) { if (RNA_property_is_set(op->ptr, prop)) { if (RNA_property_boolean_get(op->ptr, prop)) { - t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; + t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT_SLIDE; } else { - t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT; + t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT_SLIDE; } } else { RNA_property_boolean_set( - op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0); + op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0); } } } @@ -550,7 +535,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve orient_types[2] = orient_type_scene; } else { - if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode))) { + if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode)) && + (t->mode != TFM_ALIGN)) { orient_types[0] = V3D_ORIENT_VIEW; } else { @@ -636,45 +622,45 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */ if (op && (prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) { if (RNA_property_is_set(op->ptr, prop)) { - int proportional = 0; if (RNA_property_boolean_get(op->ptr, prop)) { - proportional |= PROP_EDIT_USE; + t->flag |= T_PROP_EDIT; if (RNA_boolean_get(op->ptr, "use_proportional_connected")) { - proportional |= PROP_EDIT_CONNECTED; + t->flag |= T_PROP_CONNECTED; } if (RNA_boolean_get(op->ptr, "use_proportional_projected")) { - proportional |= PROP_EDIT_PROJECTED; + t->flag |= T_PROP_PROJECTED; } } - t->flag |= initTransInfo_edit_pet_to_flag(proportional); } else { /* use settings from scene only if modal */ if (t->flag & T_MODAL) { if ((t->options & CTX_NO_PET) == 0) { + bool use_prop_edit = false; if (t->spacetype == SPACE_GRAPH) { - t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve); + use_prop_edit = ts->proportional_fcurve; } else if (t->spacetype == SPACE_ACTION) { - t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action); + use_prop_edit = ts->proportional_action; } - else if (t->obedit_type != -1) { - t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_edit); + else if (t->options & CTX_MASK) { + use_prop_edit = ts->proportional_mask; } - else if (t->options & CTX_GPENCIL_STROKES) { - t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_edit); + else if (obact && obact->mode == OB_MODE_OBJECT) { + use_prop_edit = ts->proportional_objects; } - else if (t->options & CTX_MASK) { - if (ts->proportional_mask) { - t->flag |= T_PROP_EDIT; - - if (ts->proportional_edit & PROP_EDIT_CONNECTED) { - t->flag |= T_PROP_CONNECTED; - } - } + else { + use_prop_edit = (ts->proportional_edit & PROP_EDIT_USE) != 0; } - else if (!(t->options & CTX_CURSOR) && ts->proportional_objects) { + + if (use_prop_edit) { t->flag |= T_PROP_EDIT; + if (ts->proportional_edit & PROP_EDIT_CONNECTED) { + t->flag |= T_PROP_CONNECTED; + } + if (ts->proportional_edit & PROP_EDIT_PROJECTED) { + t->flag |= T_PROP_PROJECTED; + } } } } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index f028044809f..831ea90b4e4 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -50,6 +50,23 @@ /* Own include. */ #include "transform_mode.h" +int transform_mode_really_used(bContext *C, int mode) +{ + if (mode == TFM_BONESIZE) { + Object *ob = CTX_data_active_object(C); + BLI_assert(ob); + if (ob->type != OB_ARMATURE) { + return TFM_RESIZE; + } + bArmature *arm = ob->data; + if (arm->drawtype == ARM_ENVELOPE) { + return TFM_BONE_ENVELOPE_DIST; + } + } + + return mode; +} + bool transdata_check_local_center(TransInfo *t, short around) { return ((around == V3D_AROUND_LOCAL_ORIGINS) && @@ -1174,25 +1191,12 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) case TFM_CREASE: initCrease(t); break; - case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ - /* Note: we have to pick one, use the active object. */ - TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); - bArmature *arm = tc->poseobj->data; - if (arm->drawtype == ARM_ENVELOPE) { - initBoneEnvelope(t); - t->mode = TFM_BONE_ENVELOPE_DIST; - } - else { - initBoneSize(t); - } + case TFM_BONESIZE: + initBoneSize(t); break; - } case TFM_BONE_ENVELOPE: - initBoneEnvelope(t); - break; case TFM_BONE_ENVELOPE_DIST: initBoneEnvelope(t); - t->mode = TFM_BONE_ENVELOPE_DIST; break; case TFM_EDGE_SLIDE: case TFM_VERT_SLIDE: { @@ -1267,6 +1271,12 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) break; } + if (t->data_type == TC_MESH_VERTS) { + /* Init Custom Data correction. + * Ideally this should be called when creating the TransData. */ + trans_mesh_customdata_correction_init(t); + } + /* TODO(germano): Some of these operations change the `t->mode`. * This can be bad for Redo. * BLI_assert(t->mode == mode); */ diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index 464deff983b..5cda8e3063a 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -26,6 +26,7 @@ #define __TRANSFORM_MODE_H__ struct AnimData; +struct bContext; struct LinkNode; struct TransData; struct TransDataContainer; @@ -40,6 +41,7 @@ typedef struct TransDataGenericSlideVert { } TransDataGenericSlideVert; /* transform_mode.c */ +int transform_mode_really_used(struct bContext *C, int mode); bool transdata_check_local_center(TransInfo *t, short around); bool transform_mode_is_changeable(const int mode); void protectedTransBits(short protectflag, float vec[3]); @@ -95,7 +97,6 @@ void initSeqSlide(TransInfo *t); /* transform_mode_edge_slide.c */ void drawEdgeSlide(TransInfo *t); -void doEdgeSlide(TransInfo *t, float perc); void initEdgeSlide_ex( TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp); void initEdgeSlide(TransInfo *t); @@ -153,7 +154,6 @@ void initTranslation(TransInfo *t); /* transform_mode_vert_slide.c */ void drawVertSlide(TransInfo *t); -void doVertSlide(TransInfo *t, float perc); void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp); void initVertSlide(TransInfo *t); #endif diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c index 77850e74785..2c2253630c0 100644 --- a/source/blender/editors/transform/transform_mode_bbone_resize.c +++ b/source/blender/editors/transform/transform_mode_bbone_resize.c @@ -132,6 +132,11 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) if (t->con.applySize) { t->con.applySize(t, NULL, NULL, mat); + for (i = 0; i < 3; i++) { + if (!(t->con.mode & (CON_AXIS0 << i))) { + t->values_final[i] = 1.0f; + } + } } copy_m3_m3(t->mat, mat); // used in gizmo diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c index 7045d190478..b7a34769f5a 100644 --- a/source/blender/editors/transform/transform_mode_boneenvelope.c +++ b/source/blender/editors/transform/transform_mode_boneenvelope.c @@ -96,7 +96,6 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) void initBoneEnvelope(TransInfo *t) { - t->mode = TFM_BONE_ENVELOPE; t->transform = applyBoneEnvelope; initMouseInputMode(t, &t->mouse, INPUT_SPRING); diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 42f75f041b9..ed22afc404e 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -50,6 +50,7 @@ #include "BLT_translation.h" #include "transform.h" +#include "transform_constraints.h" #include "transform_convert.h" #include "transform_mode.h" #include "transform_snap.h" @@ -96,24 +97,28 @@ typedef struct EdgeSlideParams { } EdgeSlideParams; /** - * Get the first valid EdgeSlideData. + * Get the first valid TransDataContainer *. * * Note we cannot trust TRANS_DATA_CONTAINER_FIRST_OK because of multi-object that * may leave items with invalid custom data in the transform data container. */ -static EdgeSlideData *edgeSlideFirstGet(TransInfo *t) +static TransDataContainer *edge_slide_container_first_ok(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - if (sld == NULL) { - continue; + if (tc->custom.mode.data) { + return tc; } - return sld; } BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid"); return NULL; } +static EdgeSlideData *edgeSlideFirstGet(TransInfo *t) +{ + TransDataContainer *tc = edge_slide_container_first_ok(t); + return tc->custom.mode.data; +} + static void calcEdgeSlideCustomPoints(struct TransInfo *t) { EdgeSlideData *sld = edgeSlideFirstGet(t); @@ -1129,132 +1134,226 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven void drawEdgeSlide(TransInfo *t) { - if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) { - const EdgeSlideParams *slp = t->custom.mode.data; - EdgeSlideData *sld = edgeSlideFirstGet(t); - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (t->mode != TFM_EDGE_SLIDE) { + return; + } - /* Even mode */ - if ((slp->use_even == true) || (is_clamp == false)) { - const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + EdgeSlideData *sld = edgeSlideFirstGet(t); + if (sld == NULL) { + return; + } - GPU_depth_test(false); + const EdgeSlideParams *slp = t->custom.mode.data; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - GPU_blend(true); - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - GPU_matrix_push(); - GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_depth_test(false); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - if (slp->use_even == true) { - float co_a[3], co_b[3], co_mark[3]; - TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float fac = (slp->perc + 1.0f) / 2.0f; - const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - const float guide_size = ctrl_size - 0.5f; - const int alpha_shade = -30; + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); - add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - GPU_line_width(line_size); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBeginAtMost(GPU_PRIM_LINES, 4); - if (curr_sv->v_side[0]) { - immVertex3fv(pos, curr_sv->v_side[0]->co); - immVertex3fv(pos, curr_sv->v_co_orig); - } + if (slp->use_even == true) { + /* Even mode */ + float co_a[3], co_b[3], co_mark[3]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float fac = (slp->perc + 1.0f) / 2.0f; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float guide_size = ctrl_size - 0.5f; + const int alpha_shade = -30; + + add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); + add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GPU_PRIM_LINES, 4); + if (curr_sv->v_side[0]) { + immVertex3fv(pos, curr_sv->v_side[0]->co); + immVertex3fv(pos, curr_sv->v_co_orig); + } + if (curr_sv->v_side[1]) { + immVertex3fv(pos, curr_sv->v_side[1]->co); + immVertex3fv(pos, curr_sv->v_co_orig); + } + immEnd(); + + { + float *co_test = NULL; + if (slp->flipped) { if (curr_sv->v_side[1]) { - immVertex3fv(pos, curr_sv->v_side[1]->co); - immVertex3fv(pos, curr_sv->v_co_orig); + co_test = curr_sv->v_side[1]->co; } - immEnd(); - - { - float *co_test = NULL; - if (slp->flipped) { - if (curr_sv->v_side[1]) { - co_test = curr_sv->v_side[1]->co; - } - } - else { - if (curr_sv->v_side[0]) { - co_test = curr_sv->v_side[0]->co; - } - } - - if (co_test != NULL) { - immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); - GPU_point_size(ctrl_size); - immBegin(GPU_PRIM_POINTS, 1); - immVertex3fv(pos, co_test); - immEnd(); - } + } + else { + if (curr_sv->v_side[0]) { + co_test = curr_sv->v_side[0]->co; } + } - immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); - GPU_point_size(guide_size); + if (co_test != NULL) { + immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + GPU_point_size(ctrl_size); immBegin(GPU_PRIM_POINTS, 1); - interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); - immVertex3fv(pos, co_mark); + immVertex3fv(pos, co_test); immEnd(); } + } + + immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + GPU_point_size(guide_size); + immBegin(GPU_PRIM_POINTS, 1); + interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); + immVertex3fv(pos, co_mark); + immEnd(); + } + else if (is_clamp == false) { + const int side_index = sld->curr_side_unclamp; + TransDataEdgeSlideVert *sv; + int i; + const int alpha_shade = -160; + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); + + /* TODO(campbell): Loop over all verts */ + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(a, sv->dir_side[side_index]); + } else { - if (is_clamp == false) { - const int side_index = sld->curr_side_unclamp; - TransDataEdgeSlideVert *sv; - int i; - const int alpha_shade = -160; + copy_v3_v3(a, sv->dir_side[!side_index]); + } - GPU_line_width(line_size); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBegin(GPU_PRIM_LINES, sld->totsv * 2); + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->v_co_orig); + add_v3_v3(b, sv->v_co_orig); - /* TODO(campbell): Loop over all verts */ - sv = sld->sv; - for (i = 0; i < sld->totsv; i++, sv++) { - float a[3], b[3]; + immVertex3fv(pos, a); + immVertex3fv(pos, b); + } + immEnd(); + } + else { + /* Common case. */ + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const int alpha_shade = -160; + + float co_dir[3]; + add_v3_v3v3(co_dir, curr_sv->v_co_orig, curr_sv->dir_side[sld->curr_side_unclamp]); + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GPU_PRIM_LINES, 2); + immVertex3fv(pos, curr_sv->v_co_orig); + immVertex3fv(pos, co_dir); + immEnd(); + } - if (!is_zero_v3(sv->dir_side[side_index])) { - copy_v3_v3(a, sv->dir_side[side_index]); - } - else { - copy_v3_v3(a, sv->dir_side[!side_index]); - } + immUnbindProgram(); - mul_v3_fl(a, 100.0f); - negate_v3_v3(b, a); - add_v3_v3(a, sv->v_co_orig); - add_v3_v3(b, sv->v_co_orig); + GPU_matrix_pop(); - immVertex3fv(pos, a); - immVertex3fv(pos, b); - } - immEnd(); - } - else { - BLI_assert(0); - } - } + GPU_blend(false); - immUnbindProgram(); + GPU_depth_test(true); +} - GPU_matrix_pop(); +static void edge_slide_snap_apply(TransInfo *t, float *value) +{ + TransDataContainer *tc = edge_slide_container_first_ok(t); + EdgeSlideParams *slp = t->custom.mode.data; + EdgeSlideData *sld_active = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = &sld_active->sv[sld_active->curr_sv_index]; + float snap_point[3], co_orig[3], co_dest[2][3], dvec[3]; + + copy_v3_v3(co_orig, sv->v_co_orig); + add_v3_v3v3(co_dest[0], co_orig, sv->dir_side[0]); + add_v3_v3v3(co_dest[1], co_orig, sv->dir_side[1]); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, co_orig); + mul_m4_v3(tc->mat, co_dest[0]); + mul_m4_v3(tc->mat, co_dest[1]); + } - GPU_blend(false); + getSnapPoint(t, dvec); + sub_v3_v3(dvec, t->tsnap.snapTarget); + add_v3_v3v3(snap_point, co_orig, dvec); - GPU_depth_test(true); + float perc = *value; + int side_index; + float t_mid; + if (slp->use_even == false) { + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { + side_index = perc < 0.0f; + } + else { + side_index = sld_active->curr_side_unclamp; } } + else { + /* Could be pre-calculated. */ + t_mid = line_point_factor_v3((float[3]){0.0f, 0.0f, 0.0f}, sv->dir_side[0], sv->dir_side[1]); + + float t_snap = line_point_factor_v3(snap_point, co_dest[0], co_dest[1]); + side_index = t_snap >= t_mid; + } + + if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) { + float co_dir[3]; + sub_v3_v3v3(co_dir, co_dest[side_index], co_orig); + if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) { + transform_constraint_snap_axis_to_edge(t, co_dir, dvec); + } + else { + transform_constraint_snap_axis_to_face(t, co_dir, dvec); + } + add_v3_v3v3(snap_point, co_orig, dvec); + } + + perc = line_point_factor_v3(snap_point, co_orig, co_dest[side_index]); + if (slp->use_even == false) { + if (side_index) { + perc *= -1; + } + } + else { + if (!side_index) { + perc = (1.0f - perc) * t_mid; + } + else { + perc = perc * (1.0f - t_mid) + t_mid; + } + + if (slp->flipped) { + perc = 1.0f - perc; + } + + perc = (2 * perc) - 1.0f; + + if (!slp->flipped) { + perc *= -1; + } + } + + *value = perc; } -void doEdgeSlide(TransInfo *t, float perc) +static void doEdgeSlide(TransInfo *t, float perc) { EdgeSlideParams *slp = t->custom.mode.data; EdgeSlideData *sld_active = edgeSlideFirstGet(t); @@ -1365,6 +1464,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; + applySnapping(t, &final); snapGridIncrement(t, &final); /* only do this so out of range values are not displayed */ @@ -1413,6 +1513,8 @@ void initEdgeSlide_ex( t->mode = TFM_EDGE_SLIDE; t->transform = applyEdgeSlide; t->handleEvent = handleEventEdgeSlide; + t->tsnap.applySnap = edge_slide_snap_apply; + t->tsnap.distance = transform_snap_distance_len_squared_fn; { EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); @@ -1432,16 +1534,13 @@ void initEdgeSlide_ex( t->custom.mode.use_free = true; } - if (use_double_side) { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - sld = use_double_side ? createEdgeSlideVerts_double_side(t, tc) : - createEdgeSlideVerts_single_side(t, tc); - if (sld) { - tc->custom.mode.data = sld; - tc->custom.mode.free_cb = freeEdgeSlideVerts; - trans_mesh_customdata_correction_init(t, tc); - ok = true; - } + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + sld = use_double_side ? createEdgeSlideVerts_double_side(t, tc) : + createEdgeSlideVerts_single_side(t, tc); + if (sld) { + tc->custom.mode.data = sld; + tc->custom.mode.free_cb = freeEdgeSlideVerts; + ok = true; } } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index ebce32a598e..5fb46b30e0d 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -44,6 +44,39 @@ /** \name Transform Resize * \{ */ +static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) +{ + float d1[3], d2[3], len_d1; + + sub_v3_v3v3(d1, p1, t->center_global); + sub_v3_v3v3(d2, p2, t->center_global); + + if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { + mul_m3_v3(t->con.pmtx, d1); + mul_m3_v3(t->con.pmtx, d2); + } + + project_v3_v3v3(d1, d1, d2); + + len_d1 = len_v3(d1); + + /* Use 'invalid' dist when `center == p1` (after projecting), + * in this case scale will _never_ move the point in relation to the center, + * so it makes no sense to take it into account when scaling. see: T46503 */ + return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; +} + +static void ApplySnapResize(TransInfo *t, float vec[3]) +{ + float point[3]; + getSnapPoint(t, point); + + float dist = ResizeBetween(t, t->tsnap.snapTarget, point); + if (dist != TRANSFORM_DIST_INVALID) { + copy_v3_fl(vec, dist); + } +} + static void applyResize(TransInfo *t, const int UNUSED(mval[2])) { float mat[3][3]; @@ -134,6 +167,8 @@ void initResize(TransInfo *t) { t->mode = TFM_RESIZE; t->transform = applyResize; + t->tsnap.applySnap = ApplySnapResize; + t->tsnap.distance = ResizeBetween; initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 6480cb6c30e..4fa5dffc473 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -42,6 +42,67 @@ /** \name Transform Rotation * \{ */ +static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) +{ + float angle, start[3], end[3]; + + sub_v3_v3v3(start, p1, t->center_global); + sub_v3_v3v3(end, p2, t->center_global); + + // Angle around a constraint axis (error prone, will need debug) + if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { + float axis[3], tmp[3]; + + t->con.applyRot(t, NULL, NULL, axis, NULL); + + project_v3_v3v3(tmp, end, axis); + sub_v3_v3v3(end, end, tmp); + + project_v3_v3v3(tmp, start, axis); + sub_v3_v3v3(start, start, tmp); + + normalize_v3(end); + normalize_v3(start); + + cross_v3_v3v3(tmp, start, end); + + if (dot_v3v3(tmp, axis) < 0.0f) { + angle = -acosf(dot_v3v3(start, end)); + } + else { + angle = acosf(dot_v3v3(start, end)); + } + } + else { + float mtx[3][3]; + + copy_m3_m4(mtx, t->viewmat); + + mul_m3_v3(mtx, end); + mul_m3_v3(mtx, start); + + angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]); + } + + if (angle > (float)M_PI) { + angle = angle - 2 * (float)M_PI; + } + else if (angle < -((float)M_PI)) { + angle = 2.0f * (float)M_PI + angle; + } + + return angle; +} + +static void ApplySnapRotation(TransInfo *t, float *value) +{ + float point[3]; + getSnapPoint(t, point); + + float dist = RotationBetween(t, t->tsnap.snapTarget, point); + *value = dist; +} + static float large_rotation_limit(float angle) { /* Limit rotation to 1001 turns max @@ -173,6 +234,8 @@ void initRotation(TransInfo *t) { t->mode = TFM_ROTATION; t->transform = applyRotation; + t->tsnap.applySnap = ApplySnapRotation; + t->tsnap.distance = RotationBetween; setInputPostFct(&t->mouse, postInputRotation); initMouseInputMode(t, &t->mouse, INPUT_ANGLE); diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 60caa257a40..aee05197f10 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -34,6 +34,7 @@ #include "BKE_report.h" #include "BKE_unit.h" +#include "ED_node.h" #include "ED_screen.h" #include "WM_api.h" @@ -214,6 +215,34 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } } +static void ApplySnapTranslation(TransInfo *t, float vec[3]) +{ + float point[3]; + getSnapPoint(t, point); + + if (t->spacetype == SPACE_NODE) { + char border = t->tsnap.snapNodeBorder; + if (border & (NODE_LEFT | NODE_RIGHT)) { + vec[0] = point[0] - t->tsnap.snapTarget[0]; + } + if (border & (NODE_BOTTOM | NODE_TOP)) { + vec[1] = point[1] - t->tsnap.snapTarget[1]; + } + } + else { + if (t->spacetype == SPACE_VIEW3D) { + if (t->options & CTX_PAINT_CURVE) { + if (ED_view3d_project_float_global(t->region, point, point, V3D_PROJ_TEST_NOP) != + V3D_PROJ_RET_OK) { + zero_v3(point); /* no good answer here... */ + } + } + } + + sub_v3_v3v3(vec, point, t->tsnap.snapTarget); + } +} + static void applyTranslationValue(TransInfo *t, const float vec[3]) { const bool apply_snap_align_rotation = usingSnappingNormal( @@ -376,6 +405,8 @@ void initTranslation(TransInfo *t) } t->transform = applyTranslation; + t->tsnap.applySnap = ApplySnapTranslation; + t->tsnap.distance = transform_snap_distance_len_squared_fn; initMouseInputMode(t, &t->mouse, INPUT_VECTOR); diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 62415b1ddc6..4b75c362da9 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -47,6 +47,7 @@ #include "BLT_translation.h" #include "transform.h" +#include "transform_constraints.h" #include "transform_convert.h" #include "transform_mode.h" #include "transform_snap.h" @@ -491,7 +492,7 @@ void drawVertSlide(TransInfo *t) } } -void doVertSlide(TransInfo *t, float perc) +static void doVertSlide(TransInfo *t, float perc) { VertSlideParams *slp = t->custom.mode.data; @@ -538,6 +539,37 @@ void doVertSlide(TransInfo *t, float perc) } } +static void vert_slide_snap_apply(TransInfo *t, float *value) +{ + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); + VertSlideData *sld = tc->custom.mode.data; + TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; + + float snap_point[3], co_orig_3d[3], co_curr_3d[3], dvec[3]; + copy_v3_v3(co_orig_3d, sv->co_orig_3d); + copy_v3_v3(co_curr_3d, sv->co_link_orig_3d[sv->co_link_curr]); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, co_orig_3d); + mul_m4_v3(tc->mat, co_curr_3d); + } + + getSnapPoint(t, dvec); + sub_v3_v3(dvec, t->tsnap.snapTarget); + if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) { + float co_dir_3d[3]; + sub_v3_v3v3(co_dir_3d, co_curr_3d, co_orig_3d); + if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) { + transform_constraint_snap_axis_to_edge(t, co_dir_3d, dvec); + } + else { + transform_constraint_snap_axis_to_face(t, co_dir_3d, dvec); + } + } + + add_v3_v3v3(snap_point, co_orig_3d, dvec); + *value = line_point_factor_v3(snap_point, co_orig_3d, co_curr_3d); +} + static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; @@ -551,6 +583,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; + applySnapping(t, &final); snapGridIncrement(t, &final); /* only do this so out of range values are not displayed */ @@ -596,6 +629,8 @@ void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp) t->mode = TFM_VERT_SLIDE; t->transform = applyVertSlide; t->handleEvent = handleEventVertSlide; + t->tsnap.applySnap = vert_slide_snap_apply; + t->tsnap.distance = transform_snap_distance_len_squared_fn; { VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); @@ -617,7 +652,6 @@ void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp) if (sld) { tc->custom.mode.data = sld; tc->custom.mode.free_cb = freeVertSlideVerts; - trans_mesh_customdata_correction_init(t, tc); ok = true; } } diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 95249f4d17b..f86bcc41bee 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1049,11 +1049,11 @@ static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot) ot->exec = transform_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; - ot->poll = ED_operator_editarmature; + ot->poll = ED_operator_object_active; ot->poll_property = transform_poll_property; RNA_def_float_translation( - ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Display Size", "", -FLT_MAX, FLT_MAX); + ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Display Size", "", -FLT_MAX, FLT_MAX); WM_operatortype_props_advanced_begin(ot); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index b508507cd4e..2943c3cb8ea 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -22,23 +22,13 @@ */ #include <float.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> #include "PIL_time.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" -#include "BLI_utildefines.h" #include "GPU_immediate.h" #include "GPU_state.h" @@ -58,7 +48,6 @@ #include "ED_node.h" #include "ED_transform_snap_object_context.h" #include "ED_uvedit.h" -#include "ED_view3d.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -80,10 +69,6 @@ static void setSnappingCallback(TransInfo *t); -static void ApplySnapTranslation(TransInfo *t, float vec[3]); -static void ApplySnapRotation(TransInfo *t, float *vec); -static void ApplySnapResize(TransInfo *t, float vec[2]); - /* static void CalcSnapGrid(TransInfo *t, float *vec); */ static void CalcSnapGeometry(TransInfo *t, float *vec); @@ -92,10 +77,6 @@ static void TargetSnapCenter(TransInfo *t); static void TargetSnapClosest(TransInfo *t); static void TargetSnapActive(TransInfo *t); -static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]); -static float TranslationBetween(TransInfo *t, const float p1[3], const float p2[3]); -static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]); - /** \} */ /* -------------------------------------------------------------------- */ @@ -143,6 +124,12 @@ bool transformModeUseSnap(const TransInfo *t) if (t->mode == TFM_RESIZE) { return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0; } + if (t->mode == TFM_VERT_SLIDE) { + return true; + } + if (t->mode == TFM_EDGE_SLIDE) { + return true; + } return false; } @@ -476,7 +463,6 @@ void resetSnapping(TransInfo *t) t->tsnap.modeSelect = 0; t->tsnap.target = 0; t->tsnap.last = 0; - t->tsnap.applySnap = NULL; t->tsnap.snapNormal[0] = 0; t->tsnap.snapNormal[1] = 0; @@ -557,35 +543,32 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = ts->snap_mode; } - if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */ - (t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */ - { + if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && (t->flag & T_CAMERA) == 0) { + /* Only 3D view or UV. */ + /* Not with camera selected in camera view. */ + setSnappingCallback(t); - /* Edit mode */ - if (t->tsnap.applySnap != NULL && // A snapping function actually exist - ((obedit_type != -1) && - /* Temporary limited to edit mode meshes, armature, curves, metaballs. */ - ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL))) { - /* Exclude editmesh if using proportional edit */ + if ((obedit_type != -1) && + ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) { + /* Edit mode */ + /* Temporary limited to edit mode meshes, armature, curves, metaballs. */ + if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) { + /* Exclude editmesh if using proportional edit */ t->tsnap.modeSelect = SNAP_NOT_ACTIVE; } else { t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE; } } - /* Particles edit mode*/ - else if (t->tsnap.applySnap != NULL && // A snapping function actually exist - ((obedit_type == -1) && base_act && base_act->object && - base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { + else if ((obedit_type == -1) && base_act && base_act->object && + (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { + /* Particles edit mode. */ t->tsnap.modeSelect = SNAP_ALL; } - /* Object mode */ - else if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (obedit_type == -1)) // Object Mode - { - + else if (obedit_type == -1) { + /* Object mode */ if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { /* In "Edit Strokes" mode, * snap tool can perform snap to selected or active objects (see T49632) @@ -605,14 +588,7 @@ static void initSnappingMode(TransInfo *t) } else if (t->spacetype == SPACE_NODE) { setSnappingCallback(t); - - if (t->tsnap.applySnap != NULL) { - t->tsnap.modeSelect = SNAP_NOT_SELECTED; - } - else { - /* Grid if snap is not possible */ - t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; - } + t->tsnap.modeSelect = SNAP_NOT_SELECTED; } else if (t->spacetype == SPACE_SEQ) { /* We do our own snapping currently, so nothing here */ @@ -720,8 +696,13 @@ static void setSnappingCallback(TransInfo *t) t->tsnap.targetSnap = TargetSnapClosest; break; case SCE_SNAP_TARGET_CENTER: - t->tsnap.targetSnap = TargetSnapCenter; - break; + if (!ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { + t->tsnap.targetSnap = TargetSnapCenter; + break; + } + /* Can't do TARGET_CENTER with these modes, + * use TARGET_MEDIAN instead. */ + ATTR_FALLTHROUGH; case SCE_SNAP_TARGET_MEDIAN: t->tsnap.targetSnap = TargetSnapMedian; break; @@ -729,36 +710,6 @@ static void setSnappingCallback(TransInfo *t) t->tsnap.targetSnap = TargetSnapActive; break; } - - switch (t->mode) { - case TFM_TRANSLATION: - t->tsnap.applySnap = ApplySnapTranslation; - t->tsnap.distance = TranslationBetween; - break; - case TFM_ROTATION: - t->tsnap.applySnap = ApplySnapRotation; - t->tsnap.distance = RotationBetween; - - // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead - if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) { - t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - } - break; - case TFM_RESIZE: - t->tsnap.applySnap = ApplySnapResize; - t->tsnap.distance = ResizeBetween; - - // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead - if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) { - t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - } - break; - default: - t->tsnap.applySnap = NULL; - break; - } } void addSnapPoint(TransInfo *t) @@ -859,145 +810,6 @@ void getSnapPoint(const TransInfo *t, float vec[3]) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Apply Snap - * \{ */ - -static void ApplySnapTranslation(TransInfo *t, float vec[3]) -{ - float point[3]; - getSnapPoint(t, point); - - if (t->spacetype == SPACE_NODE) { - char border = t->tsnap.snapNodeBorder; - if (border & (NODE_LEFT | NODE_RIGHT)) { - vec[0] = point[0] - t->tsnap.snapTarget[0]; - } - if (border & (NODE_BOTTOM | NODE_TOP)) { - vec[1] = point[1] - t->tsnap.snapTarget[1]; - } - } - else { - if (t->spacetype == SPACE_VIEW3D) { - if (t->options & CTX_PAINT_CURVE) { - if (ED_view3d_project_float_global(t->region, point, point, V3D_PROJ_TEST_NOP) != - V3D_PROJ_RET_OK) { - zero_v3(point); /* no good answer here... */ - } - } - } - - sub_v3_v3v3(vec, point, t->tsnap.snapTarget); - } -} - -static void ApplySnapRotation(TransInfo *t, float *value) -{ - float point[3]; - getSnapPoint(t, point); - - float dist = RotationBetween(t, t->tsnap.snapTarget, point); - *value = dist; -} - -static void ApplySnapResize(TransInfo *t, float vec[3]) -{ - float point[3]; - getSnapPoint(t, point); - - float dist = ResizeBetween(t, t->tsnap.snapTarget, point); - if (dist != TRANSFORM_DIST_INVALID) { - copy_v3_fl(vec, dist); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Distance - * \{ */ - -static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const float p2[3]) -{ - return len_squared_v3v3(p1, p2); -} - -static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) -{ - float angle, start[3], end[3]; - - sub_v3_v3v3(start, p1, t->center_global); - sub_v3_v3v3(end, p2, t->center_global); - - // Angle around a constraint axis (error prone, will need debug) - if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { - float axis[3], tmp[3]; - - t->con.applyRot(t, NULL, NULL, axis, NULL); - - project_v3_v3v3(tmp, end, axis); - sub_v3_v3v3(end, end, tmp); - - project_v3_v3v3(tmp, start, axis); - sub_v3_v3v3(start, start, tmp); - - normalize_v3(end); - normalize_v3(start); - - cross_v3_v3v3(tmp, start, end); - - if (dot_v3v3(tmp, axis) < 0.0f) { - angle = -acosf(dot_v3v3(start, end)); - } - else { - angle = acosf(dot_v3v3(start, end)); - } - } - else { - float mtx[3][3]; - - copy_m3_m4(mtx, t->viewmat); - - mul_m3_v3(mtx, end); - mul_m3_v3(mtx, start); - - angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]); - } - - if (angle > (float)M_PI) { - angle = angle - 2 * (float)M_PI; - } - else if (angle < -((float)M_PI)) { - angle = 2.0f * (float)M_PI + angle; - } - - return angle; -} - -static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) -{ - float d1[3], d2[3], len_d1; - - sub_v3_v3v3(d1, p1, t->center_global); - sub_v3_v3v3(d2, p2, t->center_global); - - if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { - mul_m3_v3(t->con.pmtx, d1); - mul_m3_v3(t->con.pmtx, d2); - } - - project_v3_v3v3(d1, d1, d2); - - len_d1 = len_v3(d1); - - /* Use 'invalid' dist when `center == p1` (after projecting), - * in this case scale will _never_ move the point in relation to the center, - * so it makes no sense to take it into account when scaling. see: T46503 */ - return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Calc Snap (Generic) * \{ */ @@ -1734,3 +1546,16 @@ static void applyGridIncrement( } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generic callbacks + * \{ */ + +float transform_snap_distance_len_squared_fn(TransInfo *UNUSED(t), + const float p1[3], + const float p2[3]) +{ + return len_squared_v3v3(p1, p2); +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h index c088cf80f0d..688661bc2cb 100644 --- a/source/blender/editors/transform/transform_snap.h +++ b/source/blender/editors/transform/transform_snap.h @@ -87,4 +87,6 @@ void addSnapPoint(TransInfo *t); eRedrawFlag updateSelectedSnapPoint(TransInfo *t); void removeSnapPoint(TransInfo *t); +float transform_snap_distance_len_squared_fn(TransInfo *t, const float p1[3], const float p2[3]); + #endif /* __TRANSFORM_SNAP_H__ */ diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 08ef5109a74..4198b4c02a3 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -367,17 +367,15 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, * \{ */ typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, - bool use_obedit, - bool use_backface_culling, Object *ob, float obmat[4][4], + bool use_obedit, + bool use_backface_culling, + bool is_object_active, void *data); /** * Walks through all objects in the scene to create the list of objects to snap. - * - * \param sctx: Snap context to store data. - * \param snap_select: from enum #eSnapSelect. */ static void iter_snap_objects(SnapObjectContext *sctx, Depsgraph *depsgraph, @@ -393,7 +391,6 @@ static void iter_snap_objects(SnapObjectContext *sctx, Base *base_act = view_layer->basact; for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { - if (!BASE_VISIBLE(v3d, base)) { continue; } @@ -405,13 +402,14 @@ static void iter_snap_objects(SnapObjectContext *sctx, continue; } + const bool is_object_active = (base == base_act); if (snap_select == SNAP_NOT_SELECTED) { if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { continue; } } else if (snap_select == SNAP_NOT_ACTIVE) { - if (base == base_act) { + if (is_object_active) { continue; } } @@ -421,14 +419,24 @@ static void iter_snap_objects(SnapObjectContext *sctx, DupliObject *dupli_ob; ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - sob_callback( - sctx, use_object_edit_cage, use_backface_culling, dupli_ob->ob, dupli_ob->mat, data); + sob_callback(sctx, + dupli_ob->ob, + dupli_ob->mat, + use_object_edit_cage, + use_backface_culling, + is_object_active, + data); } free_object_duplilist(lb); } - sob_callback( - sctx, use_object_edit_cage, use_backface_culling, obj_eval, obj_eval->obmat, data); + sob_callback(sctx, + obj_eval, + obj_eval->obmat, + use_object_edit_cage, + use_backface_culling, + is_object_active, + data); } } @@ -956,10 +964,11 @@ struct RaycastObjUserData { * \note Duplicate args here are documented at #snapObjectsRay */ static void raycast_obj_fn(SnapObjectContext *sctx, - bool use_obedit, - bool use_backface_culling, Object *ob, float obmat[4][4], + bool use_obedit, + bool use_backface_culling, + bool is_object_active, void *data) { struct RaycastObjUserData *dt = data; @@ -1032,24 +1041,26 @@ static void raycast_obj_fn(SnapObjectContext *sctx, case OB_CURVE: case OB_SURF: case OB_FONT: { - Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); - if (mesh_eval) { - retval = raycastMesh(sctx, - dt->ray_start, - dt->ray_dir, - ob, - mesh_eval, - obmat, - ob_index, - false, - use_backface_culling, - ray_depth, - dt->r_loc, - dt->r_no, - dt->r_index, - dt->r_hit_list); - break; + if (!is_object_active) { + Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); + if (mesh_eval) { + retval = raycastMesh(sctx, + dt->ray_start, + dt->ray_dir, + ob, + mesh_eval, + obmat, + ob_index, + false, + use_backface_culling, + ray_depth, + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); + } } + break; } } @@ -1071,9 +1082,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx, * Walks through all objects in the scene to find the `hit` on object surface. * * \param sctx: Snap context to store data. - * \param snap_select: from enum eSnapSelect. - * \param use_object_edit_cage: Uses the coordinates of BMesh(if any) to do the snapping. - * \param obj_list: List with objects to snap (created in `create_object_list`). + * \param params: Snapping behavior. * * Read/Write Args * --------------- @@ -2054,15 +2063,15 @@ static short snapCurve(SnapData *snapdata, } /* may extend later (for now just snaps to empty center) */ -static short snapEmpty(SnapData *snapdata, - Object *ob, - const float obmat[4][4], - /* read/write args */ - float *dist_px, - /* return args */ - float r_loc[3], - float *UNUSED(r_no), - int *r_index) +static short snap_object_center(SnapData *snapdata, + Object *ob, + const float obmat[4][4], + /* read/write args */ + float *dist_px, + /* return args */ + float r_loc[3], + float *UNUSED(r_no), + int *r_index) { short retval = 0; @@ -2117,7 +2126,7 @@ static short snapCamera(const SnapObjectContext *sctx, float *dist_px, /* return args */ float r_loc[3], - float *UNUSED(r_no), + float *r_no, int *r_index) { short retval = 0; @@ -2132,7 +2141,7 @@ static short snapCamera(const SnapObjectContext *sctx, MovieTracking *tracking; if (clip == NULL) { - return retval; + return snap_object_center(snapdata, object, obmat, dist_px, r_loc, r_no, r_index); } if (object->transflag & OB_DUPLI) { return retval; @@ -2650,11 +2659,12 @@ struct SnapObjUserData { * * \note Duplicate args here are documented at #snapObjectsRay */ -static void sanp_obj_fn(SnapObjectContext *sctx, - bool use_obedit, - bool use_backface_culling, +static void snap_obj_fn(SnapObjectContext *sctx, Object *ob, float obmat[4][4], + bool use_obedit, + bool use_backface_culling, + bool UNUSED(is_object_active), void *data) { struct SnapObjUserData *dt = data; @@ -2729,10 +2739,10 @@ static void sanp_obj_fn(SnapObjectContext *sctx, break; } case OB_EMPTY: - retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); - break; case OB_GPENCIL: - retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); + case OB_LAMP: + retval = snap_object_center( + dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_CAMERA: retval = snapCamera( @@ -2800,7 +2810,7 @@ static short snapObjectsRay(SnapObjectContext *sctx, .ret = 0, }; - iter_snap_objects(sctx, depsgraph, params, sanp_obj_fn, &data); + iter_snap_objects(sctx, depsgraph, params, snap_obj_fn, &data); return data.ret; } @@ -3205,7 +3215,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, * \param mval: Screenspace coordinate. * \param prev_co: Coordinate for perpendicular point calculation (optional). * \param dist_px: Maximum distance to snap (in pixels). - * \param r_co: hit location. + * \param r_loc: hit location. * \param r_no: hit normal (optional). * \return Snap success */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 897e2f13774..df6e4f70e99 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -409,70 +409,49 @@ static void draw_uvs(SpaceImage *sima, GPU_blend(true); } - switch (sima->dt_uv) { - case SI_UVDT_DASH: { - float dash_colors[2][4] = { - {0.56f, 0.56f, 0.56f, overlay_alpha}, - {0.07f, 0.07f, 0.07f, overlay_alpha}, - }; - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - - GPU_line_width(1.0f); - GPU_batch_program_set_builtin(batch->edges, GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - GPU_batch_uniform_4fv_array(batch->edges, "colors", 2, (float *)dash_colors); - GPU_batch_uniform_2f(batch->edges, - "viewport_size", - viewport_size[2] / UI_DPI_FAC, - viewport_size[3] / UI_DPI_FAC); - GPU_batch_uniform_1i(batch->edges, "colors_len", 2); /* "advanced" mode */ - GPU_batch_uniform_1f(batch->edges, "dash_width", 4.0f); - GPU_batch_uniform_1f(batch->edges, "dash_factor", 0.5f); - GPU_batch_draw(batch->edges); - break; - } - case SI_UVDT_BLACK: - case SI_UVDT_WHITE: - case SI_UVDT_OUTLINE: { - /* We could modify the vbo's data filling - * instead of modifying the provoking vert. */ - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - - UI_GetThemeColor3fv(TH_EDGE_SELECT, col2); - col2[3] = overlay_alpha; - - GPU_batch_program_set_builtin( - batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); - - if (sima->dt_uv == SI_UVDT_OUTLINE) { - /* Black Outline. */ - GPU_line_width(3.0f); - GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha); - GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha); - GPU_batch_draw(batch->edges); - - UI_GetThemeColor3fv(TH_WIRE_EDIT, col1); - } - else if (sima->dt_uv == SI_UVDT_WHITE) { - copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f); - } - else { - copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f); - } - col1[3] = overlay_alpha; + { + /* We could modify the vbo's data filling + * instead of modifying the provoking vert. */ + glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); + + UI_GetThemeColor3fv(TH_EDGE_SELECT, col2); + col2[3] = overlay_alpha; - /* Inner Line. Use depth test to insure selection is drawn on top. */ - GPU_depth_test(true); - GPU_line_width(1.0f); - GPU_batch_uniform_4fv(batch->edges, "edgeColor", col1); - GPU_batch_uniform_4fv(batch->edges, "selectColor", col2); + float dash_width = (sima->dt_uv & SI_UVDT_DASH) ? (4.0f * UI_DPI_FAC) : 9999.0f; + + GPU_batch_program_set_builtin( + batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); + + if (sima->dt_uv == SI_UVDT_OUTLINE) { + /* Black Outline. */ + GPU_line_width(3.0f); + GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha); + GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha); + GPU_batch_uniform_1f(batch->edges, "dashWidth", dash_width); GPU_batch_draw(batch->edges); - GPU_depth_test(false); - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); - break; + UI_GetThemeColor3fv(TH_WIRE_EDIT, col1); + } + else if (sima->dt_uv == SI_UVDT_BLACK) { + copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f); } + else { + copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f); + } + col1[3] = overlay_alpha; + + /* Inner Line. Use depth test to insure selection is drawn on top. */ + GPU_depth_test(true); + GPU_line_width(1.0f); + GPU_batch_uniform_4fv(batch->edges, "edgeColor", col1); + GPU_batch_uniform_4fv(batch->edges, "selectColor", col2); + GPU_batch_uniform_1f(batch->edges, "dashWidth", dash_width); + GPU_batch_draw(batch->edges); + GPU_depth_test(false); + + glProvokingVertex(GL_LAST_VERTEX_CONVENTION); } + if (sima->flag & SI_SMOOTH_UV) { GPU_line_smooth(false); GPU_blend(false); @@ -481,6 +460,7 @@ static void draw_uvs(SpaceImage *sima, GPU_blend(false); } } + if (batch->verts || batch->facedots) { UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2); if (batch->verts) { |