Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_modifier.c
| /* | /* | ||||
| * ***** BEGIN GPL LICENSE BLOCK ***** | * ***** BEGIN GPL LICENSE BLOCK ***** | ||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License | * modify it under the terms of the GNU General Public License | ||||
| * as published by the Free Software Foundation; either version 2 | * as published by the Free Software Foundation; either version 2 | ||||
| * of the License, or (at your option) any later version. | * of the License, or (at your option) any later version. | ||||
| * | * | ||||
| * This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | ||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| * GNU General Public License for more details. | * GNU General Public License for more details. | ||||
| * | * | ||||
| * You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
| * along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
| * | * | ||||
| * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | ||||
| * All rights reserved. | * All rights reserved. | ||||
| * | * | ||||
| * Contributor(s): Blender Foundation, 2009 | * Contributor(s): Blender Foundation, 2009 | ||||
| * | * | ||||
| * ***** END GPL LICENSE BLOCK ***** | * ***** END GPL LICENSE BLOCK ***** | ||||
| */ | */ | ||||
| /** \file blender/editors/object/object_modifier.c | /** \file blender/editors/object/object_modifier.c | ||||
| * \ingroup edobj | * \ingroup edobj | ||||
| */ | */ | ||||
| #include <math.h> | #include <math.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | if (mti->flags & eModifierTypeFlag_Single) { | ||||
| if (modifiers_findByType(ob, type)) { | if (modifiers_findByType(ob, type)) { | ||||
| BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); | BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| if (type == eModifierType_ParticleSystem) { | if (type == eModifierType_ParticleSystem) { | ||||
| /* don't need to worry about the new modifier's name, since that is set to the number | /* 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 | * of particle systems which shouldn't have too many duplicates | ||||
| */ | */ | ||||
| new_md = object_add_particle_system(bmain, scene, ob, name); | new_md = object_add_particle_system(bmain, scene, ob, name); | ||||
| } | } | ||||
| else { | else { | ||||
| /* get new modifier data to add */ | /* get new modifier data to add */ | ||||
| new_md = modifier_new(type); | new_md = modifier_new(type); | ||||
| if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { | if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { | ||||
| md = ob->modifiers.first; | md = ob->modifiers.first; | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | ||||
| DEG_relations_tag_update(bmain); | DEG_relations_tag_update(bmain); | ||||
| return new_md; | return new_md; | ||||
| } | } | ||||
| /* Return true if the object has a modifier of type 'type' other than | /* Return true if the object has a modifier of type 'type' other than | ||||
| * the modifier pointed to be 'exclude', otherwise returns false. */ | * the modifier pointed to be 'exclude', otherwise returns false. */ | ||||
| static bool object_has_modifier(const Object *ob, const ModifierData *exclude, | static bool object_has_modifier(const Object *ob, const ModifierData *exclude, | ||||
| ModifierType type) | ModifierType type) | ||||
| { | { | ||||
| ModifierData *md; | ModifierData *md; | ||||
| for (md = ob->modifiers.first; md; md = md->next) { | for (md = ob->modifiers.first; md; md = md->next) { | ||||
| if ((md != exclude) && (md->type == type)) | if ((md != exclude) && (md->type == type)) | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* If the object data of 'orig_ob' has other users, run 'callback' on | /* If the object data of 'orig_ob' has other users, run 'callback' on | ||||
| * each of them. | * each of them. | ||||
| * | * | ||||
| * If include_orig is true, the callback will run on 'orig_ob' too. | * If include_orig is true, the callback will run on 'orig_ob' too. | ||||
| * | * | ||||
| * If the callback ever returns true, iteration will stop and the | * If the callback ever returns true, iteration will stop and the | ||||
| * function value will be true. Otherwise the function returns false. | * function value will be true. Otherwise the function returns false. | ||||
| */ | */ | ||||
| bool ED_object_iter_other(Main *bmain, Object *orig_ob, const bool include_orig, | bool ED_object_iter_other(Main *bmain, Object *orig_ob, const bool include_orig, | ||||
| bool (*callback)(Object *ob, void *callback_data), | bool (*callback)(Object *ob, void *callback_data), | ||||
| void *callback_data) | void *callback_data) | ||||
| { | { | ||||
| ID *ob_data_id = orig_ob->data; | ID *ob_data_id = orig_ob->data; | ||||
| int users = ob_data_id->us; | int users = ob_data_id->us; | ||||
| if (ob_data_id->flag & LIB_FAKEUSER) | if (ob_data_id->flag & LIB_FAKEUSER) | ||||
| users--; | users--; | ||||
| /* First check that the object's data has multiple users */ | /* First check that the object's data has multiple users */ | ||||
| if (users > 1) { | if (users > 1) { | ||||
| Object *ob; | Object *ob; | ||||
| int totfound = include_orig ? 0 : 1; | int totfound = include_orig ? 0 : 1; | ||||
| for (ob = bmain->object.first; ob && totfound < users; | for (ob = bmain->object.first; ob && totfound < users; | ||||
| ob = ob->id.next) | ob = ob->id.next) | ||||
| { | { | ||||
| if (((ob != orig_ob) || include_orig) && | if (((ob != orig_ob) || include_orig) && | ||||
| (ob->data == orig_ob->data)) | (ob->data == orig_ob->data)) | ||||
| { | { | ||||
| if (callback(ob, callback_data)) | if (callback(ob, callback_data)) | ||||
| return true; | return true; | ||||
| totfound++; | totfound++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (include_orig) { | else if (include_orig) { | ||||
| return callback(orig_ob, callback_data); | return callback(orig_ob, callback_data); | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool object_has_modifier_cb(Object *ob, void *data) | static bool object_has_modifier_cb(Object *ob, void *data) | ||||
| { | { | ||||
| ModifierType type = *((ModifierType *)data); | ModifierType type = *((ModifierType *)data); | ||||
| return object_has_modifier(ob, NULL, type); | return object_has_modifier(ob, NULL, type); | ||||
| } | } | ||||
| /* Use with ED_object_iter_other(). Sets the total number of levels | /* Use with ED_object_iter_other(). Sets the total number of levels | ||||
| * for any multires modifiers on the object to the int pointed to by | * for any multires modifiers on the object to the int pointed to by | ||||
| * callback_data. */ | * callback_data. */ | ||||
| bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v) | bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v) | ||||
| { | { | ||||
| ModifierData *md; | ModifierData *md; | ||||
| int totlevel = *((char *)totlevel_v); | int totlevel = *((char *)totlevel_v); | ||||
| for (md = ob->modifiers.first; md; md = md->next) { | for (md = ob->modifiers.first; md; md = md->next) { | ||||
| if (md->type == eModifierType_Multires) { | if (md->type == eModifierType_Multires) { | ||||
| multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel); | multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel); | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Return true if no modifier of type 'type' other than 'exclude' */ | /* Return true if no modifier of type 'type' other than 'exclude' */ | ||||
| static bool object_modifier_safe_to_delete(Main *bmain, Object *ob, | static bool object_modifier_safe_to_delete(Main *bmain, Object *ob, | ||||
| ModifierData *exclude, | ModifierData *exclude, | ||||
| ModifierType type) | ModifierType type) | ||||
| { | { | ||||
| return (!object_has_modifier(ob, exclude, type) && | return (!object_has_modifier(ob, exclude, type) && | ||||
| !ED_object_iter_other(bmain, ob, false, | !ED_object_iter_other(bmain, ob, false, | ||||
| object_has_modifier_cb, &type)); | object_has_modifier_cb, &type)); | ||||
| } | } | ||||
| static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md, | static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md, | ||||
| bool *r_sort_depsgraph) | bool *r_sort_depsgraph) | ||||
| { | { | ||||
| /* It seems on rapid delete it is possible to | /* It seems on rapid delete it is possible to | ||||
| * get called twice on same modifier, so make | * get called twice on same modifier, so make | ||||
| * sure it is in list. */ | * sure it is in list. */ | ||||
| if (BLI_findindex(&ob->modifiers, md) == -1) { | if (BLI_findindex(&ob->modifiers, md) == -1) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* special cases */ | /* special cases */ | ||||
| if (md->type == eModifierType_ParticleSystem) { | if (md->type == eModifierType_ParticleSystem) { | ||||
| ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | ||||
| Show All 23 Lines | static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md, | ||||
| } | } | ||||
| else if (md->type == eModifierType_Skin) { | else if (md->type == eModifierType_Skin) { | ||||
| /* Delete MVertSkin layer if not used by another skin modifier */ | /* Delete MVertSkin layer if not used by another skin modifier */ | ||||
| if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin)) | if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin)) | ||||
| modifier_skin_customdata_delete(ob); | modifier_skin_customdata_delete(ob); | ||||
| } | } | ||||
| if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) && | if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) && | ||||
| BLI_listbase_is_empty(&ob->particlesystem)) | BLI_listbase_is_empty(&ob->particlesystem)) | ||||
| { | { | ||||
| ob->mode &= ~OB_MODE_PARTICLE_EDIT; | ob->mode &= ~OB_MODE_PARTICLE_EDIT; | ||||
| } | } | ||||
| BLI_remlink(&ob->modifiers, md); | BLI_remlink(&ob->modifiers, md); | ||||
| modifier_free(md); | modifier_free(md); | ||||
| BKE_object_free_derived_caches(ob); | BKE_object_free_derived_caches(ob); | ||||
| ▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, ModifierData *md) | ||||
| } | } | ||||
| DEG_relations_tag_update(bmain); | DEG_relations_tag_update(bmain); | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| static int modifier_apply_shape( | static int modifier_apply_shape( | ||||
| Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md) | Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md) | ||||
| { | { | ||||
| const ModifierTypeInfo *mti = modifierType_getInfo(md->type); | const ModifierTypeInfo *mti = modifierType_getInfo(md->type); | ||||
| if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { | if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { | ||||
| BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); | BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* | /* | ||||
| * It should be ridiculously easy to extract the original verts that we want | * 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 | * 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 | * whatever I ended up calling it, too tired to check now), though this would | ||||
| * by necessity have to make some potentially ugly assumptions about the order | * by necessity 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 | * 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 | * 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 | * copies/interpolates, but that's an assumption that would need to be tested | ||||
| * and then predominantly stated in comments in a half dozen headers. | * and then predominantly stated in comments in a half dozen headers. | ||||
| */ | */ | ||||
| if (ob->type == OB_MESH) { | if (ob->type == OB_MESH) { | ||||
| Mesh *mesh_applied; | Mesh *mesh_applied; | ||||
| Mesh *me = ob->data; | Mesh *me = ob->data; | ||||
| Key *key = me->key; | Key *key = me->key; | ||||
| KeyBlock *kb; | KeyBlock *kb; | ||||
| if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { | if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { | ||||
| BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); | BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| mesh_applied = BKE_mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 0); | mesh_applied = BKE_mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 0); | ||||
| if (!mesh_applied) { | if (!mesh_applied) { | ||||
| BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply"); | BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (key == NULL) { | if (key == NULL) { | ||||
| key = me->key = BKE_key_add(bmain, (ID *)me); | key = me->key = BKE_key_add(bmain, (ID *)me); | ||||
| key->type = KEY_RELATIVE; | key->type = KEY_RELATIVE; | ||||
| /* if that was the first key block added, then it was the basis. | /* if that was the first key block added, then it was the basis. | ||||
| * Initialize it with the mesh, and add another for the modifier */ | * Initialize it with the mesh, and add another for the modifier */ | ||||
| kb = BKE_keyblock_add(key, NULL); | kb = BKE_keyblock_add(key, NULL); | ||||
| BKE_keyblock_convert_from_mesh(me, key, kb); | BKE_keyblock_convert_from_mesh(me, key, kb); | ||||
| } | } | ||||
| kb = BKE_keyblock_add(key, md->name); | kb = BKE_keyblock_add(key, md->name); | ||||
| BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb); | BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb); | ||||
| BKE_id_free(NULL, mesh_applied); | BKE_id_free(NULL, mesh_applied); | ||||
| ▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | for (; psys; psys = psys->next) { | ||||
| psys_apply_hair_lattice(depsgraph, scene, ob, psys); | psys_apply_hair_lattice(depsgraph, scene, ob, psys); | ||||
| } | } | ||||
| } | } | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| int ED_object_modifier_apply( | int ED_object_modifier_apply( | ||||
| Main *bmain, ReportList *reports, Depsgraph *depsgraph, | Main *bmain, ReportList *reports, Depsgraph *depsgraph, | ||||
| Scene *scene, Object *ob, ModifierData *md, int mode) | Scene *scene, Object *ob, ModifierData *md, int mode) | ||||
| { | { | ||||
| int prev_mode; | int prev_mode; | ||||
| if (BKE_object_is_in_editmode(ob)) { | if (BKE_object_is_in_editmode(ob)) { | ||||
| BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode"); | BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| else if (((ID *) ob->data)->us > 1) { | else if (((ID *) ob->data)->us > 1) { | ||||
| BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data"); | BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| else if ((ob->mode & OB_MODE_SCULPT) && | else if ((ob->mode & OB_MODE_SCULPT) && | ||||
| (find_multires_modifier_before(scene, md)) && | (find_multires_modifier_before(scene, md)) && | ||||
| (modifier_isSameTopology(md) == false)) | (modifier_isSameTopology(md) == false)) | ||||
| { | { | ||||
| BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); | BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (md != ob->modifiers.first) | if (md != ob->modifiers.first) | ||||
| BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected"); | BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected"); | ||||
| /* Get evaluated modifier, so object links pointer to evaluated data, | /* Get evaluated modifier, so object links pointer to evaluated data, | ||||
| * but still use original object it is applied to the original mesh. */ | * but still use original object it is applied to the original mesh. */ | ||||
| Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); | Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); | ||||
| ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md; | ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md; | ||||
| /* allow apply of a not-realtime modifier, by first re-enabling realtime. */ | /* allow apply of a not-realtime modifier, by first re-enabling realtime. */ | ||||
| prev_mode = md_eval->mode; | prev_mode = md_eval->mode; | ||||
| md_eval->mode |= eModifierMode_Realtime; | md_eval->mode |= eModifierMode_Realtime; | ||||
| if (mode == MODIFIER_APPLY_SHAPE) { | if (mode == MODIFIER_APPLY_SHAPE) { | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type)) | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static const EnumPropertyItem *modifier_add_itemf( | static const EnumPropertyItem *modifier_add_itemf( | ||||
| bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) | bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) | ||||
| { | { | ||||
| Object *ob = ED_object_active_context(C); | Object *ob = ED_object_active_context(C); | ||||
| EnumPropertyItem *item = NULL; | EnumPropertyItem *item = NULL; | ||||
| const EnumPropertyItem *md_item, *group_item = NULL; | const EnumPropertyItem *md_item, *group_item = NULL; | ||||
| const ModifierTypeInfo *mti; | const ModifierTypeInfo *mti; | ||||
| int totitem = 0, a; | int totitem = 0, a; | ||||
| if (!ob) | if (!ob) | ||||
| ▲ Show 20 Lines • Show All 396 Lines • ▼ Show 20 Lines | static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op) | ||||
| MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); | MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); | ||||
| if (!mmd) | if (!mmd) | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| multiresModifier_del_levels(mmd, scene, ob, 1); | multiresModifier_del_levels(mmd, scene, ob, 1); | ||||
| ED_object_iter_other(CTX_data_main(C), ob, true, | ED_object_iter_other(CTX_data_main(C), ob, true, | ||||
| ED_object_multires_update_totlevels_cb, | ED_object_multires_update_totlevels_cb, | ||||
| &mmd->totlvl); | &mmd->totlvl); | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | ||||
| { | { | ||||
| Show All 27 Lines | static int multires_subdivide_exec(bContext *C, wmOperator *op) | ||||
| MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); | MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); | ||||
| if (!mmd) | if (!mmd) | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple); | multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple); | ||||
| ED_object_iter_other(CTX_data_main(C), ob, true, | ED_object_iter_other(CTX_data_main(C), ob, true, | ||||
| ED_object_multires_update_totlevels_cb, | ED_object_multires_update_totlevels_cb, | ||||
| &mmd->totlvl); | &mmd->totlvl); | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | ||||
| if (ob->mode & OB_MODE_SCULPT) { | if (ob->mode & OB_MODE_SCULPT) { | ||||
| /* ensure that grid paint mask layer is created */ | /* ensure that grid paint mask layer is created */ | ||||
| BKE_sculpt_mask_layers_ensure(ob, mmd); | BKE_sculpt_mask_layers_ensure(ob, mmd); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | void OBJECT_OT_multires_external_save(wmOperatorType *ot) | ||||
| ot->exec = multires_external_save_exec; | ot->exec = multires_external_save_exec; | ||||
| ot->invoke = multires_external_save_invoke; | ot->invoke = multires_external_save_invoke; | ||||
| ot->poll = multires_poll; | ot->poll = multires_poll; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ||||
| WM_operator_properties_filesel( | WM_operator_properties_filesel( | ||||
| ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE, | ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE, | ||||
| WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); | WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); | ||||
| edit_modifier_properties(ot); | edit_modifier_properties(ot); | ||||
| } | } | ||||
| /****************** multires pack operator *********************/ | /****************** multires pack operator *********************/ | ||||
| static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op)) | static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op)) | ||||
| { | { | ||||
| Object *ob = ED_object_active_context(C); | Object *ob = ED_object_active_context(C); | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | if (em) | ||||
| BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN); | BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN); | ||||
| else | else | ||||
| CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert); | CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert); | ||||
| } | } | ||||
| static bool skin_poll(bContext *C) | static bool skin_poll(bContext *C) | ||||
| { | { | ||||
| return (!CTX_data_edit_object(C) && | return (!CTX_data_edit_object(C) && | ||||
| edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); | edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); | ||||
| } | } | ||||
| static bool skin_edit_poll(bContext *C) | static bool skin_edit_poll(bContext *C) | ||||
| { | { | ||||
| return (CTX_data_edit_object(C) && | return (CTX_data_edit_object(C) && | ||||
| edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); | edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); | ||||
| } | } | ||||
| static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset) | static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset) | ||||
| { | { | ||||
| BMEdge *bm_edge; | BMEdge *bm_edge; | ||||
| BMIter bm_iter; | BMIter bm_iter; | ||||
| BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) { | BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) { | ||||
| Show All 22 Lines | static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) | ||||
| visited = BLI_gset_ptr_new(__func__); | visited = BLI_gset_ptr_new(__func__); | ||||
| BKE_mesh_ensure_skin_customdata(ob->data); | BKE_mesh_ensure_skin_customdata(ob->data); | ||||
| const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); | const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); | ||||
| BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { | ||||
| if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && | if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && | ||||
| BLI_gset_add(visited, bm_vert)) | BLI_gset_add(visited, bm_vert)) | ||||
| { | { | ||||
| MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset); | MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset); | ||||
| /* mark vertex as root and add to visited set */ | /* mark vertex as root and add to visited set */ | ||||
| vs->flag |= MVERT_SKIN_ROOT; | vs->flag |= MVERT_SKIN_ROOT; | ||||
| /* clear root flag from all connected vertices (recursively) */ | /* clear root flag from all connected vertices (recursively) */ | ||||
| skin_root_clear(bm_vert, visited, cd_vert_skin_offset); | skin_root_clear(bm_vert, visited, cd_vert_skin_offset); | ||||
| Show All 37 Lines | static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op) | ||||
| if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { | if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { | ||||
| if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) { | if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) { | ||||
| MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, | MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, | ||||
| bm_vert->head.data, | bm_vert->head.data, | ||||
| CD_MVERT_SKIN); | CD_MVERT_SKIN); | ||||
| switch (action) { | switch (action) { | ||||
| case SKIN_LOOSE_MARK: | case SKIN_LOOSE_MARK: | ||||
| vs->flag |= MVERT_SKIN_LOOSE; | vs->flag |= MVERT_SKIN_LOOSE; | ||||
| break; | break; | ||||
| case SKIN_LOOSE_CLEAR: | case SKIN_LOOSE_CLEAR: | ||||
| vs->flag &= ~MVERT_SKIN_LOOSE; | vs->flag &= ~MVERT_SKIN_LOOSE; | ||||
| Show All 39 Lines | static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op)) | ||||
| if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { | if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { | ||||
| if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) { | if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) { | ||||
| MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, | MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, | ||||
| bm_vert->head.data, | bm_vert->head.data, | ||||
| CD_MVERT_SKIN); | CD_MVERT_SKIN); | ||||
| float avg = (vs->radius[0] + vs->radius[1]) * 0.5f; | float avg = (vs->radius[0] + vs->radius[1]) * 0.5f; | ||||
| vs->radius[0] = vs->radius[1] = avg; | vs->radius[0] = vs->radius[1] = avg; | ||||
| } | } | ||||
| } | } | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | ||||
| Show All 10 Lines | void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot) | ||||
| ot->poll = skin_edit_poll; | ot->poll = skin_edit_poll; | ||||
| ot->exec = skin_radii_equalize_exec; | ot->exec = skin_radii_equalize_exec; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| } | } | ||||
| static void skin_armature_bone_create(Object *skin_ob, | static void skin_armature_bone_create(Object *skin_ob, | ||||
| MVert *mvert, MEdge *medge, | MVert *mvert, MEdge *medge, | ||||
| bArmature *arm, | bArmature *arm, | ||||
| BLI_bitmap *edges_visited, | BLI_bitmap *edges_visited, | ||||
| const MeshElemMap *emap, | const MeshElemMap *emap, | ||||
| EditBone *parent_bone, | EditBone *parent_bone, | ||||
| int parent_v) | int parent_v) | ||||
| { | { | ||||
| int i; | int i; | ||||
| for (i = 0; i < emap[parent_v].count; i++) { | for (i = 0; i < emap[parent_v].count; i++) { | ||||
| int endx = emap[parent_v].indices[i]; | int endx = emap[parent_v].indices[i]; | ||||
| const MEdge *e = &medge[endx]; | const MEdge *e = &medge[endx]; | ||||
| EditBone *bone; | EditBone *bone; | ||||
| bDeformGroup *dg; | bDeformGroup *dg; | ||||
| Show All 18 Lines | for (i = 0; i < emap[parent_v].count; i++) { | ||||
| /* add bDeformGroup */ | /* add bDeformGroup */ | ||||
| if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) { | if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) { | ||||
| ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE); | ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE); | ||||
| ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE); | ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE); | ||||
| } | } | ||||
| skin_armature_bone_create(skin_ob, | skin_armature_bone_create(skin_ob, | ||||
| mvert, medge, | mvert, medge, | ||||
| arm, | arm, | ||||
| edges_visited, | edges_visited, | ||||
| emap, | emap, | ||||
| bone, | bone, | ||||
| v); | v); | ||||
| } | } | ||||
| } | } | ||||
| static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *skin_ob) | static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *skin_ob) | ||||
| { | { | ||||
| BLI_bitmap *edges_visited; | BLI_bitmap *edges_visited; | ||||
| DerivedMesh *deform_dm; | DerivedMesh *deform_dm; | ||||
| MVert *mvert; | MVert *mvert; | ||||
| Mesh *me = skin_ob->data; | Mesh *me = skin_ob->data; | ||||
| Object *arm_ob; | Object *arm_ob; | ||||
| bArmature *arm; | bArmature *arm; | ||||
| MVertSkin *mvert_skin; | MVertSkin *mvert_skin; | ||||
| MeshElemMap *emap; | MeshElemMap *emap; | ||||
| int *emap_mem; | int *emap_mem; | ||||
| int v; | int v; | ||||
| deform_dm = mesh_get_derived_deform(depsgraph, scene, skin_ob, CD_MASK_BAREMESH); | deform_dm = mesh_get_derived_deform(depsgraph, scene, skin_ob, CD_MASK_BAREMESH); | ||||
| mvert = deform_dm->getVertArray(deform_dm); | mvert = deform_dm->getVertArray(deform_dm); | ||||
| /* add vertex weights to original mesh */ | /* add vertex weights to original mesh */ | ||||
| CustomData_add_layer(&me->vdata, | CustomData_add_layer(&me->vdata, | ||||
| CD_MDEFORMVERT, | CD_MDEFORMVERT, | ||||
| CD_CALLOC, | CD_CALLOC, | ||||
| NULL, | NULL, | ||||
| me->totvert); | me->totvert); | ||||
| ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); | ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); | ||||
| arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL); | arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL); | ||||
| BKE_object_transform_copy(arm_ob, skin_ob); | BKE_object_transform_copy(arm_ob, skin_ob); | ||||
| arm = arm_ob->data; | arm = arm_ob->data; | ||||
| arm->layer = 1; | arm->layer = 1; | ||||
| arm_ob->dtx |= OB_DRAWXRAY; | arm_ob->dtx |= OB_DRAWXRAY; | ||||
| arm->drawtype = ARM_LINE; | arm->drawtype = ARM_LINE; | ||||
| arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); | arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); | ||||
| mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN); | mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN); | ||||
| BKE_mesh_vert_edge_map_create(&emap, &emap_mem, | BKE_mesh_vert_edge_map_create(&emap, &emap_mem, | ||||
| me->medge, me->totvert, me->totedge); | me->medge, me->totvert, me->totedge); | ||||
| edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); | edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); | ||||
| /* note: we use EditBones here, easier to set them up and use | /* note: we use EditBones here, easier to set them up and use | ||||
| * edit-armature functions to convert back to regular bones */ | * edit-armature functions to convert back to regular bones */ | ||||
| for (v = 0; v < me->totvert; v++) { | for (v = 0; v < me->totvert; v++) { | ||||
| if (mvert_skin[v].flag & MVERT_SKIN_ROOT) { | if (mvert_skin[v].flag & MVERT_SKIN_ROOT) { | ||||
| EditBone *bone = NULL; | EditBone *bone = NULL; | ||||
| /* Unless the skin root has just one adjacent edge, create | /* Unless the skin root has just one adjacent edge, create | ||||
| * a fake root bone (have it going off in the Y direction | * a fake root bone (have it going off in the Y direction | ||||
| * (arbitrary) */ | * (arbitrary) */ | ||||
| if (emap[v].count > 1) { | if (emap[v].count > 1) { | ||||
| bone = ED_armature_ebone_add(arm, "Bone"); | bone = ED_armature_ebone_add(arm, "Bone"); | ||||
| copy_v3_v3(bone->head, me->mvert[v].co); | copy_v3_v3(bone->head, me->mvert[v].co); | ||||
| copy_v3_v3(bone->tail, me->mvert[v].co); | copy_v3_v3(bone->tail, me->mvert[v].co); | ||||
| bone->head[1] = 1.0f; | bone->head[1] = 1.0f; | ||||
| bone->rad_head = bone->rad_tail = 0.25; | bone->rad_head = bone->rad_tail = 0.25; | ||||
| } | } | ||||
| if (emap[v].count >= 1) { | if (emap[v].count >= 1) { | ||||
| skin_armature_bone_create(skin_ob, | skin_armature_bone_create(skin_ob, | ||||
| mvert, me->medge, | mvert, me->medge, | ||||
| arm, | arm, | ||||
| edges_visited, | edges_visited, | ||||
| emap, | emap, | ||||
| bone, | bone, | ||||
| v); | v); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(edges_visited); | MEM_freeN(edges_visited); | ||||
| MEM_freeN(emap); | MEM_freeN(emap); | ||||
| MEM_freeN(emap_mem); | MEM_freeN(emap_mem); | ||||
| ▲ Show 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | |||||
| /* called by oceanbake, only to check job 'stop' value */ | /* called by oceanbake, only to check job 'stop' value */ | ||||
| static int oceanbake_breakjob(void *UNUSED(customdata)) | static int oceanbake_breakjob(void *UNUSED(customdata)) | ||||
| { | { | ||||
| //OceanBakeJob *ob = (OceanBakeJob *)customdata; | //OceanBakeJob *ob = (OceanBakeJob *)customdata; | ||||
| //return *(ob->stop); | //return *(ob->stop); | ||||
| /* this is not nice yet, need to make the jobs list template better | /* this is not nice yet, need to make the jobs list template better | ||||
| * for identifying/acting upon various different jobs */ | * for identifying/acting upon various different jobs */ | ||||
| /* but for now we'll reuse the render break... */ | /* but for now we'll reuse the render break... */ | ||||
| return (G.is_break); | return (G.is_break); | ||||
| } | } | ||||
| /* called by oceanbake, wmJob sends notifier */ | /* called by oceanbake, wmJob sends notifier */ | ||||
| static void oceanbake_update(void *customdata, float progress, int *cancel) | static void oceanbake_update(void *customdata, float progress, int *cancel) | ||||
| { | { | ||||
| OceanBakeJob *oj = customdata; | OceanBakeJob *oj = customdata; | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | static int ocean_bake_exec(bContext *C, wmOperator *op) | ||||
| if (free) { | if (free) { | ||||
| BKE_ocean_free_modifier_cache(omd); | BKE_ocean_free_modifier_cache(omd); | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE); | DEG_id_tag_update(&ob->id, OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE); | ||||
| WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(bmain, ob), | och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(bmain, ob), | ||||
| omd->bakestart, omd->bakeend, omd->wave_scale, | omd->bakestart, omd->bakeend, omd->wave_scale, | ||||
| omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution); | omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution); | ||||
| och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time"); | och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time"); | ||||
| cfra = scene->r.cfra; | cfra = scene->r.cfra; | ||||
| /* precalculate time variable before baking */ | /* precalculate time variable before baking */ | ||||
| for (f = omd->bakestart; f <= omd->bakeend; f++) { | for (f = omd->bakestart; f <= omd->bakeend; f++) { | ||||
| /* from physics_fluid.c: | /* from physics_fluid.c: | ||||
| * | * | ||||
| * XXX: This can't be used due to an anim sys optimization that ignores recalc object animation, | * XXX: This can't be used due to an anim sys optimization that ignores recalc object animation, | ||||
| * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) | * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) | ||||
| * --> BKE_animsys_evaluate_all_animation(bmain, eval_time); | * --> BKE_animsys_evaluate_all_animation(bmain, eval_time); | ||||
| * This doesn't work with drivers: | * This doesn't work with drivers: | ||||
| * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL); | * --> 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 | /* Modifying the global scene isn't nice, but we can do it in | ||||
| * this part of the process before a threaded job is created */ | * this part of the process before a threaded job is created */ | ||||
| //scene->r.cfra = f; | //scene->r.cfra = f; | ||||
| //ED_update_for_newframe(bmain, scene); | //ED_update_for_newframe(bmain, scene); | ||||
| /* ok, this doesn't work with drivers, but is way faster. | /* 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... */ | * let's use this for now and hope nobody wants to drive the time value... */ | ||||
| BKE_animsys_evaluate_animdata(CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM); | BKE_animsys_evaluate_animdata(CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM); | ||||
| och->time[i] = omd->time; | och->time[i] = omd->time; | ||||
| i++; | i++; | ||||
| } | } | ||||
| /* make a copy of ocean to use for baking - threadsafety */ | /* make a copy of ocean to use for baking - threadsafety */ | ||||
| ocean = BKE_ocean_add(); | ocean = BKE_ocean_add(); | ||||
| Show All 12 Lines | |||||
| #endif | #endif | ||||
| /* job stuff */ | /* job stuff */ | ||||
| scene->r.cfra = cfra; | scene->r.cfra = cfra; | ||||
| /* setup job */ | /* setup job */ | ||||
| wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", | wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", | ||||
| WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN); | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN); | ||||
| oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job"); | oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job"); | ||||
| oj->owner = ob; | oj->owner = ob; | ||||
| oj->ocean = ocean; | oj->ocean = ocean; | ||||
| oj->och = och; | oj->och = och; | ||||
| oj->omd = omd; | oj->omd = omd; | ||||
| WM_jobs_customdata_set(wm_job, oj, oceanbake_free); | WM_jobs_customdata_set(wm_job, oj, oceanbake_free); | ||||
| WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER); | WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER); | ||||
| ▲ Show 20 Lines • Show All 187 Lines • Show Last 20 Lines | |||||