diff options
-rw-r--r-- | doc/classes/Animation.xml | 13 | ||||
-rw-r--r-- | doc/classes/RigidBody.xml | 4 | ||||
-rw-r--r-- | editor/animation_track_editor.cpp | 8 | ||||
-rw-r--r-- | editor/code_editor.cpp | 16 | ||||
-rw-r--r-- | editor/editor_node.cpp | 2 | ||||
-rw-r--r-- | editor/editor_resource_preview.cpp | 4 | ||||
-rw-r--r-- | editor/filesystem_dock.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/animation_player_editor_plugin.cpp | 44 | ||||
-rw-r--r-- | editor/plugins/animation_player_editor_plugin.h | 2 | ||||
-rw-r--r-- | editor/plugins/particles_2d_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/particles_editor_plugin.cpp | 8 | ||||
-rw-r--r-- | editor/scene_tree_dock.cpp | 3 | ||||
-rw-r--r-- | scene/3d/camera.cpp | 28 | ||||
-rw-r--r-- | scene/3d/camera.h | 1 | ||||
-rw-r--r-- | scene/3d/collision_shape.cpp | 4 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 36 | ||||
-rw-r--r-- | scene/resources/animation.cpp | 73 | ||||
-rw-r--r-- | scene/resources/animation.h | 1 |
18 files changed, 160 insertions, 91 deletions
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index 9885f30883..53d3663d4f 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -562,6 +562,19 @@ Set the value of an existing key. </description> </method> + <method name="track_set_key_time"> + <return type="void"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="key_idx" type="int"> + </argument> + <argument index="2" name="time" type="float"> + </argument> + <description> + Set the time of an existing key. + </description> + </method> <method name="track_set_path"> <return type="void"> </return> diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml index 9ea6bb0fe1..8dadca49e1 100644 --- a/doc/classes/RigidBody.xml +++ b/doc/classes/RigidBody.xml @@ -119,10 +119,10 @@ Lock the body's movement in the x-axis. </member> <member name="axis_lock_linear_y" type="bool" setter="set_axis_lock" getter="get_axis_lock"> - Lock the body's movement in the x-axis. + Lock the body's movement in the y-axis. </member> <member name="axis_lock_linear_z" type="bool" setter="set_axis_lock" getter="get_axis_lock"> - Lock the body's movement in the x-axis. + Lock the body's movement in the z-axis. </member> <member name="bounce" type="float" setter="set_bounce" getter="get_bounce"> RigidBody's bounciness. diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index e8490e8729..7dadbf88fb 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3633,6 +3633,9 @@ void AnimationTrackEditor::_animation_update() { bezier_edit->update(); _update_step_spinbox(); + emit_signal("animation_step_changed", animation->get_step()); + emit_signal("animation_len_changed", animation->get_length()); + EditorNode::get_singleton()->get_inspector()->refresh(); animation_changing_awaiting_update = false; } @@ -3685,8 +3688,7 @@ void AnimationTrackEditor::_update_step(double p_new_step) { step->set_block_signals(true); undo_redo->commit_action(); step->set_block_signals(false); - emit_signal("animation_step_changed", p_new_step); - animation->_change_notify("step"); + emit_signal("animation_step_changed", step_value); } void AnimationTrackEditor::_update_length(double p_new_len) { @@ -4973,6 +4975,7 @@ void AnimationTrackEditor::_bind_methods() { ClassDB::bind_method("_update_scroll", &AnimationTrackEditor::_update_scroll); ClassDB::bind_method("_update_tracks", &AnimationTrackEditor::_update_tracks); ClassDB::bind_method("_update_step", &AnimationTrackEditor::_update_step); + ClassDB::bind_method("_update_length", &AnimationTrackEditor::_update_length); ClassDB::bind_method("_dropped_track", &AnimationTrackEditor::_dropped_track); ClassDB::bind_method("_add_track", &AnimationTrackEditor::_add_track); ClassDB::bind_method("_new_track_node_selected", &AnimationTrackEditor::_new_track_node_selected); @@ -5033,6 +5036,7 @@ AnimationTrackEditor::AnimationTrackEditor() { timeline->connect("name_limit_changed", this, "_name_limit_changed"); timeline->connect("track_added", this, "_add_track"); timeline->connect("value_changed", this, "_timeline_value_changed"); + timeline->connect("length_changed", this, "_update_length"); scroll = memnew(ScrollContainer); timeline_vbox->add_child(scroll); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 695560ca34..33adb33c8c 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -675,14 +675,14 @@ void CodeTextEditor::_line_col_changed() { } } - StringBuilder *sb = memnew(StringBuilder); - sb->append("("); - sb->append(itos(text_editor->cursor_get_line() + 1).lpad(3)); - sb->append(","); - sb->append(itos(positional_column + 1).lpad(3)); - sb->append(")"); - - line_and_col_txt->set_text(sb->as_string()); + StringBuilder sb; + sb.append("("); + sb.append(itos(text_editor->cursor_get_line() + 1).lpad(3)); + sb.append(","); + sb.append(itos(positional_column + 1).lpad(3)); + sb.append(")"); + + line_and_col_txt->set_text(sb.as_string()); } void CodeTextEditor::_text_changed() { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 1dd68309ae..b8f3ee23f0 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1283,7 +1283,7 @@ void EditorNode::_dialog_action(String p_file) { Node *scene = editor_data.get_edited_scene_root(); // If the previous scene is rootless, just close it in favor of the new one. if (!scene) - _menu_option_confirm(FILE_CLOSE, false); + _menu_option_confirm(FILE_CLOSE, true); load_scene(p_file, false, true); } break; diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 2baad8c904..6cca0a0ffa 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -203,7 +203,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< if (has_small_texture) { ResourceSaver::save(cache_base + "_small.png", r_small_texture); } - FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE); + Error err; + FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE, &err); + ERR_FAIL_COND(err != OK); f->store_line(itos(thumbnail_size)); f->store_line(itos(has_small_texture)); f->store_line(itos(FileAccess::get_modified_time(p_item.path))); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 194a131095..6a4d9fea0c 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -451,9 +451,11 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa } else if (dirAccess->dir_exists(p_path)) { path = target_path + "/"; } else { + memdelete(dirAccess); ERR_EXPLAIN(vformat(TTR("Cannot navigate to '%s' as it has not been found in the file system!"), p_path)); ERR_FAIL(); } + memdelete(dirAccess); } _set_current_path_text(path); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 951e971615..7d96f0b87b 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -289,39 +289,24 @@ void AnimationPlayerEditor::_pause_pressed() { //player->set_pause( pause->is_pressed() ); } +void AnimationPlayerEditor::_animation_selected(int p_which) { -String AnimationPlayerEditor::_get_current_animation() const { - + if (updating) + return; // when selecting an animation, the idea is that the only interesting behavior // ui-wise is that it should play/blend the next one if currently playing + String current; if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) { - return animation->get_item_text(animation->get_selected()); + current = animation->get_item_text(animation->get_selected()); } - return ""; -} - -void AnimationPlayerEditor::_animation_selected(int p_which) { - - if (updating) - return; - - _current_animation_updated(); -} - -void AnimationPlayerEditor::_current_animation_updated() { - - String current = _get_current_animation(); - if (current != "") { - Ref<Animation> anim = player->get_animation(current); player->set_assigned_animation(current); - { - if (!anim->is_connected("changed", this, "_current_animation_updated")) - anim->connect("changed", this, "_current_animation_updated"); + Ref<Animation> anim = player->get_animation(current); + { track_editor->set_animation(anim); Node *root = player->get_node(player->get_root()); @@ -1078,19 +1063,17 @@ void AnimationPlayerEditor::_list_changed() { _update_player(); } +void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len) { + + frame->set_max(p_len); +} + void AnimationPlayerEditor::_animation_key_editor_anim_step_changed(float p_len) { if (p_len) frame->set_step(p_len); else frame->set_step(0.00001); - - String current = _get_current_animation(); - - if (current != "") { - Ref<Animation> anim = player->get_animation(current); - anim->_change_notify("step"); - } } void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag) { @@ -1568,7 +1551,6 @@ void AnimationPlayerEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_autoplay_pressed"), &AnimationPlayerEditor::_autoplay_pressed); ClassDB::bind_method(D_METHOD("_pause_pressed"), &AnimationPlayerEditor::_pause_pressed); ClassDB::bind_method(D_METHOD("_animation_selected"), &AnimationPlayerEditor::_animation_selected); - ClassDB::bind_method(D_METHOD("_current_animation_updated"), &AnimationPlayerEditor::_current_animation_updated); ClassDB::bind_method(D_METHOD("_animation_name_edited"), &AnimationPlayerEditor::_animation_name_edited); ClassDB::bind_method(D_METHOD("_animation_new"), &AnimationPlayerEditor::_animation_new); ClassDB::bind_method(D_METHOD("_animation_rename"), &AnimationPlayerEditor::_animation_rename); @@ -1588,6 +1570,7 @@ void AnimationPlayerEditor::_bind_methods() { //ClassDB::bind_method(D_METHOD("_editor_load_all"),&AnimationPlayerEditor::_editor_load_all); ClassDB::bind_method(D_METHOD("_list_changed"), &AnimationPlayerEditor::_list_changed); ClassDB::bind_method(D_METHOD("_animation_key_editor_seek"), &AnimationPlayerEditor::_animation_key_editor_seek); + ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_len_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_len_changed); ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_step_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_step_changed); ClassDB::bind_method(D_METHOD("_hide_anim_editors"), &AnimationPlayerEditor::_hide_anim_editors); ClassDB::bind_method(D_METHOD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate); @@ -1801,6 +1784,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay add_child(track_editor); track_editor->set_v_size_flags(SIZE_EXPAND_FILL); track_editor->connect("timeline_changed", this, "_animation_key_editor_seek"); + track_editor->connect("animation_len_changed", this, "_animation_key_editor_anim_len_changed"); track_editor->connect("animation_step_changed", this, "_animation_key_editor_anim_step_changed"); _update_player(); diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index b1026b5b9f..dedce16bbc 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -171,9 +171,7 @@ class AnimationPlayerEditor : public VBoxContainer { void _autoplay_pressed(); void _stop_pressed(); void _pause_pressed(); - String _get_current_animation() const; void _animation_selected(int p_which); - void _current_animation_updated(); void _animation_new(); void _animation_rename(); void _animation_name_edited(); diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index 4c354b8002..6fabdc93c6 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -94,7 +94,7 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { cpu_particles->set_z_index(particles->get_z_index()); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Convert from Particles2D")); + ur->create_action(TTR("Convert to CPUParticles")); ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", particles, cpu_particles, true, false); ur->add_do_reference(particles); ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, particles, false, false); diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 09180edf2a..66cecf7068 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -312,7 +312,13 @@ void ParticlesEditor::_menu_option(int p_option) { cpu_particles->set_visible(node->is_visible()); cpu_particles->set_pause_mode(node->get_pause_mode()); - EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, cpu_particles, false); + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Convert to CPUParticles")); + ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, cpu_particles, true, false); + ur->add_do_reference(node); + ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", cpu_particles, node, false, false); + ur->add_undo_reference(this); + ur->commit_action(); } break; } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index ce2795f37b..e8f5139cd5 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1082,7 +1082,7 @@ void SceneTreeDock::_notification(int p_what) { bool show_create_root = bool(EDITOR_GET("interface/editors/show_scene_tree_root_selection")) && get_tree()->get_edited_scene_root() == NULL; - if (show_create_root != create_root_dialog->is_visible_in_tree()) { + if (show_create_root != create_root_dialog->is_visible_in_tree() && !remote_tree->is_visible()) { if (show_create_root) { create_root_dialog->show(); scene_tree->hide(); @@ -2367,6 +2367,7 @@ void SceneTreeDock::hide_tab_buttons() { void SceneTreeDock::_remote_tree_selected() { scene_tree->hide(); + create_root_dialog->hide(); if (remote_tree) remote_tree->show(); edit_remote->set_pressed(true); diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 29002c6701..a00f2173c0 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -106,9 +106,15 @@ void Camera::_notification(int p_what) { case NOTIFICATION_ENTER_WORLD: { - bool first_camera = get_viewport()->_camera_add(this); - if (!get_tree()->is_node_being_edited(this) && (current || first_camera)) - make_current(); + // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD + // and Spatial will handle it first, including clearing its reference to the Viewport, + // therefore making it impossible to subclasses to access it + viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + + bool first_camera = viewport->_camera_add(this); + if (current || first_camera) + viewport->_camera_set(this); } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -130,17 +136,20 @@ void Camera::_notification(int p_what) { } } - get_viewport()->_camera_remove(this); + if (viewport) { + viewport->_camera_remove(this); + viewport = NULL; + } } break; case NOTIFICATION_BECAME_CURRENT: { - if (get_world().is_valid()) { - get_world()->_register_camera(this); + if (viewport) { + viewport->find_world()->_register_camera(this); } } break; case NOTIFICATION_LOST_CURRENT: { - if (get_world().is_valid()) { - get_world()->_remove_camera(this); + if (viewport) { + viewport->find_world()->_remove_camera(this); } } break; } @@ -255,8 +264,6 @@ bool Camera::is_current() const { return get_viewport()->get_camera() == this; } else return current; - - return false; } bool Camera::_can_gizmo_scale() const { @@ -694,6 +701,7 @@ Camera::Camera() { near = 0; far = 0; current = false; + viewport = NULL; force_change = false; mode = PROJECTION_PERSPECTIVE; set_perspective(70.0, 0.05, 100.0); diff --git a/scene/3d/camera.h b/scene/3d/camera.h index cbcefbb0ae..1cd729199d 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -64,6 +64,7 @@ public: private: bool force_change; bool current; + Viewport *viewport; Projection mode; diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp index 3190e1e0b2..219ea56681 100644 --- a/scene/3d/collision_shape.cpp +++ b/scene/3d/collision_shape.cpp @@ -228,7 +228,9 @@ void CollisionShape::_update_debug_shape() { void CollisionShape::_shape_changed() { // If this is a heightfield shape our center may have changed - _update_in_shape_owner(true); + if (parent) { + _update_in_shape_owner(true); + } if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) { debug_shape_dirty = true; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index b5e5022e63..c02873cdeb 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -886,7 +886,7 @@ void Viewport::_camera_set(Camera *p_camera) { if (camera == p_camera) return; - if (camera && find_world().is_valid()) { + if (camera) { camera->notification(Camera::NOTIFICATION_LOST_CURRENT); } camera = p_camera; @@ -895,7 +895,7 @@ void Viewport::_camera_set(Camera *p_camera) { else VisualServer::get_singleton()->viewport_attach_camera(viewport, RID()); - if (camera && find_world().is_valid()) { + if (camera) { camera->notification(Camera::NOTIFICATION_BECAME_CURRENT); } @@ -914,9 +914,7 @@ void Viewport::_camera_remove(Camera *p_camera) { cameras.erase(p_camera); if (camera == p_camera) { - if (camera && find_world().is_valid()) { - camera->notification(Camera::NOTIFICATION_LOST_CURRENT); - } + camera->notification(Camera::NOTIFICATION_LOST_CURRENT); camera = NULL; } } @@ -1013,7 +1011,7 @@ void Viewport::_propagate_enter_world(Node *p_node) { Viewport *v = Object::cast_to<Viewport>(p_node); if (v) { - if (v->world.is_valid()) + if (v->world.is_valid() || v->own_world.is_valid()) return; } } @@ -1050,7 +1048,7 @@ void Viewport::_propagate_exit_world(Node *p_node) { Viewport *v = Object::cast_to<Viewport>(p_node); if (v) { - if (v->world.is_valid()) + if (v->world.is_valid() || v->own_world.is_valid()) return; } } @@ -1070,23 +1068,11 @@ void Viewport::set_world(const Ref<World> &p_world) { if (is_inside_tree()) _propagate_exit_world(this); -#ifndef _3D_DISABLED - if (find_world().is_valid() && camera) - camera->notification(Camera::NOTIFICATION_LOST_CURRENT); -#endif - world = p_world; if (is_inside_tree()) _propagate_enter_world(this); -#ifndef _3D_DISABLED - if (find_world().is_valid() && camera) - camera->notification(Camera::NOTIFICATION_BECAME_CURRENT); -#endif - - //propagate exit - if (is_inside_tree()) { VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); } @@ -2722,11 +2708,6 @@ void Viewport::set_use_own_world(bool p_world) { if (is_inside_tree()) _propagate_exit_world(this); -#ifndef _3D_DISABLED - if (find_world().is_valid() && camera) - camera->notification(Camera::NOTIFICATION_LOST_CURRENT); -#endif - if (!p_world) own_world = Ref<World>(); else @@ -2735,13 +2716,6 @@ void Viewport::set_use_own_world(bool p_world) { if (is_inside_tree()) _propagate_enter_world(this); -#ifndef _3D_DISABLED - if (find_world().is_valid() && camera) - camera->notification(Camera::NOTIFICATION_BECAME_CURRENT); -#endif - - //propagate exit - if (is_inside_tree()) { VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); } diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 6ab78326b2..b49b551252 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1298,6 +1298,78 @@ float Animation::track_get_key_time(int p_track, int p_key_idx) const { ERR_FAIL_V(-1); } +void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { + + ERR_FAIL_INDEX(p_track, tracks.size()); + Track *t = tracks[p_track]; + + switch (t->type) { + + case TYPE_TRANSFORM: { + + TransformTrack *tt = static_cast<TransformTrack *>(t); + ERR_FAIL_INDEX(p_key_idx, tt->transforms.size()); + TKey<TransformKey> key = tt->transforms[p_key_idx]; + key.time = p_time; + tt->transforms.remove(p_key_idx); + _insert(p_time, tt->transforms, key); + return; + } + case TYPE_VALUE: { + + ValueTrack *vt = static_cast<ValueTrack *>(t); + ERR_FAIL_INDEX(p_key_idx, vt->values.size()); + TKey<Variant> key = vt->values[p_key_idx]; + key.time = p_time; + vt->values.remove(p_key_idx); + _insert(p_time, vt->values, key); + return; + } + case TYPE_METHOD: { + + MethodTrack *mt = static_cast<MethodTrack *>(t); + ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); + MethodKey key = mt->methods[p_key_idx]; + key.time = p_time; + mt->methods.remove(p_key_idx); + _insert(p_time, mt->methods, key); + return; + } + case TYPE_BEZIER: { + + BezierTrack *bt = static_cast<BezierTrack *>(t); + ERR_FAIL_INDEX(p_key_idx, bt->values.size()); + TKey<BezierKey> key = bt->values[p_key_idx]; + key.time = p_time; + bt->values.remove(p_key_idx); + _insert(p_time, bt->values, key); + return; + } + case TYPE_AUDIO: { + + AudioTrack *at = static_cast<AudioTrack *>(t); + ERR_FAIL_INDEX(p_key_idx, at->values.size()); + TKey<AudioKey> key = at->values[p_key_idx]; + key.time = p_time; + at->values.remove(p_key_idx); + _insert(p_time, at->values, key); + return; + } + case TYPE_ANIMATION: { + + AnimationTrack *at = static_cast<AnimationTrack *>(t); + ERR_FAIL_INDEX(p_key_idx, at->values.size()); + TKey<StringName> key = at->values[p_key_idx]; + key.time = p_time; + at->values.remove(p_key_idx); + _insert(p_time, at->values, key); + return; + } + } + + ERR_FAIL(); +} + float Animation::track_get_key_transition(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); @@ -2691,6 +2763,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("track_remove_key_at_position", "idx", "position"), &Animation::track_remove_key_at_position); ClassDB::bind_method(D_METHOD("track_set_key_value", "idx", "key", "value"), &Animation::track_set_key_value); ClassDB::bind_method(D_METHOD("track_set_key_transition", "idx", "key_idx", "transition"), &Animation::track_set_key_transition); + ClassDB::bind_method(D_METHOD("track_set_key_time", "idx", "key_idx", "time"), &Animation::track_set_key_time); ClassDB::bind_method(D_METHOD("track_get_key_transition", "idx", "key_idx"), &Animation::track_get_key_transition); ClassDB::bind_method(D_METHOD("track_get_key_count", "idx"), &Animation::track_get_key_count); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 36ebaa25d5..59f2ae24c7 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -305,6 +305,7 @@ public: void track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition = 1); void track_set_key_transition(int p_track, int p_key_idx, float p_transition); void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value); + void track_set_key_time(int p_track, int p_key_idx, float p_time); int track_find_key(int p_track, float p_time, bool p_exact = false) const; void track_remove_key(int p_track, int p_idx); void track_remove_key_at_position(int p_track, float p_pos); |