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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-03-19 16:49:59 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-19 17:45:50 +0300
commitc78ebf9f26d01fcc3cf16baa9da922ee183f4b09 (patch)
tree4c1beea139b23f93eaa2ac0fa25657baca346677 /source/blender/editors/lattice
parent342a18287f5e0d3cf3147669709dcce21b967946 (diff)
Cleanup: split lattice into own library
Was mixed with object functionality.
Diffstat (limited to 'source/blender/editors/lattice')
-rw-r--r--source/blender/editors/lattice/CMakeLists.txt45
-rw-r--r--source/blender/editors/lattice/editlattice_select.c558
-rw-r--r--source/blender/editors/lattice/editlattice_tools.c340
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c113
-rw-r--r--source/blender/editors/lattice/lattice_intern.h44
-rw-r--r--source/blender/editors/lattice/lattice_ops.c80
6 files changed, 1180 insertions, 0 deletions
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 <stdlib.h>
+
+#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 = &lt->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 = &lt->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 = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
+ bpB = &lt->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 <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#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);
+}