diff --git a/procedural_animation.cpp b/procedural_animation.cpp index 7ee2ddc..f92eb06 100644 --- a/procedural_animation.cpp +++ b/procedural_animation.cpp @@ -228,80 +228,45 @@ void ProceduralAnimation::process_animation_data() { } } - float previous_keyframe_time = 0; float target_keyframe_time = 0; - for (Map::Element *K = _keyframes.front(); K; K = K->next()) { - int keyframe_index = K->get()->animation_keyframe_index; + float key_step = _animation->get_length() / static_cast(_animation_fps); + int next_animation_key = _start_frame_index; + while (next_animation_key != -1) { + ERR_BREAK(!_keyframes.has(next_animation_key)); - load_keyframe_data(target_keyframe_time, previous_keyframe_time, keyframe_index); + AnimationKeyFrame *frame = _keyframes[next_animation_key]; + next_animation_key = frame->next_keyframe; - //TODO add param - previous_keyframe_time = target_keyframe_time; - target_keyframe_time += 1.0; - } -} + int animation_keyframe_index = frame->animation_keyframe_index; -void ProceduralAnimation::load_keyframe_data(const float target_keyframe_time, const float previous_keyframe_time, const int keyframe_index, const bool interpolation_allowed) { - ERR_FAIL_COND(!_animation.is_valid()); - ERR_FAIL_COND(!_keyframes.has(keyframe_index)); + float time = animation_keyframe_index * key_step; - float time = keyframe_index * _animation->get_length() / static_cast(_animation_fps); - float step_time = 1 / static_cast(_animation_fps); - int steps = static_cast((target_keyframe_time - previous_keyframe_time) / step_time + 0.5); + bool found_keyframe = false; + for (int i = 0; i < _animation->get_track_count(); ++i) { + int key_index = _animation->track_find_key(i, time, true); + Variant key_value; - for (int i = 0; i < _animation->get_track_count(); ++i) { - int key_index = _animation->track_find_key(i, time, true); - Variant key_value; + if (key_index == -1) { + key_index = _animation->track_find_key(i, time, false); - if (key_index == -1) { - key_index = _animation->track_find_key(i, time, false); + if (key_index != -1) + key_value = _animation->track_get_key_value(i, key_index); + } - if (key_index != -1) - key_value = _animation->track_get_key_value(i, key_index); - /* - else { - if (interpolation_allowed) { - //track doesn't have a key at the specified time. Try to create one with interpolations. + if (key_value.get_type() == Variant::NIL) + continue; - Animation::TrackType tt = _animation->track_get_type(i); + track_insert_key(i, target_keyframe_time, key_value, frame->transition); - switch (tt) { - case Animation::TYPE_VALUE: { - Variant val = value_track_interpolate(i, time); - - track_insert_key(i, target_keyframe_time, val); - } break; - case Animation::TYPE_TRANSFORM: { - Vector3 loc; - Quat rot; - Vector3 scale; - - if (_animation->transform_track_interpolate(i, time, &loc, &rot, &scale) == OK) { - transform_track_insert_key(i, target_keyframe_time, loc, rot, scale); - } - } break; - case Animation::TYPE_METHOD: { - } break; - case Animation::TYPE_BEZIER: { - } break; - case Animation::TYPE_AUDIO: { - } break; - case Animation::TYPE_ANIMATION: { - } break; - } - } - }*/ + found_keyframe = true; } - if (key_value.get_type() == Variant::NIL) - continue; + if (!found_keyframe) + ERR_PRINT("Could not find any keyframe! Index: " + String::num(animation_keyframe_index) + " at time: " + String::num(time)); - AnimationKeyFrame *frame = _keyframes[keyframe_index]; - - track_insert_key(i, target_keyframe_time, key_value, frame->transition); + //TODO add param + target_keyframe_time += 1.0; } - - optimize(); } ProceduralAnimation::ProceduralAnimation() { @@ -473,12 +438,8 @@ void ProceduralAnimation::_bind_methods() { ClassDB::bind_method(D_METHOD("get_keyframe_transition", "keyframe_index"), &ProceduralAnimation::get_keyframe_transition); ClassDB::bind_method(D_METHOD("set_keyframe_transition", "keyframe_index", "value"), &ProceduralAnimation::set_keyframe_transition); - //ClassDB::bind_method(D_METHOD("get_keyframe_in_curve", "keyframe_index"), &ProceduralAnimation::get_keyframe_in_curve); - //ClassDB::bind_method(D_METHOD("set_keyframe_in_curve", "keyframe_index", "value"), &ProceduralAnimation::set_keyframe_in_curve); - ClassDB::bind_method(D_METHOD("get_keyframe_node_position", "keyframe_index"), &ProceduralAnimation::get_keyframe_node_position); ClassDB::bind_method(D_METHOD("set_keyframe_node_position", "keyframe_index", "value"), &ProceduralAnimation::set_keyframe_node_position); ClassDB::bind_method(D_METHOD("process_animation_data"), &ProceduralAnimation::process_animation_data); - ClassDB::bind_method(D_METHOD("load_keyframe_data", "keyframe_index", "keyframe_index", "interpolation_allowed"), &ProceduralAnimation::load_keyframe_data, DEFVAL(false)); } \ No newline at end of file diff --git a/procedural_animation.h b/procedural_animation.h index 6aac942..899419f 100644 --- a/procedural_animation.h +++ b/procedural_animation.h @@ -94,7 +94,6 @@ public: void set_keyframe_node_position(const int keyframe_index, const Vector2 &value); void process_animation_data(); - void load_keyframe_data(const float keyframe_time, const float previous_keyframe_time, const int keyframe_index, const bool interpolation_allowed = false); ProceduralAnimation(); ~ProceduralAnimation(); diff --git a/procedural_animation_editor_plugin.cpp b/procedural_animation_editor_plugin.cpp index 5a4b580..62cc487 100644 --- a/procedural_animation_editor_plugin.cpp +++ b/procedural_animation_editor_plugin.cpp @@ -38,6 +38,10 @@ void ProceduralAnimationEditor::edit(const Ref &animation) if (animation.is_valid()) load_animation(); + + _animation_target_animation_property->update_property(); + _animation_fps_spinbox->set_value(_animation->get_animation_fps()); + _loop_checkbox->set_pressed(_animation->has_loop()); } void ProceduralAnimationEditor::load_animation() { @@ -159,6 +163,39 @@ void ProceduralAnimationEditor::add_frame_button_pressed() { _graph_edit->add_child(gn); } +Ref ProceduralAnimationEditor::get_animation_target_animation() { + if (!_animation.is_valid()) + return Ref(); + + return _animation->get_animation(); +} +void ProceduralAnimationEditor::set_animation_target_animation(const Ref &animation) { + if (!_animation.is_valid()) + return; + + _animation->set_animation(animation); +} + +void ProceduralAnimationEditor::on_animation_fps_changed(const float value) { + if (!_animation.is_valid()) + return; + + if (_animation->get_animation_fps() == value) + return; + + _animation->set_animation_fps(value); +} + +void ProceduralAnimationEditor::on_loop_checkbox_toggled(const bool value) { + if (!_animation.is_valid()) + return; + + if (_animation->has_loop() == value) + return; + + _animation->set_loop(value); +} + void ProceduralAnimationEditor::_notification(int p_what) { switch (p_what) { @@ -175,6 +212,13 @@ void ProceduralAnimationEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("on_connection_request", "from", "from_slot", "to", "to_slot"), &ProceduralAnimationEditor::on_connection_request); ClassDB::bind_method(D_METHOD("on_disconnection_request", "from", "from_slot", "to", "to_slot"), &ProceduralAnimationEditor::on_disconnection_request); + + ClassDB::bind_method(D_METHOD("get_animation_target_animation"), &ProceduralAnimationEditor::get_animation_target_animation); + ClassDB::bind_method(D_METHOD("set_animation_target_animation", "animation"), &ProceduralAnimationEditor::set_animation_target_animation); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "animation_target_animation", PROPERTY_HINT_RESOURCE_TYPE, "Animation"), "set_animation_target_animation", "get_animation_target_animation"); + + ClassDB::bind_method(D_METHOD("on_animation_fps_changed", "value"), &ProceduralAnimationEditor::on_animation_fps_changed); + ClassDB::bind_method(D_METHOD("on_loop_checkbox_toggled", "value"), &ProceduralAnimationEditor::on_loop_checkbox_toggled); } ProceduralAnimationEditor::ProceduralAnimationEditor() { @@ -187,6 +231,29 @@ ProceduralAnimationEditor::ProceduralAnimationEditor(EditorNode *p_editor) { HBoxContainer *hbc = memnew(HBoxContainer); add_child(hbc); + _animation_target_animation_property = memnew(EditorPropertyResource); + _animation_target_animation_property->set_margin(MARGIN_TOP, 5 * EDSCALE); + _animation_target_animation_property->set_margin(MARGIN_BOTTOM, 5 * EDSCALE); + _animation_target_animation_property->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); + _animation_target_animation_property->set_label("Animation"); + _animation_target_animation_property->set_object_and_property(this, "animation_target_animation"); + hbc->add_child(_animation_target_animation_property); + + Label *fl = memnew(Label); + fl->set_text("FPS"); + hbc->add_child(fl); + + _animation_fps_spinbox = memnew(SpinBox); + _animation_fps_spinbox->set_max(999999999); + _animation_fps_spinbox->set_step(1); + _animation_fps_spinbox->connect("value_changed", this, "on_animation_fps_changed"); + hbc->add_child(_animation_fps_spinbox); + + _loop_checkbox = memnew(CheckBox); + _loop_checkbox->set_text("Loop"); + _loop_checkbox->connect("toggled", this, "on_loop_checkbox_toggled"); + hbc->add_child(_loop_checkbox); + Control *spacer = memnew(Control); spacer->set_h_size_flags(SIZE_EXPAND_FILL); hbc->add_child(spacer); @@ -374,11 +441,10 @@ ProceduralAnimationEditorGraphNode::ProceduralAnimationEditorGraphNode() { _animation_keyframe_spinbox->connect("value_changed", this, "on_animation_keyframe_spinbox_value_changed"); add_child(_animation_keyframe_spinbox); - Label *l3 = memnew(Label); - l3->set_text("Easing"); - add_child(l3); - _transition_editor = memnew(EditorPropertyEasing); + _transition_editor->set_margin(MARGIN_TOP, 5 * EDSCALE); + _transition_editor->set_margin(MARGIN_BOTTOM, 5 * EDSCALE); + _transition_editor->set_label("Easing"); _transition_editor->set_object_and_property(this, "transition"); _transition_editor->set_h_size_flags(SIZE_EXPAND_FILL); add_child(_transition_editor); diff --git a/procedural_animation_editor_plugin.h b/procedural_animation_editor_plugin.h index 63cc120..875665d 100644 --- a/procedural_animation_editor_plugin.h +++ b/procedural_animation_editor_plugin.h @@ -33,6 +33,7 @@ SOFTWARE. #include "procedural_animation.h" class EditorPropertyEasing; +class EditorPropertyResource; class ProceduralAnimationEditor : public VBoxContainer { GDCLASS(ProceduralAnimationEditor, VBoxContainer); @@ -62,6 +63,12 @@ public: ~ProceduralAnimationEditor(); protected: + Ref get_animation_target_animation(); + void set_animation_target_animation(const Ref &animation); + + void on_animation_fps_changed(const float value); + void on_loop_checkbox_toggled(const bool value); + void _notification(int p_what); static void _bind_methods(); @@ -73,6 +80,10 @@ private: Label *_name_pupup_label; LineEdit *_name_popup_line_edit; + EditorPropertyResource *_animation_target_animation_property; + SpinBox *_animation_fps_spinbox; + CheckBox *_loop_checkbox; + GraphNode *_start_node; Ref _animation; GraphEdit *_graph_edit;