diff options
Diffstat (limited to 'source/blender/editors/physics')
-rw-r--r-- | source/blender/editors/physics/CMakeLists.txt | 6 | ||||
-rw-r--r-- | source/blender/editors/physics/SConscript | 7 | ||||
-rw-r--r-- | source/blender/editors/physics/dynamicpaint_ops.c | 14 | ||||
-rw-r--r-- | source/blender/editors/physics/particle_edit.c | 322 | ||||
-rw-r--r-- | source/blender/editors/physics/particle_object.c | 495 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_fluid.c | 2 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_ops.c | 8 | ||||
-rw-r--r-- | source/blender/editors/physics/rigidbody_constraint.c | 2 | ||||
-rw-r--r-- | source/blender/editors/physics/rigidbody_object.c | 8 | ||||
-rw-r--r-- | source/blender/editors/physics/rigidbody_world.c | 8 |
11 files changed, 768 insertions, 108 deletions
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index 892d71befb4..898422dac51 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -20,14 +20,16 @@ set(INC ../include - ../../blenfont ../../blenkernel ../../blenlib + ../../blentranslation + ../../gpu ../../makesdna ../../makesrna ../../windowmanager ../../../../intern/elbeem/extern ../../../../intern/guardedalloc + ../../../../intern/glew-mx ) set(INC_SYS @@ -64,4 +66,6 @@ if(WITH_BULLET) add_definitions(-DWITH_BULLET) endif() +add_definitions(${GL_DEFINITIONS}) + blender_add_lib(bf_editor_physics "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript index 9436280de43..be399a58732 100644 --- a/source/blender/editors/physics/SConscript +++ b/source/blender/editors/physics/SConscript @@ -31,13 +31,15 @@ sources = env.Glob('*.c') incs = [ '#/intern/guardedalloc', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#/intern/rigidbody', - '#/extern/glew/include', '#/intern/elbeem/extern', '../include', - '../../blenfont', '../../blenkernel', '../../blenlib', + '../../blentranslation', + '../../gpu', '../../makesdna', '../../makesrna', '../../windowmanager', @@ -45,6 +47,7 @@ incs = [ incs = ' '.join(incs) defs = [] +defs += env['BF_GL_DEFINITIONS'] if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 637af5d6536..93daa15e608 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -30,7 +30,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "DNA_dynamicpaint_types.h" #include "DNA_modifier_types.h" @@ -40,6 +40,7 @@ #include "BKE_blender.h" #include "BKE_context.h" #include "BKE_deform.h" +#include "BKE_object_deform.h" #include "BKE_depsgraph.h" #include "BKE_dynamicpaint.h" #include "BKE_global.h" @@ -235,11 +236,11 @@ static int output_toggle_exec(bContext *C, wmOperator *op) /* Vertex Weight Layer */ else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { if (!exists) { - ED_vgroup_add_name(ob, name); + BKE_object_defgroup_add_name(ob, name); } else { bDeformGroup *defgroup = defgroup_find_name(ob, name); - if (defgroup) ED_vgroup_delete(ob, defgroup); + if (defgroup) BKE_object_defgroup_remove(ob, defgroup); } } } @@ -395,13 +396,8 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) /* Bake was successful: * Report for ended bake and how long it took */ if (status) { - /* Format time string */ - char time_str[30]; - double time = PIL_check_seconds_timer() - timer; - BLI_timestr(time, time_str, sizeof(time_str)); - /* Show bake info */ - BKE_reportf(op->reports, RPT_INFO, "Bake complete! (%s)", time_str); + BKE_reportf(op->reports, RPT_INFO, "Bake complete! (%.2f)", PIL_check_seconds_timer() - timer); } else { if (strlen(canvas->error)) { /* If an error occurred */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 76344b77dd3..892545a8efd 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -61,7 +61,7 @@ #include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_report.h" - +#include "BKE_bvhutils.h" #include "BKE_pointcache.h" #include "BIF_gl.h" @@ -83,9 +83,11 @@ #include "physics_intern.h" -static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); -static void PTCacheUndo_clear(PTCacheEdit *edit); -static void recalc_emitter_field(Object *ob, ParticleSystem *psys); +void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); +void PTCacheUndo_clear(PTCacheEdit *edit); +void recalc_lengths(PTCacheEdit *edit); +void recalc_emitter_field(Object *ob, ParticleSystem *psys); +void update_world_cos(Object *ob, PTCacheEdit *edit); #define KEY_K PTCacheEditKey *key; int k #define POINT_P PTCacheEditPoint *point; int p @@ -355,6 +357,7 @@ typedef struct PEData { Object *ob; DerivedMesh *dm; PTCacheEdit *edit; + BVHTreeFromMesh shape_bvh; const int *mval; rcti *rect; @@ -397,12 +400,12 @@ static void PE_set_view3d_data(bContext *C, PEData *data) /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */ view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats); - if ((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(data->vc.v3d)) { if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) { /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - view3d_validate_backbuf(&data->vc); + ED_view3d_backbuf_validate(&data->vc); /* we may need to force an update here by setting the rv3d as dirty * for now it seems ok, but take care!: * rv3d->depths->dirty = 1; */ @@ -411,6 +414,25 @@ static void PE_set_view3d_data(bContext *C, PEData *data) } } +static bool PE_create_shape_tree(PEData *data, Object *shapeob) +{ + DerivedMesh *dm = shapeob->derivedFinal; + + memset(&data->shape_bvh, 0, sizeof(data->shape_bvh)); + + if (!dm) { + return false; + } + + DM_ensure_looptri(dm); + return (bvhtree_from_mesh_looptri(&data->shape_bvh, dm, 0.0f, 4, 8) != NULL); +} + +static void PE_free_shape_tree(PEData *data) +{ + free_bvhtree_from_mesh(&data->shape_bvh); +} + /*************************** selection utilities *******************************/ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2]) @@ -421,8 +443,8 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ float depth; /* nothing to do */ - if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0) - return 1; + if (!V3D_IS_ZBUF(v3d)) + return true; /* used to calculate here but all callers have the screen_co already, so pass as arg */ #if 0 @@ -1055,7 +1077,7 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) } } /* set current distances to be kept between neighbouting keys */ -static void recalc_lengths(PTCacheEdit *edit) +void recalc_lengths(PTCacheEdit *edit) { POINT_P; KEY_K; @@ -1071,7 +1093,7 @@ static void recalc_lengths(PTCacheEdit *edit) } /* calculate a tree for finding nearest emitter's vertice */ -static void recalc_emitter_field(Object *ob, ParticleSystem *psys) +void recalc_emitter_field(Object *ob, ParticleSystem *psys) { DerivedMesh *dm=psys_get_modifier(ob, psys)->dm; PTCacheEdit *edit= psys->edit; @@ -1159,7 +1181,7 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag) point->flag &= ~PEP_EDIT_RECALC; } -static void update_world_cos(Object *ob, PTCacheEdit *edit) +void update_world_cos(Object *ob, PTCacheEdit *edit) { ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); @@ -1588,6 +1610,87 @@ void PARTICLE_OT_select_tips(wmOperatorType *ot) WM_operator_properties_select_action(ot, SEL_SELECT); } +/*********************** select random operator ************************/ + +enum { RAN_HAIR, RAN_POINTS }; + +static EnumPropertyItem select_random_type_items[] = { + {RAN_HAIR, "HAIR", 0, "Hair", ""}, + {RAN_POINTS, "POINTS", 0, "Points", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static int select_random_exec(bContext *C, wmOperator *op) +{ + PEData data; + int type; + Scene *scene; + Object *ob; + + /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */ + PTCacheEdit *edit; + PTCacheEditPoint *point; + PTCacheEditKey *key; + int p; + int k; + + const float randf = RNA_float_get (op->ptr, "percent") / 100.0f; + + type = RNA_enum_get(op->ptr, "type"); + + PE_set_data(C, &data); + data.select_action = SEL_SELECT; + scene = CTX_data_scene(C); + ob = CTX_data_active_object(C); + edit = PE_get_current(scene, ob); + + switch (type) { + case RAN_HAIR: + LOOP_VISIBLE_POINTS { + int flag = (BLI_frand() < randf) ? SEL_SELECT : SEL_DESELECT; + LOOP_KEYS { + select_action_apply (point, key, flag); + } + } + break; + case RAN_POINTS: + LOOP_VISIBLE_POINTS { + LOOP_VISIBLE_KEYS { + int flag = (BLI_frand() < randf) ? SEL_SELECT : SEL_DESELECT; + select_action_apply (point, key, flag); + } + } + break; + } + + PE_update_selection(data.scene, data.ob, 1); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob); + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_select_random(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Random"; + ot->idname = "PARTICLE_OT_select_random"; + ot->description = "Select a randomly distributed set of hair or points"; + + /* api callbacks */ + ot->exec = select_random_exec; + ot->poll = PE_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_float_percentage (ot->srna, "percent", 50.0f, 0.0f, 100.0f, "Percent", + "Percentage (mean) of elements in randomly selected set", + 0.0f, 100.0f); + ot->prop = RNA_def_enum (ot->srna, "type", select_random_type_items, RAN_HAIR, + "Type", "Select either hair or points"); +} + /************************ select linked operator ************************/ static int select_linked_exec(bContext *C, wmOperator *op) @@ -3148,7 +3251,7 @@ static void brush_puff(PEData *data, int point_index) static void BKE_brush_weight_get(PEData *data, float UNUSED(mat[4][4]), float UNUSED(imat[4][4]), int point_index, int key_index, PTCacheEditKey *UNUSED(key)) { - /* roots have full weight allways */ + /* roots have full weight always */ if (key_index) { PTCacheEdit *edit = data->edit; ParticleSystem *psys = edit->psys; @@ -3382,7 +3485,7 @@ static int brush_add(PEData *data, short number) if (psmd->dm->deformedOnly || psys->part->use_modifier_stack) dm = psmd->dm; else { - dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE); release_dm = true; } @@ -3951,6 +4054,184 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot) RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } +/*********************** cut shape ***************************/ + +static int shape_cut_poll(bContext *C) +{ + if (PE_hair_poll(C)) { + Scene *scene = CTX_data_scene(C); + ParticleEditSettings *pset = PE_settings(scene); + + if (pset->shape_object && (pset->shape_object->type == OB_MESH)) { + return true; + } + } + + return false; +} + +typedef struct PointInsideBVH { + BVHTreeFromMesh bvhdata; + int num_hits; +} PointInsideBVH; + +static void point_inside_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + PointInsideBVH *data = userdata; + + data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit); + + if (hit->index != -1) + ++data->num_hits; +} + +/* true if the point is inside the shape mesh */ +static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key) +{ + BVHTreeFromMesh *shape_bvh = &data->shape_bvh; + const float dir[3] = {1.0f, 0.0f, 0.0f}; + PointInsideBVH userdata; + + userdata.bvhdata = data->shape_bvh; + userdata.num_hits = 0; + + BLI_bvhtree_ray_cast_all(shape_bvh->tree, key->co, dir, 0.0f, point_inside_bvh_cb, &userdata); + + /* for any point inside a watertight mesh the number of hits is uneven */ + return (userdata.num_hits % 2) == 1; +} + +static void shape_cut(PEData *data, int pa_index) +{ + PTCacheEdit *edit = data->edit; + Object *ob = data->ob; + ParticleEditSettings *pset = PE_settings(data->scene); + ParticleCacheKey *key; + + bool cut; + float cut_time = 1.0; + int k, totkeys = 1 << pset->draw_step; + + /* don't cut hidden */ + if (edit->points[pa_index].flag & PEP_HIDE) + return; + + cut = false; + + /* check if root is inside the cut shape */ + key = edit->pathcache[pa_index]; + if (!shape_cut_test_point(data, key)) { + cut_time = -1.0f; + cut = true; + } + else { + for (k = 0; k < totkeys; k++, key++) { + BVHTreeRayHit hit; + float dir[3]; + float len; + + sub_v3_v3v3(dir, (key+1)->co, key->co); + len = normalize_v3(dir); + + memset(&hit, 0, sizeof(hit)); + hit.index = -1; + hit.dist = len; + BLI_bvhtree_ray_cast(data->shape_bvh.tree, key->co, dir, 0.0f, &hit, data->shape_bvh.raycast_callback, &data->shape_bvh); + if (hit.index >= 0) { + if (hit.dist < len) { + cut_time = (hit.dist / len + (float)k) / (float)totkeys; + cut = true; + break; + } + } + } + } + + if (cut) { + if (cut_time < 0.0f) { + edit->points[pa_index].flag |= PEP_TAG; + } + else { + rekey_particle_to_time(data->scene, ob, pa_index, cut_time); + edit->points[pa_index].flag |= PEP_EDIT_RECALC; + } + } +} + +static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + ParticleEditSettings *pset = PE_settings(scene); + PTCacheEdit *edit = PE_get_current(scene, ob); + Object *shapeob = pset->shape_object; + int selected = count_selected_keys(scene, edit); + int lock_root = pset->flag & PE_LOCK_FIRST; + + if (!PE_start_edit(edit)) + return OPERATOR_CANCELLED; + + /* disable locking temporatily for disconnected hair */ + if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) + pset->flag &= ~PE_LOCK_FIRST; + + if (edit->psys && edit->pathcache) { + PEData data; + int removed; + + PE_set_data(C, &data); + if (!PE_create_shape_tree(&data, shapeob)) { + /* shapeob may not have faces... */ + return OPERATOR_CANCELLED; + } + + if (selected) + foreach_selected_point(&data, shape_cut); + else + foreach_point(&data, shape_cut); + + removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob)); + recalc_lengths(edit); + + if (removed) { + update_world_cos(ob, edit); + psys_free_path_cache(NULL, edit); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + else + PE_update_object(scene, ob, 1); + + if (edit->psys) { + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); + } + else { + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); + } + + PE_free_shape_tree(&data); + } + + pset->flag |= lock_root; + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_shape_cut(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Shape Cut"; + ot->idname = "PARTICLE_OT_shape_cut"; + ot->description = "Cut hair to conform to the set shape object"; + + /* api callbacks */ + ot->exec = shape_cut_exec; + ot->poll = shape_cut_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + /*********************** undo ***************************/ static void free_PTCacheUndo(PTCacheUndo *undo) @@ -4168,7 +4449,7 @@ void PE_undo_step(Scene *scene, int step) DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA); } -int PE_undo_valid(Scene *scene) +bool PE_undo_is_valid(Scene *scene) { PTCacheEdit *edit= PE_get_current(scene, OBACT); @@ -4178,7 +4459,7 @@ int PE_undo_valid(Scene *scene) return 0; } -static void PTCacheUndo_clear(PTCacheEdit *edit) +void PTCacheUndo_clear(PTCacheEdit *edit) { PTCacheUndo *undo; @@ -4219,18 +4500,19 @@ void PE_undo_number(Scene *scene, int nr) /* get name of undo item, return null if no item with this index */ /* if active pointer, set it to 1 if true */ -const char *PE_undo_get_name(Scene *scene, int nr, int *active) +const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active) { PTCacheEdit *edit= PE_get_current(scene, OBACT); PTCacheUndo *undo; - if (active) *active= 0; + if (r_active) *r_active = false; if (edit) { undo= BLI_findlink(&edit->undo, nr); if (undo) { - if (active && undo==edit->curundo) - *active= 1; + if (r_active && (undo == edit->curundo)) { + *r_active = true; + } return undo->name; } } @@ -4279,7 +4561,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) /************************ particle edit toggle operator ************************/ /* initialize needed data for bake edit */ -static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) +void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) { PTCacheEdit *edit; ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL; diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 5a61f77e5a8..327ce060df9 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -40,18 +40,21 @@ #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "BLI_string.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" #include "BKE_global.h" +#include "BKE_library.h" #include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_report.h" - #include "RNA_access.h" #include "RNA_define.h" @@ -62,8 +65,37 @@ #include "ED_screen.h" #include "ED_object.h" +#include "UI_resources.h" + #include "physics_intern.h" +extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); +extern void PTCacheUndo_clear(PTCacheEdit *edit); +extern void recalc_lengths(PTCacheEdit *edit); +extern void recalc_emitter_field(Object *ob, ParticleSystem *psys); +extern void update_world_cos(Object *ob, PTCacheEdit *edit); + +#define KEY_K PTCacheEditKey *key; int k +#define POINT_P PTCacheEditPoint *point; int p +#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) +#if 0 +#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE)) +#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point)) +#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point)) +#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC) +#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG) +#endif +#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) +#if 0 +#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE)) +#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE)) +#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG) + +#define KEY_WCO (key->flag & PEK_USE_WCO ? key->world_co : key->co) +#endif + +static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}; + /********************** particle system slot operators *********************/ static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op)) @@ -623,38 +655,50 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); } -static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) +/* from/to_world_space : whether from/to particles are in world or hair space + * from/to_mat : additional transform for from/to particles (e.g. for using object space copying) + */ +static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys, + Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit, + float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global) { - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - ParticleData *pa; - PTCacheEdit *edit; - PTCacheEditPoint *point; - PTCacheEditKey *ekey = NULL; - HairKey *key; + ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys); + ParticleData *pa, *tpa; + PTCacheEditPoint *edit_point; + PTCacheEditKey *ekey; BVHTreeFromMesh bvhtree= {NULL}; - BVHTreeNearest nearest; MFace *mface = NULL, *mf; MEdge *medge = NULL, *me; MVert *mvert; - DerivedMesh *dm = NULL; + DerivedMesh *dm, *target_dm; int numverts; int i, k; - float hairmat[4][4], imat[4][4]; - float v[4][3], vec[3]; + float from_ob_imat[4][4], to_ob_imat[4][4]; + float from_imat[4][4], to_imat[4][4]; - if (!psys || !psys->part || psys->part->type != PART_HAIR || !psmd->dm) + if (!target_psmd->dm) + return false; + if (!psys->part || psys->part->type != PART_HAIR) return false; + if (!target_psys->part || target_psys->part->type != PART_HAIR) + return false; + + edit_point = target_edit ? target_edit->points : NULL; - edit= psys->edit; - point= edit ? edit->points : NULL; + invert_m4_m4(from_ob_imat, ob->obmat); + invert_m4_m4(to_ob_imat, target_ob->obmat); + invert_m4_m4(from_imat, from_mat); + invert_m4_m4(to_imat, to_mat); - if (psmd->dm->deformedOnly) { - /* we don't want to mess up psmd->dm when converting to global coordinates below */ - dm = psmd->dm; + if (target_psmd->dm->deformedOnly) { + /* we don't want to mess up target_psmd->dm when converting to global coordinates below */ + dm = target_psmd->dm; } else { - dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + /* warning: this rebuilds target_psmd->dm! */ + dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH | CD_MASK_MFACE); } + target_dm = target_psmd->dm; /* don't modify the original vertices */ dm = CDDM_copy(dm); @@ -662,12 +706,11 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) DM_ensure_tessface(dm); numverts = dm->getNumVerts(dm); - mvert = dm->getVertArray(dm); /* convert to global coordinates */ for (i=0; i<numverts; i++) - mul_m4_v3(ob->obmat, mvert[i].co); + mul_m4_v3(to_mat, mvert[i].co); if (dm->getNumTessFaces(dm) != 0) { mface = dm->getTessFaceArray(dm); @@ -682,13 +725,23 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) return false; } - for (i=0, pa= psys->particles; i<psys->totpart; i++, pa++) { - key = pa->hair; + for (i = 0, tpa = target_psys->particles, pa = psys->particles; + i < target_psys->totpart; + i++, tpa++, pa++) { + + float from_co[3]; + BVHTreeNearest nearest; + + if (from_global) + mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co); + else + mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co); + mul_m4_v3(from_mat, from_co); nearest.index = -1; nearest.dist_sq = FLT_MAX; - BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree); + BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); if (nearest.index == -1) { if (G.debug & G_DEBUG) @@ -697,6 +750,8 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) } if (mface) { + float v[4][3]; + mf = &mface[nearest.index]; copy_v3_v3(v[0], mvert[mf->v1].co); @@ -704,44 +759,80 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) copy_v3_v3(v[2], mvert[mf->v3].co); if (mf->v4) { copy_v3_v3(v[3], mvert[mf->v4].co); - interp_weights_poly_v3(pa->fuv, v, 4, nearest.co); + interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co); } else - interp_weights_poly_v3(pa->fuv, v, 3, nearest.co); + interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co); + tpa->foffset = 0.0f; - pa->num = nearest.index; - pa->num_dmcache = psys_particle_dm_face_lookup(ob, psmd->dm, pa->num, pa->fuv, NULL); + tpa->num = nearest.index; + tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL); } else { me = &medge[nearest.index]; - pa->fuv[1] = line_point_factor_v3(nearest.co, - mvert[me->v2].co, - mvert[me->v2].co); - pa->fuv[0] = 1.0f - pa->fuv[1]; - pa->fuv[2] = pa->fuv[3] = 0.0f; + tpa->fuv[1] = line_point_factor_v3(nearest.co, + mvert[me->v1].co, + mvert[me->v2].co); + tpa->fuv[0] = 1.0f - tpa->fuv[1]; + tpa->fuv[2] = tpa->fuv[3] = 0.0f; + tpa->foffset = 0.0f; - pa->num = nearest.index; - pa->num_dmcache = -1; + tpa->num = nearest.index; + tpa->num_dmcache = -1; } - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); - invert_m4_m4(imat, hairmat); - - sub_v3_v3v3(vec, nearest.co, key->co); - - if (point) { - ekey = point->keys; - point++; - } - - for (k=0, key=pa->hair; k<pa->totkey; k++, key++) { - add_v3_v3(key->co, vec); - mul_m4_v3(imat, key->co); - - if (ekey) { - ekey->flag |= PEK_USE_WCO; - ekey++; + /* translate hair keys */ + { + HairKey *key, *tkey; + float hairmat[4][4], imat[4][4]; + float offset[3]; + + if (to_global) + copy_m4_m4(imat, target_ob->obmat); + else { + /* note: using target_dm here, which is in target_ob object space and has full modifiers */ + psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat); + invert_m4_m4(imat, hairmat); + } + mul_m4_m4m4(imat, imat, to_imat); + + /* offset in world space */ + sub_v3_v3v3(offset, nearest.co, from_co); + + if (edit_point) { + for (k=0, key=pa->hair, tkey=tpa->hair, ekey = edit_point->keys; k<tpa->totkey; k++, key++, tkey++, ekey++) { + float co_orig[3]; + + if (from_global) + mul_v3_m4v3(co_orig, from_ob_imat, key->co); + else + mul_v3_m4v3(co_orig, from_ob_imat, key->world_co); + mul_m4_v3(from_mat, co_orig); + + add_v3_v3v3(tkey->co, co_orig, offset); + + mul_m4_v3(imat, tkey->co); + + ekey->flag |= PEK_USE_WCO; + } + + edit_point++; + } + else { + for (k=0, key=pa->hair, tkey=tpa->hair; k<tpa->totkey; k++, key++, tkey++) { + float co_orig[3]; + + if (from_global) + mul_v3_m4v3(co_orig, from_ob_imat, key->co); + else + mul_v3_m4v3(co_orig, from_ob_imat, key->world_co); + mul_m4_v3(from_mat, co_orig); + + add_v3_v3v3(tkey->co, co_orig, offset); + + mul_m4_v3(imat, tkey->co); + } } } } @@ -749,15 +840,26 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) free_bvhtree_from_mesh(&bvhtree); dm->release(dm); - psys_free_path_cache(psys, psys->edit); + psys_free_path_cache(target_psys, target_edit); - psys->flag &= ~PSYS_GLOBAL_HAIR; - - PE_update_object(scene, ob, 0); + PE_update_object(scene, target_ob, 0); return true; } +static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) +{ + bool ok; + + if (!psys) + return false; + + ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false); + psys->flag &= ~PSYS_GLOBAL_HAIR; + + return ok; +} + static int connect_hair_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); @@ -805,3 +907,284 @@ void PARTICLE_OT_connect_hair(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); } +/************************ particle system copy operator *********************/ + +typedef enum eCopyParticlesSpace { + PAR_COPY_SPACE_OBJECT = 0, + PAR_COPY_SPACE_WORLD = 1, +} eCopyParticlesSpace; + +static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from) +{ + PTCacheEdit *edit_from = psys_from->edit, *edit; + ParticleData *pa; + KEY_K; + POINT_P; + + if (!edit_from) + return; + + edit = MEM_dupallocN(edit_from); + edit->psys = psys; + psys->edit = edit; + + edit->pathcache = NULL; + BLI_listbase_clear(&edit->pathcachebufs); + + edit->emitter_field = NULL; + edit->emitter_cosnos = NULL; + + BLI_listbase_clear(&edit->undo); + edit->curundo = NULL; + + edit->points = MEM_dupallocN(edit_from->points); + pa = psys->particles; + LOOP_POINTS { + HairKey *hkey = pa->hair; + + point->keys= MEM_dupallocN(point->keys); + LOOP_KEYS { + key->co = hkey->co; + key->time = &hkey->time; + key->flag = hkey->editflag; + if (!(psys->flag & PSYS_GLOBAL_HAIR)) { + key->flag |= PEK_USE_WCO; + hkey->editflag |= PEK_USE_WCO; + } + + hkey++; + } + + pa++; + } + update_world_cos(ob, edit); + + UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); + UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); + + recalc_lengths(edit); + recalc_emitter_field(ob, psys); + PE_update_object(scene, ob, true); + + PTCacheUndo_clear(edit); + PE_undo_push(scene, "Original"); +} + +static void remove_particle_systems_from_object(Object *ob_to) +{ + ModifierData *md, *md_next; + + if (ob_to->type != OB_MESH) + return; + if (!ob_to->data || ((ID *)ob_to->data)->lib) + return; + + for (md = ob_to->modifiers.first; md; md = md_next) { + md_next = md->next; + + /* remove all particle system modifiers as well, + * these need to sync to the particle system list + */ + if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) { + BLI_remlink(&ob_to->modifiers, md); + modifier_free(md); + } + } + + BKE_object_free_particlesystems(ob_to); +} + +/* single_psys_from is optional, if NULL all psys of ob_from are copied */ +static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, ParticleSystem *single_psys_from, Object *ob_to, int space) +{ + ModifierData *md; + ParticleSystem *psys_start = NULL, *psys, *psys_from; + ParticleSystem **tmp_psys; + DerivedMesh *final_dm; + CustomDataMask cdmask; + int i, totpsys; + + if (ob_to->type != OB_MESH) + return false; + if (!ob_to->data || ((ID *)ob_to->data)->lib) + return false; + + /* For remapping we need a valid DM. + * Because the modifiers are appended at the end it's safe to use + * the final DM of the object without particles. + * However, when evaluating the DM all the particle modifiers must be valid, + * i.e. have the psys assigned already. + * To break this hen/egg problem we create all psys separately first (to collect required customdata masks), + * then create the DM, then add them to the object and make the psys modifiers ... + */ + #define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first) + #define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next) + totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem); + + tmp_psys = MEM_mallocN(sizeof(ParticleSystem*) * totpsys, "temporary particle system array"); + + cdmask = 0; + for (psys_from = PSYS_FROM_FIRST, i = 0; + psys_from; + psys_from = PSYS_FROM_NEXT(psys_from), ++i) { + + psys = BKE_object_copy_particlesystem(psys_from); + tmp_psys[i] = psys; + + if (psys_start == NULL) + psys_start = psys; + + cdmask |= psys_emitter_customdata_mask(psys); + } + /* to iterate source and target psys in sync, + * we need to know where the newly added psys start + */ + psys_start = totpsys > 0 ? tmp_psys[0] : NULL; + + /* get the DM (psys and their modifiers have not been appended yet) */ + final_dm = mesh_get_derived_final(scene, ob_to, cdmask); + + /* now append psys to the object and make modifiers */ + for (i = 0, psys_from = PSYS_FROM_FIRST; + i < totpsys; + ++i, psys_from = PSYS_FROM_NEXT(psys_from)) { + + ParticleSystemModifierData *psmd; + + psys = tmp_psys[i]; + + /* append to the object */ + BLI_addtail(&ob_to->particlesystem, psys); + + /* add a particle system modifier for each system */ + md = modifier_new(eModifierType_ParticleSystem); + psmd = (ParticleSystemModifierData *)md; + /* push on top of the stack, no use trying to reproduce old stack order */ + BLI_addtail(&ob_to->modifiers, md); + + BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i); + modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); + + psmd->psys = psys; + psmd->dm = CDDM_copy(final_dm); + CDDM_calc_normals(psmd->dm); + DM_ensure_tessface(psmd->dm); + + if (psys_from->edit) + copy_particle_edit(scene, ob_to, psys, psys_from); + } + MEM_freeN(tmp_psys); + + /* note: do this after creating DM copies for all the particle system modifiers, + * the remapping otherwise makes final_dm invalid! + */ + for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; + psys; + psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) { + + float (*from_mat)[4], (*to_mat)[4]; + + switch (space) { + case PAR_COPY_SPACE_OBJECT: + from_mat = I; + to_mat = I; + break; + case PAR_COPY_SPACE_WORLD: + from_mat = ob_from->obmat; + to_mat = ob_to->obmat; + break; + default: + /* should not happen */ + BLI_assert(false); + break; + } + + remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR); + + /* tag for recalc */ +// psys->recalc |= PSYS_RECALC_RESET; + } + + #undef PSYS_FROM_FIRST + #undef PSYS_FROM_NEXT + + DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA); + WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to); + return true; +} + +static int copy_particle_systems_poll(bContext *C) +{ + Object *ob; + if (!ED_operator_object_active_editable(C)) + return false; + + ob = ED_object_active_context(C); + if (BLI_listbase_is_empty(&ob->particlesystem)) + return false; + + return true; +} + +static int copy_particle_systems_exec(bContext *C, wmOperator *op) +{ + const int space = RNA_enum_get(op->ptr, "space"); + const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles"); + const bool use_active = RNA_boolean_get(op->ptr, "use_active"); + Scene *scene = CTX_data_scene(C); + Object *ob_from = ED_object_active_context(C); + ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL; + + int changed_tot = 0; + int fail = 0; + + CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects) + { + if (ob_from != ob_to) { + bool changed = false; + if (remove_target_particles) { + remove_particle_systems_from_object(ob_to); + changed = true; + } + if (copy_particle_systems_to_object(scene, ob_from, psys_from, ob_to, space)) + changed = true; + else + fail++; + + if (changed) + changed_tot++; + } + } + CTX_DATA_END; + + if ((changed_tot == 0 && fail == 0) || fail) { + BKE_reportf(op->reports, RPT_ERROR, + "Copy particle systems to selected: %d done, %d failed", + changed_tot, fail); + } + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot) +{ + static EnumPropertyItem space_items[] = { + {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"}, + {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"}, + {0, NULL, 0, NULL, NULL} + }; + + ot->name = "Copy Particle Systems"; + ot->description = "Copy particle systems from the active object to selected objects"; + ot->idname = "PARTICLE_OT_copy_particle_systems"; + + ot->poll = copy_particle_systems_poll; + ot->exec = copy_particle_systems_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another"); + RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects"); + RNA_def_boolean(ot->srna, "use_active", false, "Use Active", "Use the active particle system from the context"); +} diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index b53891f4880..b5adf38527b 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -72,8 +72,6 @@ #include "DNA_scene_types.h" #include "DNA_mesh_types.h" -#include "PIL_time.h" - static float get_fluid_viscosity(FluidsimSettings *settings) { diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index 77ce5a334e6..666ed2397d2 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -39,6 +39,7 @@ struct wmOperatorType; void PARTICLE_OT_select_all(struct wmOperatorType *ot); void PARTICLE_OT_select_roots(struct wmOperatorType *ot); void PARTICLE_OT_select_tips(struct wmOperatorType *ot); +void PARTICLE_OT_select_random(struct wmOperatorType *ot); void PARTICLE_OT_select_linked(struct wmOperatorType *ot); void PARTICLE_OT_select_less(struct wmOperatorType *ot); void PARTICLE_OT_select_more(struct wmOperatorType *ot); @@ -55,6 +56,8 @@ void PARTICLE_OT_mirror(struct wmOperatorType *ot); void PARTICLE_OT_brush_edit(struct wmOperatorType *ot); +void PARTICLE_OT_shape_cut(struct wmOperatorType *ot); + void PARTICLE_OT_particle_edit_toggle(struct wmOperatorType *ot); void PARTICLE_OT_edited_clear(struct wmOperatorType *ot); @@ -69,6 +72,7 @@ void PARTICLE_OT_target_move_up(struct wmOperatorType *ot); void PARTICLE_OT_target_move_down(struct wmOperatorType *ot); void PARTICLE_OT_connect_hair(struct wmOperatorType *ot); void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot); +void PARTICLE_OT_copy_particle_systems(struct wmOperatorType *ot); void PARTICLE_OT_dupliob_copy(struct wmOperatorType *ot); void PARTICLE_OT_dupliob_remove(struct wmOperatorType *ot); diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index 48cc51ffb55..c765bff796e 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -29,10 +29,6 @@ #include <stdlib.h> -#include "DNA_scene_types.h" - -#include "BLI_utildefines.h" - #include "RNA_access.h" #include "WM_api.h" @@ -51,6 +47,7 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_select_all); WM_operatortype_append(PARTICLE_OT_select_roots); WM_operatortype_append(PARTICLE_OT_select_tips); + WM_operatortype_append(PARTICLE_OT_select_random); WM_operatortype_append(PARTICLE_OT_select_linked); WM_operatortype_append(PARTICLE_OT_select_less); WM_operatortype_append(PARTICLE_OT_select_more); @@ -67,6 +64,8 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_brush_edit); + WM_operatortype_append(PARTICLE_OT_shape_cut); + WM_operatortype_append(PARTICLE_OT_particle_edit_toggle); WM_operatortype_append(PARTICLE_OT_edited_clear); @@ -81,6 +80,7 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_target_move_down); WM_operatortype_append(PARTICLE_OT_connect_hair); WM_operatortype_append(PARTICLE_OT_disconnect_hair); + WM_operatortype_append(PARTICLE_OT_copy_particle_systems); WM_operatortype_append(PARTICLE_OT_dupliob_copy); WM_operatortype_append(PARTICLE_OT_dupliob_remove); diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index dd0816e509d..85b059d5574 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -37,8 +37,6 @@ #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" -#include "BLI_math.h" - #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 13a3d7a523f..949084973cf 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -33,24 +33,19 @@ #include <stdlib.h> #include <string.h> -#include "MEM_guardedalloc.h" -#include "DNA_group_types.h" #include "DNA_object_types.h" -#include "DNA_mesh_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_group.h" -#include "BKE_object.h" #include "BKE_report.h" #include "BKE_rigidbody.h" @@ -353,6 +348,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op) if (changed) { /* send updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* done */ return OPERATOR_FINISHED; diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c index 1c893992cf2..0bd9ec5f4cd 100644 --- a/source/blender/editors/physics/rigidbody_world.c +++ b/source/blender/editors/physics/rigidbody_world.c @@ -37,8 +37,6 @@ #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" -#include "BLI_math.h" - #ifdef WITH_BULLET # include "RBI_api.h" #endif @@ -48,8 +46,6 @@ #include "BKE_rigidbody.h" #include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -171,7 +167,7 @@ static int rigidbody_world_export_exec(bContext *C, wmOperator *op) static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!RNA_struct_property_is_set(op->ptr, "relative_path")) - RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS)); + RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS) != 0); if (RNA_struct_property_is_set(op->ptr, "filepath")) return rigidbody_world_export_exec(C, op); @@ -199,5 +195,5 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - WM_operator_properties_filesel(ot, FOLDERFILE, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY); + WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); } |