~ubuntu-branches/ubuntu/trusty/blender/trusty-proposed

« back to all changes in this revision

Viewing changes to source/blender/editors/physics/rigidbody_object.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2013-08-14 10:43:49 UTC
  • mfrom: (14.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20130814104349-t1d5mtwkphp12dyj
Tags: 2.68a-3
* Upload to unstable
* debian/: python3.3 Depends simplified
  - debian/control: python3.3 Depends dropped
    for blender-data package
  - 0001-blender_thumbnailer.patch refreshed
* debian/control: libavcodec b-dep versioning dropped

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
#include "BLI_blenlib.h"
45
45
#include "BLI_math.h"
46
46
 
 
47
#include "BLF_translation.h"
 
48
 
47
49
#include "BKE_context.h"
48
50
#include "BKE_depsgraph.h"
49
51
#include "BKE_global.h"
59
61
#include "WM_api.h"
60
62
#include "WM_types.h"
61
63
 
 
64
#include "ED_object.h"
62
65
#include "ED_physics.h"
63
66
#include "ED_screen.h"
64
67
 
70
73
static int ED_operator_rigidbody_active_poll(bContext *C)
71
74
{
72
75
        if (ED_operator_object_active_editable(C)) {
73
 
                Object *ob = CTX_data_active_object(C);
 
76
                Object *ob = ED_object_active_context(C);
74
77
                return (ob && ob->rigidbody_object);
75
78
        }
76
79
        else
77
80
                return 0;
78
81
}
79
82
 
80
 
static int ED_operator_rigidbody_add_poll(bContext *C)
81
 
{
82
 
        if (ED_operator_object_active_editable(C)) {
83
 
                Object *ob = CTX_data_active_object(C);
84
 
                return (ob && ob->type == OB_MESH);
85
 
        }
86
 
        else
87
 
                return 0;
88
 
}
89
 
 
90
83
/* ----------------- */
91
84
 
92
 
void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type)
 
85
bool ED_rigidbody_object_add(Scene *scene, Object *ob, int type, ReportList *reports)
93
86
{
94
87
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
95
88
 
96
89
        if (ob->type != OB_MESH) {
97
 
                BKE_report(op->reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
98
 
                return;
 
90
                BKE_report(reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
 
91
                return false;
99
92
        }
100
93
        if (((Mesh *)ob->data)->totpoly == 0) {
101
 
                BKE_report(op->reports, RPT_ERROR, "Can't create Rigid Body from mesh with no polygons");
102
 
                return;
 
94
                BKE_report(reports, RPT_ERROR, "Can't create Rigid Body from mesh with no polygons");
 
95
                return false;
103
96
        }
104
97
 
105
98
        /* Add rigid body world and group if they don't exist for convenience */
106
99
        if (rbw == NULL) {
107
100
                rbw = BKE_rigidbody_create_world(scene);
 
101
                if (rbw == NULL) {
 
102
                        BKE_report(reports, RPT_ERROR, "Can't create Rigid Body world");
 
103
                        return false;
 
104
                }
108
105
                BKE_rigidbody_validate_sim_world(scene, rbw, false);
109
106
                scene->rigidbody_world = rbw;
110
107
        }
111
108
        if (rbw->group == NULL) {
112
 
                rbw->group = add_group(G.main, "RigidBodyWorld");
 
109
                rbw->group = BKE_group_add(G.main, "RigidBodyWorld");
113
110
        }
114
111
 
115
112
        /* make rigidbody object settings */
120
117
        ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
121
118
 
122
119
        /* add object to rigid body group */
123
 
        add_to_group(rbw->group, ob, scene, NULL);
 
120
        BKE_group_object_add(rbw->group, ob, scene, NULL);
124
121
 
125
122
        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 
123
 
 
124
        return true;
126
125
}
127
126
 
128
 
void ED_rigidbody_ob_remove(Scene *scene, Object *ob)
 
127
void ED_rigidbody_object_remove(Scene *scene, Object *ob)
129
128
{
130
129
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
131
130
 
132
131
        BKE_rigidbody_remove_object(scene, ob);
133
132
        if (rbw)
134
 
                rem_from_group(rbw->group, ob, scene, NULL);
 
133
                BKE_group_object_unlink(rbw->group, ob, scene, NULL);
135
134
 
136
135
        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
137
136
}
141
140
 
142
141
/* ************ Add Rigid Body ************** */
143
142
 
144
 
static int rigidbody_ob_add_exec(bContext *C, wmOperator *op)
 
143
static int rigidbody_object_add_exec(bContext *C, wmOperator *op)
145
144
{
146
145
        Scene *scene = CTX_data_scene(C);
147
 
        Object *ob = (scene) ? OBACT : NULL;
 
146
        Object *ob = ED_object_active_context(C);
148
147
        int type = RNA_enum_get(op->ptr, "type");
 
148
        bool change;
149
149
 
150
150
        /* apply to active object */
151
 
        ED_rigidbody_ob_add(op, scene, ob, type);
152
 
 
153
 
        /* send updates */
154
 
        DAG_ids_flush_update(CTX_data_main(C), 0);
155
 
 
156
 
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
157
 
 
158
 
        /* done */
159
 
        return OPERATOR_FINISHED;
 
151
        change = ED_rigidbody_object_add(scene, ob, type, op->reports);
 
152
 
 
153
        if (change) {
 
154
                /* send updates */
 
155
                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
156
                WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
 
157
 
 
158
                /* done */
 
159
                return OPERATOR_FINISHED;
 
160
        }
 
161
        else {
 
162
                return OPERATOR_CANCELLED;
 
163
        }
160
164
}
161
165
 
162
166
void RIGIDBODY_OT_object_add(wmOperatorType *ot)
167
171
        ot->description = "Add active object as Rigid Body";
168
172
 
169
173
        /* callbacks */
170
 
        ot->exec = rigidbody_ob_add_exec;
171
 
        ot->poll = ED_operator_rigidbody_add_poll;
 
174
        ot->exec = rigidbody_object_add_exec;
 
175
        ot->poll = ED_operator_object_active_editable_mesh;
172
176
 
173
177
        /* flags */
174
178
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
175
179
 
176
180
        /* properties */
177
 
        ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
 
181
        ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_object_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
178
182
}
179
183
 
180
184
/* ************ Remove Rigid Body ************** */
181
185
 
182
 
static int rigidbody_ob_remove_exec(bContext *C, wmOperator *op)
 
186
static int rigidbody_object_remove_exec(bContext *C, wmOperator *op)
183
187
{
184
188
        Scene *scene = CTX_data_scene(C);
185
 
        Object *ob = (scene) ? OBACT : NULL;
186
 
 
187
 
        /* sanity checks */
188
 
        if (scene == NULL)
189
 
                return OPERATOR_CANCELLED;
 
189
        Object *ob = ED_object_active_context(C);
 
190
        bool change = false;
190
191
 
191
192
        /* apply to active object */
192
 
        if (ELEM(NULL, ob, ob->rigidbody_object)) {
 
193
        if (!ELEM(NULL, ob, ob->rigidbody_object)) {
 
194
                ED_rigidbody_object_remove(scene, ob);
 
195
                change = true;
 
196
        }
 
197
 
 
198
        if (change) {
 
199
                /* send updates */
 
200
                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
201
                WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
 
202
 
 
203
                /* done */
 
204
                return OPERATOR_FINISHED;
 
205
        }
 
206
        else {
193
207
                BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
194
208
                return OPERATOR_CANCELLED;
195
209
        }
196
 
        else
197
 
                ED_rigidbody_ob_remove(scene, ob);
198
 
 
199
 
        /* send updates */
200
 
        DAG_ids_flush_update(CTX_data_main(C), 0);
201
 
 
202
 
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
203
 
 
204
 
        /* done */
205
 
        return OPERATOR_FINISHED;
206
210
}
207
211
 
208
212
void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
213
217
        ot->description = "Remove Rigid Body settings from Object";
214
218
 
215
219
        /* callbacks */
216
 
        ot->exec = rigidbody_ob_remove_exec;
 
220
        ot->exec = rigidbody_object_remove_exec;
217
221
        ot->poll = ED_operator_rigidbody_active_poll;
218
222
 
219
223
        /* flags */
225
229
 
226
230
/* ************ Add Rigid Bodies ************** */
227
231
 
228
 
static int rigidbody_obs_add_exec(bContext *C, wmOperator *op)
 
232
static int rigidbody_objects_add_exec(bContext *C, wmOperator *op)
229
233
{
230
234
        Scene *scene = CTX_data_scene(C);
231
235
        int type = RNA_enum_get(op->ptr, "type");
 
236
        bool change = false;
232
237
 
233
 
        /* sanity check */
234
 
        if (scene == NULL) {
235
 
                BKE_report(op->reports, RPT_ERROR, "No Scene to add Rigid Bodies to");
236
 
                return OPERATOR_CANCELLED;
237
 
        }
238
238
        /* create rigid body objects and add them to the world's group */
239
239
        CTX_DATA_BEGIN(C, Object *, ob, selected_objects) {
240
 
                ED_rigidbody_ob_add(op, scene, ob, type);
 
240
                change |= ED_rigidbody_object_add(scene, ob, type, op->reports);
241
241
        }
242
242
        CTX_DATA_END;
243
243
 
244
 
        /* send updates */
245
 
        DAG_ids_flush_update(CTX_data_main(C), 0);
246
 
 
247
 
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
248
 
        WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
249
 
 
250
 
        /* done */
251
 
        return OPERATOR_FINISHED;
 
244
        if (change) {
 
245
                /* send updates */
 
246
                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
247
                WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
 
248
 
 
249
                /* done */
 
250
                return OPERATOR_FINISHED;
 
251
        }
 
252
        else {
 
253
                return OPERATOR_CANCELLED;
 
254
        }
252
255
}
253
256
 
254
257
void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
259
262
        ot->description = "Add selected objects as Rigid Bodies";
260
263
 
261
264
        /* callbacks */
262
 
        ot->exec = rigidbody_obs_add_exec;
263
 
        ot->poll = ED_operator_rigidbody_add_poll;
 
265
        ot->exec = rigidbody_objects_add_exec;
 
266
        ot->poll = ED_operator_object_active_editable_mesh;
264
267
 
265
268
        /* flags */
266
269
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
267
270
 
268
271
        /* properties */
269
 
        ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
 
272
        ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_object_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
270
273
}
271
274
 
272
275
/* ************ Remove Rigid Bodies ************** */
273
276
 
274
 
static int rigidbody_obs_remove_exec(bContext *C, wmOperator *UNUSED(op))
 
277
static int rigidbody_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
275
278
{
276
279
        Scene *scene = CTX_data_scene(C);
277
 
 
278
 
        /* sanity checks */
279
 
        if (scene == NULL)
280
 
                return OPERATOR_CANCELLED;
 
280
        bool change = false;
281
281
 
282
282
        /* apply this to all selected objects... */
283
283
        CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
284
284
        {
285
285
                if (ob->rigidbody_object) {
286
 
                        ED_rigidbody_ob_remove(scene, ob);
 
286
                        ED_rigidbody_object_remove(scene, ob);
 
287
                        change = true;
287
288
                }
288
289
        }
289
290
        CTX_DATA_END;
290
291
 
291
 
        /* send updates */
292
 
        DAG_ids_flush_update(CTX_data_main(C), 0);
293
 
 
294
 
        WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
295
 
 
296
 
        /* done */
297
 
        return OPERATOR_FINISHED;
 
292
        if (change) {
 
293
                /* send updates */
 
294
                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
 
295
                WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
 
296
 
 
297
                /* done */
 
298
                return OPERATOR_FINISHED;
 
299
        }
 
300
        else {
 
301
                return OPERATOR_CANCELLED;
 
302
        }
298
303
}
299
304
 
300
305
void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
305
310
        ot->description = "Remove selected objects from Rigid Body simulation";
306
311
 
307
312
        /* callbacks */
308
 
        ot->exec = rigidbody_obs_remove_exec;
309
 
        ot->poll = ED_operator_rigidbody_active_poll;
 
313
        ot->exec = rigidbody_objects_remove_exec;
 
314
        ot->poll = ED_operator_scene_editable;
310
315
 
311
316
        /* flags */
312
317
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
317
322
 
318
323
/* ************ Change Collision Shapes ************** */
319
324
 
320
 
static int rigidbody_obs_shape_change_exec(bContext *C, wmOperator *op)
 
325
static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
321
326
{
322
 
        Scene *scene = CTX_data_scene(C);
323
327
        int shape = RNA_enum_get(op->ptr, "type");
324
 
 
325
 
        /* sanity checks */
326
 
        if (scene == NULL)
327
 
                return OPERATOR_CANCELLED;
 
328
        bool change = false;
328
329
 
329
330
        /* apply this to all selected objects... */
330
331
        CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
337
338
                        RNA_enum_set(&ptr, "collision_shape", shape);
338
339
 
339
340
                        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 
341
 
 
342
                        change = true;
340
343
                }
341
344
        }
342
345
        CTX_DATA_END;
343
346
 
344
 
        /* send updates */
345
 
        WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
 
347
        if (change) {
 
348
                /* send updates */
 
349
                WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
346
350
 
347
 
        /* done */
348
 
        return OPERATOR_FINISHED;
 
351
                /* done */
 
352
                return OPERATOR_FINISHED;
 
353
        }
 
354
        else {
 
355
                return OPERATOR_CANCELLED;
 
356
        }
349
357
}
350
358
 
351
359
void RIGIDBODY_OT_shape_change(wmOperatorType *ot)
357
365
 
358
366
        /* callbacks */
359
367
        ot->invoke = WM_menu_invoke;
360
 
        ot->exec = rigidbody_obs_shape_change_exec;
361
 
        ot->poll = ED_operator_rigidbody_active_poll;
 
368
        ot->exec = rigidbody_objects_shape_change_exec;
 
369
        ot->poll = ED_operator_scene_editable;
362
370
 
363
371
        /* flags */
364
372
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
365
373
 
366
374
        /* properties */
367
 
        ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", "");
 
375
        ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_object_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", "");
368
376
}
369
377
 
370
378
/* ************ Calculate Mass ************** */
382
390
 * 3) http://www.avlandesign.com/density_metal.htm
383
391
 */
384
392
static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = {
385
 
        {"Air", 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
386
 
        {"Acrylic", 1400.0f},
387
 
        {"Asphalt (Crushed)", 721.0f},
388
 
        {"Bark", 240.0f},
389
 
        {"Beans (Cocoa)", 593.0f},
390
 
        {"Beans (Soy)", 721.0f},
391
 
        {"Brick (Pressed)", 2400.0f},
392
 
        {"Brick (Common)", 2000.0f},
393
 
        {"Brick (Soft)", 1600.0f},
394
 
        {"Brass", 8216.0f},
395
 
        {"Bronze", 8860.0f},
396
 
        {"Carbon (Solid)", 2146.0f},
397
 
        {"Cardboard", 689.0f},
398
 
        {"Cast Iron", 7150.0f},
399
 
        //{"Cement", 1442.0f},
400
 
        {"Chalk (Solid)", 2499.0f},
401
 
        //{"Coffee (Fresh/Roast)", ~500},
402
 
        {"Concrete", 2320.0f},
403
 
        {"Charcoal", 208.0f},
404
 
        {"Cork", 240.0f},
405
 
        {"Copper", 8933.0f},
406
 
        {"Garbage", 481.0f},
407
 
        {"Glass (Broken)", 1940.0f},
408
 
        {"Glass (Solid)", 2190.0f},
409
 
        {"Gold", 19282.0f},
410
 
        {"Granite (Broken)", 1650.0f},
411
 
        {"Granite (Solid)", 2691.0f},
412
 
        {"Gravel", 2780.0f},
413
 
        {"Ice (Crushed)", 593.0f},
414
 
        {"Ice (Solid)", 919.0f},
415
 
        {"Iron", 7874.0f},
416
 
        {"Lead", 11342.0f},
417
 
        {"Limestone (Broken)", 1554.0f},
418
 
        {"Limestone (Solid)", 2611.0f},
419
 
        {"Marble (Broken)", 1570.0f},
420
 
        {"Marble (Solid)", 2563.0f},
421
 
        {"Paper", 1201.0f},
422
 
        {"Peanuts (Shelled)", 641.0f},
423
 
        {"Peanuts (Not Shelled)", 272.0f},
424
 
        {"Plaster", 849.0f},
425
 
        {"Plastic", 1200.0f},
426
 
        {"Polystyrene", 1050.0f},
427
 
        {"Rubber", 1522.0f},
428
 
        {"Silver", 10501.0f},
429
 
        {"Steel", 7860.0f},
430
 
        {"Stone", 2515.0f},
431
 
        {"Stone (Crushed)", 1602.0f},
432
 
        {"Timber", 610.0f}
 
393
        {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
 
394
        {N_("Acrylic"), 1400.0f},
 
395
        {N_("Asphalt (Crushed)"), 721.0f},
 
396
        {N_("Bark"), 240.0f},
 
397
        {N_("Beans (Cocoa)"), 593.0f},
 
398
        {N_("Beans (Soy)"), 721.0f},
 
399
        {N_("Brick (Pressed)"), 2400.0f},
 
400
        {N_("Brick (Common)"), 2000.0f},
 
401
        {N_("Brick (Soft)"), 1600.0f},
 
402
        {N_("Brass"), 8216.0f},
 
403
        {N_("Bronze"), 8860.0f},
 
404
        {N_("Carbon (Solid)"), 2146.0f},
 
405
        {N_("Cardboard"), 689.0f},
 
406
        {N_("Cast Iron"), 7150.0f},
 
407
        /* {N_("Cement"), 1442.0f}, */
 
408
        {N_("Chalk (Solid)"), 2499.0f},
 
409
        /* {N_("Coffee (Fresh/Roast)"), ~500}, */
 
410
        {N_("Concrete"), 2320.0f},
 
411
        {N_("Charcoal"), 208.0f},
 
412
        {N_("Cork"), 240.0f},
 
413
        {N_("Copper"), 8933.0f},
 
414
        {N_("Garbage"), 481.0f},
 
415
        {N_("Glass (Broken)"), 1940.0f},
 
416
        {N_("Glass (Solid)"), 2190.0f},
 
417
        {N_("Gold"), 19282.0f},
 
418
        {N_("Granite (Broken)"), 1650.0f},
 
419
        {N_("Granite (Solid)"), 2691.0f},
 
420
        {N_("Gravel"), 2780.0f},
 
421
        {N_("Ice (Crushed)"), 593.0f},
 
422
        {N_("Ice (Solid)"), 919.0f},
 
423
        {N_("Iron"), 7874.0f},
 
424
        {N_("Lead"), 11342.0f},
 
425
        {N_("Limestone (Broken)"), 1554.0f},
 
426
        {N_("Limestone (Solid)"), 2611.0f},
 
427
        {N_("Marble (Broken)"), 1570.0f},
 
428
        {N_("Marble (Solid)"), 2563.0f},
 
429
        {N_("Paper"), 1201.0f},
 
430
        {N_("Peanuts (Shelled)"), 641.0f},
 
431
        {N_("Peanuts (Not Shelled)"), 272.0f},
 
432
        {N_("Plaster"), 849.0f},
 
433
        {N_("Plastic"), 1200.0f},
 
434
        {N_("Polystyrene"), 1050.0f},
 
435
        {N_("Rubber"), 1522.0f},
 
436
        {N_("Silver"), 10501.0f},
 
437
        {N_("Steel"), 7860.0f},
 
438
        {N_("Stone"), 2515.0f},
 
439
        {N_("Stone (Crushed)"), 1602.0f},
 
440
        {N_("Timber"), 610.0f}
433
441
};
434
442
static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem);
435
443
 
436
444
 
437
445
/* dynamically generate list of items
438
446
 * - Although there is a runtime cost, this has a lower maintenance cost
439
 
 *       in the long run than other two-list solutions...
 
447
 *   in the long run than other two-list solutions...
440
448
 */
441
449
static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
442
450
{
449
457
        for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
450
458
                rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i];
451
459
 
452
 
                item_tmp.identifier = item_tmp.name = preset->name;
 
460
                item_tmp.identifier = preset->name;
 
461
                item_tmp.name = IFACE_(preset->name);
453
462
                item_tmp.value = i;
454
463
                RNA_enum_item_add(&item, &totitem, &item_tmp);
455
464
        }
456
465
 
457
466
        /* add special "custom" entry to the end of the list */
458
467
        {
459
 
                item_tmp.identifier = item_tmp.name = "Custom";
 
468
                item_tmp.identifier = "Custom";
 
469
                item_tmp.name = IFACE_("Custom");
460
470
                item_tmp.value = -1;
461
471
                RNA_enum_item_add(&item, &totitem, &item_tmp);
462
472
        }
471
481
 
472
482
/* helper function to calculate volume of rigidbody object */
473
483
// TODO: allow a parameter to specify method used to calculate this?
474
 
static float calc_rigidbody_ob_volume(Object *ob)
 
484
static float rigidbody_object_calc_volume(Object *ob)
475
485
{
476
486
        RigidBodyOb *rbo = ob->rigidbody_object;
477
487
 
541
551
 
542
552
/* ------------------------------------------ */
543
553
 
544
 
static int rigidbody_obs_calc_mass_exec(bContext *C, wmOperator *op)
 
554
static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
545
555
{
546
 
        Scene *scene = CTX_data_scene(C);
547
556
        int material = RNA_enum_get(op->ptr, "material");
548
557
        float density;
549
 
 
550
 
        /* sanity checks */
551
 
        if (scene == NULL)
552
 
                return OPERATOR_CANCELLED;
 
558
        bool change = false;
553
559
 
554
560
        /* get density (kg/m^3) to apply */
555
561
        if (material >= 0) {
577
583
                        /* mass is calculated from the approximate volume of the object,
578
584
                         * and the density of the material we're simulating
579
585
                         */
580
 
                        volume = calc_rigidbody_ob_volume(ob);
 
586
                        volume = rigidbody_object_calc_volume(ob);
581
587
                        mass = volume * density;
582
588
 
583
589
                        /* use RNA-system to change the property and perform all necessary changes */
585
591
                        RNA_float_set(&ptr, "mass", mass);
586
592
 
587
593
                        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 
594
 
 
595
                        change = true;
588
596
                }
589
597
        }
590
598
        CTX_DATA_END;
591
599
 
592
 
        /* send updates */
593
 
        WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
 
600
        if (change) {
 
601
                /* send updates */
 
602
                WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
594
603
 
595
 
        /* done */
596
 
        return OPERATOR_FINISHED;
 
604
                /* done */
 
605
                return OPERATOR_FINISHED;
 
606
        }
 
607
        else {
 
608
                return OPERATOR_CANCELLED;
 
609
        }
597
610
}
598
611
 
599
612
void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
607
620
 
608
621
        /* callbacks */
609
622
        ot->invoke = WM_menu_invoke; // XXX
610
 
        ot->exec = rigidbody_obs_calc_mass_exec;
611
 
        ot->poll = ED_operator_rigidbody_active_poll;
 
623
        ot->exec = rigidbody_objects_calc_mass_exec;
 
624
        ot->poll = ED_operator_scene_editable;
612
625
 
613
626
        /* flags */
614
627
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;