This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/object/object_lattice.c

434 lines
9.7 KiB
C
Raw Normal View History

/*
* ***** 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,
2010-02-12 13:34:04 +00:00
* 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 *****
*/
2011-02-27 20:29:51 +00:00
/** \file blender/editors/object/object_lattice.c
* \ingroup edobj
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_key_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 "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "ED_lattice.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
#include "WM_api.h"
#include "WM_types.h"
#include "object_intern.h"
/********************** Load/Make/Free ********************/
void free_editLatt(Object *ob)
{
2012-04-28 15:42:27 +00:00
Lattice *lt = ob->data;
if (lt->editlatt) {
2012-04-28 15:42:27 +00:00
Lattice *editlt = lt->editlatt->latt;
if (editlt->def)
MEM_freeN(editlt->def);
if (editlt->dvert)
2012-04-28 15:42:27 +00:00
free_dverts(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
MEM_freeN(editlt);
MEM_freeN(lt->editlatt);
2012-04-28 15:42:27 +00:00
lt->editlatt = NULL;
}
}
void make_editLatt(Object *obedit)
{
2012-04-28 15:42:27 +00:00
Lattice *lt = obedit->data;
KeyBlock *actkey;
free_editLatt(obedit);
actkey = BKE_keyblock_from_object(obedit);
if (actkey)
BKE_key_convert_to_lattice(actkey, lt);
2012-04-28 15:42:27 +00:00
lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
lt->editlatt->latt = MEM_dupallocN(lt);
lt->editlatt->latt->def = MEM_dupallocN(lt->def);
if (lt->dvert) {
2012-04-28 15:42:27 +00:00
int tot = lt->pntsu * lt->pntsv * lt->pntsw;
lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
}
2012-04-28 15:42:27 +00:00
if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
}
void load_editLatt(Object *obedit)
{
Lattice *lt, *editlt;
KeyBlock *actkey;
BPoint *bp;
float *fp;
int tot;
2012-04-28 15:42:27 +00:00
lt = obedit->data;
editlt = lt->editlatt->latt;
if (lt->editlatt->shapenr) {
2012-04-28 15:42:27 +00:00
actkey = BLI_findlink(&lt->key->block, lt->editlatt->shapenr - 1);
/* active key: vertices */
2012-04-28 15:42:27 +00:00
tot = editlt->pntsu * editlt->pntsv * editlt->pntsw;
if (actkey->data) MEM_freeN(actkey->data);
2012-04-28 15:42:27 +00:00
fp = actkey->data = MEM_callocN(lt->key->elemsize * tot, "actkey->data");
actkey->totelem = tot;
2012-04-28 15:42:27 +00:00
bp = editlt->def;
while (tot--) {
copy_v3_v3(fp, bp->vec);
2012-04-28 15:42:27 +00:00
fp += 3;
bp++;
}
}
else {
MEM_freeN(lt->def);
2012-04-28 15:42:27 +00:00
lt->def = MEM_dupallocN(editlt->def);
2012-04-28 15:42:27 +00:00
lt->flag = editlt->flag;
2012-04-28 15:42:27 +00:00
lt->pntsu = editlt->pntsu;
lt->pntsv = editlt->pntsv;
lt->pntsw = editlt->pntsw;
2012-04-28 15:42:27 +00:00
lt->typeu = editlt->typeu;
lt->typev = editlt->typev;
lt->typew = editlt->typew;
}
if (lt->dvert) {
2012-04-28 15:42:27 +00:00
free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
lt->dvert = NULL;
}
if (editlt->dvert) {
2012-04-28 15:42:27 +00:00
tot = lt->pntsu * lt->pntsv * lt->pntsw;
lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
copy_dverts(lt->dvert, editlt->dvert, tot);
}
}
/************************** Operators *************************/
void ED_setflagsLatt(Object *obedit, int flag)
{
2012-04-28 15:42:27 +00:00
Lattice *lt = obedit->data;
BPoint *bp;
int a;
2012-04-28 15:42:27 +00:00
bp = lt->editlatt->latt->def;
2012-04-28 15:42:27 +00:00
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
while (a--) {
2012-04-28 15:42:27 +00:00
if (bp->hide == 0) {
bp->f1 = flag;
}
bp++;
}
}
static int lattice_select_all_exec(bContext *C, wmOperator *op)
{
2012-04-28 15:42:27 +00:00
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;
2012-04-28 15:42:27 +00:00
bp = lt->editlatt->latt->def;
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
while (a--) {
2012-04-28 15:42:27 +00:00
if (bp->hide == 0) {
2012-07-19 11:40:25 +00:00
if (bp->f1 & SELECT) {
action = SEL_DESELECT;
break;
}
}
bp++;
}
}
switch (action) {
2012-04-28 15:42:27 +00:00
case SEL_SELECT:
ED_setflagsLatt(obedit, 1);
break;
case SEL_DESELECT:
ED_setflagsLatt(obedit, 0);
break;
case SEL_INVERT:
bp = lt->editlatt->latt->def;
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
while (a--) {
if (bp->hide == 0) {
2012-07-19 11:40:25 +00:00
bp->f1 ^= SELECT;
2012-04-28 15:42:27 +00:00
}
bp++;
}
2012-04-28 15:42:27 +00:00
break;
}
2012-04-28 15:42:27 +00:00
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 */
2012-04-28 15:42:27 +00:00
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_select_all(ot);
}
static int make_regular_poll(bContext *C)
{
Object *ob;
if (ED_operator_editlattice(C)) return 1;
2012-04-28 15:42:27 +00:00
ob = CTX_data_active_object(C);
return (ob && ob->type == OB_LATTICE);
}
static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
{
2012-04-28 15:42:27 +00:00
Object *ob = CTX_data_edit_object(C);
Lattice *lt;
if (ob) {
2012-04-28 15:42:27 +00:00
lt = ob->data;
BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
}
else {
2012-04-28 15:42:27 +00:00
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);
2012-04-28 15:42:27 +00:00
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 */
2012-04-28 15:42:27 +00:00
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/****************************** Mouse Selection *************************/
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)
{
2012-04-28 15:42:27 +00:00
/* 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 = 100;
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);
return data.bp;
}
int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int toggle)
{
ViewContext vc;
2012-04-28 15:42:27 +00:00
BPoint *bp = NULL;
view3d_set_viewcontext(C, &vc);
bp = findnearestLattvert(&vc, mval, TRUE);
if (bp) {
2012-06-05 21:54:21 +00:00
if (extend) {
bp->f1 |= SELECT;
}
else if (deselect) {
bp->f1 &= ~SELECT;
}
else if (toggle) {
bp->f1 ^= SELECT; /* swap */
}
2012-06-05 21:54:21 +00:00
else {
ED_setflagsLatt(vc.obedit, 0);
bp->f1 |= SELECT;
}
2012-04-28 15:42:27 +00:00
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return 1;
}
return 0;
}
/******************************** Undo *************************/
typedef struct UndoLattice {
BPoint *def;
int pntsu, pntsv, pntsw;
} UndoLattice;
static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
{
2012-04-28 15:42:27 +00:00
UndoLattice *ult = (UndoLattice *)data;
EditLatt *editlatt = (EditLatt *)edata;
int a = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
2012-04-28 15:42:27 +00:00
memcpy(editlatt->latt->def, ult->def, a * sizeof(BPoint));
}
static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
{
2012-04-28 15:42:27 +00:00
UndoLattice *ult = MEM_callocN(sizeof(UndoLattice), "UndoLattice");
EditLatt *editlatt = (EditLatt *)edata;
2012-04-28 15:42:27 +00:00
ult->def = MEM_dupallocN(editlatt->latt->def);
ult->pntsu = editlatt->latt->pntsu;
ult->pntsv = editlatt->latt->pntsv;
ult->pntsw = editlatt->latt->pntsw;
return ult;
}
static void free_undoLatt(void *data)
{
2012-04-28 15:42:27 +00:00
UndoLattice *ult = (UndoLattice *)data;
if (ult->def) MEM_freeN(ult->def);
MEM_freeN(ult);
}
static int validate_undoLatt(void *data, void *edata)
{
2012-04-28 15:42:27 +00:00
UndoLattice *ult = (UndoLattice *)data;
EditLatt *editlatt = (EditLatt *)edata;
return (ult->pntsu == editlatt->latt->pntsu &&
2012-04-28 15:42:27 +00:00
ult->pntsv == editlatt->latt->pntsv &&
ult->pntsw == editlatt->latt->pntsw);
}
static void *get_editlatt(bContext *C)
{
2012-04-28 15:42:27 +00:00
Object *obedit = CTX_data_edit_object(C);
2012-04-28 15:42:27 +00:00
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);
}