From 2525f9c5f31e90bcb8f2e8c84558a2bc35e3207c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 12 Mar 2014 23:57:33 +0600 Subject: backport revisions from master for 2.70-rc2 tag This includes: 68ef679, d0ad48f, e913eab + 8d09ec6, 9630fa7, 4ce7d5c, b839fb9, 43b5f0a, 4d47e75, 89c793f, b23a439, 0a3850f de86b70, cfefc5d, 997b49a, 6919ffb, c1be7e1, 6ddd54f 7a9838b + 98abc80, 23fbc9f, 41dde55, 500088d, c2045ef c31c8fa, 7461fea, d219312, 0844451 + c05896e, ef51b69 19935f0, b977cfd, 3c3c2cd, 9ecf73f, 20f7a34, f03df4f 2de9da6, ba81fb7, a7ab389, d7cff8f7 --- source/blender/editors/animation/anim_filter.c | 9 +- source/blender/editors/interface/interface_ops.c | 6 +- source/blender/editors/mask/mask_shapekey.c | 9 +- source/blender/editors/mesh/editmesh_knife.c | 4 +- source/blender/editors/object/object_add.c | 30 +++- source/blender/editors/sculpt_paint/paint_vertex.c | 1 + source/blender/editors/sculpt_paint/sculpt.c | 9 +- source/blender/editors/sculpt_paint/sculpt_uv.c | 2 + source/blender/editors/space_action/action_edit.c | 9 +- source/blender/editors/space_clip/clip_editor.c | 8 +- source/blender/editors/space_clip/clip_ops.c | 5 +- source/blender/editors/space_image/space_image.c | 7 +- source/blender/editors/space_view3d/drawobject.c | 8 +- source/blender/editors/space_view3d/view3d_draw.c | 6 +- .../blender/editors/space_view3d/view3d_select.c | 12 +- .../editors/transform/transform_conversions.c | 199 ++++++--------------- 16 files changed, 144 insertions(+), 180 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 9d54d938cc7..a4a1e951477 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1796,9 +1796,14 @@ static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data Material *base = give_current_material(ob, a); Material *ma = give_node_material(base); - /* add channels from the nested material if it exists */ - if (ma) + /* add channels from the nested material if it exists + * - skip if the same material is referenced in its node tree + * (which is common for BI materials) as that results in + * confusing duplicates + */ + if ((ma) && (ma != base)) { items += animdata_filter_ds_material(ac, anim_data, ads, ma, filter_mode); + } } } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 370e2960709..4bbccec7f9d 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -334,7 +334,7 @@ static int copy_to_selected_button_exec(bContext *C, wmOperator *op) { PointerRNA ptr, lptr, idptr; PropertyRNA *prop, *lprop; - int success = 0; + bool success = false; int index; const bool all = RNA_boolean_get(op->ptr, "all"); @@ -349,7 +349,7 @@ static int copy_to_selected_button_exec(bContext *C, wmOperator *op) ListBase lb; if (!copy_to_selected_list(C, &ptr, &lb, &use_path)) - return success; + return OPERATOR_CANCELLED; if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) { for (link = lb.first; link; link = link->next) { @@ -368,7 +368,7 @@ static int copy_to_selected_button_exec(bContext *C, wmOperator *op) if (RNA_property_editable(&lptr, lprop)) { if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) { RNA_property_update(C, &lptr, prop); - success = 1; + success = true; } } } diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index cea350219c0..30c960bda0f 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -272,16 +272,18 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) } if (masklay->splines_shapes.first) { - MaskLayerShape *masklay_shape; + MaskLayerShape *masklay_shape, *masklay_shape_next; MaskLayerShape *masklay_shape_lastsel = NULL; for (masklay_shape = masklay->splines_shapes.first; masklay_shape; - masklay_shape = masklay_shape->next) + masklay_shape = masklay_shape_next) { MaskLayerShape *masklay_shape_a = NULL; MaskLayerShape *masklay_shape_b = NULL; + masklay_shape_next = masklay_shape->next; + /* find contiguous selections */ if (masklay_shape->flag & MASK_SHAPE_SELECT) { if (masklay_shape_lastsel == NULL) { @@ -293,6 +295,9 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) masklay_shape_a = masklay_shape_lastsel; masklay_shape_b = masklay_shape; masklay_shape_lastsel = NULL; + + /* this will be freed below, step over selection */ + masklay_shape_next = masklay_shape->next; } } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index c762c82442e..772fe7d306e 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -77,7 +77,7 @@ #define KNIFE_FLT_EPS 0.00001f #define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS) -#define KNIFE_FLT_EPSBIG 0.001f +#define KNIFE_FLT_EPSBIG 0.0005f typedef struct KnifeColors { unsigned char line[3]; @@ -653,7 +653,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd, KnifeLineHit *lh1, Knife } /* Check if edge actually lies within face (might not, if this face is concave) */ - if (lh1->v && lh2->v) { + if ((lh1->v && !lh1->kfe) && (lh2->v && !lh2->kfe)) { if (!knife_verts_edge_in_face(lh1->v, lh2->v, f)) { return; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index a2101716dbf..b29fafea90d 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1298,6 +1298,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BKE_free_animdata(&ob->id); ob->adt = NULL; + /* Proxies are not to be copied. */ + ob->proxy_from = NULL; + ob->proxy_group = NULL; + ob->proxy = NULL; + ob->parent = NULL; BLI_listbase_clear(&ob->constraints); ob->curve_cache = NULL; @@ -1453,10 +1458,24 @@ static EnumPropertyItem convert_target_items[] = { {0, NULL, 0, NULL, NULL} }; -static void curvetomesh(Object *ob) +static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob) { - BLI_assert(ob->curve_cache != NULL); + if (ob->curve_cache == NULL) { + /* Force creation. This is normally not needed but on operator + * redo we might end up with an object which isn't evaluated yet. + */ + if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { + BKE_displist_make_curveTypes(scene, ob, FALSE); + } + else if (ob->type == OB_MBALL) { + BKE_displist_make_mball(bmain->eval_ctx, scene, ob); + } + } +} +static void curvetomesh(Main *bmain, Scene *scene, Object *ob) +{ + convert_ensure_curve_cache(bmain, scene, ob); BKE_mesh_from_nurbs(ob); /* also does users */ if (ob->type == OB_MESH) @@ -1508,7 +1527,7 @@ static int convert_exec(bContext *C, wmOperator *op) MetaBall *mb; Mesh *me; const short target = RNA_enum_get(op->ptr, "target"); - const short keep_original = RNA_boolean_get(op->ptr, "keep_original"); + const bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); int a, mballConverted = 0; /* don't forget multiple users! */ @@ -1667,7 +1686,7 @@ static int convert_exec(bContext *C, wmOperator *op) BKE_curve_curve_dimension_update(cu); if (target == OB_MESH) { - curvetomesh(newob); + curvetomesh(bmain, scene, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -1691,7 +1710,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - curvetomesh(newob); + curvetomesh(bmain, scene, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -1729,6 +1748,7 @@ static int convert_exec(bContext *C, wmOperator *op) for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]); } + convert_ensure_curve_cache(bmain, scene, baseob); BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data); if (obact->type == OB_MBALL) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 55296aeda18..12eb1524515 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -189,6 +189,7 @@ static VPaint *new_vpaint(int wpaint) VPaint *vp = MEM_callocN(sizeof(VPaint), "VPaint"); vp->flag = (wpaint) ? 0 : VP_SPRAY; + vp->paint.flags |= PAINT_SHOW_BRUSH; return vp; } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 5d4037a2bd3..d74e9c9e17b 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2195,7 +2195,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode mul_v3_v3fl(val, offset, *disp); - if (ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { + if (!ss->multires && !ss->bm && ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) { int index = vd.vert_indices[vd.i]; /* persistent base */ @@ -3953,6 +3953,12 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } } } + + if (ss->bm) { + /* Free any remaining layer displacements from nodes. If not and topology changes + * from using another tool, then next layer toolstroke can access past disp array bounds */ + BKE_pbvh_free_layer_disp(ss->pbvh); + } } /* Make copies of the mesh vertex locations and normals for some tools */ @@ -5119,6 +5125,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) /* Turn on X plane mirror symmetry by default */ ts->sculpt->paint.symmetry_flags |= PAINT_SYMM_X; + ts->sculpt->paint.flags |= PAINT_SHOW_BRUSH; /* Make sure at least dyntopo subdivision is enabled */ ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE; diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 4dc2c87ca0a..da2b62bce8b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -194,6 +194,8 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB; settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS; settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN; + /* Uv sculpting does not include explicit brush view control yet, always enable */ + settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH; } BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index e2ca45bbdc9..4c2cb16bdd1 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -368,7 +368,7 @@ static int actkeys_viewall(bContext *C, const bool only_sel, const bool only_xax { bAnimContext ac; View2D *v2d; - float extra; + float extra, min, max; bool found; /* get editor data */ @@ -377,11 +377,14 @@ static int actkeys_viewall(bContext *C, const bool only_sel, const bool only_xax v2d = &ac.ar->v2d; /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ - found = get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel); + found = get_keyframe_extents(&ac, &min, &max, only_sel); if (only_sel && (found == false)) return OPERATOR_CANCELLED; - + + v2d->cur.xmin = min; + v2d->cur.xmax = max; + extra = 0.1f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 0543e348b5b..18652aabefe 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -765,12 +765,18 @@ static void *do_prefetch_thread(void *data_v) MovieClipUser user = {0}; int flag = IB_rect | IB_alphamode_detect; int result; + char *colorspace_name = NULL; user.framenr = current_frame; user.render_size = data->queue->render_size; user.render_flag = data->queue->render_flag; - ibuf = IMB_ibImageFromMemory(mem, size, flag, clip->colorspace_settings.name, "prefetch frame"); + /* Proxies are stored in the display space. */ + if (data->queue->render_flag & MCLIP_USE_PROXY) { + colorspace_name = clip->colorspace_settings.name; + } + + ibuf = IMB_ibImageFromMemory(mem, size, flag, colorspace_name, "prefetch frame"); result = BKE_movieclip_put_frame_if_possible(data->clip, &user, ibuf); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 7a6c4268aab..bb6c50d6224 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1002,7 +1002,7 @@ static void do_movie_proxy(void *pjv, int *UNUSED(build_sizes), int UNUSED(build } else { sfra = 1; - efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE); + efra = clip->len; } if (build_undistort_count) { @@ -1118,7 +1118,8 @@ static void *do_proxy_thread(void *data_v) while ((mem = proxy_thread_next_frame(data->queue, data->clip, &size, &cfra))) { ImBuf *ibuf; - ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, NULL, "proxy frame"); + ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, + data->clip->colorspace_settings.name, "proxy frame"); BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra, data->build_sizes, data->build_count, false); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 5c9fd233a5c..14fd486c546 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -512,18 +512,21 @@ static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) } case NC_OBJECT: { - Object *ob = OBACT; switch (wmn->data) { case ND_TRANSFORM: case ND_MODIFIER: - if (ob == (Object *)wmn->reference && (ob->mode & OB_MODE_EDIT)) { + { + Object *ob = OBACT; + if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) { if (sima->lock && (sima->flag & SI_DRAWSHADOW)) { ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); } } break; + } } + break; } } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index b0eb8d20554..c1adbafe413 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -4649,8 +4649,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv else pa_health = -1.0; - r_tilt = 2.0f * (PSYS_FRAND(a + 21) - 0.5f); - r_length = PSYS_FRAND(a + 22); + r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f); + r_length = psys_frand(psys, a + 22); if (part->draw_col > PART_DRAW_COL_MAT) { switch (part->draw_col) { @@ -4677,8 +4677,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pa_health = -1.0; - r_tilt = 2.0f * (PSYS_FRAND(a + 21) - 0.5f); - r_length = PSYS_FRAND(a + 22); + r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f); + r_length = psys_frand(psys, a + 22); } drawn = 0; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 18f3d150eb2..ad54e8a5eff 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3262,9 +3262,11 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const glEnable(GL_MULTISAMPLE_ARB); } - - /* needs to be done always, gridview is adjusted in drawgrid() now */ + /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */ rv3d->gridview = v3d->grid; + if (scene->unit.system) { + rv3d->gridview /= scene->unit.scale_length; + } if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 47f30e3e279..1c355889398 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -568,8 +568,10 @@ static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); - if (extend == false && select) - ED_curve_deselect_all(vc->obedit->data); + if (extend == false && select) { + Curve *curve = (Curve *) vc->obedit->data; + ED_curve_deselect_all(curve->editnurb); + } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -1735,8 +1737,10 @@ static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool ex view3d_userdata_boxselect_init(&data, vc, rect, select); - if (extend == false && select) - ED_curve_deselect_all(vc->obedit->data); + if (extend == false && select) { + Curve *curve = (Curve *) vc->obedit->data; + ED_curve_deselect_all(curve->editnurb); + } ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index beb49a5443e..8dc0c6ddaa8 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3001,6 +3001,34 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* ********************* ACTION EDITOR ****************** */ +static int gpf_cmp_frame(void *thunk, void *a, void *b) +{ + bGPDframe *frame_a = a; + bGPDframe *frame_b = b; + + if (frame_a->framenum < frame_b->framenum) return -1; + if (frame_a->framenum > frame_b->framenum) return 1; + *((bool *)thunk) = true; + /* selected last */ + if ((frame_a->flag & GP_FRAME_SELECT) && + ((frame_b->flag & GP_FRAME_SELECT) == 0)) return 1; + return 0; +} + +static int masklay_shape_cmp_frame(void *thunk, void *a, void *b) +{ + MaskLayerShape *frame_a = a; + MaskLayerShape *frame_b = b; + + if (frame_a->frame < frame_b->frame) return -1; + if (frame_a->frame > frame_b->frame) return 1; + *((bool *)thunk) = true; + /* selected last */ + if ((frame_a->flag & MASK_SHAPE_SELECT) && + ((frame_b->flag & MASK_SHAPE_SELECT) == 0)) return 1; + return 0; +} + /* Called by special_aftertrans_update to make sure selected gp-frames replace * any other gp-frames which may reside on that frame (that are not selected). * It also makes sure gp-frames are still stored in chronological order after @@ -3011,175 +3039,52 @@ static void posttrans_gpd_clean(bGPdata *gpd) bGPDlayer *gpl; for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - ListBase sel_buffer = {NULL, NULL}; bGPDframe *gpf, *gpfn; - bGPDframe *gfs, *gfsn; - - /* loop 1: loop through and isolate selected gp-frames to buffer - * (these need to be sorted as they are isolated) - */ - for (gpf = gpl->frames.first; gpf; gpf = gpfn) { - short added = 0; - gpfn = gpf->next; - - if (gpf->flag & GP_FRAME_SELECT) { - BLI_remlink(&gpl->frames, gpf); - - /* find place to add them in buffer - * - go backwards as most frames will still be in order, - * so doing it this way will be faster - */ - for (gfs = sel_buffer.last; gfs; gfs = gfs->prev) { - /* if current (gpf) occurs after this one in buffer, add! */ - if (gfs->framenum < gpf->framenum) { - BLI_insertlinkafter(&sel_buffer, gfs, gpf); - added = 1; - break; - } - } - if (added == 0) - BLI_addhead(&sel_buffer, gpf); - } - } - - /* error checking: it is unlikely, but may be possible to have none selected */ - if (BLI_listbase_is_empty(&sel_buffer)) - continue; - - /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */ - if (BLI_listbase_is_empty(&gpl->frames)) { - gpl->frames.first = sel_buffer.first; - gpl->frames.last = sel_buffer.last; - - continue; - } - - /* loop 2: remove duplicates of frames in buffers */ - for (gpf = gpl->frames.first; gpf && sel_buffer.first; gpf = gpfn) { - gpfn = gpf->next; - - /* loop through sel_buffer, emptying stuff from front of buffer if ok */ - for (gfs = sel_buffer.first; gfs && gpf; gfs = gfsn) { - gfsn = gfs->next; - - /* if this buffer frame needs to go before current, add it! */ - if (gfs->framenum < gpf->framenum) { - /* transfer buffer frame to frames list (before current) */ - BLI_remlink(&sel_buffer, gfs); - BLI_insertlinkbefore(&gpl->frames, gpf, gfs); - } - /* if this buffer frame is on same frame, replace current with it and stop */ - else if (gfs->framenum == gpf->framenum) { - /* transfer buffer frame to frames list (before current) */ - BLI_remlink(&sel_buffer, gfs); - BLI_insertlinkbefore(&gpl->frames, gpf, gfs); - - /* get rid of current frame */ + bool is_double = false; + + BLI_sortlist_r(&gpl->frames, &is_double, gpf_cmp_frame); + + if (is_double) { + for (gpf = gpl->frames.first; gpf; gpf = gpfn) { + gpfn = gpf->next; + if (gpfn && gpf->framenum == gpfn->framenum) { gpencil_layer_delframe(gpl, gpf); } } } - - /* if anything is still in buffer, append to end */ - for (gfs = sel_buffer.first; gfs; gfs = gfsn) { - gfsn = gfs->next; - - BLI_remlink(&sel_buffer, gfs); - BLI_addtail(&gpl->frames, gfs); + +#ifdef DEBUG + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + BLI_assert(!gpf->next || gpf->framenum < gpf->next->framenum); } +#endif } } - -/* Called by special_aftertrans_update to make sure selected gp-frames replace - * any other gp-frames which may reside on that frame (that are not selected). - * It also makes sure sorted are still stored in chronological order after - * transform. - */ static void posttrans_mask_clean(Mask *mask) { MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - ListBase sel_buffer = {NULL, NULL}; - MaskLayerShape *masklay_shape, *masklay_shape_new; - MaskLayerShape *masklay_shape_sort, *masklay_shape_sort_new; - - /* loop 1: loop through and isolate selected gp-frames to buffer - * (these need to be sorted as they are isolated) - */ - for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_new) { - short added = 0; - masklay_shape_new = masklay_shape->next; + MaskLayerShape *masklay_shape, *masklay_shape_next; + bool is_double = false; - if (masklay_shape->flag & MASK_SHAPE_SELECT) { - BLI_remlink(&masklay->splines_shapes, masklay_shape); + BLI_sortlist_r(&masklay->splines_shapes, &is_double, masklay_shape_cmp_frame); - /* find place to add them in buffer - * - go backwards as most frames will still be in order, - * so doing it this way will be faster - */ - for (masklay_shape_sort = sel_buffer.last; masklay_shape_sort; masklay_shape_sort = masklay_shape_sort->prev) { - /* if current (masklay_shape) occurs after this one in buffer, add! */ - if (masklay_shape_sort->frame < masklay_shape->frame) { - BLI_insertlinkafter(&sel_buffer, masklay_shape_sort, masklay_shape); - added = 1; - break; - } - } - if (added == 0) - BLI_addhead(&sel_buffer, masklay_shape); - } - } - - /* error checking: it is unlikely, but may be possible to have none selected */ - if (BLI_listbase_is_empty(&sel_buffer)) - continue; - - /* if all were selected (i.e. masklay->splines_shapes is empty), then just transfer sel-buf over */ - if (BLI_listbase_is_empty(&masklay->splines_shapes)) { - masklay->splines_shapes.first = sel_buffer.first; - masklay->splines_shapes.last = sel_buffer.last; - - continue; - } - - /* loop 2: remove duplicates of splines_shapes in buffers */ - for (masklay_shape = masklay->splines_shapes.first; masklay_shape && sel_buffer.first; masklay_shape = masklay_shape_new) { - masklay_shape_new = masklay_shape->next; - - /* loop through sel_buffer, emptying stuff from front of buffer if ok */ - for (masklay_shape_sort = sel_buffer.first; masklay_shape_sort && masklay_shape; masklay_shape_sort = masklay_shape_sort_new) { - masklay_shape_sort_new = masklay_shape_sort->next; - - /* if this buffer frame needs to go before current, add it! */ - if (masklay_shape_sort->frame < masklay_shape->frame) { - /* transfer buffer frame to splines_shapes list (before current) */ - BLI_remlink(&sel_buffer, masklay_shape_sort); - BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort); - } - /* if this buffer frame is on same frame, replace current with it and stop */ - else if (masklay_shape_sort->frame == masklay_shape->frame) { - /* transfer buffer frame to splines_shapes list (before current) */ - BLI_remlink(&sel_buffer, masklay_shape_sort); - BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort); - - /* get rid of current frame */ + if (is_double) { + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) { + masklay_shape_next = masklay_shape->next; + if (masklay_shape_next && masklay_shape->frame == masklay_shape_next->frame) { BKE_mask_layer_shape_unlink(masklay, masklay_shape); } } } - /* if anything is still in buffer, append to end */ - for (masklay_shape_sort = sel_buffer.first; masklay_shape_sort; masklay_shape_sort = masklay_shape_sort_new) { - masklay_shape_sort_new = masklay_shape_sort->next; - - BLI_remlink(&sel_buffer, masklay_shape_sort); - BLI_addtail(&masklay->splines_shapes, masklay_shape_sort); +#ifdef DEBUG + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + BLI_assert(!masklay_shape->next || masklay_shape->frame < masklay_shape->next->frame); } - - /* NOTE: this is the only difference to grease pencil code above */ - BKE_mask_layer_shape_sort(masklay); +#endif } } -- cgit v1.2.3