Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_convert_graph.c
| /* | /* | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License | * modify it under the terms of the GNU General Public License | ||||
| * as published by the Free Software Foundation; either version 2 | * as published by the Free Software Foundation; either version 2 | ||||
| * of the License, or (at your option) any later version. | * of the License, or (at your option) any later version. | ||||
| * | * | ||||
| * This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | ||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | static bool graph_edit_is_translation_mode(TransInfo *t) | ||||
| return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE); | return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE); | ||||
| } | } | ||||
| static bool graph_edit_use_local_center(TransInfo *t) | static bool graph_edit_use_local_center(TransInfo *t) | ||||
| { | { | ||||
| return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false)); | return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false)); | ||||
| } | } | ||||
| /** | |||||
| * Get the effective selection of a triple for transform, i.e. return if the left handle, right | |||||
| * handle and/or the center point should be affected by transform. | |||||
| */ | |||||
| static void graph_bezt_get_transform_selection(const TransInfo *t, | |||||
| const BezTriple *bezt, | |||||
| const bool use_handle, | |||||
| bool *r_left_handle, | |||||
| bool *r_key, | |||||
| bool *r_right_handle) | |||||
| { | |||||
| SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; | |||||
| bool key = (bezt->f2 & SELECT) != 0; | |||||
| bool left = use_handle ? ((bezt->f1 & SELECT) != 0) : key; | |||||
| bool right = use_handle ? ((bezt->f3 & SELECT) != 0) : key; | |||||
| if (use_handle && t->is_launch_event_tweak) { | |||||
| if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT) { | |||||
| key = right = false; | |||||
| } | |||||
| else if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT) { | |||||
| left = key = false; | |||||
| } | |||||
| } | |||||
| /* Whenever we move the key, we also move both handles. */ | |||||
| if (key) { | |||||
| left = right = true; | |||||
| } | |||||
| *r_key = key; | |||||
| *r_left_handle = left; | |||||
| *r_right_handle = right; | |||||
| } | |||||
| static void graph_key_shortest_dist( | static void graph_key_shortest_dist( | ||||
| TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle) | TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle) | ||||
| { | { | ||||
| int j = 0; | int j = 0; | ||||
| TransData *td_iter = td_start; | TransData *td_iter = td_start; | ||||
| bool sel_key, sel_left, sel_right; | |||||
| td->dist = FLT_MAX; | td->dist = FLT_MAX; | ||||
| for (; j < fcu->totvert; j++) { | for (; j < fcu->totvert; j++) { | ||||
| BezTriple *bezt = fcu->bezt + j; | BezTriple *bezt = fcu->bezt + j; | ||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| const bool sel2 = (bezt->f2 & SELECT) != 0; | graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | ||||
| const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; | |||||
| const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; | |||||
| if (sel1 || sel2 || sel3) { | if (sel_left || sel_key || sel_right) { | ||||
| td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); | td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); | ||||
| } | } | ||||
| td_iter += 3; | td_iter += 3; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * It is important to note that this doesn't always act on the selection (like it's usually done), | |||||
| * it acts on a subset of it. E.g. the selection code may leave a hint that we just dragged on a | |||||
| * left or right handle (SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT/RIGHT) and then we only transform the | |||||
| * selected left or right handles accordingly. | |||||
| * The points to be transformed are tagged with BEZT_FLAG_TEMP_TAG; some lower level curve | |||||
| * functions may need to be made aware of this. It's ugly that these act based on selection state | |||||
| * anyway. | |||||
| */ | |||||
| void createTransGraphEditData(bContext *C, TransInfo *t) | void createTransGraphEditData(bContext *C, TransInfo *t) | ||||
| { | { | ||||
| SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; | SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; | ||||
| Scene *scene = t->scene; | Scene *scene = t->scene; | ||||
| ARegion *ar = t->ar; | ARegion *ar = t->ar; | ||||
| View2D *v2d = &ar->v2d; | View2D *v2d = &ar->v2d; | ||||
| TransData *td = NULL; | TransData *td = NULL; | ||||
| TransData2D *td2d = NULL; | TransData2D *td2d = NULL; | ||||
| TransDataGraph *tdg = NULL; | TransDataGraph *tdg = NULL; | ||||
| bAnimContext ac; | bAnimContext ac; | ||||
| ListBase anim_data = {NULL, NULL}; | ListBase anim_data = {NULL, NULL}; | ||||
| bAnimListElem *ale; | bAnimListElem *ale; | ||||
| int filter; | int filter; | ||||
| BezTriple *bezt; | BezTriple *bezt; | ||||
| int count = 0, i; | int count = 0, i; | ||||
| float mtx[3][3], smtx[3][3]; | float mtx[3][3], smtx[3][3]; | ||||
| const bool is_translation_mode = graph_edit_is_translation_mode(t); | |||||
| const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); | const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); | ||||
| const bool use_local_center = graph_edit_use_local_center(t); | const bool use_local_center = graph_edit_use_local_center(t); | ||||
| const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; | const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; | ||||
| short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; | short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; | ||||
| bool sel_key, sel_left, sel_right; | |||||
| /* determine what type of data we are operating on */ | /* determine what type of data we are operating on */ | ||||
| if (ANIM_animdata_get_context(C, &ac) == 0) { | if (ANIM_animdata_get_context(C, &ac) == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| anim_map_flag |= ANIM_get_normalization_flags(&ac); | anim_map_flag |= ANIM_get_normalization_flags(&ac); | ||||
| Show All 34 Lines | for (ale = anim_data.first; ale; ale = ale->next) { | ||||
| */ | */ | ||||
| if (adt) { | if (adt) { | ||||
| cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); | cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); | ||||
| } | } | ||||
| else { | else { | ||||
| cfra = (float)CFRA; | cfra = (float)CFRA; | ||||
| } | } | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | |||||
| /* Only include BezTriples whose 'keyframe' | /* Only include BezTriples whose 'keyframe' | ||||
| * occurs on the same side of the current frame as mouse. */ | * occurs on the same side of the current frame as mouse. */ | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | |||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| const bool sel2 = (bezt->f2 & SELECT) != 0; | graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | ||||
| const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; | |||||
| const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; | |||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| curvecount += 3; | curvecount += 3; | ||||
| if (sel2 || sel1 || sel3) { | if (sel_key || sel_left || sel_right) { | ||||
| selected = true; | selected = true; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (!is_translation_mode || !(sel2)) { | if (sel_left) { | ||||
| if (sel1) { | |||||
| count++; | count++; | ||||
| } | } | ||||
| if (sel3) { | if (sel_right) { | ||||
| count++; | count++; | ||||
| } | } | ||||
| } | |||||
| /* only include main vert if selected */ | /* only include main vert if selected */ | ||||
| if (sel2 && !use_local_center) { | if (sel_key && !use_local_center) { | ||||
| count++; | count++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| if (selected) { | if (selected) { | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | for (ale = anim_data.first; ale; ale = ale->next) { | ||||
| } | } | ||||
| else { | else { | ||||
| cfra = (float)CFRA; | cfra = (float)CFRA; | ||||
| } | } | ||||
| unit_scale = ANIM_unit_mapping_get_factor( | unit_scale = ANIM_unit_mapping_get_factor( | ||||
| ac.scene, ale->id, ale->key_data, anim_map_flag, &offset); | ac.scene, ale->id, ale->key_data, anim_map_flag, &offset); | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | |||||
| /* Ensure temp flag is cleared for all triples, we use it. */ | |||||
| bezt->f1 &= ~BEZT_FLAG_TEMP_TAG; | |||||
| bezt->f2 &= ~BEZT_FLAG_TEMP_TAG; | |||||
| bezt->f3 &= ~BEZT_FLAG_TEMP_TAG; | |||||
| /* only include BezTriples whose 'keyframe' occurs on the same side | /* only include BezTriples whose 'keyframe' occurs on the same side | ||||
| * of the current frame as mouse (if applicable) */ | * of the current frame as mouse (if applicable) */ | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | |||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| const bool sel2 = (bezt->f2 & SELECT) != 0; | |||||
| const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; | |||||
| const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; | |||||
| TransDataCurveHandleFlags *hdata = NULL; | TransDataCurveHandleFlags *hdata = NULL; | ||||
| /* short h1=1, h2=1; */ /* UNUSED */ | |||||
| graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | |||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| bool is_sel = (sel2 || sel1 || sel3); | bool is_sel = (sel_key || sel_left || sel_right); | ||||
| /* we always select all handles for proportional editing if central handle is selected */ | /* we always select all handles for proportional editing if central handle is selected */ | ||||
| initTransDataCurveHandles(td, bezt); | initTransDataCurveHandles(td, bezt); | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td++, | ||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 0, | 0, | ||||
| Show All 27 Lines | for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | ||||
| 2, | 2, | ||||
| is_sel, | is_sel, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| if (is_sel) { | |||||
| bezt->f1 |= BEZT_FLAG_TEMP_TAG; | |||||
| bezt->f2 |= BEZT_FLAG_TEMP_TAG; | |||||
| bezt->f3 |= BEZT_FLAG_TEMP_TAG; | |||||
| } | |||||
| } | } | ||||
| else { | else { | ||||
| /* only include handles if selected, irrespective of the interpolation modes. | /* only include handles if selected, irrespective of the interpolation modes. | ||||
| * also, only treat handles specially if the center point isn't selected. | * also, only treat handles specially if the center point isn't selected. | ||||
| */ | */ | ||||
| if (!is_translation_mode || !(sel2)) { | if (sel_left) { | ||||
| if (sel1) { | |||||
| hdata = initTransDataCurveHandles(td, bezt); | hdata = initTransDataCurveHandles(td, bezt); | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td++, | ||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 0, | 0, | ||||
| sel1, | sel_left, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| } | bezt->f1 |= BEZT_FLAG_TEMP_TAG; | ||||
| else { | |||||
| /* h1 = 0; */ /* UNUSED */ | |||||
| } | } | ||||
| if (sel3) { | if (sel_right) { | ||||
| if (hdata == NULL) { | if (hdata == NULL) { | ||||
| hdata = initTransDataCurveHandles(td, bezt); | hdata = initTransDataCurveHandles(td, bezt); | ||||
| } | } | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td++, | ||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 2, | 2, | ||||
| sel3, | sel_right, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| } | bezt->f3 |= BEZT_FLAG_TEMP_TAG; | ||||
| else { | |||||
| /* h2 = 0; */ /* UNUSED */ | |||||
| } | |||||
| } | } | ||||
| /* only include main vert if selected */ | /* only include main vert if selected */ | ||||
| if (sel2 && !use_local_center) { | if (sel_key && !use_local_center) { | ||||
| /* move handles relative to center */ | /* move handles relative to center */ | ||||
| if (is_translation_mode) { | if (graph_edit_is_translation_mode(t)) { | ||||
| if (sel1) { | if (sel_left) { | ||||
| td->flag |= TD_MOVEHANDLE1; | td->flag |= TD_MOVEHANDLE1; | ||||
| } | } | ||||
| if (sel3) { | if (sel_right) { | ||||
| td->flag |= TD_MOVEHANDLE2; | td->flag |= TD_MOVEHANDLE2; | ||||
| } | } | ||||
| } | } | ||||
| /* if handles were not selected, store their selection status */ | /* if handles were not selected, store their selection status */ | ||||
| if (!(sel1) || !(sel3)) { | if (!(sel_left) || !(sel_right)) { | ||||
| if (hdata == NULL) { | if (hdata == NULL) { | ||||
| hdata = initTransDataCurveHandles(td, bezt); | hdata = initTransDataCurveHandles(td, bezt); | ||||
| } | } | ||||
| } | } | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td++, | ||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 1, | 1, | ||||
| sel2, | sel_key, | ||||
| false, | false, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| bezt->f2 |= BEZT_FLAG_TEMP_TAG; | |||||
| } | } | ||||
| /* Special hack (must be done after #initTransDataCurveHandles(), | /* Special hack (must be done after #initTransDataCurveHandles(), | ||||
| * as that stores handle settings to restore...): | * as that stores handle settings to restore...): | ||||
| * | * | ||||
| * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, | * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, | ||||
| * then check if we're using auto-handles. | * then check if we're using auto-handles. | ||||
| * - If so, change them auto-handles to aligned handles so that handles get affected too | * - If so, change them auto-handles to aligned handles so that handles get affected too | ||||
| */ | */ | ||||
| if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && | if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) && | ||||
| ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { | ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { | ||||
| if (hdata && (sel1) && (sel3)) { | if (hdata && (sel_left) && (sel_right)) { | ||||
| bezt->h1 = HD_ALIGN; | bezt->h1 = HD_ALIGN; | ||||
| bezt->h2 = HD_ALIGN; | bezt->h2 = HD_ALIGN; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Sets handles based on the selection */ | /* Sets handles based on the selection */ | ||||
| testhandles_fcurve(fcu, use_handle); | testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle); | ||||
| } | } | ||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| /* loop 2: build transdata arrays */ | /* loop 2: build transdata arrays */ | ||||
| td = tc->data; | td = tc->data; | ||||
| for (ale = anim_data.first; ale; ale = ale->next) { | for (ale = anim_data.first; ale; ale = ale->next) { | ||||
| AnimData *adt = ANIM_nla_mapping_get(&ac, ale); | AnimData *adt = ANIM_nla_mapping_get(&ac, ale); | ||||
| Show All 11 Lines | for (ale = anim_data.first; ale; ale = ale->next) { | ||||
| */ | */ | ||||
| if (adt) { | if (adt) { | ||||
| cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); | cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); | ||||
| } | } | ||||
| else { | else { | ||||
| cfra = (float)CFRA; | cfra = (float)CFRA; | ||||
| } | } | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | |||||
| /* only include BezTriples whose 'keyframe' occurs on the | /* only include BezTriples whose 'keyframe' occurs on the | ||||
| * same side of the current frame as mouse (if applicable) */ | * same side of the current frame as mouse (if applicable) */ | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | |||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| const bool sel2 = (bezt->f2 & SELECT) != 0; | graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | ||||
| const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; | |||||
| const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; | |||||
| if (sel1 || sel2) { | if (sel_left || sel_key) { | ||||
| td->dist = td->rdist = 0.0f; | td->dist = td->rdist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | ||||
| } | } | ||||
| td++; | td++; | ||||
| if (sel2) { | if (sel_key) { | ||||
| td->dist = td->rdist = 0.0f; | td->dist = td->rdist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | ||||
| } | } | ||||
| td++; | td++; | ||||
| if (sel3 || sel2) { | if (sel_right || sel_key) { | ||||
| td->dist = td->rdist = 0.0f; | td->dist = td->rdist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | ||||
| } | } | ||||
| td++; | td++; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 114 Lines • Show Last 20 Lines | |||||