2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-07-29 12:35:09 +00:00
|
|
|
* ***** 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.
|
2009-07-29 12:35:09 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:29:51 +00:00
|
|
|
/** \file blender/editors/metaball/mball_edit.c
|
|
|
|
* \ingroup edmeta
|
|
|
|
*/
|
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
#include "BLI_rand.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2011-12-04 06:05:48 +00:00
|
|
|
#include "DNA_defs.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
|
|
#include "RNA_define.h"
|
|
|
|
#include "RNA_access.h"
|
|
|
|
|
|
|
|
#include "BKE_context.h"
|
2010-09-07 05:47:34 +00:00
|
|
|
#include "BKE_mball.h"
|
2018-05-12 22:16:09 +02:00
|
|
|
#include "BKE_layer.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
2011-02-14 17:55:27 +00:00
|
|
|
#include "ED_mball.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "ED_view3d.h"
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
2011-02-14 17:55:27 +00:00
|
|
|
#include "mball_intern.h"
|
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* This function is used to free all MetaElems from MetaBall */
|
2015-11-18 12:20:28 +11:00
|
|
|
void ED_mball_editmball_free(Object *obedit)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2010-07-05 12:52:47 +00:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
mb->editelems = NULL;
|
|
|
|
mb->lastelem = NULL;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called, when MetaBall Object is
|
|
|
|
* switched from object mode to edit mode */
|
2015-11-18 12:20:28 +11:00
|
|
|
void ED_mball_editmball_make(Object *obedit)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
|
|
|
MetaElem *ml; /*, *newml;*/
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = mb->elems.first;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
while (ml) {
|
|
|
|
if (ml->flag & SELECT) mb->lastelem = ml;
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = ml->next;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mb->editelems = &mb->elems;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is called, when MetaBall Object switched from
|
2014-01-17 17:35:03 +11:00
|
|
|
* edit mode to object mode. List of MetaElements is copied
|
2010-04-25 15:24:18 +00:00
|
|
|
* from object->data->edit_elems to object->data->elems. */
|
2015-11-18 12:20:28 +11:00
|
|
|
void ED_mball_editmball_load(Object *UNUSED(obedit))
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add metaelem primitive to metaball object (which is in edit mode) */
|
2015-11-18 12:20:28 +11:00
|
|
|
MetaElem *ED_mball_add_primitive(bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
MetaBall *mball = (MetaBall *)obedit->data;
|
2009-07-29 12:35:09 +00:00
|
|
|
MetaElem *ml;
|
|
|
|
|
|
|
|
/* Deselect all existing metaelems */
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = mball->editelems->first;
|
2012-03-24 06:38:07 +00:00
|
|
|
while (ml) {
|
2009-07-29 12:35:09 +00:00
|
|
|
ml->flag &= ~SELECT;
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = ml->next;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = BKE_mball_element_add(mball, type);
|
2012-10-19 12:53:03 +00:00
|
|
|
ml->rad *= dia;
|
2013-08-19 17:58:28 +00:00
|
|
|
mball->wiresize *= dia;
|
|
|
|
mball->rendersize *= dia;
|
2010-09-07 05:47:34 +00:00
|
|
|
copy_v3_v3(&ml->x, mat[3]);
|
|
|
|
|
|
|
|
ml->flag |= SELECT;
|
2012-05-08 18:29:02 +00:00
|
|
|
mball->lastelem = ml;
|
2009-07-29 12:35:09 +00:00
|
|
|
return ml;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************** Select/Deselect operator *****************************/
|
|
|
|
|
|
|
|
/* Select or deselect all MetaElements */
|
2011-10-28 03:02:09 +00:00
|
|
|
static int mball_select_all_exec(bContext *C, wmOperator *op)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2009-07-29 12:35:09 +00:00
|
|
|
MetaElem *ml;
|
2009-11-29 22:16:29 +00:00
|
|
|
int action = RNA_enum_get(op->ptr, "action");
|
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
if (BLI_listbase_is_empty(mb->editelems))
|
2012-10-06 03:02:14 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2012-10-06 03:02:14 +00:00
|
|
|
if (action == SEL_TOGGLE) {
|
|
|
|
action = SEL_SELECT;
|
|
|
|
for (ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (ml->flag & SELECT) {
|
|
|
|
action = SEL_DESELECT;
|
|
|
|
break;
|
2009-11-29 22:16:29 +00:00
|
|
|
}
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-06 03:02:14 +00:00
|
|
|
switch (action) {
|
|
|
|
case SEL_SELECT:
|
|
|
|
BKE_mball_select_all(mb);
|
|
|
|
break;
|
|
|
|
case SEL_DESELECT:
|
|
|
|
BKE_mball_deselect_all(mb);
|
|
|
|
break;
|
|
|
|
case SEL_INVERT:
|
|
|
|
BKE_mball_select_swap(mb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-06-13 15:26:59 +02:00
|
|
|
DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
|
2012-10-06 03:02:14 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
|
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2009-11-29 22:16:29 +00:00
|
|
|
void MBALL_OT_select_all(wmOperatorType *ot)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "(De)select All";
|
|
|
|
ot->description = "Change selection of all meta elements";
|
|
|
|
ot->idname = "MBALL_OT_select_all";
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* callback functions */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = mball_select_all_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-11-29 22:16:29 +00:00
|
|
|
|
|
|
|
WM_operator_properties_select_all(ot);
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Select Similar */
|
|
|
|
|
|
|
|
enum {
|
|
|
|
SIMMBALL_TYPE = 1,
|
|
|
|
SIMMBALL_RADIUS,
|
|
|
|
SIMMBALL_STIFFNESS,
|
|
|
|
SIMMBALL_ROTATION
|
|
|
|
};
|
|
|
|
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem prop_similar_types[] = {
|
2013-10-25 05:17:55 +00:00
|
|
|
{SIMMBALL_TYPE, "TYPE", 0, "Type", ""},
|
|
|
|
{SIMMBALL_RADIUS, "RADIUS", 0, "Radius", ""},
|
2014-05-14 15:00:47 +10:00
|
|
|
{SIMMBALL_STIFFNESS, "STIFFNESS", 0, "Stiffness", ""},
|
2013-10-25 05:17:55 +00:00
|
|
|
{SIMMBALL_ROTATION, "ROTATION", 0, "Rotation", ""},
|
|
|
|
{0, NULL, 0, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool mball_select_similar_type(MetaBall *mb)
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
for (ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (ml->flag & SELECT) {
|
|
|
|
MetaElem *ml_iter;
|
|
|
|
|
|
|
|
for (ml_iter = mb->editelems->first; ml_iter; ml_iter = ml_iter->next) {
|
|
|
|
if ((ml_iter->flag & SELECT) == 0) {
|
|
|
|
if (ml->type == ml_iter->type) {
|
2013-10-25 05:21:17 +00:00
|
|
|
ml_iter->flag |= SELECT;
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool mball_select_similar_radius(MetaBall *mb, const float thresh)
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
for (ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (ml->flag & SELECT) {
|
|
|
|
MetaElem *ml_iter;
|
|
|
|
|
|
|
|
for (ml_iter = mb->editelems->first; ml_iter; ml_iter = ml_iter->next) {
|
|
|
|
if ((ml_iter->flag & SELECT) == 0) {
|
|
|
|
if (fabsf(ml_iter->rad - ml->rad) <= (thresh * ml->rad)) {
|
|
|
|
ml_iter->flag |= SELECT;
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool mball_select_similar_stiffness(MetaBall *mb, const float thresh)
|
|
|
|
{
|
|
|
|
MetaElem *ml;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
for (ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (ml->flag & SELECT) {
|
|
|
|
MetaElem *ml_iter;
|
|
|
|
|
|
|
|
for (ml_iter = mb->editelems->first; ml_iter; ml_iter = ml_iter->next) {
|
|
|
|
if ((ml_iter->flag & SELECT) == 0) {
|
|
|
|
if (fabsf(ml_iter->s - ml->s) <= thresh) {
|
|
|
|
ml_iter->flag |= SELECT;
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool mball_select_similar_rotation(MetaBall *mb, const float thresh)
|
|
|
|
{
|
|
|
|
const float thresh_rad = thresh * (float)M_PI_2;
|
|
|
|
MetaElem *ml;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
for (ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (ml->flag & SELECT) {
|
|
|
|
MetaElem *ml_iter;
|
|
|
|
|
|
|
|
float ml_mat[3][3];
|
|
|
|
|
|
|
|
unit_m3(ml_mat);
|
|
|
|
mul_qt_v3(ml->quat, ml_mat[0]);
|
|
|
|
mul_qt_v3(ml->quat, ml_mat[1]);
|
|
|
|
mul_qt_v3(ml->quat, ml_mat[2]);
|
|
|
|
normalize_m3(ml_mat);
|
|
|
|
|
|
|
|
for (ml_iter = mb->editelems->first; ml_iter; ml_iter = ml_iter->next) {
|
|
|
|
if ((ml_iter->flag & SELECT) == 0) {
|
|
|
|
float ml_iter_mat[3][3];
|
|
|
|
|
|
|
|
unit_m3(ml_iter_mat);
|
|
|
|
mul_qt_v3(ml_iter->quat, ml_iter_mat[0]);
|
|
|
|
mul_qt_v3(ml_iter->quat, ml_iter_mat[1]);
|
|
|
|
mul_qt_v3(ml_iter->quat, ml_iter_mat[2]);
|
|
|
|
normalize_m3(ml_iter_mat);
|
|
|
|
|
|
|
|
if ((angle_normalized_v3v3(ml_mat[0], ml_iter_mat[0]) +
|
|
|
|
angle_normalized_v3v3(ml_mat[1], ml_iter_mat[1]) +
|
|
|
|
angle_normalized_v3v3(ml_mat[2], ml_iter_mat[2])) < thresh_rad)
|
|
|
|
{
|
|
|
|
ml_iter->flag |= SELECT;
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int mball_select_similar_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2013-10-25 05:21:17 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
int type = RNA_enum_get(op->ptr, "type");
|
|
|
|
float thresh = RNA_float_get(op->ptr, "threshold");
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case SIMMBALL_TYPE:
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = mball_select_similar_type(mb);
|
2013-10-25 05:17:55 +00:00
|
|
|
break;
|
|
|
|
case SIMMBALL_RADIUS:
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = mball_select_similar_radius(mb, thresh);
|
2013-10-25 05:17:55 +00:00
|
|
|
break;
|
|
|
|
case SIMMBALL_STIFFNESS:
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = mball_select_similar_stiffness(mb, thresh);
|
2013-10-25 05:17:55 +00:00
|
|
|
break;
|
|
|
|
case SIMMBALL_ROTATION:
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = mball_select_similar_rotation(mb, thresh);
|
2013-10-25 05:17:55 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(0);
|
2013-10-29 03:04:46 +00:00
|
|
|
break;
|
2013-10-25 05:17:55 +00:00
|
|
|
}
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
if (changed) {
|
2018-06-13 15:26:59 +02:00
|
|
|
DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
|
2013-10-25 05:17:55 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MBALL_OT_select_similar(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Select Similar";
|
|
|
|
ot->idname = "MBALL_OT_select_similar";
|
|
|
|
|
|
|
|
/* callback functions */
|
|
|
|
ot->invoke = WM_menu_invoke;
|
|
|
|
ot->exec = mball_select_similar_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
|
|
|
ot->description = "Select similar metaballs by property types";
|
|
|
|
|
|
|
|
/* flags */
|
2013-10-25 05:21:17 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2013-10-25 05:17:55 +00:00
|
|
|
|
|
|
|
/* properties */
|
|
|
|
ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
|
|
|
|
|
|
|
|
RNA_def_float(ot->srna, "threshold", 0.1, 0.0, 1.0, "Threshold", "", 0.01, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/***************************** Select random operator *****************************/
|
|
|
|
|
|
|
|
/* Random metaball selection */
|
|
|
|
static int select_random_metaelems_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2014-01-13 20:36:38 +11:00
|
|
|
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
|
2015-10-10 23:47:41 +11:00
|
|
|
const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
|
2016-03-29 01:20:45 +11:00
|
|
|
const int seed = WM_operator_properties_select_random_seed_increment_get(op);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-05-12 22:16:09 +02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
|
|
uint objects_len = 0;
|
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
|
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *obedit = objects[ob_index];
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
|
|
|
if (!BKE_mball_is_any_unselected(mb)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int seed_iter = seed;
|
2015-10-10 23:47:41 +11:00
|
|
|
|
2018-05-12 22:16:09 +02:00
|
|
|
/* This gives a consistent result regardless of object order. */
|
|
|
|
if (ob_index) {
|
|
|
|
seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
|
2014-01-13 20:36:38 +11:00
|
|
|
}
|
2015-10-10 23:47:41 +11:00
|
|
|
|
2018-05-12 22:16:09 +02:00
|
|
|
RNG *rng = BLI_rng_new_srandom(seed_iter);
|
2015-10-10 23:47:41 +11:00
|
|
|
|
2018-05-12 22:16:09 +02:00
|
|
|
for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (BLI_rng_get_float(rng) < randfac) {
|
|
|
|
if (select) {
|
|
|
|
ml->flag |= SELECT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ml->flag &= ~SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_rng_free(rng);
|
|
|
|
|
2018-06-13 15:26:59 +02:00
|
|
|
DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
|
2018-05-12 22:16:09 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
|
|
|
|
}
|
|
|
|
MEM_freeN(objects);
|
2009-07-29 12:35:09 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2014-01-13 20:36:38 +11:00
|
|
|
ot->name = "Select Random";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->description = "Randomly select metaelements";
|
|
|
|
ot->idname = "MBALL_OT_select_random_metaelems";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* callback functions */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = select_random_metaelems_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* flags */
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* properties */
|
2015-10-10 23:47:41 +11:00
|
|
|
WM_operator_properties_select_random(ot);
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************** Duplicate operator *****************************/
|
|
|
|
|
|
|
|
/* Duplicate selected MetaElements */
|
2010-10-15 01:36:14 +00:00
|
|
|
static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2009-07-29 12:35:09 +00:00
|
|
|
MetaElem *ml, *newml;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = mb->editelems->last;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ml) {
|
|
|
|
while (ml) {
|
|
|
|
if (ml->flag & SELECT) {
|
2012-05-08 18:29:02 +00:00
|
|
|
newml = MEM_dupallocN(ml);
|
2009-07-29 12:35:09 +00:00
|
|
|
BLI_addtail(mb->editelems, newml);
|
2012-05-08 18:29:02 +00:00
|
|
|
mb->lastelem = newml;
|
2009-07-29 12:35:09 +00:00
|
|
|
ml->flag &= ~SELECT;
|
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = ml->prev;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(obedit->data, 0);
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MBALL_OT_duplicate_metaelems(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Duplicate Metaelements";
|
2012-05-12 20:50:46 +00:00
|
|
|
ot->description = "Duplicate selected metaelement(s)";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "MBALL_OT_duplicate_metaelems";
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* callback functions */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = duplicate_metaelems_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************** Delete operator *****************************/
|
|
|
|
|
|
|
|
/* Delete all selected MetaElems (not MetaBall) */
|
2010-10-15 01:36:14 +00:00
|
|
|
static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2009-07-29 12:35:09 +00:00
|
|
|
MetaElem *ml, *next;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = mb->editelems->first;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ml) {
|
|
|
|
while (ml) {
|
2012-05-08 18:29:02 +00:00
|
|
|
next = ml->next;
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ml->flag & SELECT) {
|
2012-05-08 18:29:02 +00:00
|
|
|
if (mb->lastelem == ml) mb->lastelem = NULL;
|
2009-07-29 12:35:09 +00:00
|
|
|
BLI_remlink(mb->editelems, ml);
|
|
|
|
MEM_freeN(ml);
|
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = next;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(obedit->data, 0);
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MBALL_OT_delete_metaelems(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Delete";
|
|
|
|
ot->description = "Delete selected metaelement(s)";
|
|
|
|
ot->idname = "MBALL_OT_delete_metaelems";
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* callback functions */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = delete_metaelems_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************** Hide operator *****************************/
|
|
|
|
|
|
|
|
/* Hide selected MetaElems */
|
|
|
|
static int hide_metaelems_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2009-07-29 12:35:09 +00:00
|
|
|
MetaElem *ml;
|
2014-04-11 11:25:41 +10:00
|
|
|
const bool invert = RNA_boolean_get(op->ptr, "unselected") ? SELECT : 0;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = mb->editelems->first;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ml) {
|
|
|
|
while (ml) {
|
|
|
|
if ((ml->flag & SELECT) != invert)
|
2011-02-24 16:04:36 +00:00
|
|
|
ml->flag |= MB_HIDE;
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = ml->next;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(obedit->data, 0);
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MBALL_OT_hide_metaelems(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Hide";
|
|
|
|
ot->description = "Hide (un)selected metaelement(s)";
|
|
|
|
ot->idname = "MBALL_OT_hide_metaelems";
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* callback functions */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = hide_metaelems_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* props */
|
2015-06-21 16:06:44 +02:00
|
|
|
RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************** Unhide operator *****************************/
|
|
|
|
|
|
|
|
/* Unhide all edited MetaElems */
|
2017-11-20 02:28:07 +11:00
|
|
|
static int reveal_metaelems_exec(bContext *C, wmOperator *op)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2017-11-20 02:28:07 +11:00
|
|
|
const bool select = RNA_boolean_get(op->ptr, "select");
|
|
|
|
bool changed = false;
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2017-11-20 02:28:07 +11:00
|
|
|
for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
|
|
|
|
if (ml->flag & MB_HIDE) {
|
|
|
|
SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
|
2009-07-29 12:35:09 +00:00
|
|
|
ml->flag &= ~MB_HIDE;
|
2017-11-20 02:28:07 +11:00
|
|
|
changed = true;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2017-11-20 02:28:07 +11:00
|
|
|
}
|
|
|
|
if (changed) {
|
2012-05-08 18:29:02 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(obedit->data, 0);
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Reveal";
|
|
|
|
ot->description = "Reveal all hidden metaelements";
|
|
|
|
ot->idname = "MBALL_OT_reveal_metaelems";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* callback functions */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = reveal_metaelems_exec;
|
|
|
|
ot->poll = ED_operator_editmball;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* flags */
|
2012-05-08 18:29:02 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2017-11-20 02:28:07 +11:00
|
|
|
|
|
|
|
/* props */
|
|
|
|
RNA_def_boolean(ot->srna, "select", true, "Select", "");
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Select MetaElement with mouse click (user can select radius circle or
|
|
|
|
* stiffness circle) */
|
2015-11-18 12:20:28 +11:00
|
|
|
bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
|
2009-07-29 12:35:09 +00:00
|
|
|
{
|
2012-05-08 18:29:02 +00:00
|
|
|
static MetaElem *startelem = NULL;
|
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
2009-07-29 12:35:09 +00:00
|
|
|
ViewContext vc;
|
2012-05-08 18:29:02 +00:00
|
|
|
MetaBall *mb = (MetaBall *)obedit->data;
|
2012-10-06 03:02:14 +00:00
|
|
|
MetaElem *ml, *ml_act = NULL;
|
2009-07-29 12:35:09 +00:00
|
|
|
int a, hits;
|
2015-02-24 17:19:07 +01:00
|
|
|
unsigned int buffer[MAXPICKBUF];
|
2009-07-29 12:35:09 +00:00
|
|
|
rcti rect;
|
|
|
|
|
2018-03-08 17:30:24 +11:00
|
|
|
ED_view3d_viewcontext_init(C, &vc);
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2017-03-08 23:10:31 +11:00
|
|
|
BLI_rcti_init_pt_radius(&rect, mval, 12);
|
2009-07-29 12:35:09 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
|
2009-07-29 12:35:09 +00:00
|
|
|
|
|
|
|
/* does startelem exist? */
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = mb->editelems->first;
|
2012-03-24 06:38:07 +00:00
|
|
|
while (ml) {
|
2012-05-08 18:29:02 +00:00
|
|
|
if (ml == startelem) break;
|
|
|
|
ml = ml->next;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
if (ml == NULL) startelem = mb->editelems->first;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-08 18:29:02 +00:00
|
|
|
if (hits > 0) {
|
|
|
|
ml = startelem;
|
2012-03-24 06:38:07 +00:00
|
|
|
while (ml) {
|
2012-05-08 18:29:02 +00:00
|
|
|
for (a = 0; a < hits; a++) {
|
2009-07-29 12:35:09 +00:00
|
|
|
/* index converted for gl stuff */
|
2012-05-08 18:29:02 +00:00
|
|
|
if (ml->selcol1 == buffer[4 * a + 3]) {
|
2009-07-29 12:35:09 +00:00
|
|
|
ml->flag |= MB_SCALE_RAD;
|
2012-10-06 03:02:14 +00:00
|
|
|
ml_act = ml;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2012-05-08 18:29:02 +00:00
|
|
|
if (ml->selcol2 == buffer[4 * a + 3]) {
|
2009-07-29 12:35:09 +00:00
|
|
|
ml->flag &= ~MB_SCALE_RAD;
|
2012-10-06 03:02:14 +00:00
|
|
|
ml_act = ml;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-06 03:02:14 +00:00
|
|
|
if (ml_act) break;
|
2012-05-08 18:29:02 +00:00
|
|
|
ml = ml->next;
|
|
|
|
if (ml == NULL) ml = mb->editelems->first;
|
|
|
|
if (ml == startelem) break;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-07-20 10:41:08 +00:00
|
|
|
/* When some metaelem was found, then it is necessary to select or
|
2012-03-04 04:35:12 +00:00
|
|
|
* deselect it. */
|
2012-10-06 03:02:14 +00:00
|
|
|
if (ml_act) {
|
2012-05-24 21:05:27 +00:00
|
|
|
if (extend) {
|
2012-10-06 03:02:14 +00:00
|
|
|
ml_act->flag |= SELECT;
|
2012-05-24 21:05:27 +00:00
|
|
|
}
|
|
|
|
else if (deselect) {
|
2012-10-06 03:02:14 +00:00
|
|
|
ml_act->flag &= ~SELECT;
|
2012-05-24 21:05:27 +00:00
|
|
|
}
|
|
|
|
else if (toggle) {
|
2012-10-06 03:02:14 +00:00
|
|
|
if (ml_act->flag & SELECT)
|
|
|
|
ml_act->flag &= ~SELECT;
|
2012-05-24 21:05:27 +00:00
|
|
|
else
|
2012-10-06 03:02:14 +00:00
|
|
|
ml_act->flag |= SELECT;
|
2012-05-24 21:05:27 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-07-29 12:35:09 +00:00
|
|
|
/* Deselect all existing metaelems */
|
2012-10-06 03:02:14 +00:00
|
|
|
BKE_mball_deselect_all(mb);
|
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
/* Select only metaelem clicked on */
|
2012-10-06 03:02:14 +00:00
|
|
|
ml_act->flag |= SELECT;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-10-06 03:02:14 +00:00
|
|
|
mb->lastelem = ml_act;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-06-13 15:26:59 +02:00
|
|
|
DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
|
2012-05-08 18:29:02 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
|
2009-11-24 04:59:52 +00:00
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
return true;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-24 04:59:52 +00:00
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
return false;
|
2009-07-29 12:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|