From c78ebf9f26d01fcc3cf16baa9da922ee183f4b09 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 19 Mar 2018 14:49:59 +0100 Subject: Cleanup: split lattice into own library Was mixed with object functionality. --- source/blender/editors/lattice/CMakeLists.txt | 45 ++ .../blender/editors/lattice/editlattice_select.c | 558 +++++++++++++++++++++ source/blender/editors/lattice/editlattice_tools.c | 340 +++++++++++++ source/blender/editors/lattice/editlattice_undo.c | 113 +++++ source/blender/editors/lattice/lattice_intern.h | 44 ++ source/blender/editors/lattice/lattice_ops.c | 80 +++ 6 files changed, 1180 insertions(+) create mode 100644 source/blender/editors/lattice/CMakeLists.txt create mode 100644 source/blender/editors/lattice/editlattice_select.c create mode 100644 source/blender/editors/lattice/editlattice_tools.c create mode 100644 source/blender/editors/lattice/editlattice_undo.c create mode 100644 source/blender/editors/lattice/lattice_intern.h create mode 100644 source/blender/editors/lattice/lattice_ops.c (limited to 'source/blender/editors/lattice') diff --git a/source/blender/editors/lattice/CMakeLists.txt b/source/blender/editors/lattice/CMakeLists.txt new file mode 100644 index 00000000000..3bb954ddf46 --- /dev/null +++ b/source/blender/editors/lattice/CMakeLists.txt @@ -0,0 +1,45 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# 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. +# +# Contributor(s): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenlib + ../../makesdna + ../../makesrna + ../../render/extern/include + ../../windowmanager + ../../../../intern/guardedalloc +) + +set(INC_SYS + +) + +set(SRC + editlattice_select.c + editlattice_tools.c + editlattice_undo.c + lattice_ops.c + + lattice_intern.h +) + +blender_add_lib(bf_editor_lattice "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c new file mode 100644 index 00000000000..d0d64b85195 --- /dev/null +++ b/source/blender/editors/lattice/editlattice_select.c @@ -0,0 +1,558 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/lattice/editlattice_select.c + * \ingroup edlattice + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" +#include "BLI_rand.h" +#include "BLI_bitmap.h" + +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "BKE_context.h" +#include "BKE_lattice.h" +#include "BKE_report.h" + +#include "ED_screen.h" +#include "ED_lattice.h" +#include "ED_view3d.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "lattice_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Utility Functions + * \{ */ + +static void bpoint_select_set(BPoint *bp, bool select) +{ + if (select) { + if (!bp->hide) { + bp->f1 |= SELECT; + } + } + else { + bp->f1 &= ~SELECT; + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Random Operator + * \{ */ + +static int lattice_select_random_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; + + const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const int seed = WM_operator_properties_select_random_seed_increment_get(op); + const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); + + RNG *rng = BLI_rng_new_srandom(seed); + + int tot; + BPoint *bp; + + tot = lt->pntsu * lt->pntsv * lt->pntsw; + bp = lt->def; + while (tot--) { + if (!bp->hide) { + if (BLI_rng_get_float(rng) < randfac) { + bpoint_select_set(bp, select); + } + } + bp++; + } + + if (select == false) { + lt->actbp = LT_ACTBP_NONE; + } + + BLI_rng_free(rng); + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_random(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Random"; + ot->description = "Randomly select UVW control points"; + ot->idname = "LATTICE_OT_select_random"; + + /* api callbacks */ + ot->exec = lattice_select_random_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + WM_operator_properties_select_random(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Mirror Operator + * \{ */ + +static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend) +{ + const int tot = lt->pntsu * lt->pntsv * lt->pntsw; + int i; + BPoint *bp; + BLI_bitmap *selpoints; + + bool flip_uvw[3] = {false}; + flip_uvw[axis] = true; + + /* we could flip this too */ + if (!extend) { + lt->actbp = LT_ACTBP_NONE; + } + + /* store "original" selection */ + selpoints = BLI_BITMAP_NEW(tot, __func__); + BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false); + + /* actual (de)selection */ + for (i = 0; i < tot; i++) { + const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]); + bp = <->def[i]; + if (!bp->hide) { + if (BLI_BITMAP_TEST(selpoints, i_flip)) { + bp->f1 |= SELECT; + } + else { + if (!extend) { + bp->f1 &= ~SELECT; + } + } + } + } + + + MEM_freeN(selpoints); +} + +static int lattice_select_mirror_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; + const int axis_flag = RNA_enum_get(op->ptr, "axis"); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + + for (int axis = 0; axis < 3; axis++) { + if ((1 << axis) & axis_flag) { + ed_lattice_select_mirrored(lt, axis, extend); + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_mirror(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Mirror"; + ot->description = "Select mirrored lattice points"; + ot->idname = "LATTICE_OT_select_mirror"; + + /* api callbacks */ + ot->exec = lattice_select_mirror_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", ""); + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More/Less Operator + * \{ */ + +static bool lattice_test_bitmap_uvw(Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected) +{ + if ((u < 0 || u >= lt->pntsu) || + (v < 0 || v >= lt->pntsv) || + (w < 0 || w >= lt->pntsw)) + { + return false; + } + else { + int i = BKE_lattice_index_from_uvw(lt, u, v, w); + if (lt->def[i].hide == 0) { + return (BLI_BITMAP_TEST(selpoints, i) != 0) == selected; + } + return false; + } +} + +static int lattice_select_more_less(bContext *C, const bool select) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; + BPoint *bp; + const int tot = lt->pntsu * lt->pntsv * lt->pntsw; + int u, v, w; + BLI_bitmap *selpoints; + + lt->actbp = LT_ACTBP_NONE; + + selpoints = BLI_BITMAP_NEW(tot, __func__); + BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false); + + bp = lt->def; + for (w = 0; w < lt->pntsw; w++) { + for (v = 0; v < lt->pntsv; v++) { + for (u = 0; u < lt->pntsu; u++) { + if ((bp->hide == 0) && (((bp->f1 & SELECT) == 0) == select)) { + if (lattice_test_bitmap_uvw(lt, selpoints, u + 1, v, w, select) || + lattice_test_bitmap_uvw(lt, selpoints, u - 1, v, w, select) || + lattice_test_bitmap_uvw(lt, selpoints, u, v + 1, w, select) || + lattice_test_bitmap_uvw(lt, selpoints, u, v - 1, w, select) || + lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) || + lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select)) + { + SET_FLAG_FROM_TEST(bp->f1, select, SELECT); + } + } + bp++; + } + } + } + + MEM_freeN(selpoints); + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + return OPERATOR_FINISHED; +} + +static int lattice_select_more_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return lattice_select_more_less(C, true); +} + +static int lattice_select_less_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return lattice_select_more_less(C, false); +} + +void LATTICE_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->description = "Select vertex directly linked to already selected ones"; + ot->idname = "LATTICE_OT_select_more"; + + /* api callbacks */ + ot->exec = lattice_select_more_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +void LATTICE_OT_select_less(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->description = "Deselect vertices at the boundary of each selection region"; + ot->idname = "LATTICE_OT_select_less"; + + /* api callbacks */ + ot->exec = lattice_select_less_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select All Operator + * \{ */ + +void ED_lattice_flags_set(Object *obedit, int flag) +{ + Lattice *lt = obedit->data; + BPoint *bp; + int a; + + bp = lt->editlatt->latt->def; + + a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + lt->editlatt->latt->actbp = LT_ACTBP_NONE; + + while (a--) { + if (bp->hide == 0) { + bp->f1 = flag; + } + bp++; + } +} + +static int lattice_select_all_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = obedit->data; + BPoint *bp; + int a; + int action = RNA_enum_get(op->ptr, "action"); + + if (action == SEL_TOGGLE) { + action = SEL_SELECT; + + bp = lt->editlatt->latt->def; + a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + + while (a--) { + if (bp->hide == 0) { + if (bp->f1 & SELECT) { + action = SEL_DESELECT; + break; + } + } + bp++; + } + } + + switch (action) { + case SEL_SELECT: + ED_lattice_flags_set(obedit, 1); + break; + case SEL_DESELECT: + ED_lattice_flags_set(obedit, 0); + break; + case SEL_INVERT: + bp = lt->editlatt->latt->def; + a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + lt->editlatt->latt->actbp = LT_ACTBP_NONE; + + while (a--) { + if (bp->hide == 0) { + bp->f1 ^= SELECT; + } + bp++; + } + break; + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "(De)select All"; + ot->description = "Change selection of all UVW control points"; + ot->idname = "LATTICE_OT_select_all"; + + /* api callbacks */ + ot->exec = lattice_select_all_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + WM_operator_properties_select_all(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Ungrouped Verts Operator + * \{ */ + +static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; + MDeformVert *dv; + BPoint *bp; + int a, tot; + + if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) { + BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); + return OPERATOR_CANCELLED; + } + + if (!RNA_boolean_get(op->ptr, "extend")) { + ED_lattice_flags_set(obedit, 0); + } + + dv = lt->dvert; + tot = lt->pntsu * lt->pntsv * lt->pntsw; + + for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) { + if (bp->hide == 0) { + if (dv->dw == NULL) { + bp->f1 |= SELECT; + } + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_ungrouped(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Ungrouped"; + ot->idname = "LATTICE_OT_select_ungrouped"; + ot->description = "Select vertices without a group"; + + /* api callbacks */ + ot->exec = lattice_select_ungrouped_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name Select Picking API + * + * Here actual select happens, + * Gets called via generic mouse select operator. + * \{ */ + + +static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2]) +{ + struct { BPoint *bp; float dist; int select; float mval_fl[2]; } *data = userData; + float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); + + if ((bp->f1 & SELECT) && data->select) + dist_test += 5.0f; + + if (dist_test < data->dist) { + data->dist = dist_test; + + data->bp = bp; + } +} + +static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel) +{ + /* (sel == 1): selected gets a disadvantage */ + /* in nurb and bezt or bp the nearest is written */ + /* return 0 1 2: handlepunt */ + struct { BPoint *bp; float dist; int select; float mval_fl[2]; } data = {NULL}; + + data.dist = ED_view3d_select_dist_px(); + data.select = sel; + data.mval_fl[0] = mval[0]; + data.mval_fl[1] = mval[1]; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + return data.bp; +} + +bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) +{ + ViewContext vc; + BPoint *bp = NULL; + Lattice *lt; + + ED_view3d_viewcontext_init(C, &vc); + lt = ((Lattice *)vc.obedit->data)->editlatt->latt; + bp = findnearestLattvert(&vc, mval, true); + + if (bp) { + if (extend) { + bp->f1 |= SELECT; + } + else if (deselect) { + bp->f1 &= ~SELECT; + } + else if (toggle) { + bp->f1 ^= SELECT; /* swap */ + } + else { + ED_lattice_flags_set(vc.obedit, 0); + bp->f1 |= SELECT; + } + + if (bp->f1 & SELECT) { + lt->actbp = bp - lt->def; + } + else { + lt->actbp = LT_ACTBP_NONE; + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); + + return true; + } + + return false; +} + +/** \} */ diff --git a/source/blender/editors/lattice/editlattice_tools.c b/source/blender/editors/lattice/editlattice_tools.c new file mode 100644 index 00000000000..c39ba44c1dc --- /dev/null +++ b/source/blender/editors/lattice/editlattice_tools.c @@ -0,0 +1,340 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/lattice/editlattice_tools.c + * \ingroup edlattice + */ + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_lattice.h" + +#include "ED_screen.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "lattice_intern.h" + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Make Regular Operator + * \{ */ + +static int make_regular_poll(bContext *C) +{ + Object *ob; + + if (ED_operator_editlattice(C)) return 1; + + ob = CTX_data_active_object(C); + return (ob && ob->type == OB_LATTICE); +} + +static int make_regular_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_edit_object(C); + Lattice *lt; + + if (ob) { + lt = ob->data; + BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL); + } + else { + ob = CTX_data_active_object(C); + lt = ob->data; + BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL); + } + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_make_regular(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Make Regular"; + ot->description = "Set UVW control points a uniform distance apart"; + ot->idname = "LATTICE_OT_make_regular"; + + /* api callbacks */ + ot->exec = make_regular_exec; + ot->poll = make_regular_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Flip Verts Operator + * \{ */ + +/* flipping options */ +typedef enum eLattice_FlipAxes { + LATTICE_FLIP_U = 0, + LATTICE_FLIP_V = 1, + LATTICE_FLIP_W = 2 +} eLattice_FlipAxes; + +/** + * Flip midpoint value so that relative distances between midpoint and neighbor-pair is maintained + * ! Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes) + * - Helper for lattice_flip_exec() + */ +static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis) +{ + BPoint *bp; + float diff; + + /* just the point in the middle (unpaired) */ + bp = <->def[BKE_lattice_index_from_uvw(lt, u, v, w)]; + + /* flip over axis */ + diff = mid - bp->vec[axis]; + bp->vec[axis] = mid + diff; +} + +/** + * Swap pairs of lattice points along a specified axis + * - Helper for lattice_flip_exec() + */ +static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis) +{ + BPoint *bpA, *bpB; + + int numU = lt->pntsu; + int numV = lt->pntsv; + int numW = lt->pntsw; + + int u0 = u, u1 = u; + int v0 = v, v1 = v; + int w0 = w, w1 = w; + + /* get pair index by just overriding the relevant pair-value + * - "-1" else buffer overflow + */ + switch (axis) { + case LATTICE_FLIP_U: + u1 = numU - u - 1; + break; + case LATTICE_FLIP_V: + v1 = numV - v - 1; + break; + case LATTICE_FLIP_W: + w1 = numW - w - 1; + break; + } + + /* get points to operate on */ + bpA = <->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)]; + bpB = <->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)]; + + /* Swap all coordinates, so that flipped coordinates belong to + * the indices on the correct side of the lattice. + * + * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4) + * Indices: (0,L) (1,R) --> (0,L) (1,R) + */ + swap_v3_v3(bpA->vec, bpB->vec); + + /* However, we need to mirror the coordinate values on the axis we're dealing with, + * otherwise we'd have effectively only rotated the points around. If we don't do this, + * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms + * such as flipped normals, etc. + * + * Coords: (3 4) |0| (-2 4) --\ + * \-> (-3 4) |0| (2 4) + * Indices: (0,L) (1,R) --> (0,L) (1,R) + */ + lattice_flip_point_value(lt, u0, v0, w0, mid, axis); + lattice_flip_point_value(lt, u1, v1, w1, mid, axis); +} + +static int lattice_flip_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt; + + eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis"); + int numU, numV, numW; + int totP; + + float mid = 0.0f; + short isOdd = 0; + + /* get lattice - we need the "edit lattice" from the lattice... confusing... */ + lt = (Lattice *)obedit->data; + lt = lt->editlatt->latt; + + numU = lt->pntsu; + numV = lt->pntsv; + numW = lt->pntsw; + totP = numU * numV * numW; + + /* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */ + switch (axis) { + case LATTICE_FLIP_U: + isOdd = numU & 1; + break; + case LATTICE_FLIP_V: + isOdd = numV & 1; + break; + case LATTICE_FLIP_W: + isOdd = numW & 1; + break; + + default: + printf("lattice_flip(): Unknown flipping axis (%u)\n", axis); + return OPERATOR_CANCELLED; + } + + if (isOdd) { + BPoint *bp; + float avgInv = 1.0f / (float)totP; + int i; + + /* midpoint calculation - assuming that u/v/w are axis-aligned */ + for (i = 0, bp = lt->def; i < totP; i++, bp++) { + mid += bp->vec[axis] * avgInv; + } + } + + /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */ + switch (axis) { + case LATTICE_FLIP_U: + { + int u, v, w; + + /* v/w strips - front to back, top to bottom */ + for (w = 0; w < numW; w++) { + for (v = 0; v < numV; v++) { + /* swap coordinates of pairs of vertices on u */ + for (u = 0; u < (numU / 2); u++) { + lattice_swap_point_pairs(lt, u, v, w, mid, axis); + } + + /* flip u-coordinate of midpoint (i.e. unpaired point on u) */ + if (isOdd) { + u = (numU / 2); + lattice_flip_point_value(lt, u, v, w, mid, axis); + } + } + } + break; + } + case LATTICE_FLIP_V: + { + int u, v, w; + + /* u/w strips - front to back, left to right */ + for (w = 0; w < numW; w++) { + for (u = 0; u < numU; u++) { + /* swap coordinates of pairs of vertices on v */ + for (v = 0; v < (numV / 2); v++) { + lattice_swap_point_pairs(lt, u, v, w, mid, axis); + } + + /* flip v-coordinate of midpoint (i.e. unpaired point on v) */ + if (isOdd) { + v = (numV / 2); + lattice_flip_point_value(lt, u, v, w, mid, axis); + } + } + } + break; + } + case LATTICE_FLIP_W: + { + int u, v, w; + + for (v = 0; v < numV; v++) { + for (u = 0; u < numU; u++) { + /* swap coordinates of pairs of vertices on w */ + for (w = 0; w < (numW / 2); w++) { + lattice_swap_point_pairs(lt, u, v, w, mid, axis); + } + + /* flip w-coordinate of midpoint (i.e. unpaired point on w) */ + if (isOdd) { + w = (numW / 2); + lattice_flip_point_value(lt, u, v, w, mid, axis); + } + } + } + break; + } + default: /* shouldn't happen, but just in case */ + break; + } + + /* updates */ + DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_flip(wmOperatorType *ot) +{ + static const EnumPropertyItem flip_items[] = { + {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""}, + {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""}, + {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""}, + {0, NULL, 0, NULL, NULL}}; + + /* identifiers */ + ot->name = "Flip (Distortion Free)"; + ot->description = "Mirror all control points without inverting the lattice deform"; + ot->idname = "LATTICE_OT_flip"; + + /* api callbacks */ + ot->poll = ED_operator_editlattice; + ot->invoke = WM_menu_invoke; + ot->exec = lattice_flip_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "axis", flip_items, LATTICE_FLIP_U, "Flip Axis", "Coordinates along this axis get flipped"); +} + +/** \} */ diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c new file mode 100644 index 00000000000..aa817928f92 --- /dev/null +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -0,0 +1,113 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/lattice/editlattice_undo.c + * \ingroup edlattice + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_context.h" + +#include "ED_lattice.h" +#include "ED_util.h" + +#include "lattice_intern.h" + +typedef struct UndoLattice { + BPoint *def; + int pntsu, pntsv, pntsw, actbp; +} UndoLattice; + +static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata)) +{ + UndoLattice *ult = (UndoLattice *)data; + EditLatt *editlatt = (EditLatt *)edata; + int a = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw; + + memcpy(editlatt->latt->def, ult->def, a * sizeof(BPoint)); + editlatt->latt->actbp = ult->actbp; +} + +static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata)) +{ + UndoLattice *ult = MEM_callocN(sizeof(UndoLattice), "UndoLattice"); + EditLatt *editlatt = (EditLatt *)edata; + + ult->def = MEM_dupallocN(editlatt->latt->def); + ult->pntsu = editlatt->latt->pntsu; + ult->pntsv = editlatt->latt->pntsv; + ult->pntsw = editlatt->latt->pntsw; + ult->actbp = editlatt->latt->actbp; + + return ult; +} + +static void free_undoLatt(void *data) +{ + UndoLattice *ult = (UndoLattice *)data; + + if (ult->def) MEM_freeN(ult->def); + MEM_freeN(ult); +} + +static int validate_undoLatt(void *data, void *edata) +{ + UndoLattice *ult = (UndoLattice *)data; + EditLatt *editlatt = (EditLatt *)edata; + + return (ult->pntsu == editlatt->latt->pntsu && + ult->pntsv == editlatt->latt->pntsv && + ult->pntsw == editlatt->latt->pntsw); +} + +static void *get_editlatt(bContext *C) +{ + Object *obedit = CTX_data_edit_object(C); + + if (obedit && obedit->type == OB_LATTICE) { + Lattice *lt = obedit->data; + return lt->editlatt; + } + + return NULL; +} + +/* and this is all the undo system needs to know */ +void undo_push_lattice(bContext *C, const char *name) +{ + undo_editmode_push(C, name, get_editlatt, free_undoLatt, undoLatt_to_editLatt, editLatt_to_undoLatt, validate_undoLatt); +} diff --git a/source/blender/editors/lattice/lattice_intern.h b/source/blender/editors/lattice/lattice_intern.h new file mode 100644 index 00000000000..94f528a0457 --- /dev/null +++ b/source/blender/editors/lattice/lattice_intern.h @@ -0,0 +1,44 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/metaball/lattice_intern.h + * \ingroup edlattice + */ + + +#ifndef __LATTICE_INTERN_H__ +#define __LATTICE_INTERN_H__ + +/* editlattice_select.c */ +void LATTICE_OT_select_all(struct wmOperatorType *ot); +void LATTICE_OT_select_more(struct wmOperatorType *ot); +void LATTICE_OT_select_less(struct wmOperatorType *ot); +void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot); +void LATTICE_OT_select_random(struct wmOperatorType *ot); +void LATTICE_OT_select_mirror(struct wmOperatorType *ot); + +/* editlattice_tools.c */ +void LATTICE_OT_make_regular(struct wmOperatorType *ot); +void LATTICE_OT_flip(struct wmOperatorType *ot); + +#endif /* __LATTICE_INTERN_H__ */ diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c new file mode 100644 index 00000000000..37a10cbe12a --- /dev/null +++ b/source/blender/editors/lattice/lattice_ops.c @@ -0,0 +1,80 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/metaball/lattice_ops.c + * \ingroup edlattice + */ + +#include "DNA_scene_types.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_object.h" +#include "ED_lattice.h" + +#include "lattice_intern.h" + +void ED_operatortypes_lattice(void) +{ + WM_operatortype_append(LATTICE_OT_select_all); + WM_operatortype_append(LATTICE_OT_select_more); + WM_operatortype_append(LATTICE_OT_select_less); + WM_operatortype_append(LATTICE_OT_select_ungrouped); + WM_operatortype_append(LATTICE_OT_select_random); + WM_operatortype_append(LATTICE_OT_select_mirror); + WM_operatortype_append(LATTICE_OT_make_regular); + WM_operatortype_append(LATTICE_OT_flip); +} + +void ED_keymap_lattice(wmKeyConfig *keyconf) +{ + wmKeyMap *keymap; + wmKeyMapItem *kmi; + + keymap = WM_keymap_find(keyconf, "Lattice", 0, 0); + keymap->poll = ED_operator_editlattice; + + kmi = WM_keymap_add_item(keymap, "LATTICE_OT_select_all", AKEY, KM_PRESS, 0, 0); + RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); + kmi = WM_keymap_add_item(keymap, "LATTICE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + WM_keymap_add_item(keymap, "LATTICE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "LATTICE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + + WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); + + WM_keymap_add_item(keymap, "LATTICE_OT_flip", FKEY, KM_PRESS, KM_CTRL, 0); + + /* menus */ + WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0); + + ED_keymap_proportional_cycle(keyconf, keymap); + ED_keymap_proportional_editmode(keyconf, keymap, false); +} -- cgit v1.2.3