svn merge ^/trunk/blender -r48995:49000
This commit is contained in:
@@ -2159,7 +2159,9 @@ static void integrate_particle(ParticleSettings *part, ParticleData *pa, float d
|
||||
break;
|
||||
}
|
||||
|
||||
copy_particle_key(states, &pa->state, 1);
|
||||
for (i=0; i<steps; i++) {
|
||||
copy_particle_key(states + i, &pa->state, 1);
|
||||
}
|
||||
|
||||
states->time = 0.f;
|
||||
|
||||
@@ -2441,7 +2443,8 @@ static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
|
||||
int i;
|
||||
float flow[3], offset[3], dist;
|
||||
|
||||
flow[0] = flow[1] = flow[2] = 0.0f;
|
||||
zero_v3(flow);
|
||||
|
||||
dist = 0.0f;
|
||||
if (pfr->tot_neighbors > 0) {
|
||||
pa = pfr->pa;
|
||||
@@ -2733,13 +2736,17 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
|
||||
{
|
||||
float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep, extrotfac;
|
||||
|
||||
if ((part->flag & PART_ROTATIONS)==0) {
|
||||
pa->state.rot[0]=1.0f;
|
||||
pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0;
|
||||
if ((part->flag & PART_ROTATIONS) == 0) {
|
||||
unit_qt(pa->state.rot);
|
||||
return;
|
||||
}
|
||||
|
||||
extrotfac = len_v3(pa->state.ave);
|
||||
if (part->flag & PART_ROT_DYN) {
|
||||
extrotfac = len_v3(pa->state.ave);
|
||||
}
|
||||
else {
|
||||
extrotfac = 0.0f;
|
||||
}
|
||||
|
||||
if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
|
||||
float angle;
|
||||
@@ -2747,8 +2754,9 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
|
||||
float len2 = len_v3(pa->state.vel);
|
||||
float vec[3];
|
||||
|
||||
if (len1==0.0f || len2==0.0f)
|
||||
pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
|
||||
if (len1 == 0.0f || len2 == 0.0f) {
|
||||
zero_v3(pa->state.ave);
|
||||
}
|
||||
else {
|
||||
cross_v3_v3v3(pa->state.ave, pa->prev_state.vel, pa->state.vel);
|
||||
normalize_v3(pa->state.ave);
|
||||
@@ -2761,9 +2769,8 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
|
||||
}
|
||||
|
||||
rotfac = len_v3(pa->state.ave);
|
||||
if (rotfac == 0.0f || (part->flag & PART_ROT_DYN)==0 || extrotfac == 0.0f) { /* unit_qt(in VecRotToQuat) doesn't give unit quat [1,0,0,0]?? */
|
||||
rot1[0]=1.0f;
|
||||
rot1[1]=rot1[2]=rot1[3]=0;
|
||||
if (rotfac == 0.0f || (part->flag & PART_ROT_DYN)==0 || extrotfac == 0.0f) {
|
||||
unit_qt(rot1);
|
||||
}
|
||||
else {
|
||||
axis_angle_to_quat(rot1,pa->state.ave,rotfac*dtime);
|
||||
@@ -3750,8 +3757,10 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
|
||||
pa->totkey++;
|
||||
|
||||
/* root is always in the origin of hair space so we set it to be so after the last key is saved*/
|
||||
if (pa->totkey == psys->part->hair_step + 1)
|
||||
root->co[0] = root->co[1] = root->co[2] = 0.0f;
|
||||
if (pa->totkey == psys->part->hair_step + 1) {
|
||||
zero_v3(root->co);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4130,9 +4139,8 @@ static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra))
|
||||
pa->state.vel[j] = wrf;
|
||||
}
|
||||
|
||||
pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f;
|
||||
pa->state.rot[0] = 1.0;
|
||||
pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0;
|
||||
zero_v3(pa->state.ave);
|
||||
unit_qt(pa->state.rot);
|
||||
|
||||
pa->time = 1.f;
|
||||
pa->dietime = sim->scene->r.efra + 1;
|
||||
|
||||
@@ -326,8 +326,7 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf
|
||||
|
||||
/* default to no rotation */
|
||||
if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
|
||||
pa->state.rot[0]=1.0f;
|
||||
pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0;
|
||||
unit_qt(pa->state.rot);
|
||||
}
|
||||
}
|
||||
static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
|
||||
|
||||
@@ -55,6 +55,7 @@ void ANIM_OT_keyframe_delete_v3d(struct wmOperatorType *ot);
|
||||
/* Keyframe managment operators for UI buttons (RMB menu). */
|
||||
void ANIM_OT_keyframe_insert_button(struct wmOperatorType *ot);
|
||||
void ANIM_OT_keyframe_delete_button(struct wmOperatorType *ot);
|
||||
void ANIM_OT_keyframe_clear_button(struct wmOperatorType *ot);
|
||||
|
||||
/* .......... */
|
||||
|
||||
|
||||
@@ -294,6 +294,7 @@ void ED_operatortypes_anim(void)
|
||||
WM_operatortype_append(ANIM_OT_keyframe_delete_v3d);
|
||||
WM_operatortype_append(ANIM_OT_keyframe_insert_button);
|
||||
WM_operatortype_append(ANIM_OT_keyframe_delete_button);
|
||||
WM_operatortype_append(ANIM_OT_keyframe_clear_button);
|
||||
|
||||
|
||||
WM_operatortype_append(ANIM_OT_driver_button_add);
|
||||
|
||||
@@ -1079,6 +1079,91 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ************************************************** */
|
||||
/* KEYFRAME CLEAR */
|
||||
|
||||
/* Main Keyframing API call:
|
||||
* Use this when validation of necessary animation data isn't necessary as it
|
||||
* already exists. It will clear the current buttons fcurve(s).
|
||||
*
|
||||
* The flag argument is used for special settings that alter the behavior of
|
||||
* the keyframe deletion. These include the quick refresh options.
|
||||
*/
|
||||
short clear_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, short UNUSED(flag))
|
||||
{
|
||||
AnimData *adt = BKE_animdata_from_id(id);
|
||||
PointerRNA id_ptr, ptr;
|
||||
PropertyRNA *prop;
|
||||
int array_index_max = array_index + 1;
|
||||
int ret = 0;
|
||||
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, id, adt)) {
|
||||
BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* validate pointer first - exit if failure */
|
||||
RNA_id_pointer_create(id, &id_ptr);
|
||||
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Could not clear keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get F-Curve
|
||||
* Note: here is one of the places where we don't want new Action + F-Curve added!
|
||||
* so 'add' var must be 0
|
||||
*/
|
||||
if (act == NULL) {
|
||||
/* if no action is provided, use the default one attached to this ID-block
|
||||
* - if it doesn't exist, then we're out of options...
|
||||
*/
|
||||
if (adt->action) {
|
||||
act = adt->action;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s\n", id->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* key entire array convenience method */
|
||||
if (array_index == -1) {
|
||||
array_index = 0;
|
||||
array_index_max = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
/* for single properties, increase max_index so that the property itself gets included,
|
||||
* but don't do this for standard arrays since that can cause corruption issues
|
||||
* (extra unused curves)
|
||||
*/
|
||||
if (array_index_max == array_index)
|
||||
array_index_max++;
|
||||
}
|
||||
|
||||
/* will only loop once unless the array index was -1 */
|
||||
for (; array_index < array_index_max; array_index++) {
|
||||
FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
|
||||
|
||||
/* check if F-Curve exists and/or whether it can be edited */
|
||||
if (fcu == NULL)
|
||||
continue;
|
||||
|
||||
if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
|
||||
if (G.debug & G_DEBUG)
|
||||
printf("WARNING: not deleting keyframe for locked F-Curve\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
|
||||
|
||||
/* return success */
|
||||
ret++;
|
||||
}
|
||||
|
||||
/* return success/failure */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ******************************************* */
|
||||
/* KEYFRAME MODIFICATION */
|
||||
|
||||
@@ -1584,6 +1669,78 @@ void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
|
||||
}
|
||||
|
||||
|
||||
/* Clear Key Button Operator ------------------------ */
|
||||
|
||||
static int clear_key_button_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
PointerRNA ptr = {{NULL}};
|
||||
PropertyRNA *prop = NULL;
|
||||
char *path;
|
||||
short success = 0;
|
||||
int a, index, length, all = RNA_boolean_get(op->ptr, "all");
|
||||
|
||||
/* try to insert keyframe using property retrieved from UI */
|
||||
uiContextActiveProperty(C, &ptr, &prop, &index);
|
||||
|
||||
if (ptr.id.data && ptr.data && prop) {
|
||||
path = RNA_path_from_ID_to_property(&ptr, prop);
|
||||
|
||||
if (path) {
|
||||
if (all) {
|
||||
length = RNA_property_array_length(&ptr, prop);
|
||||
|
||||
if (length) index = 0;
|
||||
else length = 1;
|
||||
}
|
||||
else
|
||||
length = 1;
|
||||
|
||||
for (a = 0; a < length; a++)
|
||||
success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0);
|
||||
|
||||
MEM_freeN(path);
|
||||
}
|
||||
else if (G.debug & G_DEBUG)
|
||||
printf("Button Clear-Key: no path to property\n");
|
||||
}
|
||||
else if (G.debug & G_DEBUG) {
|
||||
printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
|
||||
}
|
||||
|
||||
|
||||
if (success) {
|
||||
/* send updates */
|
||||
uiContextAnimUpdate(C);
|
||||
|
||||
DAG_ids_flush_update(bmain, 0);
|
||||
|
||||
/* send notifiers that keyframes have been changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
|
||||
}
|
||||
|
||||
return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Clear Keyframe (Buttons)";
|
||||
ot->idname = "ANIM_OT_keyframe_clear_button";
|
||||
ot->description = "Clear all keyframes on the currently active property";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = clear_key_button_exec;
|
||||
ot->poll = modify_key_op_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
|
||||
}
|
||||
|
||||
/* ******************************************* */
|
||||
/* AUTO KEYFRAME */
|
||||
|
||||
|
||||
@@ -212,6 +212,12 @@ void ui_but_anim_delete_keyframe(bContext *C)
|
||||
WM_operator_name_call(C, "ANIM_OT_keyframe_delete_button", WM_OP_INVOKE_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
void ui_but_anim_clear_keyframe(bContext *C)
|
||||
{
|
||||
/* this operator calls uiContextActiveProperty */
|
||||
WM_operator_name_call(C, "ANIM_OT_keyframe_clear_button", WM_OP_INVOKE_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
void ui_but_anim_add_driver(bContext *C)
|
||||
{
|
||||
/* this operator calls uiContextActiveProperty */
|
||||
|
||||
@@ -4474,6 +4474,19 @@ static int ui_but_menu(bContext *C, uiBut *but)
|
||||
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
|
||||
}
|
||||
|
||||
if (but->flag & UI_BUT_ANIMATED) {
|
||||
if (length) {
|
||||
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
|
||||
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
|
||||
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
|
||||
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
|
||||
}
|
||||
else {
|
||||
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
|
||||
ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Drivers */
|
||||
if (but->flag & UI_BUT_DRIVEN) {
|
||||
uiItemS(layout);
|
||||
@@ -4687,11 +4700,18 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
|
||||
ui_but_drop(C, event, but, data);
|
||||
}
|
||||
/* handle keyframing */
|
||||
else if (event->type == IKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
|
||||
if (event->alt)
|
||||
ui_but_anim_delete_keyframe(C);
|
||||
else
|
||||
else if (event->type == IKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) && event->val == KM_PRESS) {
|
||||
if (event->alt) {
|
||||
if (event->shift) {
|
||||
ui_but_anim_clear_keyframe(C);
|
||||
}
|
||||
else {
|
||||
ui_but_anim_delete_keyframe(C);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui_but_anim_insert_keyframe(C);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(CTX_wm_region(C));
|
||||
|
||||
|
||||
@@ -508,6 +508,7 @@ void ui_but_add_shortcut(uiBut *but, const char *key_str, const short do_strip);
|
||||
void ui_but_anim_flag(uiBut *but, float cfra);
|
||||
void ui_but_anim_insert_keyframe(struct bContext *C);
|
||||
void ui_but_anim_delete_keyframe(struct bContext *C);
|
||||
void ui_but_anim_clear_keyframe(struct bContext *C);
|
||||
void ui_but_anim_add_driver(struct bContext *C);
|
||||
void ui_but_anim_remove_driver(struct bContext *C);
|
||||
void ui_but_anim_copy_driver(struct bContext *C);
|
||||
|
||||
@@ -238,8 +238,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
|
||||
|
||||
/* TODO: incremental rotations somehow */
|
||||
if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
|
||||
state.rot[0] = 1;
|
||||
state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
|
||||
unit_qt(state.rot);
|
||||
}
|
||||
else {
|
||||
float temp[3] = {0.0f, 0.0f, 0.0f};
|
||||
@@ -250,7 +249,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
|
||||
/* state.vel[axis] is the only component surviving from a dot product with the axis */
|
||||
axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
state.time = -1.0;
|
||||
|
||||
Reference in New Issue
Block a user