diff options
-rw-r--r-- | release/ui/buttons_physics_softbody.py | 48 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_softbody.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/softbody.c | 156 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh.c | 2 | ||||
-rw-r--r-- | source/blender/editors/physics/ed_pointcache.c | 110 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 12 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object_force.c | 28 |
8 files changed, 282 insertions, 84 deletions
diff --git a/release/ui/buttons_physics_softbody.py b/release/ui/buttons_physics_softbody.py index 80e11f92d6b..bff9b13f464 100644 --- a/release/ui/buttons_physics_softbody.py +++ b/release/ui/buttons_physics_softbody.py @@ -51,7 +51,54 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel): col.itemL(text="Simulation:") col.itemR(softbody, "gravity") col.itemR(softbody, "speed") + +class PHYSICS_PT_softbody_cache(PhysicButtonsPanel): + __label__ = "Soft Body Cache" + __default_closed__ = True + + def poll(self, context): + return (context.soft_body) + + def draw(self, context): + layout = self.layout + + cache = context.soft_body.point_cache + + row = layout.row() + row.itemR(cache, "name") + + row = layout.row() + row.itemR(cache, "start_frame") + row.itemR(cache, "end_frame") + + row = layout.row() + + if cache.baked == True: + row.itemO("ptcache.free_bake_softbody", text="Free Bake") + else: + row.item_booleanO("ptcache.cache_softbody", "bake", True, text="Bake") + + sub = row.row() + sub.enabled = cache.frames_skipped or cache.outdated + sub.itemO("ptcache.cache_softbody", text="Calculate to Current Frame") + + row = layout.row() + row.itemO("ptcache.bake_from_softbody_cache", text="Current Cache to Bake") + row.itemR(cache, "step"); + row = layout.row() + row.itemR(cache, "quick_cache") + row.itemR(cache, "disk_cache") + + layout.itemL(text=cache.info) + + layout.itemS() + + row = layout.row() + row.itemO("ptcache.bake_all", "bake", True, text="Bake All Dynamics") + row.itemO("ptcache.free_bake_all", text="Free All Bakes") + layout.itemO("ptcache.bake_all", text="Update All Dynamics to current frame") + class PHYSICS_PT_softbody_goal(PhysicButtonsPanel): __label__ = "Soft Body Goal" @@ -211,6 +258,7 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel): layout.itemR(softbody, "diagnose") bpy.types.register(PHYSICS_PT_softbody) +bpy.types.register(PHYSICS_PT_softbody_cache) bpy.types.register(PHYSICS_PT_softbody_goal) bpy.types.register(PHYSICS_PT_softbody_edge) bpy.types.register(PHYSICS_PT_softbody_collision) diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 971ac7a5f01..0d9682cf842 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -69,7 +69,7 @@ extern void sbObjectToSoftbody(struct Object *ob); extern void sbSetInterruptCallBack(int (*f)(void)); /* writing to cache for bake editing */ -extern void sbWriteCache(struct Object *ob, int framenr); +extern void softbody_write_cache(struct Object *ob, struct SoftBody *soft, int cfra); #endif diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 4bb571aa8ca..beb72c2c13f 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -310,7 +310,7 @@ int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot) static int ptcache_pid_elemsize(PTCacheID *pid) { if(pid->type==PTCACHE_TYPE_SOFTBODY) - return 0; // TODO + return 6 * sizeof(float); else if(pid->type==PTCACHE_TYPE_PARTICLES) return sizeof(ParticleKey); else if(pid->type==PTCACHE_TYPE_CLOTH) @@ -320,8 +320,10 @@ static int ptcache_pid_elemsize(PTCacheID *pid) } static int ptcache_pid_totelem(PTCacheID *pid) { - if(pid->type==PTCACHE_TYPE_SOFTBODY) - return 0; // TODO + if(pid->type==PTCACHE_TYPE_SOFTBODY) { + SoftBody *soft = pid->data; + return soft->totpoint; + } else if(pid->type==PTCACHE_TYPE_PARTICLES) { ParticleSystem *psys = pid->data; return psys->totpart; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index fe63585ae1c..0a1963c84f2 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3687,64 +3687,85 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, } } -void sbWriteCache(Object *ob, int framenr) +static void softbody_write_state(int index, void *soft_v, float *data) { - SoftBody *sb= ob->soft; - BodyPoint *bp; - PTCacheID pid; - PTCacheFile *pf; - int a; + SoftBody *soft= soft_v; + BodyPoint *bp = soft->bpoint + index; - if(sb->totpoint == 0) - return; + memcpy(data, bp->pos, 3 * sizeof(float)); + memcpy(data + 3, bp->vec, 3 * sizeof(float)); +} +static void softbody_read_state(int index, void *soft_v, float *data) +{ + SoftBody *soft= soft_v; + BodyPoint *bp = soft->bpoint + index; + + memcpy(bp->pos, data, 3 * sizeof(float)); + memcpy(bp->vec, data + 3, 3 * sizeof(float)); +} +static void softbody_cache_interpolate(int index, void *soft_v, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2) +{ + SoftBody *soft= soft_v; + BodyPoint *bp = soft->bpoint + index; + ParticleKey keys[4]; + float dfra; - BKE_ptcache_id_from_softbody(&pid, ob, sb); - pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr); - if(!pf) + if(cfra1 == cfra2) { + softbody_read_state(index, soft, data1); return; - - for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) - BKE_ptcache_file_write_floats(pf, bp->pos, 3); + } - for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) - BKE_ptcache_file_write_floats(pf, bp->vec, 3); + memcpy(keys[1].co, data1, 3 * sizeof(float)); + memcpy(keys[1].vel, data1 + 3, 3 * sizeof(float)); - BKE_ptcache_file_close(pf); -} + memcpy(keys[2].co, data2, 3 * sizeof(float)); + memcpy(keys[2].vel, data2 + 3, 3 * sizeof(float)); + + dfra = cfra2 - cfra1; + + VecMulf(keys[1].vel, dfra); + VecMulf(keys[2].vel, dfra); + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); -static int softbody_read_cache(Object *ob, float framenr) + VecMulf(keys->vel, 1.0f / dfra); + + memcpy(bp->pos, keys->co, 3 * sizeof(float)); + memcpy(bp->vec, keys->vel, 3 * sizeof(float)); +} +void softbody_write_cache(Object *ob, SoftBody *soft, int cfra) { - SoftBody *sb= ob->soft; - BodyPoint *bp; + PTCacheWriter writer; PTCacheID pid; - PTCacheFile *pf; - int a; - - if(sb->totpoint == 0) - return 0; - - BKE_ptcache_id_from_softbody(&pid, ob, sb); - pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr); - if(!pf) - return 0; - for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) { - if(!BKE_ptcache_file_read_floats(pf, bp->pos, 3)) { - BKE_ptcache_file_close(pf); - return 0; - } - } + BKE_ptcache_id_from_softbody(&pid, ob, soft); - for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) { - if(!BKE_ptcache_file_read_floats(pf, bp->vec, 3)) { - BKE_ptcache_file_close(pf); - return 0; - } - } + writer.calldata = soft; + writer.cfra = cfra; + writer.set_elem = softbody_write_state; + writer.pid = &pid; + writer.totelem = soft->totpoint; - BKE_ptcache_file_close(pf); + BKE_ptcache_write_cache(&writer); +} - return 1; +int softbody_read_cache(Scene *scene, Object *ob, SoftBody *soft, float cfra, int *old_framenr) +{ + PTCacheReader reader; + PTCacheID pid; + + BKE_ptcache_id_from_softbody(&pid, ob, soft); + + reader.calldata = soft; + reader.cfra = cfra; + reader.interpolate_elem = softbody_cache_interpolate; + reader.old_frame = old_framenr; + reader.pid = &pid; + reader.scene = scene; + reader.set_elem = softbody_read_state; + reader.totelem = soft->totpoint; + + return BKE_ptcache_read_cache(&reader); } /* +++ ************ maintaining scratch *************** */ @@ -4114,6 +4135,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i PTCacheID pid; float dtime, timescale; int framedelta, framenr, startframe, endframe; + int cache_result, old_framenr; cache= sb->pointcache; @@ -4128,7 +4150,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(sb->bpoint && numVerts != sb->totpoint) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; - + cache->last_exact= 0; return; } @@ -4136,6 +4158,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(framenr < startframe) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; + cache->last_exact= 0; return; } @@ -4198,26 +4221,36 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i } /* try to read from cache */ - if(softbody_read_cache(ob, framenr)) { - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, sb->local); + cache_result = softbody_read_cache(scene, ob, sb, framenr, &old_framenr); + if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; + if(sb->particles==0) + softbody_to_object(ob, vertexCos, numVerts, sb->local); + return; } + else if(cache_result==PTCACHE_READ_OLD) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= old_framenr; + } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { /* if baked and nothing in cache, do nothing */ - if(cache->flag & PTCACHE_SIMULATION_VALID) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - } - + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; return; } if(framenr == startframe) { + if(cache->flag & PTCACHE_REDO_NEEDED) { + softbody_update_positions(ob, sb, vertexCos, numVerts); + softbody_reset(ob, sb, vertexCos, numVerts); + cache->flag &= ~PTCACHE_REDO_NEEDED; + } /* first frame, no simulation to do, just set the positions */ softbody_update_positions(ob, sb, vertexCos, numVerts); @@ -4227,10 +4260,10 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i /* don't write cache on first frame, but on second frame write * cache for frame 1 and 2 */ } - else if(framedelta == 1) { + else { /* if on second frame, write cache for first frame */ - if(framenr == startframe+1) - sbWriteCache(ob, startframe); + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + softbody_write_cache(ob, sb, startframe); softbody_update_positions(ob, sb, vertexCos, numVerts); @@ -4246,14 +4279,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(sb->particles==0) softbody_to_object(ob, vertexCos, numVerts, 0); - sbWriteCache(ob, framenr); - } - else { - /* time step backwards or too large forward - do nothing */ - if(cache->flag & PTCACHE_SIMULATION_VALID) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - } + softbody_write_cache(ob, sb, framenr); } } diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c index 6c66ae468fa..e32dd0e8ac7 100644 --- a/source/blender/editors/mesh/editmesh.c +++ b/source/blender/editors/mesh/editmesh.c @@ -1160,7 +1160,7 @@ void load_editMesh(Scene *scene, Object *ob) if(pid.type == PTCACHE_TYPE_CLOTH) cloth_write_cache(ob, pid.data, pid.cache->editframe); else if(pid.type == PTCACHE_TYPE_SOFTBODY) - sbWriteCache(ob, pid.cache->editframe); + softbody_write_cache(ob, pid.data, pid.cache->editframe); } /* the edges */ diff --git a/source/blender/editors/physics/ed_pointcache.c b/source/blender/editors/physics/ed_pointcache.c index 4bf6612df67..5d0a6d21fac 100644 --- a/source/blender/editors/physics/ed_pointcache.c +++ b/source/blender/editors/physics/ed_pointcache.c @@ -146,6 +146,113 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/**************************** softbody **********************************/ +static int ptcache_bake_softbody_poll(bContext *C) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + SoftBody *sb = ob->soft; + + if(!scene || !ob || ob->id.lib || !sb) + return 0; + + return 1; +} + +static int ptcache_bake_softbody_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + SoftBody *sb = ob->soft; + PTCacheID pid; + PTCacheBaker baker; + + BKE_ptcache_id_from_softbody(&pid, ob, sb); + + baker.scene = scene; + baker.pid = &pid; + baker.bake = RNA_boolean_get(op->ptr, "bake"); + baker.render = 0; + baker.anim_init = 0; + baker.quick_step = 1; + baker.break_test = cache_break_test; + baker.break_data = NULL; + baker.progressbar = (void (*)(void *, int))WM_timecursor; + baker.progresscontext = CTX_wm_window(C); + + BKE_ptcache_make_cache(&baker); + + WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); + + return OPERATOR_FINISHED; +} +static int ptcache_free_bake_softbody_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + SoftBody *sb = ob->soft; + PTCacheID pid; + + BKE_ptcache_id_from_softbody(&pid, ob, sb); + pid.cache->flag &= ~PTCACHE_BAKED; + + WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); + + return OPERATOR_FINISHED; +} +void PTCACHE_OT_cache_softbody(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bake Softbody"; + ot->idname= "PTCACHE_OT_cache_softbody"; + + /* api callbacks */ + ot->exec= ptcache_bake_softbody_exec; + ot->poll= ptcache_bake_softbody_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "bake", 0, "Bake", ""); +} +void PTCACHE_OT_free_bake_softbody(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Free SoftBody Bake"; + ot->idname= "PTCACHE_OT_free_bake_softbody"; + + /* api callbacks */ + ot->exec= ptcache_free_bake_softbody_exec; + ot->poll= ptcache_bake_softbody_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} +static int ptcache_bake_from_softbody_cache_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_active_object(C); + SoftBody *sb = ob->soft; + PTCacheID pid; + + BKE_ptcache_id_from_softbody(&pid, ob, sb); + pid.cache->flag |= PTCACHE_BAKED; + + return OPERATOR_FINISHED; +} +void PTCACHE_OT_bake_from_softbody_cache(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bake From Cache"; + ot->idname= "PTCACHE_OT_bake_from_softbody_cache"; + + /* api callbacks */ + ot->exec= ptcache_bake_from_softbody_cache_exec; + ot->poll= ptcache_bake_softbody_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /**************************** cloth **********************************/ static int ptcache_bake_cloth_poll(bContext *C) { @@ -371,6 +478,9 @@ void ED_operatortypes_pointcache(void) WM_operatortype_append(PTCACHE_OT_cache_cloth); WM_operatortype_append(PTCACHE_OT_free_bake_cloth); WM_operatortype_append(PTCACHE_OT_bake_from_cloth_cache); + WM_operatortype_append(PTCACHE_OT_cache_softbody); + WM_operatortype_append(PTCACHE_OT_free_bake_softbody); + WM_operatortype_append(PTCACHE_OT_bake_from_softbody_cache); } //void ED_keymap_pointcache(wmWindowManager *wm) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 5192e2df611..80bc46bb2f0 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -34,6 +34,7 @@ #include "DNA_armature_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" #include "DNA_scene_types.h" #include "BKE_bmesh.h" /* For BevelModifierData */ @@ -383,6 +384,12 @@ static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_SoftBodySettings, ob->soft); } +static PointerRNA rna_SoftBodyModifier_point_cache_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->pointcache); +} + static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -883,6 +890,11 @@ static void rna_def_modifier_softbody(BlenderRNA *brna) RNA_def_property_struct_type(prop, "SoftBodySettings"); RNA_def_property_pointer_funcs(prop, "rna_SoftBodyModifier_settings_get", NULL, NULL); RNA_def_property_ui_text(prop, "Soft Body Settings", ""); + + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "PointCache"); + RNA_def_property_pointer_funcs(prop, "rna_SoftBodyModifier_point_cache_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Soft Body Point Cache", ""); } static void rna_def_modifier_boolean(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 215a1e71e0d..e229afedc62 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -171,91 +171,91 @@ static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr) static int rna_SoftBodySettings_use_edges_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_EDGES) != 0); } static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_EDGES; else data->softflag &= ~OB_SB_EDGES; } static int rna_SoftBodySettings_use_goal_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_GOAL) != 0); } static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_GOAL; else data->softflag &= ~OB_SB_GOAL; } static int rna_SoftBodySettings_stiff_quads_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_QUADS) != 0); } static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_QUADS; else data->softflag &= ~OB_SB_QUADS; } static int rna_SoftBodySettings_self_collision_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_SELF) != 0); } static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_SELF; else data->softflag &= ~OB_SB_SELF; } static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_AERO_ANGLE) != 0); } static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_AERO_ANGLE; else data->softflag &= ~OB_SB_AERO_ANGLE; } static int rna_SoftBodySettings_face_collision_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_FACECOLL) != 0); } static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_FACECOLL; else data->softflag &= ~OB_SB_FACECOLL; } static int rna_SoftBodySettings_edge_collision_get(PointerRNA *ptr) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); return (((data->softflag) & OB_SB_EDGECOLL) != 0); } static void rna_SoftBodySettings_edge_collision_set(PointerRNA *ptr, int value) { - Object *data= (Object*)(ptr->data); + Object *data= (Object*)(ptr->id.data); if(value) data->softflag |= OB_SB_EDGECOLL; else data->softflag &= ~OB_SB_EDGECOLL; } |