Skip to content

Commit

Permalink
Bezier Editor - add "Apply Function on Selected Keys"
Browse files Browse the repository at this point in the history
Added Apply Function on Selected Key(s) feature so you can now scale, move keys
and more easily create effects (like Bounce, Overshoot, etc)
Functions can have parameters "time" and "value", "time" is the time of the key,
"value" is the current value of the key.
  • Loading branch information
puthre committed Aug 30, 2019
1 parent 3db1d40 commit 8ded883
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
103 changes: 103 additions & 0 deletions editor/animation_bezier_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "animation_bezier_editor.h"

#include "core/math/expression.h"
#include "editor/editor_node.h"

float AnimationBezierTrackEdit::_bezier_h_to_pixel(float p_h) {
Expand Down Expand Up @@ -673,6 +674,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
menu->add_separator();
menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE);
menu->add_separator();
//menu->add_icon_item(get_icon("Path", "EditorIcons"), TTR("Apply Function on Selected Key(s)"), MENU_KEY_APPLY_FUNCTION);
menu->add_item(TTR("Apply Function on Selected Key(s)"), MENU_KEY_APPLY_FUNCTION);
menu->add_separator();
menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE);
}

Expand Down Expand Up @@ -1079,6 +1083,12 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) {
case MENU_KEY_DELETE: {
delete_selection();
} break;
case MENU_KEY_APPLY_FUNCTION: {
apply_function_dialog->popup_centered(Size2(200, 100) * EDSCALE);
} break;
case EDIT_FUNCTION_CONFIRM: {
apply_function_on_selection();
} break;
}
}

Expand Down Expand Up @@ -1140,6 +1150,87 @@ void AnimationBezierTrackEdit::duplicate_selection() {
update();
}

void AnimationBezierTrackEdit::apply_function_on_selection() {

String function_text = apply_function_value->get_line_edit()->get_text();

Ref<Expression> expr;
expr.instance();

Vector<String> params;
params.push_back("time");
params.push_back("value");

Error err = expr->parse(function_text, params);
if (err != OK) {
return;
}

if (selection.size() == 0)
return;

undo_redo->create_action(TTR("Anim Apply Function"));

List<AnimMoveRestore> to_restore;
// 1-remove the keys
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {

undo_redo->add_do_method(animation.ptr(), "track_remove_key", track, E->get());
}

// 2-move the keys (re insert them)
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {

float t = editor->snap_time(animation->track_get_key_time(track, E->get()));

Array key = animation->track_get_key_value(track, E->get());
float v = key[0];

Array a;
a.push_back(t);
a.push_back(v);

Variant res = expr->execute(a, NULL, false);
if (res.get_type() == Variant::REAL || res.get_type() == Variant::INT) {
v = float(res);
}

key[0] = v;
undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, t, key, 1);
}

// 3-(undo) remove inserted keys
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {

float newpos = editor->snap_time(animation->track_get_key_time(track, E->get()));

undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", track, newpos);
}

// 4-(undo) reinsert keys
for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {

float oldpos = animation->track_get_key_time(track, E->get());
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, oldpos, animation->track_get_key_value(track, E->get()), 1);
}

undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);

// 5-reselect

for (Set<int>::Element *E = selection.back(); E; E = E->prev()) {

float oldpos = animation->track_get_key_time(track, E->get());
float newpos = editor->snap_time(oldpos + moving_selection_offset.x);

undo_redo->add_do_method(this, "_select_at_anim", animation, track, newpos);
undo_redo->add_undo_method(this, "_select_at_anim", animation, track, oldpos);
}

undo_redo->commit_action();
}

void AnimationBezierTrackEdit::delete_selection() {
if (selection.size()) {
undo_redo->create_action(TTR("Anim Delete Keys"));
Expand Down Expand Up @@ -1221,5 +1312,17 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() {
add_child(menu);
menu->connect("id_pressed", this, "_menu_selected");

apply_function_dialog = memnew(ConfirmationDialog);
VBoxContainer *vbc = memnew(VBoxContainer);
apply_function_dialog->add_child(vbc);

apply_function_value = memnew(SpinBox);
apply_function_value->set_min(-99999);
apply_function_value->set_max(99999);
apply_function_value->set_step(0.001);
vbc->add_margin_child(TTR("Function (time,value):"), apply_function_value);
apply_function_dialog->connect("confirmed", this, "_menu_selected", varray(EDIT_FUNCTION_CONFIRM));
add_child(apply_function_dialog);

//set_mouse_filter(MOUSE_FILTER_PASS); //scroll has to work too for selection
}
8 changes: 7 additions & 1 deletion editor/animation_bezier_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class AnimationBezierTrackEdit : public Control {
enum {
MENU_KEY_INSERT,
MENU_KEY_DUPLICATE,
MENU_KEY_DELETE
MENU_KEY_DELETE,
MENU_KEY_APPLY_FUNCTION,
EDIT_FUNCTION_CONFIRM
};

HandleMode handle_mode;
Expand Down Expand Up @@ -76,6 +78,9 @@ class AnimationBezierTrackEdit : public Control {

PopupMenu *menu;

ConfirmationDialog *apply_function_dialog;
SpinBox *apply_function_value;

void _zoom_changed();

void _gui_input(const Ref<InputEvent> &p_event);
Expand Down Expand Up @@ -164,6 +169,7 @@ class AnimationBezierTrackEdit : public Control {

void duplicate_selection();
void delete_selection();
void apply_function_on_selection();

AnimationBezierTrackEdit();
};
Expand Down

0 comments on commit 8ded883

Please sign in to comment.