Path: blob/master/editor/animation/animation_track_editor.h
9912 views
/**************************************************************************/1/* animation_track_editor.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "editor/editor_data.h"33#include "editor/inspector/editor_properties.h"34#include "editor/inspector/property_selector.h"35#include "scene/3d/node_3d.h"36#include "scene/gui/control.h"37#include "scene/gui/menu_button.h"38#include "scene/gui/scroll_bar.h"39#include "scene/gui/tree.h"40#include "scene/resources/animation.h"4142class AnimationMarkerEdit;43class AnimationTrackEditor;44class AnimationTrackEdit;45class CheckBox;46class ColorPickerButton;47class EditorSpinSlider;48class HSlider;49class OptionButton;50class PanelContainer;51class SceneTreeDialog;52class SpinBox;53class TextureRect;54class ViewPanner;55class EditorValidationPanel;5657class AnimationTrackKeyEdit : public Object {58GDCLASS(AnimationTrackKeyEdit, Object);5960public:61bool setting = false;62bool animation_read_only = false;6364Ref<Animation> animation;65int track = -1;66float key_ofs = 0;67Node *root_path = nullptr;6869PropertyInfo hint;70NodePath base;71bool use_fps = false;72AnimationTrackEditor *editor = nullptr;7374bool _hide_script_from_inspector() { return true; }75bool _hide_metadata_from_inspector() { return true; }76bool _dont_undo_redo() { return true; }7778bool _is_read_only() { return animation_read_only; }7980void notify_change();81Node *get_root_path();82void set_use_fps(bool p_enable);8384protected:85static void _bind_methods();86void _fix_node_path(Variant &value);87void _update_obj(const Ref<Animation> &p_anim);88void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to);89bool _set(const StringName &p_name, const Variant &p_value);90bool _get(const StringName &p_name, Variant &r_ret) const;91void _get_property_list(List<PropertyInfo> *p_list) const;92};9394class AnimationMultiTrackKeyEdit : public Object {95GDCLASS(AnimationMultiTrackKeyEdit, Object);9697public:98bool setting = false;99bool animation_read_only = false;100101Ref<Animation> animation;102103RBMap<int, List<float>> key_ofs_map;104RBMap<int, NodePath> base_map;105PropertyInfo hint;106107Node *root_path = nullptr;108109bool use_fps = false;110AnimationTrackEditor *editor = nullptr;111112bool _hide_script_from_inspector() { return true; }113bool _hide_metadata_from_inspector() { return true; }114bool _dont_undo_redo() { return true; }115116bool _is_read_only() { return animation_read_only; }117118void notify_change();119Node *get_root_path();120void set_use_fps(bool p_enable);121122protected:123static void _bind_methods();124void _fix_node_path(Variant &value, NodePath &base);125void _update_obj(const Ref<Animation> &p_anim);126void _key_ofs_changed(const Ref<Animation> &p_anim, float from, float to);127bool _set(const StringName &p_name, const Variant &p_value);128bool _get(const StringName &p_name, Variant &r_ret) const;129void _get_property_list(List<PropertyInfo> *p_list) const;130};131132class AnimationMarkerKeyEdit : public Object {133GDCLASS(AnimationMarkerKeyEdit, Object);134135public:136bool animation_read_only = false;137138Ref<Animation> animation;139StringName marker_name;140bool use_fps = false;141142AnimationMarkerEdit *marker_edit = nullptr;143144bool _hide_script_from_inspector() { return true; }145bool _hide_metadata_from_inspector() { return true; }146bool _dont_undo_redo() { return true; }147148bool _is_read_only() { return animation_read_only; }149150float get_time() const;151152protected:153static void _bind_methods();154void _set_marker_name(const StringName &p_name);155bool _set(const StringName &p_name, const Variant &p_value);156bool _get(const StringName &p_name, Variant &r_ret) const;157void _get_property_list(List<PropertyInfo> *p_list) const;158};159160class AnimationMultiMarkerKeyEdit : public Object {161GDCLASS(AnimationMultiMarkerKeyEdit, Object);162163public:164bool animation_read_only = false;165166Ref<Animation> animation;167Vector<StringName> marker_names;168169AnimationMarkerEdit *marker_edit = nullptr;170171bool _hide_script_from_inspector() { return true; }172bool _hide_metadata_from_inspector() { return true; }173bool _dont_undo_redo() { return true; }174175bool _is_read_only() { return animation_read_only; }176177protected:178static void _bind_methods();179bool _set(const StringName &p_name, const Variant &p_value);180bool _get(const StringName &p_name, Variant &r_ret) const;181void _get_property_list(List<PropertyInfo> *p_list) const;182};183184class AnimationTimelineEdit : public Range {185GDCLASS(AnimationTimelineEdit, Range);186187friend class AnimationBezierTrackEdit;188friend class AnimationTrackEditor;189190static constexpr float SCROLL_ZOOM_FACTOR_IN = 1.02f; // Zoom factor per mouse scroll in the animation editor when zooming in. The closer to 1.0, the finer the control.191static constexpr float SCROLL_ZOOM_FACTOR_OUT = 0.98f; // Zoom factor when zooming out. Similar to SCROLL_ZOOM_FACTOR_IN but less than 1.0.192193Ref<Animation> animation;194bool read_only = false;195196AnimationTrackEdit *track_edit = nullptr;197int name_limit = 0;198Range *zoom = nullptr;199Range *h_scroll = nullptr;200float play_position_pos = 0.0f;201202HBoxContainer *add_track_hb = nullptr;203HBoxContainer *len_hb = nullptr;204EditorSpinSlider *length = nullptr;205Button *loop = nullptr;206TextureRect *time_icon = nullptr;207208MenuButton *add_track = nullptr;209LineEdit *filter_track = nullptr;210Control *play_position = nullptr; //separate control used to draw so updates for only position changed are much faster211HScrollBar *hscroll = nullptr;212213void _zoom_changed(double);214void _anim_length_changed(double p_new_len);215void _anim_loop_pressed();216217void _play_position_draw();218Rect2 hsize_rect;219220bool editing = false;221bool use_fps = false;222223Ref<ViewPanner> panner;224void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);225void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);226227bool dragging_timeline = false;228bool dragging_hsize = false;229float dragging_hsize_from = 0.0f;230float dragging_hsize_at = 0.0f;231double last_zoom_scale = 1.0;232double hscroll_on_zoom_buffer = -1.0;233234Vector2 zoom_scroll_origin;235bool zoom_callback_occurred = false;236237virtual void gui_input(const Ref<InputEvent> &p_event) override;238void _track_added(int p_track);239240float _get_zoom_scale(double p_zoom_value) const;241void _scroll_to_start();242243protected:244static void _bind_methods();245void _notification(int p_what);246247public:248int get_name_limit() const;249int get_buttons_width() const;250251float get_zoom_scale() const;252253virtual Size2 get_minimum_size() const override;254void set_animation(const Ref<Animation> &p_animation, bool p_read_only);255void set_track_edit(AnimationTrackEdit *p_track_edit);256void set_zoom(Range *p_zoom);257Range *get_zoom() const { return zoom; }258void auto_fit();259260void set_play_position(float p_pos);261float get_play_position() const;262void update_play_position();263264void update_values();265266void set_use_fps(bool p_use_fps);267bool is_using_fps() const;268269void set_hscroll(HScrollBar *p_hscroll);270271virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;272273AnimationTimelineEdit();274};275276class AnimationMarkerEdit : public Control {277GDCLASS(AnimationMarkerEdit, Control);278friend class AnimationTimelineEdit;279280enum {281MENU_KEY_INSERT,282MENU_KEY_RENAME,283MENU_KEY_DELETE,284MENU_KEY_TOGGLE_MARKER_NAMES,285};286287AnimationTimelineEdit *timeline = nullptr;288Control *play_position = nullptr; // Separate control used to draw so updates for only position changed are much faster.289float play_position_pos = 0.0f;290291HashSet<StringName> selection;292293Ref<Animation> animation;294bool read_only = false;295296Ref<Texture2D> type_icon;297Ref<Texture2D> selected_icon;298299PopupMenu *menu = nullptr;300301bool hovered = false;302StringName hovering_marker;303304void _zoom_changed();305306Ref<Texture2D> icon_cache;307308void _menu_selected(int p_index);309310void _play_position_draw();311bool _try_select_at_ui_pos(const Point2 &p_pos, bool p_aggregate, bool p_deselectable);312bool _is_ui_pos_in_current_section(const Point2 &p_pos);313314float insert_at_pos = 0.0f;315bool moving_selection_attempt = false;316bool moving_selection_effective = false;317float moving_selection_offset = 0.0f;318float moving_selection_pivot = 0.0f;319float moving_selection_mouse_begin_x = 0.0f;320float moving_selection_mouse_begin_y = 0.0f;321StringName select_single_attempt;322bool moving_selection = false;323void _move_selection_begin();324void _move_selection(float p_offset);325void _move_selection_commit();326void _move_selection_cancel();327328void _clear_selection_for_anim(const Ref<Animation> &p_anim);329void _select_key(const StringName &p_name, bool is_single = false);330void _deselect_key(const StringName &p_name);331332void _insert_marker(float p_ofs);333void _rename_marker(const StringName &p_name);334void _delete_selected_markers();335336ConfirmationDialog *marker_insert_confirm = nullptr;337LineEdit *marker_insert_new_name = nullptr;338ColorPickerButton *marker_insert_color = nullptr;339AcceptDialog *marker_insert_error_dialog = nullptr;340float marker_insert_ofs = 0;341342ConfirmationDialog *marker_rename_confirm = nullptr;343LineEdit *marker_rename_new_name = nullptr;344StringName marker_rename_prev_name;345346AcceptDialog *marker_rename_error_dialog = nullptr;347348bool should_show_all_marker_names = false;349350////////////// edit menu stuff351352void _marker_insert_confirmed();353void _marker_insert_new_name_changed(const String &p_text);354void _marker_rename_confirmed();355void _marker_rename_new_name_changed(const String &p_text);356357AnimationTrackEditor *editor = nullptr;358359HBoxContainer *_create_hbox_labeled_control(const String &p_text, Control *p_control) const;360361void _update_key_edit();362void _clear_key_edit();363364AnimationMarkerKeyEdit *key_edit = nullptr;365AnimationMultiMarkerKeyEdit *multi_key_edit = nullptr;366367protected:368static void _bind_methods();369void _notification(int p_what);370371virtual void gui_input(const Ref<InputEvent> &p_event) override;372373public:374virtual String get_tooltip(const Point2 &p_pos) const override;375376virtual int get_key_height() const;377virtual Rect2 get_key_rect(float p_pixels_sec) const;378virtual bool is_key_selectable_by_distance() const;379virtual void draw_key(const StringName &p_name, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);380virtual void draw_bg(int p_clip_left, int p_clip_right);381virtual void draw_fg(int p_clip_left, int p_clip_right);382383Ref<Animation> get_animation() const;384AnimationTimelineEdit *get_timeline() const { return timeline; }385AnimationTrackEditor *get_editor() const { return editor; }386bool is_selection_active() const { return !selection.is_empty(); }387bool is_moving_selection() const { return moving_selection; }388float get_moving_selection_offset() const { return moving_selection_offset; }389void set_animation(const Ref<Animation> &p_animation, bool p_read_only);390virtual Size2 get_minimum_size() const override;391392void set_timeline(AnimationTimelineEdit *p_timeline);393void set_editor(AnimationTrackEditor *p_editor);394395void set_play_position(float p_pos);396void update_play_position();397398void set_use_fps(bool p_use_fps);399400PackedStringArray get_selected_section() const;401bool is_marker_selected(const StringName &p_marker) const;402403// For use by AnimationTrackEditor.404void _clear_selection(bool p_update);405406AnimationMarkerEdit();407};408409class AnimationTrackEdit : public Control {410GDCLASS(AnimationTrackEdit, Control);411friend class AnimationTimelineEdit;412413enum {414MENU_CALL_MODE_CONTINUOUS,415MENU_CALL_MODE_DISCRETE,416MENU_CALL_MODE_CAPTURE,417MENU_INTERPOLATION_NEAREST,418MENU_INTERPOLATION_LINEAR,419MENU_INTERPOLATION_CUBIC,420MENU_INTERPOLATION_LINEAR_ANGLE,421MENU_INTERPOLATION_CUBIC_ANGLE,422MENU_LOOP_WRAP,423MENU_LOOP_CLAMP,424MENU_KEY_INSERT,425MENU_KEY_DUPLICATE,426MENU_KEY_CUT,427MENU_KEY_COPY,428MENU_KEY_PASTE,429MENU_KEY_ADD_RESET,430MENU_KEY_DELETE,431MENU_KEY_LOOKUP,432MENU_USE_BLEND_ENABLED,433MENU_USE_BLEND_DISABLED,434};435436AnimationTimelineEdit *timeline = nullptr;437Popup *path_popup = nullptr;438LineEdit *path = nullptr;439Node *root = nullptr;440Control *play_position = nullptr; //separate control used to draw so updates for only position changed are much faster441float play_position_pos = 0.0f;442NodePath node_path;443444Ref<Animation> animation;445bool read_only = false;446int track = 0;447448Rect2 check_rect;449Rect2 icon_rect;450Rect2 path_rect;451452Rect2 update_mode_rect;453Rect2 interp_mode_rect;454Rect2 loop_wrap_rect;455Rect2 remove_rect;456457Ref<Texture2D> type_icon;458Ref<Texture2D> selected_icon;459460PopupMenu *menu = nullptr;461462bool hovered = false;463bool clicking_on_name = false;464int hovering_key_idx = -1;465466void _zoom_changed();467468Ref<Texture2D> icon_cache;469String path_cache;470471void _menu_selected(int p_index);472473void _path_submitted(const String &p_text);474void _play_position_draw();475bool _is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const;476bool _try_select_at_ui_pos(const Point2 &p_pos, bool p_aggregate, bool p_deselectable);477478int lookup_key_idx = -1;479bool _lookup_key(int p_key_idx) const;480481Ref<Texture2D> _get_key_type_icon() const;482483mutable int dropping_at = 0;484float insert_at_pos = 0.0f;485bool moving_selection_attempt = false;486bool moving_selection_effective = false;487float moving_selection_pivot = 0.0f;488float moving_selection_mouse_begin_x = 0.0f;489int select_single_attempt = -1;490bool moving_selection = false;491492bool command_or_control_pressed = false;493494bool in_group = false;495AnimationTrackEditor *editor = nullptr;496497protected:498static void _bind_methods();499void _notification(int p_what);500501virtual void gui_input(const Ref<InputEvent> &p_event) override;502503public:504virtual Variant get_drag_data(const Point2 &p_point) override;505virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override;506virtual void drop_data(const Point2 &p_point, const Variant &p_data) override;507508virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;509virtual String get_tooltip(const Point2 &p_pos) const override;510511virtual int get_key_height() const;512virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);513virtual bool is_key_selectable_by_distance() const;514virtual void draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right);515virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);516virtual void draw_bg(int p_clip_left, int p_clip_right);517virtual void draw_fg(int p_clip_left, int p_clip_right);518519//helper520void draw_texture_region_clipped(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_region);521void draw_rect_clipped(const Rect2 &p_rect, const Color &p_color, bool p_filled = true);522523int get_track() const;524Ref<Animation> get_animation() const;525AnimationTimelineEdit *get_timeline() const { return timeline; }526AnimationTrackEditor *get_editor() const { return editor; }527NodePath get_path() const;528void set_animation_and_track(const Ref<Animation> &p_animation, int p_track, bool p_read_only);529virtual Size2 get_minimum_size() const override;530531void set_timeline(AnimationTimelineEdit *p_timeline);532void set_editor(AnimationTrackEditor *p_editor);533void set_root(Node *p_root);534535void set_play_position(float p_pos);536void update_play_position();537void cancel_drop();538539void set_in_group(bool p_enable);540void append_to_selection(const Rect2 &p_box, bool p_deselection);541542AnimationTrackEdit();543};544545class AnimationTrackEditPlugin : public RefCounted {546GDCLASS(AnimationTrackEditPlugin, RefCounted);547548public:549virtual AnimationTrackEdit *create_value_track_edit(Object *p_object, Variant::Type p_type, const String &p_property, PropertyHint p_hint, const String &p_hint_string, int p_usage);550virtual AnimationTrackEdit *create_audio_track_edit();551virtual AnimationTrackEdit *create_animation_track_edit(Object *p_object);552};553554class AnimationTrackKeyEdit;555class AnimationMultiTrackKeyEdit;556class AnimationBezierTrackEdit;557558class AnimationTrackEditGroup : public Control {559GDCLASS(AnimationTrackEditGroup, Control);560Ref<Texture2D> icon;561Vector2 icon_size;562String node_name;563NodePath node;564Node *root = nullptr;565AnimationTimelineEdit *timeline = nullptr;566AnimationTrackEditor *editor = nullptr;567568void _zoom_changed();569570protected:571void _notification(int p_what);572573virtual void gui_input(const Ref<InputEvent> &p_event) override;574575public:576void set_type_and_name(const Ref<Texture2D> &p_type, const String &p_name, const NodePath &p_node);577virtual Size2 get_minimum_size() const override;578void set_timeline(AnimationTimelineEdit *p_timeline);579void set_root(Node *p_root);580void set_editor(AnimationTrackEditor *p_editor);581String get_node_name() const;582583AnimationTrackEditGroup();584};585586class AnimationTrackEditor : public VBoxContainer {587GDCLASS(AnimationTrackEditor, VBoxContainer);588friend class AnimationTimelineEdit;589friend class AnimationBezierTrackEdit;590friend class AnimationMarkerKeyEditEditor;591592Ref<Animation> animation;593bool read_only = false;594Node *root = nullptr;595596MenuButton *edit = nullptr;597598PanelContainer *main_panel = nullptr;599HScrollBar *hscroll = nullptr;600ScrollContainer *scroll = nullptr;601VBoxContainer *track_vbox = nullptr;602AnimationBezierTrackEdit *bezier_edit = nullptr;603VBoxContainer *timeline_vbox = nullptr;604605Label *info_message = nullptr;606607AnimationTimelineEdit *timeline = nullptr;608AnimationMarkerEdit *marker_edit = nullptr;609HSlider *zoom = nullptr;610EditorSpinSlider *step = nullptr;611Button *fps_compat = nullptr;612Label *nearest_fps_label = nullptr;613TextureRect *zoom_icon = nullptr;614Button *snap_keys = nullptr;615Button *snap_timeline = nullptr;616Button *bezier_edit_icon = nullptr;617OptionButton *snap_mode = nullptr;618Button *auto_fit = nullptr;619Button *auto_fit_bezier = nullptr;620OptionButton *bezier_key_mode = nullptr;621622Button *imported_anim_warning = nullptr;623void _show_imported_anim_warning();624625Button *dummy_player_warning = nullptr;626void _show_dummy_player_warning();627628Button *inactive_player_warning = nullptr;629void _show_inactive_player_warning();630631void _snap_mode_changed(int p_mode);632Vector<AnimationTrackEdit *> track_edits;633Vector<AnimationTrackEditGroup *> groups;634635bool animation_changing_awaiting_update = false;636void _animation_update(); // Updated by AnimationTrackEditor(this)637int _get_track_selected();638void _animation_changed();639void _update_tracks();640void _redraw_tracks();641void _redraw_groups();642void _check_bezier_exist();643644void _name_limit_changed();645void _timeline_changed(float p_new_pos, bool p_timeline_only);646void _track_remove_request(int p_track);647void _animation_track_remove_request(int p_track, Ref<Animation> p_from_animation);648void _track_grab_focus(int p_track);649650void _update_scroll(double);651void _update_nearest_fps_label();652void _update_fps_compat_mode(bool p_enabled);653void _update_step(double p_new_step);654void _update_length(double p_new_len);655void _dropped_track(int p_from_track, int p_to_track);656657void _add_track(int p_type);658void _new_track_node_selected(NodePath p_path);659void _new_track_property_selected(const String &p_name);660661void _update_step_spinbox();662663PropertySelector *prop_selector = nullptr;664PropertySelector *method_selector = nullptr;665SceneTreeDialog *pick_track = nullptr;666int adding_track_type = 0;667NodePath adding_track_path;668669bool keying = false;670671struct InsertData {672Animation::TrackType type;673NodePath path;674int track_idx = 0;675float time = FLT_MAX; // Defaults to current timeline position.676Variant value;677String query;678bool advance = false;679};680681Label *insert_confirm_text = nullptr;682CheckBox *insert_confirm_bezier = nullptr;683CheckBox *insert_confirm_reset = nullptr;684ConfirmationDialog *insert_confirm = nullptr;685bool insert_queue = false;686List<InsertData> insert_data;687688void _query_insert(const InsertData &p_id);689Ref<Animation> _create_and_get_reset_animation();690void _confirm_insert_list();691struct TrackIndices {692int normal;693int reset;694695TrackIndices(const Animation *p_anim = nullptr, const Animation *p_reset_anim = nullptr) {696normal = p_anim ? p_anim->get_track_count() : 0;697reset = p_reset_anim ? p_reset_anim->get_track_count() : 0;698}699};700TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_reset_wanted, Ref<Animation> p_reset_anim, bool p_create_beziers);701void _insert_track(bool p_reset_wanted, bool p_create_beziers);702703void _root_removed();704705PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr);706707void _scroll_changed(const Vector2 &p_val);708void _v_scroll_changed(float p_val);709void _h_scroll_changed(float p_val);710711Ref<ViewPanner> panner;712void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);713void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);714715void _timeline_value_changed(double);716717float insert_key_from_track_call_ofs = 0.0f;718int insert_key_from_track_call_track = 0;719void _insert_key_from_track(float p_ofs, int p_track);720void _add_method_key(const String &p_method);721722void _fetch_value_track_options(const NodePath &p_path, Animation::UpdateMode *r_update_mode, Animation::InterpolationType *r_interpolation_type, bool *r_loop_wrap);723724void _clear_selection_for_anim(const Ref<Animation> &p_anim);725void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos);726727//selection728729struct SelectedKey {730int track = 0;731int key = 0;732bool operator<(const SelectedKey &p_key) const { return track == p_key.track ? key < p_key.key : track < p_key.track; }733};734735struct KeyInfo {736float pos = 0;737};738739RBMap<SelectedKey, KeyInfo> selection;740741bool moving_selection = false;742float moving_selection_offset = 0.0f;743void _move_selection_begin();744void _move_selection(float p_offset);745void _move_selection_commit();746void _move_selection_cancel();747748AnimationTrackKeyEdit *key_edit = nullptr;749AnimationMultiTrackKeyEdit *multi_key_edit = nullptr;750void _update_key_edit();751void _clear_key_edit();752753Control *box_selection_container = nullptr;754755Control *box_selection = nullptr;756void _box_selection_draw();757bool box_selecting = false;758Vector2 box_selecting_from;759Vector2 box_selecting_to;760Rect2 box_select_rect;761Vector2 prev_scroll_position;762void _scroll_input(const Ref<InputEvent> &p_event);763764Vector<Ref<AnimationTrackEditPlugin>> track_edit_plugins;765766void _toggle_bezier_edit();767void _cancel_bezier_edit();768void _bezier_edit(int p_for_track);769void _bezier_track_set_key_handle_mode(Animation *p_anim, int p_track, int p_index, Animation::HandleMode p_mode, Animation::HandleSetMode p_set_mode = Animation::HANDLE_SET_MODE_NONE);770void _bezier_track_set_key_handle_mode_at_time(Animation *p_anim, int p_track, float p_time, Animation::HandleMode p_mode, Animation::HandleSetMode p_set_mode = Animation::HANDLE_SET_MODE_NONE);771772////////////// edit menu stuff773774ConfirmationDialog *bake_dialog = nullptr;775CheckBox *bake_trs = nullptr;776CheckBox *bake_blendshape = nullptr;777CheckBox *bake_value = nullptr;778SpinBox *bake_fps = nullptr;779780ConfirmationDialog *optimize_dialog = nullptr;781SpinBox *optimize_velocity_error = nullptr;782SpinBox *optimize_angular_error = nullptr;783SpinBox *optimize_precision_error = nullptr;784785ConfirmationDialog *cleanup_dialog = nullptr;786CheckBox *cleanup_keys_with_trimming_head = nullptr;787CheckBox *cleanup_keys_with_trimming_end = nullptr;788CheckBox *cleanup_keys = nullptr;789CheckBox *cleanup_tracks = nullptr;790CheckBox *cleanup_all = nullptr;791792ConfirmationDialog *scale_dialog = nullptr;793SpinBox *scale = nullptr;794795ConfirmationDialog *ease_dialog = nullptr;796OptionButton *transition_selection = nullptr;797OptionButton *ease_selection = nullptr;798SpinBox *ease_fps = nullptr;799800void _select_all_tracks_for_copy();801802void _edit_menu_about_to_popup();803void _edit_menu_pressed(int p_option);804bool scale_from_cursor = false;805806void _cleanup_animation(Ref<Animation> p_animation);807808void _anim_duplicate_keys(float p_ofs, bool p_ofs_valid, int p_track);809810void _anim_copy_keys(bool p_cut);811812bool _is_track_compatible(int p_target_track_idx, Variant::Type p_source_value_type, Animation::TrackType p_source_track_type);813814void _anim_paste_keys(float p_ofs, bool p_ofs_valid, int p_track);815816void _toggle_function_names();817Button *function_name_toggler = nullptr;818819void _view_group_toggle();820821Button *view_group = nullptr;822Button *selected_filter = nullptr;823Button *alphabetic_sorting = nullptr;824825void _auto_fit();826void _auto_fit_bezier();827828void _selection_changed();829830ConfirmationDialog *track_copy_dialog = nullptr;831Tree *track_copy_select = nullptr;832833struct TrackClipboard {834NodePath full_path;835NodePath base_path;836Animation::TrackType track_type = Animation::TYPE_ANIMATION;837Animation::InterpolationType interp_type = Animation::INTERPOLATION_CUBIC_ANGLE;838Animation::UpdateMode update_mode = Animation::UPDATE_CAPTURE;839Animation::LoopMode loop_mode = Animation::LOOP_PINGPONG;840bool loop_wrap = false;841bool enabled = false;842bool use_blend = false;843844struct Key {845float time = 0;846float transition = 0;847Variant value;848};849Vector<Key> keys;850};851852struct KeyClipboard {853int top_track;854855struct Key {856Animation::TrackType track_type;857int track;858float time = 0;859float transition = 0;860Variant value;861};862Vector<Key> keys;863};864865Vector<TrackClipboard> track_clipboard;866KeyClipboard key_clipboard;867868void _set_key_clipboard(int p_top_track, float p_top_time, RBMap<SelectedKey, KeyInfo> &p_keymap);869void _insert_animation_key(NodePath p_path, const Variant &p_value);870871void _pick_track_filter_text_changed(const String &p_newtext);872void _pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates);873874double snap_unit;875bool fps_compatible = true;876int nearest_fps = 0;877void _update_snap_unit();878879protected:880static void _bind_methods();881void _notification(int p_what);882883public:884// Public for use with callable_mp.885void _clear_selection(bool p_update = false);886void _key_selected(int p_key, bool p_single, int p_track);887void _key_deselected(int p_key, int p_track);888889enum {890EDIT_COPY_TRACKS,891EDIT_COPY_TRACKS_CONFIRM,892EDIT_PASTE_TRACKS,893EDIT_CUT_KEYS,894EDIT_COPY_KEYS,895EDIT_PASTE_KEYS,896EDIT_SCALE_SELECTION,897EDIT_SCALE_FROM_CURSOR,898EDIT_SCALE_CONFIRM,899EDIT_SET_START_OFFSET,900EDIT_SET_END_OFFSET,901EDIT_EASE_SELECTION,902EDIT_EASE_CONFIRM,903EDIT_DUPLICATE_SELECTED_KEYS,904EDIT_DUPLICATE_SELECTION,905EDIT_DUPLICATE_TRANSPOSED,906EDIT_MOVE_FIRST_SELECTED_KEY_TO_CURSOR,907EDIT_MOVE_LAST_SELECTED_KEY_TO_CURSOR,908EDIT_ADD_RESET_KEY,909EDIT_DELETE_SELECTION,910EDIT_GOTO_NEXT_STEP,911EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation.912EDIT_GOTO_PREV_STEP,913EDIT_APPLY_RESET,914EDIT_BAKE_ANIMATION,915EDIT_BAKE_ANIMATION_CONFIRM,916EDIT_OPTIMIZE_ANIMATION,917EDIT_OPTIMIZE_ANIMATION_CONFIRM,918EDIT_CLEAN_UP_ANIMATION,919EDIT_CLEAN_UP_ANIMATION_CONFIRM920};921922void add_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);923void remove_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);924925void set_animation(const Ref<Animation> &p_anim, bool p_read_only);926Ref<Animation> get_current_animation() const;927void set_root(Node *p_root);928Node *get_root() const;929void update_keying();930bool has_keying() const;931932Dictionary get_state() const;933void set_state(const Dictionary &p_state);934void clear();935936void cleanup();937938void set_anim_pos(float p_pos);939void insert_node_value_key(Node *p_node, const String &p_property, bool p_only_if_exists = false, bool p_advance = false);940void insert_value_key(const String &p_property, bool p_advance);941void insert_transform_key(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type, const Variant &p_value);942bool has_track(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type);943void make_insert_queue();944void commit_insert_queue();945946void show_select_node_warning(bool p_show);947void show_dummy_player_warning(bool p_show);948void show_inactive_player_warning(bool p_show);949950bool is_key_selected(int p_track, int p_key) const;951bool is_selection_active() const;952bool is_key_clipboard_active() const;953bool is_moving_selection() const;954bool is_snap_timeline_enabled() const;955bool is_snap_keys_enabled() const;956bool is_bezier_editor_active() const;957bool can_add_reset_key() const;958void _on_filter_updated(const String &p_filter);959float get_moving_selection_offset() const;960float snap_time(float p_value, bool p_relative = false);961float get_snap_unit();962bool is_grouping_tracks();963bool is_sorting_alphabetically();964PackedStringArray get_selected_section() const;965bool is_marker_selected(const StringName &p_marker) const;966bool is_marker_moving_selection() const;967float get_marker_moving_selection_offset() const;968bool is_function_name_pressed();969970/** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */971void goto_prev_step(bool p_from_mouse_event);972973/** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */974void goto_next_step(bool p_from_mouse_event, bool p_timeline_only = false);975976MenuButton *get_edit_menu();977AnimationTrackEditor();978~AnimationTrackEditor();979};980981// AnimationTrackKeyEditEditorPlugin982983class AnimationTrackKeyEditEditor : public EditorProperty {984GDCLASS(AnimationTrackKeyEditEditor, EditorProperty);985986Ref<Animation> animation;987int track = -1;988real_t key_ofs = 0.0;989bool use_fps = false;990991EditorSpinSlider *spinner = nullptr;992993struct KeyDataCache {994real_t time = 0.0;995float transition = 0.0;996Variant value;997} key_data_cache;998999void _time_edit_spun();1000void _time_edit_entered();1001void _time_edit_exited();10021003public:1004AnimationTrackKeyEditEditor(Ref<Animation> p_animation, int p_track, real_t p_key_ofs, bool p_use_fps);1005};10061007// AnimationMarkerKeyEditEditorPlugin10081009class AnimationMarkerKeyEditEditor : public EditorProperty {1010GDCLASS(AnimationMarkerKeyEditEditor, EditorProperty);10111012Ref<Animation> animation;1013StringName marker_name;1014bool use_fps = false;10151016EditorSpinSlider *spinner = nullptr;10171018void _time_edit_exited();10191020public:1021AnimationMarkerKeyEditEditor(Ref<Animation> p_animation, const StringName &p_name, bool p_use_fps);1022};102310241025