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>2013-11-19 19:40:29 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-11-19 19:54:52 +0400
commit5743a6e36458874be1fe992a361ce493edbee5a4 (patch)
tree075bc48317f32c83b934c42a21333c0b9316f097 /source/blender/editors/util/ed_transverts.c
parent035d86402bbb8dab2bfb086a3027e5ec93e52748 (diff)
Code Cleanup: move trans-verts out of snap code into their own file.
Developer Note: * minmax & centroid was being calculated when creating trans-verts but never used. * static vars removed, replace with TransVertStore stack var.
Diffstat (limited to 'source/blender/editors/util/ed_transverts.c')
-rw-r--r--source/blender/editors/util/ed_transverts.c462
1 files changed, 462 insertions, 0 deletions
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
new file mode 100644
index 00000000000..4123132ad03
--- /dev/null
+++ b/source/blender/editors/util/ed_transverts.c
@@ -0,0 +1,462 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/ed_transverts.c
+ * \ingroup edutil
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_lattice.h"
+#include "BKE_editmesh.h"
+#include "BKE_DerivedMesh.h"
+
+#include "ED_armature.h"
+
+#include "ED_transverts.h" /* own include */
+
+
+/* copied from editobject.c, now uses (almost) proper depgraph */
+void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
+{
+ BLI_assert(ED_transverts_check_obedit(obedit) == true);
+
+ DAG_id_tag_update(obedit->data, 0);
+
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BM_mesh_normals_update(em->bm);
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ Nurb *nu = nurbs->first;
+
+ while (nu) {
+ /* keep handles' vectors unchanged */
+ if (nu->bezt) {
+ int a = nu->pntsu;
+ TransVert *tv = tvs->transverts;
+ BezTriple *bezt = nu->bezt;
+
+ while (a--) {
+ if (bezt->f1 & SELECT) tv++;
+
+ if (bezt->f2 & SELECT) {
+ float v[3];
+
+ if (bezt->f1 & SELECT) {
+ sub_v3_v3v3(v, (tv - 1)->oldloc, tv->oldloc);
+ add_v3_v3v3(bezt->vec[0], bezt->vec[1], v);
+ }
+
+ if (bezt->f3 & SELECT) {
+ sub_v3_v3v3(v, (tv + 1)->oldloc, tv->oldloc);
+ add_v3_v3v3(bezt->vec[2], bezt->vec[1], v);
+ }
+
+ tv++;
+ }
+
+ if (bezt->f3 & SELECT) tv++;
+
+ bezt++;
+ }
+ }
+
+ BKE_nurb_test2D(nu);
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
+ nu = nu->next;
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ EditBone *ebo;
+ TransVert *tv = tvs->transverts;
+ int a = 0;
+
+ /* Ensure all bone tails are correctly adjusted */
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ /* adjust tip if both ends selected */
+ if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
+ if (tv) {
+ float diffvec[3];
+
+ sub_v3_v3v3(diffvec, tv->loc, tv->oldloc);
+ add_v3_v3(ebo->tail, diffvec);
+
+ a++;
+ if (a < tvs->transverts_tot) tv++;
+ }
+ }
+ }
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ /* If this bone has a parent tip that has been moved */
+ if (ebo->parent->flag & BONE_TIPSEL) {
+ copy_v3_v3(ebo->head, ebo->parent->tail);
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else {
+ copy_v3_v3(ebo->parent->tail, ebo->head);
+ }
+ }
+ }
+ if (arm->flag & ARM_MIRROR_EDIT)
+ transform_armature_mirror_update(obedit);
+ }
+ else if (obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+
+ if (lt->editlatt->latt->flag & LT_OUTSIDE)
+ outside_lattice(lt->editlatt->latt);
+ }
+}
+
+static void set_mapped_co(void *vuserdata, int index, const float co[3],
+ const float UNUSED(no[3]), const short UNUSED(no_s[3]))
+{
+ void **userdata = vuserdata;
+ BMEditMesh *em = userdata[0];
+ TransVert *tv = userdata[1];
+ BMVert *eve = BM_vert_at_index(em->bm, index);
+
+ if (BM_elem_index_get(eve) != TM_INDEX_SKIP) {
+ tv = &tv[BM_elem_index_get(eve)];
+
+ /* be clever, get the closest vertex to the original,
+ * behaves most logically when the mirror modifier is used for eg [#33051]*/
+ if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) {
+ /* first time */
+ copy_v3_v3(tv->maploc, co);
+ tv->flag |= TX_VERT_USE_MAPLOC;
+ }
+ else {
+ /* find best location to use */
+ if (len_squared_v3v3(eve->co, co) < len_squared_v3v3(eve->co, tv->maploc)) {
+ copy_v3_v3(tv->maploc, co);
+ }
+ }
+ }
+}
+
+bool ED_transverts_check_obedit(Object *obedit)
+{
+ return (ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
+}
+
+void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const int mode)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ TransVert *tv = NULL;
+ MetaElem *ml;
+ BMVert *eve;
+ EditBone *ebo;
+ int a;
+
+ tvs->transverts_tot = 0;
+
+ if (obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ void *userdata[2] = {em, NULL};
+ /*int proptrans = 0; */ /*UNUSED*/
+
+ /* abuses vertex index all over, set, just set dirty here,
+ * perhaps this could use its own array instead? - campbell */
+
+ /* transform now requires awareness for select mode, so we tag the f1 flags in verts */
+ tvs->transverts_tot = 0;
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ BM_elem_index_set(eve, TM_INDEX_ON); /* set_dirty! */
+ tvs->transverts_tot++;
+ }
+ else {
+ BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
+ }
+ }
+ }
+ else if (em->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
+ }
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_elem_index_set(eed->v1, TM_INDEX_ON); /* set_dirty! */
+ BM_elem_index_set(eed->v2, TM_INDEX_ON); /* set_dirty! */
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(eve) == TM_INDEX_ON) tvs->transverts_tot++;
+ }
+ }
+ else {
+ BMFace *efa;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */
+ }
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ BM_elem_index_set(l->v, TM_INDEX_ON); /* set_dirty! */
+ }
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(eve) == TM_INDEX_ON) tvs->transverts_tot++;
+ }
+ }
+ /* for any of the 3 loops above which all dirty the indices */
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* and now make transverts */
+ if (tvs->transverts_tot) {
+ tv = tvs->transverts = MEM_callocN(tvs->transverts_tot * sizeof(TransVert), __func__);
+
+ a = 0;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(eve)) {
+ BM_elem_index_set(eve, a); /* set_dirty! */
+ copy_v3_v3(tv->oldloc, eve->co);
+ tv->loc = eve->co;
+ tv->flag = (BM_elem_index_get(eve) == TM_INDEX_ON) ? SELECT : 0;
+ tv++;
+ a++;
+ }
+ else {
+ BM_elem_index_set(eve, TM_INDEX_SKIP); /* set_dirty! */
+ }
+ }
+ /* set dirty already, above */
+
+ userdata[1] = tvs->transverts;
+ }
+
+ if (tvs->transverts && em->derivedCage) {
+ BM_mesh_elem_table_ensure(bm, BM_VERT);
+ em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata, DM_FOREACH_NOP);
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ int totmalloc = BLI_countlist(arm->edbo);
+
+ totmalloc *= 2; /* probably overkill but bones can have 2 trans verts each */
+
+ tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
+
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if (ebo->layer & arm->layer) {
+ short tipsel = (ebo->flag & BONE_TIPSEL);
+ short rootsel = (ebo->flag & BONE_ROOTSEL);
+ short rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && (ebo->parent->flag & BONE_TIPSEL)));
+
+ if ((tipsel && rootsel) || (rootsel)) {
+ /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
+ * otherwise we get zero-length bones as tips will snap to the same
+ * location as heads.
+ */
+ if (rootok) {
+ copy_v3_v3(tv->oldloc, ebo->head);
+ tv->loc = ebo->head;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+
+ if ((mode & TM_ALL_JOINTS) && (tipsel)) {
+ copy_v3_v3(tv->oldloc, ebo->tail);
+ tv->loc = ebo->tail;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ else if (tipsel) {
+ copy_v3_v3(tv->oldloc, ebo->tail);
+ tv->loc = ebo->tail;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ }
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ int totmalloc = 0;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER)
+ totmalloc += 3 * nu->pntsu;
+ else
+ totmalloc += nu->pntsu * nu->pntsv;
+ }
+ tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
+
+ nu = nurbs->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ if (bezt->hide == 0) {
+ int skip_handle = 0;
+ if (bezt->f2 & SELECT)
+ skip_handle = mode & TM_SKIP_HANDLES;
+
+ if ((bezt->f1 & SELECT) && !skip_handle) {
+ copy_v3_v3(tv->oldloc, bezt->vec[0]);
+ tv->loc = bezt->vec[0];
+ tv->flag = bezt->f1 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ if (bezt->f2 & SELECT) {
+ copy_v3_v3(tv->oldloc, bezt->vec[1]);
+ tv->loc = bezt->vec[1];
+ tv->val = &(bezt->alfa);
+ tv->oldval = bezt->alfa;
+ tv->flag = bezt->f2 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ if ((bezt->f3 & SELECT) && !skip_handle) {
+ copy_v3_v3(tv->oldloc, bezt->vec[2]);
+ tv->loc = bezt->vec[2];
+ tv->flag = bezt->f3 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ if (bp->hide == 0) {
+ if (bp->f1 & SELECT) {
+ copy_v3_v3(tv->oldloc, bp->vec);
+ tv->loc = bp->vec;
+ tv->val = &(bp->alfa);
+ tv->oldval = bp->alfa;
+ tv->flag = bp->f1 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ MetaBall *mb = obedit->data;
+ int totmalloc = BLI_countlist(mb->editelems);
+
+ tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__);
+
+ ml = mb->editelems->first;
+ while (ml) {
+ if (ml->flag & SELECT) {
+ tv->loc = &ml->x;
+ copy_v3_v3(tv->oldloc, tv->loc);
+ tv->val = &(ml->rad);
+ tv->oldval = ml->rad;
+ tv->flag = SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ ml = ml->next;
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+
+ bp = lt->editlatt->latt->def;
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+
+ tv = tvs->transverts = MEM_callocN(a * sizeof(TransVert), __func__);
+
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (bp->hide == 0) {
+ copy_v3_v3(tv->oldloc, bp->vec);
+ tv->loc = bp->vec;
+ tv->flag = bp->f1 & SELECT;
+ tv++;
+ tvs->transverts_tot++;
+ }
+ }
+ bp++;
+ }
+ }
+
+ if (!tvs->transverts_tot && tvs->transverts) {
+ /* prevent memory leak. happens for curves/latticies due to */
+ /* difficult condition of adding points to trans data */
+ MEM_freeN(tvs->transverts);
+ tvs->transverts = NULL;
+ }
+}
+
+void ED_transverts_free(TransVertStore *tvs)
+{
+ MEM_SAFE_FREE(tvs->transverts);
+ tvs->transverts_tot = 0;
+}