2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-04-27 18:05:58 +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-04-27 18:05:58 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation, 2009
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:29:51 +00:00
|
|
|
/** \file blender/editors/object/object_modifier.c
|
|
|
|
* \ingroup edobj
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
#include <math.h>
|
2009-04-27 18:05:58 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
#include "DNA_anim_types.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "DNA_curve_types.h"
|
2009-11-22 13:44:09 +00:00
|
|
|
#include "DNA_key_types.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2009-07-02 19:41:31 +00:00
|
|
|
#include "DNA_object_force.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
#include "BLI_listbase.h"
|
2009-11-28 13:33:56 +00:00
|
|
|
#include "BLI_string.h"
|
2009-12-13 17:46:30 +00:00
|
|
|
#include "BLI_path_util.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
#include "BKE_animsys.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "BKE_curve.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_depsgraph.h"
|
2009-06-03 00:09:30 +00:00
|
|
|
#include "BKE_displist.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
2009-07-02 19:41:31 +00:00
|
|
|
#include "BKE_effect.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "BKE_global.h"
|
2009-11-22 13:44:09 +00:00
|
|
|
#include "BKE_key.h"
|
2009-06-03 00:09:30 +00:00
|
|
|
#include "BKE_lattice.h"
|
2010-08-01 12:47:49 +00:00
|
|
|
#include "BKE_main.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "BKE_mesh.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
#include "BKE_modifier.h"
|
2009-05-23 07:12:55 +00:00
|
|
|
#include "BKE_multires.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "BKE_report.h"
|
|
|
|
#include "BKE_object.h"
|
2011-11-13 12:17:27 +00:00
|
|
|
#include "BKE_ocean.h"
|
2009-05-21 15:34:09 +00:00
|
|
|
#include "BKE_particle.h"
|
2009-07-02 19:41:31 +00:00
|
|
|
#include "BKE_softbody.h"
|
2011-07-25 10:07:50 +00:00
|
|
|
#include "BKE_tessmesh.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
|
|
|
#include "RNA_enum_types.h"
|
|
|
|
|
2009-11-05 18:05:55 +00:00
|
|
|
#include "ED_armature.h"
|
2009-11-22 13:44:09 +00:00
|
|
|
#include "ED_object.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
#include "ED_screen.h"
|
2010-12-13 10:24:05 +00:00
|
|
|
#include "ED_mesh.h"
|
2009-04-27 18:05:58 +00:00
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "object_intern.h"
|
|
|
|
|
2009-05-21 15:34:09 +00:00
|
|
|
/******************************** API ****************************/
|
|
|
|
|
2010-11-17 09:45:45 +00:00
|
|
|
ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
|
2009-07-02 19:41:31 +00:00
|
|
|
{
|
2009-10-09 09:48:04 +00:00
|
|
|
ModifierData *md=NULL, *new_md=NULL;
|
2009-07-02 19:41:31 +00:00
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(type);
|
2010-12-19 01:14:57 +00:00
|
|
|
|
|
|
|
/* only geometry objects should be able to get modifiers [#25291] */
|
2010-12-19 01:55:07 +00:00
|
|
|
if(!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
|
2010-12-19 01:14:57 +00:00
|
|
|
BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to Object '%s'", ob->id.name+2);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
if(mti->flags&eModifierTypeFlag_Single) {
|
|
|
|
if(modifiers_findByType(ob, type)) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_WARNING, "Only one modifier of this type allowed");
|
2009-11-22 12:28:38 +00:00
|
|
|
return NULL;
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-19 01:14:57 +00:00
|
|
|
|
2009-07-09 19:49:04 +00:00
|
|
|
if(type == eModifierType_ParticleSystem) {
|
2009-10-09 09:48:04 +00:00
|
|
|
/* don't need to worry about the new modifier's name, since that is set to the number
|
|
|
|
* of particle systems which shouldn't have too many duplicates
|
|
|
|
*/
|
2009-11-28 13:33:56 +00:00
|
|
|
new_md = object_add_particle_system(scene, ob, name);
|
2009-07-09 19:49:04 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-10-09 09:48:04 +00:00
|
|
|
/* get new modifier data to add */
|
|
|
|
new_md= modifier_new(type);
|
|
|
|
|
2009-07-09 19:49:04 +00:00
|
|
|
if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
|
|
|
|
md = ob->modifiers.first;
|
2009-10-09 09:48:04 +00:00
|
|
|
|
2009-07-09 19:49:04 +00:00
|
|
|
while(md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform)
|
|
|
|
md = md->next;
|
2009-10-09 09:48:04 +00:00
|
|
|
|
|
|
|
BLI_insertlinkbefore(&ob->modifiers, md, new_md);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
2009-07-09 19:49:04 +00:00
|
|
|
else
|
2009-10-09 09:48:04 +00:00
|
|
|
BLI_addtail(&ob->modifiers, new_md);
|
2009-11-28 13:33:56 +00:00
|
|
|
|
|
|
|
if(name)
|
|
|
|
BLI_strncpy(new_md->name, name, sizeof(new_md->name));
|
|
|
|
|
2009-10-09 09:48:04 +00:00
|
|
|
/* make sure modifier data has unique name */
|
2009-11-28 13:33:56 +00:00
|
|
|
|
2009-10-09 09:48:04 +00:00
|
|
|
modifier_unique_name(&ob->modifiers, new_md);
|
2009-07-09 19:49:04 +00:00
|
|
|
|
|
|
|
/* special cases */
|
|
|
|
if(type == eModifierType_Softbody) {
|
|
|
|
if(!ob->soft) {
|
|
|
|
ob->soft= sbNew(scene);
|
|
|
|
ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(type == eModifierType_Collision) {
|
|
|
|
if(!ob->pd)
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
ob->pd= object_add_collision_fields(0);
|
2009-10-09 09:48:04 +00:00
|
|
|
|
2009-07-09 19:49:04 +00:00
|
|
|
ob->pd->deflect= 1;
|
2010-08-01 12:47:49 +00:00
|
|
|
DAG_scene_sort(bmain, scene);
|
2009-07-09 19:49:04 +00:00
|
|
|
}
|
|
|
|
else if(type == eModifierType_Surface)
|
2010-08-01 12:47:49 +00:00
|
|
|
DAG_scene_sort(bmain, scene);
|
2010-09-26 18:29:54 +00:00
|
|
|
else if(type == eModifierType_Multires)
|
|
|
|
/* set totlvl from existing MDISPS layer if object already had it */
|
2010-09-27 09:43:21 +00:00
|
|
|
multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2009-11-22 12:28:38 +00:00
|
|
|
return new_md;
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
2011-11-23 16:12:11 +00:00
|
|
|
static int object_modifier_remove(Object *ob, ModifierData *md, int *sort_depsgraph)
|
2009-05-21 15:34:09 +00:00
|
|
|
{
|
|
|
|
ModifierData *obmd;
|
|
|
|
|
|
|
|
/* It seems on rapid delete it is possible to
|
|
|
|
* get called twice on same modifier, so make
|
|
|
|
* sure it is in list. */
|
2009-07-02 19:41:31 +00:00
|
|
|
for(obmd=ob->modifiers.first; obmd; obmd=obmd->next)
|
|
|
|
if(obmd==md)
|
2009-05-21 15:34:09 +00:00
|
|
|
break;
|
2011-11-23 16:12:11 +00:00
|
|
|
|
|
|
|
if(!obmd)
|
2009-05-21 15:34:09 +00:00
|
|
|
return 0;
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
/* special cases */
|
2009-05-21 15:34:09 +00:00
|
|
|
if(md->type == eModifierType_ParticleSystem) {
|
|
|
|
ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
|
|
|
|
|
|
|
|
BLI_remlink(&ob->particlesystem, psmd->psys);
|
|
|
|
psys_free(ob, psmd->psys);
|
2010-01-03 04:35:51 +00:00
|
|
|
psmd->psys= NULL;
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
2009-07-02 19:41:31 +00:00
|
|
|
else if(md->type == eModifierType_Softbody) {
|
|
|
|
if(ob->soft) {
|
|
|
|
sbFree(ob->soft);
|
|
|
|
ob->soft= NULL;
|
|
|
|
ob->softflag= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(md->type == eModifierType_Collision) {
|
|
|
|
if(ob->pd)
|
|
|
|
ob->pd->deflect= 0;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2011-11-23 16:12:11 +00:00
|
|
|
*sort_depsgraph = 1;
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
else if(md->type == eModifierType_Surface) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE)
|
|
|
|
ob->pd->shape = PFIELD_SHAPE_PLANE;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2011-11-23 16:12:11 +00:00
|
|
|
*sort_depsgraph = 1;
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
2009-11-11 11:49:46 +00:00
|
|
|
else if(md->type == eModifierType_Smoke) {
|
2009-12-07 10:28:36 +00:00
|
|
|
ob->dt = OB_TEXTURE;
|
2009-11-11 11:49:46 +00:00
|
|
|
}
|
2009-12-10 17:37:04 +00:00
|
|
|
else if(md->type == eModifierType_Multires) {
|
2011-05-15 13:13:51 +00:00
|
|
|
int ok= 1;
|
2009-12-10 17:37:04 +00:00
|
|
|
Mesh *me= ob->data;
|
2011-05-15 13:13:51 +00:00
|
|
|
ModifierData *tmpmd;
|
2009-12-10 17:37:04 +00:00
|
|
|
|
2011-05-15 13:13:51 +00:00
|
|
|
/* ensure MDISPS CustomData layer is't used by another multires modifiers */
|
|
|
|
for(tmpmd= ob->modifiers.first; tmpmd; tmpmd= tmpmd->next)
|
|
|
|
if(tmpmd!=md && tmpmd->type == eModifierType_Multires) {
|
|
|
|
ok= 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ok) {
|
2011-07-25 10:07:50 +00:00
|
|
|
if(me->edit_btmesh) {
|
|
|
|
BMEditMesh *em= me->edit_btmesh;
|
2011-05-15 13:13:51 +00:00
|
|
|
/* CustomData_external_remove is used here only to mark layer as non-external
|
|
|
|
for further free-ing, so zero element count looks safer than em->totface */
|
2011-07-25 10:07:50 +00:00
|
|
|
CustomData_external_remove(&em->bm->ldata, &me->id, CD_MDISPS, 0);
|
2012-02-12 10:51:45 +00:00
|
|
|
BM_data_layer_free(em->bm, &em->bm->ldata, CD_MDISPS);
|
2011-05-15 13:13:51 +00:00
|
|
|
} else {
|
2011-07-25 10:07:50 +00:00
|
|
|
CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
|
|
|
|
CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
|
2011-05-15 13:13:51 +00:00
|
|
|
}
|
2010-12-13 10:24:05 +00:00
|
|
|
}
|
2009-12-10 17:37:04 +00:00
|
|
|
}
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2010-10-19 10:17:19 +00:00
|
|
|
if(ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
|
|
|
|
ob->particlesystem.first == NULL) {
|
|
|
|
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
BLI_remlink(&ob->modifiers, md);
|
2009-05-21 15:34:09 +00:00
|
|
|
modifier_free(md);
|
|
|
|
|
2011-11-23 16:12:11 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
|
|
|
|
{
|
|
|
|
int sort_depsgraph = 0;
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
ok= object_modifier_remove(ob, md, &sort_depsgraph);
|
|
|
|
|
|
|
|
if(!ok) {
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", ob->id.name, md->name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2010-09-03 07:50:22 +00:00
|
|
|
/* sorting has to be done after the update so that dynamic systems can react properly */
|
|
|
|
if(sort_depsgraph)
|
|
|
|
DAG_scene_sort(bmain, scene);
|
|
|
|
|
2009-05-21 15:34:09 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-11-23 16:44:33 +00:00
|
|
|
void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob)
|
2011-11-23 16:12:11 +00:00
|
|
|
{
|
2012-02-23 02:23:42 +00:00
|
|
|
ModifierData *md = ob->modifiers.first;
|
2011-11-23 16:12:11 +00:00
|
|
|
int sort_depsgraph = 0;
|
|
|
|
|
|
|
|
if(!md)
|
2011-11-23 16:44:33 +00:00
|
|
|
return;
|
2011-11-23 16:12:11 +00:00
|
|
|
|
|
|
|
while(md) {
|
|
|
|
ModifierData *next_md;
|
|
|
|
|
|
|
|
next_md= md->next;
|
|
|
|
|
|
|
|
object_modifier_remove(ob, md, &sort_depsgraph);
|
|
|
|
|
|
|
|
md= next_md;
|
|
|
|
}
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2010-09-03 07:50:22 +00:00
|
|
|
/* sorting has to be done after the update so that dynamic systems can react properly */
|
|
|
|
if(sort_depsgraph)
|
|
|
|
DAG_scene_sort(bmain, scene);
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
|
|
|
|
{
|
|
|
|
if(md->prev) {
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
|
|
|
|
if(mti->type!=eModifierTypeType_OnlyDeform) {
|
|
|
|
ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
if(nmti->flags&eModifierTypeFlag_RequiresOriginalData) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
|
2009-05-21 15:34:09 +00:00
|
|
|
return 0;
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BLI_remlink(&ob->modifiers, md);
|
|
|
|
BLI_insertlink(&ob->modifiers, md->prev->prev, md);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
|
|
|
|
{
|
|
|
|
if(md->next) {
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
|
|
|
|
|
|
|
|
if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
|
|
|
|
ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
|
|
|
|
|
|
|
|
if(nmti->type!=eModifierTypeType_OnlyDeform) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
|
2009-05-21 15:34:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_remlink(&ob->modifiers, md);
|
|
|
|
BLI_insertlink(&ob->modifiers, md->next, md);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-10-16 14:32:17 +00:00
|
|
|
int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md)
|
2009-05-21 15:34:09 +00:00
|
|
|
{
|
|
|
|
Object *obn;
|
|
|
|
ParticleSystem *psys;
|
|
|
|
ParticleCacheKey *key, **cache;
|
|
|
|
ParticleSettings *part;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
MEdge *medge;
|
|
|
|
int a, k, kmax;
|
|
|
|
int totvert=0, totedge=0, cvert=0;
|
|
|
|
int totpart=0, totchild=0;
|
|
|
|
|
|
|
|
if(md->type != eModifierType_ParticleSystem) return 0;
|
2009-08-16 02:35:44 +00:00
|
|
|
if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
|
|
|
psys=((ParticleSystemModifierData *)md)->psys;
|
|
|
|
part= psys->part;
|
|
|
|
|
2011-03-05 10:29:10 +00:00
|
|
|
if(part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL)
|
2010-01-26 11:15:45 +00:00
|
|
|
return 0;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
totpart= psys->totcached;
|
|
|
|
totchild= psys->totchildcache;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
|
|
|
|
totpart= 0;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
/* count */
|
|
|
|
cache= psys->pathcache;
|
|
|
|
for(a=0; a<totpart; a++) {
|
|
|
|
key= cache[a];
|
2011-03-28 08:27:19 +00:00
|
|
|
|
|
|
|
if(key->steps > 0) {
|
|
|
|
totvert+= key->steps+1;
|
|
|
|
totedge+= key->steps;
|
|
|
|
}
|
2010-01-26 11:15:45 +00:00
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
cache= psys->childcache;
|
|
|
|
for(a=0; a<totchild; a++) {
|
|
|
|
key= cache[a];
|
2011-03-28 08:27:19 +00:00
|
|
|
|
|
|
|
if(key->steps > 0) {
|
|
|
|
totvert+= key->steps+1;
|
|
|
|
totedge+= key->steps;
|
|
|
|
}
|
2010-01-26 11:15:45 +00:00
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
if(totvert==0) return 0;
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
/* add new mesh */
|
|
|
|
obn= add_object(scene, OB_MESH);
|
|
|
|
me= obn->data;
|
|
|
|
|
|
|
|
me->totvert= totvert;
|
|
|
|
me->totedge= totedge;
|
|
|
|
|
|
|
|
me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
|
|
|
|
me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
|
|
|
|
me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
|
|
|
|
|
|
|
|
mvert= me->mvert;
|
|
|
|
medge= me->medge;
|
|
|
|
|
|
|
|
/* copy coordinates */
|
|
|
|
cache= psys->pathcache;
|
|
|
|
for(a=0; a<totpart; a++) {
|
|
|
|
key= cache[a];
|
|
|
|
kmax= key->steps;
|
|
|
|
for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
|
2011-11-07 01:38:32 +00:00
|
|
|
copy_v3_v3(mvert->co,key->co);
|
2010-01-26 11:15:45 +00:00
|
|
|
if(k) {
|
|
|
|
medge->v1= cvert-1;
|
|
|
|
medge->v2= cvert;
|
|
|
|
medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
|
|
|
|
medge++;
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
2010-03-03 19:22:02 +00:00
|
|
|
else {
|
|
|
|
/* cheap trick to select the roots */
|
|
|
|
mvert->flag |= SELECT;
|
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
2010-01-26 11:15:45 +00:00
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2010-01-26 11:15:45 +00:00
|
|
|
cache=psys->childcache;
|
|
|
|
for(a=0; a<totchild; a++) {
|
|
|
|
key=cache[a];
|
|
|
|
kmax=key->steps;
|
|
|
|
for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
|
2011-11-07 01:38:32 +00:00
|
|
|
copy_v3_v3(mvert->co,key->co);
|
2010-01-26 11:15:45 +00:00
|
|
|
if(k) {
|
|
|
|
medge->v1=cvert-1;
|
|
|
|
medge->v2=cvert;
|
|
|
|
medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
|
|
|
|
medge++;
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
2010-03-03 19:22:02 +00:00
|
|
|
else {
|
|
|
|
/* cheap trick to select the roots */
|
|
|
|
mvert->flag |= SELECT;
|
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-01 12:47:49 +00:00
|
|
|
DAG_scene_sort(bmain, scene);
|
2009-05-21 15:34:09 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
|
2009-05-21 15:34:09 +00:00
|
|
|
{
|
2011-06-13 14:11:29 +00:00
|
|
|
ModifierTypeInfo *mti= modifierType_getInfo(md->type);
|
|
|
|
|
2011-07-05 10:35:48 +00:00
|
|
|
md->scene= scene;
|
|
|
|
|
2011-06-13 14:11:29 +00:00
|
|
|
if (mti->isDisabled && mti->isDisabled(md, 0)) {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
/*
|
|
|
|
It should be ridiculously easy to extract the original verts that we want
|
|
|
|
and form the shape data. We can probably use the CD KEYINDEX layer (or
|
|
|
|
whatever I ended up calling it, too tired to check now), though this would
|
|
|
|
by necassity have to make some potentially ugly assumptions about the order
|
|
|
|
of the mesh data :-/ you can probably assume in 99% of cases that the first
|
|
|
|
element of a given index is the original, and any subsequent duplicates are
|
|
|
|
copies/interpolates, but that's an assumption that would need to be tested
|
|
|
|
and then predominantly stated in comments in a half dozen headers.
|
|
|
|
*/
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
if (ob->type==OB_MESH) {
|
|
|
|
DerivedMesh *dm;
|
|
|
|
Mesh *me= ob->data;
|
|
|
|
Key *key=me->key;
|
|
|
|
KeyBlock *kb;
|
|
|
|
|
2011-12-20 14:15:59 +00:00
|
|
|
if(!modifier_sameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
|
2009-11-28 04:04:01 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
dm = mesh_create_derived_for_modifier(scene, ob, md, 0);
|
2009-11-28 04:04:01 +00:00
|
|
|
if (!dm) {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(key == NULL) {
|
|
|
|
key= me->key= add_key((ID *)me);
|
|
|
|
key->type= KEY_RELATIVE;
|
|
|
|
/* if that was the first key block added, then it was the basis.
|
2012-03-01 12:20:18 +00:00
|
|
|
* Initialize it with the mesh, and add another for the modifier */
|
2009-12-28 18:03:04 +00:00
|
|
|
kb= add_keyblock(key, NULL);
|
2009-11-28 04:04:01 +00:00
|
|
|
mesh_to_key(me, kb);
|
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2009-12-28 18:03:04 +00:00
|
|
|
kb= add_keyblock(key, md->name);
|
2009-11-28 04:04:01 +00:00
|
|
|
DM_to_meshkey(dm, me, kb);
|
|
|
|
|
|
|
|
dm->release(dm);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
|
2009-05-21 15:34:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-11-28 04:04:01 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
|
|
|
|
{
|
2010-04-13 06:06:49 +00:00
|
|
|
ModifierTypeInfo *mti= modifierType_getInfo(md->type);
|
|
|
|
|
2011-07-05 10:35:48 +00:00
|
|
|
md->scene= scene;
|
|
|
|
|
2011-06-13 14:11:29 +00:00
|
|
|
if (mti->isDisabled && mti->isDisabled(md, 0)) {
|
2010-04-13 06:06:49 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-21 15:34:09 +00:00
|
|
|
if (ob->type==OB_MESH) {
|
2009-11-28 04:04:01 +00:00
|
|
|
DerivedMesh *dm;
|
|
|
|
Mesh *me = ob->data;
|
2010-07-05 12:20:49 +00:00
|
|
|
MultiresModifierData *mmd= find_multires_modifier_before(scene, md);
|
2011-07-25 11:34:09 +00:00
|
|
|
|
2011-12-20 14:15:59 +00:00
|
|
|
if(me->key && mti->type != eModifierTypeType_NonGeometrical) {
|
2011-07-25 11:34:09 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
/* Multires: ensure that recent sculpting is applied */
|
|
|
|
if(md->type == eModifierType_Multires)
|
|
|
|
multires_force_update(ob);
|
2010-04-13 06:06:49 +00:00
|
|
|
|
2010-07-05 12:20:49 +00:00
|
|
|
if (mmd && mmd->totlvl && mti->type==eModifierTypeType_OnlyDeform) {
|
|
|
|
if(!multiresModifier_reshapeFromDeformMod (scene, mmd, ob, md)) {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
|
|
|
|
return 0;
|
|
|
|
}
|
2010-04-13 06:06:49 +00:00
|
|
|
} else {
|
2011-07-25 10:07:50 +00:00
|
|
|
dm = mesh_create_derived_for_modifier(scene, ob, md, 1);
|
2010-04-13 06:06:49 +00:00
|
|
|
if (!dm) {
|
2010-07-05 12:20:49 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
|
2010-04-13 06:06:49 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
DM_to_mesh(dm, me, ob);
|
2010-04-13 06:06:49 +00:00
|
|
|
|
|
|
|
dm->release(dm);
|
2010-09-26 18:29:54 +00:00
|
|
|
|
|
|
|
if(md->type == eModifierType_Multires) {
|
2011-07-25 10:07:50 +00:00
|
|
|
CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
|
|
|
|
CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
|
2010-09-26 18:29:54 +00:00
|
|
|
}
|
2009-11-22 13:44:09 +00:00
|
|
|
}
|
2011-07-25 11:34:09 +00:00
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
|
2010-03-05 16:47:52 +00:00
|
|
|
Curve *cu;
|
2009-05-21 15:34:09 +00:00
|
|
|
int numVerts;
|
|
|
|
float (*vertexCos)[3];
|
2010-03-05 16:47:52 +00:00
|
|
|
|
2012-01-30 20:44:08 +00:00
|
|
|
if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
|
2010-03-05 16:47:52 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cu = ob->data;
|
2009-05-21 15:34:09 +00:00
|
|
|
BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices");
|
2010-03-05 16:47:52 +00:00
|
|
|
|
2009-05-21 15:34:09 +00:00
|
|
|
vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
|
2009-05-31 17:20:57 +00:00
|
|
|
mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0);
|
2009-05-21 15:34:09 +00:00
|
|
|
curve_applyVertexCos(cu, &cu->nurb, vertexCos);
|
|
|
|
|
|
|
|
MEM_freeN(vertexCos);
|
2010-03-05 16:47:52 +00:00
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
|
|
|
|
return 0;
|
|
|
|
}
|
2010-09-02 08:06:53 +00:00
|
|
|
|
|
|
|
/* lattice modifier can be applied to particle system too */
|
|
|
|
if(ob->particlesystem.first) {
|
|
|
|
|
|
|
|
ParticleSystem *psys = ob->particlesystem.first;
|
|
|
|
|
|
|
|
for(; psys; psys=psys->next) {
|
|
|
|
|
|
|
|
if(psys->part->type != PART_HAIR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
psys_apply_hair_lattice(scene, ob, psys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
|
|
|
|
{
|
2011-06-13 14:11:29 +00:00
|
|
|
int prev_mode;
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
if (scene->obedit) {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
|
|
|
|
return 0;
|
|
|
|
} else if (((ID*) ob->data)->us>1) {
|
|
|
|
BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
|
|
|
|
return 0;
|
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
if (md!=ob->modifiers.first)
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
|
2009-05-21 15:34:09 +00:00
|
|
|
|
2011-06-13 14:11:29 +00:00
|
|
|
/* allow apply of a not-realtime modifier, by first re-enabling realtime. */
|
|
|
|
prev_mode= md->mode;
|
|
|
|
md->mode |= eModifierMode_Realtime;
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
if (mode == MODIFIER_APPLY_SHAPE) {
|
2011-06-13 14:11:29 +00:00
|
|
|
if (!modifier_apply_shape(reports, scene, ob, md)) {
|
|
|
|
md->mode= prev_mode;
|
2009-11-28 04:04:01 +00:00
|
|
|
return 0;
|
2011-06-13 14:11:29 +00:00
|
|
|
}
|
2009-11-28 04:04:01 +00:00
|
|
|
} else {
|
2011-06-13 14:11:29 +00:00
|
|
|
if (!modifier_apply_obdata(reports, scene, ob, md)) {
|
|
|
|
md->mode= prev_mode;
|
2009-11-28 04:04:01 +00:00
|
|
|
return 0;
|
2011-06-13 14:11:29 +00:00
|
|
|
}
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
|
2009-11-28 04:04:01 +00:00
|
|
|
BLI_remlink(&ob->modifiers, md);
|
|
|
|
modifier_free(md);
|
|
|
|
|
|
|
|
return 1;
|
2009-05-21 15:34:09 +00:00
|
|
|
}
|
|
|
|
|
2010-10-16 14:32:17 +00:00
|
|
|
int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
|
2009-05-21 15:34:09 +00:00
|
|
|
{
|
|
|
|
ModifierData *nmd;
|
|
|
|
|
|
|
|
nmd = modifier_new(md->type);
|
|
|
|
modifier_copyData(md, nmd);
|
|
|
|
BLI_insertlink(&ob->modifiers, md, nmd);
|
2009-10-09 09:48:04 +00:00
|
|
|
modifier_unique_name(&ob->modifiers, nmd);
|
2009-05-21 15:34:09 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************ add modifier operator *********************/
|
2009-04-27 18:05:58 +00:00
|
|
|
|
|
|
|
static int modifier_add_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-08-01 12:47:49 +00:00
|
|
|
Main *bmain= CTX_data_main(C);
|
2009-04-27 18:05:58 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2010-03-31 00:55:01 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2009-04-27 18:05:58 +00:00
|
|
|
int type= RNA_enum_get(op->ptr, "type");
|
|
|
|
|
2010-08-01 12:47:49 +00:00
|
|
|
if(!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
|
2009-07-02 19:41:31 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2009-04-27 18:05:58 +00:00
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2011-05-26 13:38:16 +00:00
|
|
|
static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
|
2009-08-21 02:51:56 +00:00
|
|
|
{
|
2010-03-31 00:55:01 +00:00
|
|
|
Object *ob= ED_object_active_context(C);
|
2011-12-21 13:31:28 +00:00
|
|
|
EnumPropertyItem *item= NULL, *md_item, *group_item= NULL;
|
2009-08-21 02:51:56 +00:00
|
|
|
ModifierTypeInfo *mti;
|
|
|
|
int totitem= 0, a;
|
|
|
|
|
2009-10-14 19:19:43 +00:00
|
|
|
if(!ob)
|
2009-08-21 02:51:56 +00:00
|
|
|
return modifier_type_items;
|
|
|
|
|
|
|
|
for(a=0; modifier_type_items[a].identifier; a++) {
|
|
|
|
md_item= &modifier_type_items[a];
|
|
|
|
|
|
|
|
if(md_item->identifier[0]) {
|
|
|
|
mti= modifierType_getInfo(md_item->value);
|
|
|
|
|
|
|
|
if(mti->flags & eModifierTypeFlag_NoUserAdd)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
|
|
|
|
(ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
|
|
|
|
continue;
|
|
|
|
}
|
2011-12-21 13:31:28 +00:00
|
|
|
else {
|
|
|
|
group_item= md_item;
|
|
|
|
md_item= NULL;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(group_item) {
|
|
|
|
RNA_enum_item_add(&item, &totitem, group_item);
|
|
|
|
group_item= NULL;
|
|
|
|
}
|
2009-08-21 02:51:56 +00:00
|
|
|
|
|
|
|
RNA_enum_item_add(&item, &totitem, md_item);
|
|
|
|
}
|
|
|
|
|
|
|
|
RNA_enum_item_end(&item, &totitem);
|
|
|
|
*free= 1;
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2009-04-27 18:05:58 +00:00
|
|
|
void OBJECT_OT_modifier_add(wmOperatorType *ot)
|
|
|
|
{
|
2009-08-21 02:51:56 +00:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
2009-04-27 18:05:58 +00:00
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Add Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description = "Add a modifier to the active object";
|
2009-04-27 18:05:58 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_add";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->exec= modifier_add_exec;
|
2009-12-04 06:33:01 +00:00
|
|
|
ot->poll= ED_operator_object_active_editable;
|
2009-04-27 18:05:58 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
/* properties */
|
|
|
|
prop= RNA_def_enum(ot->srna, "type", modifier_type_items, eModifierType_Subsurf, "Type", "");
|
|
|
|
RNA_def_enum_funcs(prop, modifier_add_itemf);
|
2010-01-15 22:40:33 +00:00
|
|
|
ot->prop= prop;
|
2009-04-27 18:05:58 +00:00
|
|
|
}
|
|
|
|
|
2010-04-22 06:59:41 +00:00
|
|
|
/************************ generic functions for operators using mod names and data context *********************/
|
2010-04-22 01:55:10 +00:00
|
|
|
|
2010-11-04 15:59:09 +00:00
|
|
|
static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", rna_type);
|
|
|
|
Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C);
|
|
|
|
|
|
|
|
if (!ob || ob->id.lib) return 0;
|
2010-11-04 15:59:09 +00:00
|
|
|
if (obtype_flag && ((1<<ob->type) & obtype_flag)==0) return 0;
|
2011-01-14 19:35:59 +00:00
|
|
|
if (ptr.id.data && ((ID*)ptr.id.data)->lib) return 0;
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int edit_modifier_poll(bContext *C)
|
|
|
|
{
|
2010-11-04 15:59:09 +00:00
|
|
|
return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
|
2010-04-22 01:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void edit_modifier_properties(wmOperatorType *ot)
|
|
|
|
{
|
2012-01-11 08:51:06 +00:00
|
|
|
RNA_def_string(ot->srna, "modifier", "", MAX_NAME, "Modifier", "Name of the modifier to edit");
|
2010-04-22 01:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
|
|
|
|
ModifierData *md;
|
|
|
|
|
2012-01-11 16:32:12 +00:00
|
|
|
if (RNA_struct_property_is_set(op->ptr, "modifier"))
|
2010-04-22 01:55:10 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (ptr.data) {
|
|
|
|
md = ptr.data;
|
|
|
|
RNA_string_set(op->ptr, "modifier", md->name);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-16 14:32:17 +00:00
|
|
|
static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
2012-01-11 08:51:06 +00:00
|
|
|
char modifier_name[MAX_NAME];
|
2010-04-22 01:55:10 +00:00
|
|
|
ModifierData *md;
|
|
|
|
RNA_string_get(op->ptr, "modifier", modifier_name);
|
|
|
|
|
|
|
|
md = modifiers_findByName(ob, modifier_name);
|
|
|
|
|
|
|
|
if (md && type != 0 && md->type != type)
|
|
|
|
md = NULL;
|
|
|
|
|
|
|
|
return md;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
/************************ remove modifier operator *********************/
|
|
|
|
|
|
|
|
static int modifier_remove_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-08-01 12:47:49 +00:00
|
|
|
Main *bmain= CTX_data_main(C);
|
2009-07-02 19:41:31 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
2011-09-16 06:47:01 +00:00
|
|
|
int mode_orig = ob ? ob->mode : 0;
|
2010-04-22 01:55:10 +00:00
|
|
|
|
2010-08-01 12:47:49 +00:00
|
|
|
if(!ob || !md || !ED_object_modifier_remove(op->reports, bmain, scene, ob, md))
|
2009-07-02 19:41:31 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
2010-10-19 10:17:19 +00:00
|
|
|
|
|
|
|
/* if cloth/softbody was removed, particle mode could be cleared */
|
|
|
|
if(mode_orig & OB_MODE_PARTICLE_EDIT)
|
|
|
|
if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
|
|
|
|
if(scene->basact && scene->basact->object==ob)
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return modifier_remove_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
void OBJECT_OT_modifier_remove(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Remove Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Remove a modifier from the active object";
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_remove";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= modifier_remove_invoke;
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->exec= modifier_remove_exec;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= edit_modifier_poll;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************ move up modifier operator *********************/
|
|
|
|
|
|
|
|
static int modifier_move_up_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
|
2009-07-02 19:41:31 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return modifier_move_up_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Move Up Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Move modifier up in the stack";
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_move_up";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= modifier_move_up_invoke;
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->exec= modifier_move_up_exec;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= edit_modifier_poll;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************ move down modifier operator *********************/
|
|
|
|
|
|
|
|
static int modifier_move_down_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
if(!ob || !md || !ED_object_modifier_move_down(op->reports, ob, md))
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return modifier_move_down_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Move Down Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Move modifier down in the stack";
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_move_down";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= modifier_move_down_invoke;
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->exec= modifier_move_down_exec;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= edit_modifier_poll;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************ apply modifier operator *********************/
|
|
|
|
|
|
|
|
static int modifier_apply_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
2009-11-22 13:44:09 +00:00
|
|
|
int apply_as= RNA_enum_get(op->ptr, "apply_as");
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
|
2009-07-02 19:41:31 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2010-04-22 01:55:10 +00:00
|
|
|
}
|
2009-07-02 19:41:31 +00:00
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return modifier_apply_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-11-22 13:44:09 +00:00
|
|
|
static EnumPropertyItem modifier_apply_as_items[] = {
|
|
|
|
{MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
|
|
|
|
{MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
|
|
|
|
{0, NULL, 0, NULL, NULL}};
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
void OBJECT_OT_modifier_apply(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Apply Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Apply modifier and remove from the stack";
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_apply";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= modifier_apply_invoke;
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->exec= modifier_apply_exec;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= edit_modifier_poll;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2009-11-22 13:44:09 +00:00
|
|
|
|
|
|
|
RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************ convert modifier operator *********************/
|
|
|
|
|
|
|
|
static int modifier_convert_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-08-01 12:47:49 +00:00
|
|
|
Main *bmain= CTX_data_main(C);
|
2009-07-02 19:41:31 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
2010-04-22 01:55:10 +00:00
|
|
|
|
2010-08-01 12:47:49 +00:00
|
|
|
if(!ob || !md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
|
2009-07-02 19:41:31 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return modifier_convert_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
void OBJECT_OT_modifier_convert(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Convert Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Convert particles to a mesh object";
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_convert";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= modifier_convert_invoke;
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->exec= modifier_convert_exec;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= edit_modifier_poll;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************ copy modifier operator *********************/
|
|
|
|
|
|
|
|
static int modifier_copy_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
if(!ob || !md || !ED_object_modifier_copy(op->reports, ob, md))
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-07-02 19:41:31 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return modifier_copy_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-07-02 19:41:31 +00:00
|
|
|
void OBJECT_OT_modifier_copy(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Copy Modifier";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Duplicate modifier at the same position in the stack";
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->idname= "OBJECT_OT_modifier_copy";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= modifier_copy_invoke;
|
2009-07-02 19:41:31 +00:00
|
|
|
ot->exec= modifier_copy_exec;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= edit_modifier_poll;
|
2009-07-02 19:41:31 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-07-02 19:41:31 +00:00
|
|
|
}
|
|
|
|
|
2009-09-03 17:45:04 +00:00
|
|
|
/************* multires delete higher levels operator ****************/
|
|
|
|
|
2009-11-25 14:07:12 +00:00
|
|
|
static int multires_poll(bContext *C)
|
|
|
|
{
|
2010-11-04 15:59:09 +00:00
|
|
|
return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1<<OB_MESH));
|
2009-11-25 14:07:12 +00:00
|
|
|
}
|
|
|
|
|
2009-09-03 17:45:04 +00:00
|
|
|
static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
if (!mmd)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
multiresModifier_del_levels(mmd, ob, 1);
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
2009-09-03 17:45:04 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return multires_higher_levels_delete_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-09-03 17:45:04 +00:00
|
|
|
void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Delete Higher Levels";
|
2011-05-15 17:59:48 +00:00
|
|
|
ot->description= "Deletes the higher resolution mesh, potential loss of detail";
|
2009-09-03 17:45:04 +00:00
|
|
|
ot->idname= "OBJECT_OT_multires_higher_levels_delete";
|
|
|
|
|
2009-11-25 14:07:12 +00:00
|
|
|
ot->poll= multires_poll;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= multires_higher_levels_delete_invoke;
|
2009-09-03 17:45:04 +00:00
|
|
|
ot->exec= multires_higher_levels_delete_exec;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-09-03 17:45:04 +00:00
|
|
|
}
|
|
|
|
|
2009-05-27 00:03:49 +00:00
|
|
|
/****************** multires subdivide operator *********************/
|
|
|
|
|
2009-05-23 07:12:55 +00:00
|
|
|
static int multires_subdivide_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
if (!mmd)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2009-11-25 14:07:12 +00:00
|
|
|
multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-08-21 02:51:56 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
2009-05-23 07:12:55 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return multires_subdivide_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-05-23 07:12:55 +00:00
|
|
|
void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Multires Subdivide";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Add a new level of subdivision";
|
2009-05-23 07:12:55 +00:00
|
|
|
ot->idname= "OBJECT_OT_multires_subdivide";
|
|
|
|
|
2009-12-10 14:26:06 +00:00
|
|
|
ot->poll= multires_poll;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= multires_subdivide_invoke;
|
2009-05-23 07:12:55 +00:00
|
|
|
ot->exec= multires_subdivide_exec;
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-12-10 14:26:06 +00:00
|
|
|
}
|
|
|
|
|
2009-12-21 15:55:10 +00:00
|
|
|
/****************** multires reshape operator *********************/
|
|
|
|
|
|
|
|
static int multires_reshape_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob= ED_object_active_context(C), *secondob= NULL;
|
2010-06-06 15:22:27 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
|
2009-12-21 15:55:10 +00:00
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
if (!mmd)
|
|
|
|
return OPERATOR_CANCELLED;
|
2011-09-04 11:38:53 +00:00
|
|
|
|
|
|
|
if(mmd->lvl==0) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
|
2011-09-04 11:38:53 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-12-21 15:55:10 +00:00
|
|
|
CTX_DATA_BEGIN(C, Object*, selob, selected_editable_objects) {
|
|
|
|
if(selob->type == OB_MESH && selob != ob) {
|
|
|
|
secondob= selob;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
if(!secondob) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Second selected mesh object require to copy shape from");
|
2009-12-21 15:55:10 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2010-06-06 15:22:27 +00:00
|
|
|
|
|
|
|
if(!multiresModifier_reshape(scene, mmd, ob, secondob)) {
|
2011-09-19 12:26:20 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
|
2009-12-21 15:55:10 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-12-21 15:55:10 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
2010-06-06 15:22:27 +00:00
|
|
|
|
2009-12-21 15:55:10 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return multires_reshape_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-12-21 15:55:10 +00:00
|
|
|
void OBJECT_OT_multires_reshape(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Multires Reshape";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Copy vertex coordinates from other object";
|
2009-12-21 15:55:10 +00:00
|
|
|
ot->idname= "OBJECT_OT_multires_reshape";
|
|
|
|
|
|
|
|
ot->poll= multires_poll;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= multires_reshape_invoke;
|
2009-12-21 15:55:10 +00:00
|
|
|
ot->exec= multires_reshape_exec;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-12-21 15:55:10 +00:00
|
|
|
}
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
static int multires_test_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Object *ob= ED_object_active_context(C);
|
|
|
|
Mesh *me = ob->data;
|
|
|
|
MPoly *mp;
|
|
|
|
MDisps *mdisps;
|
|
|
|
int i, x = RNA_int_get(op->ptr, "x"), y = RNA_int_get(op->ptr, "y");
|
|
|
|
|
|
|
|
if (ob->type != OB_MESH || !me)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
|
|
|
|
if (!mdisps)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
mp = me->mpoly;
|
|
|
|
for (i=0; i<me->totpoly; i++, mp++) {
|
|
|
|
MLoop *ml;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
ml = me->mloop + mp->loopstart;
|
|
|
|
for (j=0; j<mp->totloop; j++, ml++) {
|
2011-12-28 07:10:27 +00:00
|
|
|
MLoop *ml_prev = ME_POLY_LOOP_PREV(me->mloop, mp, j);
|
|
|
|
MLoop *ml_next = ME_POLY_LOOP_NEXT(me->mloop, mp, j);
|
2011-07-25 10:07:50 +00:00
|
|
|
|
2011-12-28 07:10:27 +00:00
|
|
|
if ((me->mvert[ml->v].flag&SELECT) && (me->mvert[ml_prev->v].flag&SELECT) && (me->mvert[ml_next->v].flag&SELECT)) {
|
2011-07-25 10:07:50 +00:00
|
|
|
MDisps *md = mdisps + mp->loopstart + j;
|
|
|
|
int res = sqrt(md->totdisp);
|
|
|
|
|
|
|
|
if (x >= res) x = res-1;
|
|
|
|
if (y >= res) y = res-1;
|
|
|
|
|
|
|
|
md->disps[y*res + x][2] += 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_test_multires(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Multires Object Mode Test";
|
|
|
|
ot->description= "";
|
|
|
|
ot->idname= "OBJECT_OT_test_multires";
|
|
|
|
|
|
|
|
ot->poll= multires_poll;
|
|
|
|
ot->exec= multires_test_exec;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
RNA_def_int(ot->srna, "x", 0, 0, 100, "x", "x", 0, 100);
|
|
|
|
RNA_def_int(ot->srna, "y", 0, 0, 100, "y", "y", 0, 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-12-10 14:26:06 +00:00
|
|
|
/****************** multires save external operator *********************/
|
|
|
|
|
2010-06-09 14:04:34 +00:00
|
|
|
static int multires_external_save_exec(bContext *C, wmOperator *op)
|
2009-12-10 14:26:06 +00:00
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2009-12-10 14:26:06 +00:00
|
|
|
Mesh *me= (ob)? ob->data: op->customdata;
|
|
|
|
char path[FILE_MAX];
|
2010-06-09 14:04:34 +00:00
|
|
|
int relative= RNA_boolean_get(op->ptr, "relative_path");
|
2009-12-10 14:26:06 +00:00
|
|
|
|
2010-03-08 15:44:26 +00:00
|
|
|
if(!me)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
if(CustomData_external_test(&me->ldata, CD_MDISPS))
|
2009-12-10 14:26:06 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2010-06-14 03:52:10 +00:00
|
|
|
RNA_string_get(op->ptr, "filepath", path);
|
2010-05-07 09:41:26 +00:00
|
|
|
|
2010-06-09 14:04:34 +00:00
|
|
|
if(relative)
|
2010-10-18 06:41:16 +00:00
|
|
|
BLI_path_rel(path, G.main->name);
|
2009-12-10 14:26:06 +00:00
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
|
|
|
|
CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH, me->totloop, 0);
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2009-12-10 14:26:06 +00:00
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
|
|
|
MultiresModifierData *mmd;
|
2009-12-10 14:26:06 +00:00
|
|
|
Mesh *me= ob->data;
|
|
|
|
char path[FILE_MAX];
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
if (!edit_modifier_invoke_properties(C, op))
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2010-10-16 14:32:17 +00:00
|
|
|
mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
if (!mmd)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
if(CustomData_external_test(&me->ldata, CD_MDISPS))
|
2009-12-10 14:26:06 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2012-01-11 16:32:12 +00:00
|
|
|
if(RNA_struct_property_is_set(op->ptr, "filepath"))
|
2010-06-09 14:04:34 +00:00
|
|
|
return multires_external_save_exec(C, op);
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
op->customdata= me;
|
|
|
|
|
|
|
|
BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
|
2010-06-14 03:52:10 +00:00
|
|
|
RNA_string_set(op->ptr, "filepath", path);
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
WM_event_add_fileselect(C, op);
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
2010-06-09 14:04:34 +00:00
|
|
|
void OBJECT_OT_multires_external_save(wmOperatorType *ot)
|
2009-12-10 14:26:06 +00:00
|
|
|
{
|
|
|
|
ot->name= "Multires Save External";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Save displacements to an external file";
|
2010-06-09 14:04:34 +00:00
|
|
|
ot->idname= "OBJECT_OT_multires_external_save";
|
2009-12-10 14:26:06 +00:00
|
|
|
|
2010-03-08 15:44:26 +00:00
|
|
|
// XXX modifier no longer in context after file browser .. ot->poll= multires_poll;
|
2010-06-09 14:04:34 +00:00
|
|
|
ot->exec= multires_external_save_exec;
|
|
|
|
ot->invoke= multires_external_save_invoke;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= multires_poll;
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
|
2012-01-24 18:18:51 +00:00
|
|
|
WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-12-10 14:26:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************** multires pack operator *********************/
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-12-10 14:26:06 +00:00
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2009-12-10 14:26:06 +00:00
|
|
|
Mesh *me= ob->data;
|
|
|
|
|
2011-07-25 10:07:50 +00:00
|
|
|
if(!CustomData_external_test(&me->ldata, CD_MDISPS))
|
2009-12-10 14:26:06 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
// XXX don't remove..
|
2011-07-25 10:07:50 +00:00
|
|
|
CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-06-09 14:04:34 +00:00
|
|
|
void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
|
2009-12-10 14:26:06 +00:00
|
|
|
{
|
|
|
|
ot->name= "Multires Pack External";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Pack displacements from an external file";
|
2010-06-09 14:04:34 +00:00
|
|
|
ot->idname= "OBJECT_OT_multires_external_pack";
|
2009-12-10 14:26:06 +00:00
|
|
|
|
|
|
|
ot->poll= multires_poll;
|
2010-06-09 14:04:34 +00:00
|
|
|
ot->exec= multires_external_pack_exec;
|
2009-05-23 07:12:55 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2011-01-07 21:12:47 +00:00
|
|
|
/********************* multires apply base ***********************/
|
|
|
|
static int multires_base_apply_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Object *ob = ED_object_active_context(C);
|
|
|
|
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
|
|
|
|
|
|
|
|
if (!mmd)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
multiresModifier_base_apply(mmd, ob);
|
|
|
|
|
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return multires_base_apply_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Multires Apply Base";
|
|
|
|
ot->description= "Modify the base mesh to conform to the displaced mesh";
|
|
|
|
ot->idname= "OBJECT_OT_multires_base_apply";
|
|
|
|
|
|
|
|
ot->poll= multires_poll;
|
|
|
|
ot->invoke= multires_base_apply_invoke;
|
|
|
|
ot->exec= multires_base_apply_exec;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
edit_modifier_properties(ot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-03 00:09:30 +00:00
|
|
|
/************************ mdef bind operator *********************/
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
static int meshdeform_poll(bContext *C)
|
2009-06-03 00:09:30 +00:00
|
|
|
{
|
2010-11-04 15:59:09 +00:00
|
|
|
return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, (1<<OB_MESH));
|
2009-06-03 00:09:30 +00:00
|
|
|
}
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
static int meshdeform_bind_exec(bContext *C, wmOperator *op)
|
2009-06-03 00:09:30 +00:00
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
if (!mmd)
|
|
|
|
return OPERATOR_CANCELLED;
|
2009-06-03 00:09:30 +00:00
|
|
|
|
2010-05-03 02:01:38 +00:00
|
|
|
if(mmd->bindcagecos) {
|
2011-08-27 03:25:02 +00:00
|
|
|
MEM_freeN(mmd->bindcagecos);
|
2009-06-03 00:09:30 +00:00
|
|
|
if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
|
|
|
|
if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
|
2011-06-09 11:19:34 +00:00
|
|
|
if(mmd->bindinfluences) MEM_freeN(mmd->bindinfluences);
|
|
|
|
if(mmd->bindoffsets) MEM_freeN(mmd->bindoffsets);
|
2009-06-03 00:09:30 +00:00
|
|
|
if(mmd->dynverts) MEM_freeN(mmd->dynverts);
|
2011-06-09 11:19:34 +00:00
|
|
|
if(mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */
|
|
|
|
if(mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */
|
|
|
|
|
2010-05-03 02:01:38 +00:00
|
|
|
mmd->bindcagecos= NULL;
|
2009-06-03 00:09:30 +00:00
|
|
|
mmd->dyngrid= NULL;
|
|
|
|
mmd->dyninfluences= NULL;
|
2011-06-09 11:19:34 +00:00
|
|
|
mmd->bindoffsets= NULL;
|
2009-06-03 00:09:30 +00:00
|
|
|
mmd->dynverts= NULL;
|
2011-06-09 11:19:34 +00:00
|
|
|
mmd->bindweights= NULL; /* deprecated */
|
|
|
|
mmd->bindcos= NULL; /* deprecated */
|
2009-06-03 00:09:30 +00:00
|
|
|
mmd->totvert= 0;
|
|
|
|
mmd->totcagevert= 0;
|
|
|
|
mmd->totinfluence= 0;
|
2010-04-22 01:55:10 +00:00
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2010-04-22 01:55:10 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
2009-06-03 00:09:30 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
DerivedMesh *dm;
|
|
|
|
int mode= mmd->modifier.mode;
|
|
|
|
|
|
|
|
/* force modifier to run, it will call binding routine */
|
2009-11-28 13:33:17 +00:00
|
|
|
mmd->bindfunc= mesh_deform_bind;
|
2009-06-03 00:09:30 +00:00
|
|
|
mmd->modifier.mode |= eModifierMode_Realtime;
|
|
|
|
|
|
|
|
if(ob->type == OB_MESH) {
|
|
|
|
dm= mesh_create_derived_view(scene, ob, 0);
|
|
|
|
dm->release(dm);
|
|
|
|
}
|
|
|
|
else if(ob->type == OB_LATTICE) {
|
|
|
|
lattice_calc_modifiers(scene, ob);
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_MBALL) {
|
|
|
|
makeDispListMBall(scene, ob);
|
|
|
|
}
|
|
|
|
else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
|
|
|
|
makeDispListCurveTypes(scene, ob, 0);
|
|
|
|
}
|
|
|
|
|
2009-11-05 18:05:55 +00:00
|
|
|
mmd->bindfunc= NULL;
|
2009-06-03 00:09:30 +00:00
|
|
|
mmd->modifier.mode= mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return meshdeform_bind_exec(C, op);
|
2010-05-03 02:01:38 +00:00
|
|
|
else
|
2010-04-22 01:55:10 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
|
2009-06-03 00:09:30 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Mesh Deform Bind";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description = "Bind mesh to cage in mesh deform modifier";
|
2009-08-21 02:51:56 +00:00
|
|
|
ot->idname= "OBJECT_OT_meshdeform_bind";
|
2009-06-03 00:09:30 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
2009-08-21 02:51:56 +00:00
|
|
|
ot->poll= meshdeform_poll;
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->invoke= meshdeform_bind_invoke;
|
2009-08-21 02:51:56 +00:00
|
|
|
ot->exec= meshdeform_bind_exec;
|
2009-06-03 00:09:30 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-06-03 00:09:30 +00:00
|
|
|
}
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
/****************** explode refresh operator *********************/
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
static int explode_poll(bContext *C)
|
2009-06-03 00:09:30 +00:00
|
|
|
{
|
2010-11-04 15:59:09 +00:00
|
|
|
return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
|
2009-06-03 00:09:30 +00:00
|
|
|
}
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
static int explode_refresh_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2010-04-22 01:55:10 +00:00
|
|
|
Object *ob = ED_object_active_context(C);
|
2010-10-16 14:32:17 +00:00
|
|
|
ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
|
2010-04-22 01:55:10 +00:00
|
|
|
|
|
|
|
if (!emd)
|
|
|
|
return OPERATOR_CANCELLED;
|
2009-08-21 02:51:56 +00:00
|
|
|
|
|
|
|
emd->flag |= eExplodeFlag_CalcFaces;
|
|
|
|
|
2010-12-05 18:59:23 +00:00
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-08-21 02:51:56 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2010-04-22 01:55:10 +00:00
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return explode_refresh_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-21 02:51:56 +00:00
|
|
|
void OBJECT_OT_explode_refresh(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Explode Refresh";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Refresh data in the Explode modifier";
|
2009-08-21 02:51:56 +00:00
|
|
|
ot->idname= "OBJECT_OT_explode_refresh";
|
|
|
|
|
2010-04-22 01:55:10 +00:00
|
|
|
ot->poll= explode_poll;
|
|
|
|
ot->invoke= explode_refresh_invoke;
|
2009-08-21 02:51:56 +00:00
|
|
|
ot->exec= explode_refresh_exec;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2010-04-22 01:55:10 +00:00
|
|
|
edit_modifier_properties(ot);
|
2009-08-21 02:51:56 +00:00
|
|
|
}
|
2009-06-03 00:09:30 +00:00
|
|
|
|
2011-11-13 12:17:27 +00:00
|
|
|
|
|
|
|
/****************** ocean bake operator *********************/
|
|
|
|
|
|
|
|
static int ocean_bake_poll(bContext *C)
|
|
|
|
{
|
|
|
|
return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copied from init_ocean_modifier, MOD_ocean.c */
|
|
|
|
static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData *omd)
|
|
|
|
{
|
|
|
|
int do_heightfield, do_chop, do_normals, do_jacobian;
|
|
|
|
|
|
|
|
if (!omd || !oc) return;
|
|
|
|
|
|
|
|
do_heightfield = TRUE;
|
|
|
|
do_chop = (omd->chop_amount > 0);
|
|
|
|
do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
|
|
|
|
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
|
|
|
|
|
|
|
|
BKE_init_ocean(oc, omd->resolution*omd->resolution, omd->resolution*omd->resolution, omd->spatial_size, omd->spatial_size,
|
|
|
|
omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
|
|
|
|
omd->depth, omd->time,
|
|
|
|
do_heightfield, do_chop, do_normals, do_jacobian,
|
|
|
|
omd->seed);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct OceanBakeJob {
|
|
|
|
/* from wmJob */
|
|
|
|
void *owner;
|
|
|
|
short *stop, *do_update;
|
|
|
|
float *progress;
|
|
|
|
int current_frame;
|
|
|
|
struct OceanCache *och;
|
|
|
|
struct Ocean *ocean;
|
|
|
|
struct OceanModifierData *omd;
|
|
|
|
} OceanBakeJob;
|
|
|
|
|
|
|
|
static void oceanbake_free(void *customdata)
|
|
|
|
{
|
|
|
|
OceanBakeJob *oj= customdata;
|
|
|
|
MEM_freeN(oj);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* called by oceanbake, only to check job 'stop' value */
|
|
|
|
static int oceanbake_breakjob(void *UNUSED(customdata))
|
|
|
|
{
|
|
|
|
//OceanBakeJob *ob= (OceanBakeJob *)customdata;
|
|
|
|
//return *(ob->stop);
|
|
|
|
|
|
|
|
/* this is not nice yet, need to make the jobs list template better
|
|
|
|
* for identifying/acting upon various different jobs */
|
|
|
|
/* but for now we'll reuse the render break... */
|
|
|
|
return (G.afbreek);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* called by oceanbake, wmJob sends notifier */
|
|
|
|
static void oceanbake_update(void *customdata, float progress, int *cancel)
|
|
|
|
{
|
|
|
|
OceanBakeJob *oj= customdata;
|
|
|
|
|
|
|
|
if (oceanbake_breakjob(oj))
|
|
|
|
*cancel = 1;
|
|
|
|
|
|
|
|
*(oj->do_update)= 1;
|
|
|
|
*(oj->progress)= progress;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
|
|
|
|
{
|
|
|
|
OceanBakeJob *oj= customdata;
|
|
|
|
|
|
|
|
oj->stop= stop;
|
|
|
|
oj->do_update = do_update;
|
|
|
|
oj->progress = progress;
|
|
|
|
|
|
|
|
G.afbreek= 0; /* XXX shared with render - replace with job 'stop' switch */
|
|
|
|
|
|
|
|
BKE_bake_ocean(oj->ocean, oj->och, oceanbake_update, (void *)oj);
|
|
|
|
|
|
|
|
*do_update= 1;
|
|
|
|
*stop = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void oceanbake_endjob(void *customdata)
|
|
|
|
{
|
|
|
|
OceanBakeJob *oj= customdata;
|
|
|
|
|
|
|
|
if (oj->ocean) {
|
|
|
|
BKE_free_ocean(oj->ocean);
|
|
|
|
oj->ocean = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
oj->omd->oceancache = oj->och;
|
|
|
|
oj->omd->cached = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ocean_bake_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Object *ob = ED_object_active_context(C);
|
|
|
|
OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
OceanCache *och;
|
|
|
|
struct Ocean *ocean;
|
|
|
|
int f, cfra, i=0;
|
|
|
|
int free= RNA_boolean_get(op->ptr, "free");
|
|
|
|
|
|
|
|
wmJob *steve;
|
|
|
|
OceanBakeJob *oj;
|
|
|
|
|
|
|
|
if (!omd)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
if (free) {
|
|
|
|
omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
|
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2011-11-20 14:38:11 +00:00
|
|
|
|
|
|
|
och = BKE_init_ocean_cache(omd->cachepath, modifier_path_relbase(ob),
|
|
|
|
omd->bakestart, omd->bakeend, omd->wave_scale,
|
|
|
|
omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
|
2011-11-13 12:17:27 +00:00
|
|
|
|
|
|
|
och->time = MEM_mallocN(och->duration*sizeof(float), "foam bake time");
|
|
|
|
|
|
|
|
cfra = scene->r.cfra;
|
|
|
|
|
|
|
|
/* precalculate time variable before baking */
|
|
|
|
for (f=omd->bakestart; f<=omd->bakeend; f++) {
|
|
|
|
/* from physics_fluid.c:
|
|
|
|
|
2012-03-02 16:05:54 +00:00
|
|
|
* XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
|
2011-11-13 12:17:27 +00:00
|
|
|
* leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
|
|
|
|
* --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
|
|
|
|
* This doesn't work with drivers:
|
|
|
|
* --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Modifying the global scene isn't nice, but we can do it in
|
|
|
|
* this part of the process before a threaded job is created */
|
|
|
|
|
|
|
|
//scene->r.cfra = f;
|
|
|
|
//ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
|
|
|
|
|
|
|
|
/* ok, this doesn't work with drivers, but is way faster.
|
|
|
|
* let's use this for now and hope nobody wants to drive the time value... */
|
|
|
|
BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
|
|
|
|
|
|
|
|
och->time[i] = omd->time;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make a copy of ocean to use for baking - threadsafety */
|
|
|
|
ocean = BKE_add_ocean();
|
|
|
|
init_ocean_modifier_bake(ocean, omd);
|
|
|
|
|
|
|
|
/*
|
|
|
|
BKE_bake_ocean(ocean, och);
|
|
|
|
|
|
|
|
omd->oceancache = och;
|
|
|
|
omd->cached = TRUE;
|
|
|
|
|
|
|
|
scene->r.cfra = cfra;
|
|
|
|
|
|
|
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* job stuff */
|
|
|
|
|
|
|
|
scene->r.cfra = cfra;
|
|
|
|
|
|
|
|
/* setup job */
|
|
|
|
steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", WM_JOB_PROGRESS);
|
|
|
|
oj= MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
|
|
|
|
oj->ocean = ocean;
|
|
|
|
oj->och = och;
|
|
|
|
oj->omd = omd;
|
|
|
|
|
|
|
|
WM_jobs_customdata(steve, oj, oceanbake_free);
|
|
|
|
WM_jobs_timer(steve, 0.1, NC_OBJECT|ND_MODIFIER, NC_OBJECT|ND_MODIFIER);
|
|
|
|
WM_jobs_callbacks(steve, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
|
|
|
|
|
|
|
|
WM_jobs_start(CTX_wm_manager(C), steve);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ocean_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
|
|
|
{
|
|
|
|
if (edit_modifier_invoke_properties(C, op))
|
|
|
|
return ocean_bake_exec(C, op);
|
|
|
|
else
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void OBJECT_OT_ocean_bake(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
ot->name= "Bake Ocean";
|
|
|
|
ot->description= "Bake an image sequence of ocean data";
|
|
|
|
ot->idname= "OBJECT_OT_ocean_bake";
|
|
|
|
|
|
|
|
ot->poll= ocean_bake_poll;
|
|
|
|
ot->invoke= ocean_bake_invoke;
|
|
|
|
ot->exec= ocean_bake_exec;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
edit_modifier_properties(ot);
|
|
|
|
|
|
|
|
RNA_def_boolean(ot->srna, "free", FALSE, "Free", "Free the bake, rather than generating it");
|
|
|
|
}
|
|
|
|
|