Entirely new (and much improved) animation editor.

This commit is contained in:
Juan Linietsky 2018-06-07 12:46:14 -03:00
parent 3cd09cd943
commit b659fd6d74
60 changed files with 11745 additions and 5177 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,141 @@
#ifndef ANIMATION_BEZIER_EDITOR_H
#define ANIMATION_BEZIER_EDITOR_H
#include "animation_track_editor.h"
class AnimationBezierTrackEdit : public Control {
GDCLASS(AnimationBezierTrackEdit, Control)
enum HandleMode {
HANDLE_MODE_FREE,
HANDLE_MODE_BALANCED,
HANDLE_MODE_MIRROR
};
enum {
MENU_KEY_INSERT,
MENU_KEY_DUPLICATE,
MENU_KEY_DELETE
};
HandleMode handle_mode;
OptionButton *handle_mode_option;
AnimationTimelineEdit *timeline;
UndoRedo *undo_redo;
Node *root;
Control *play_position; //separate control used to draw so updates for only position changed are much faster
float play_position_pos;
Ref<Animation> animation;
int track;
Vector<Rect2> view_rects;
Ref<Texture> bezier_icon;
Ref<Texture> bezier_handle_icon;
Ref<Texture> selected_icon;
Rect2 close_icon_rect;
Map<int, Rect2> subtracks;
float v_scroll;
float v_zoom;
PopupMenu *menu;
void _zoom_changed();
void _gui_input(const Ref<InputEvent> &p_event);
void _menu_selected(int p_index);
bool *block_animation_update_ptr; //used to block all tracks re-gen (speed up)
void _play_position_draw();
Vector2 insert_at_pos;
bool moving_selection_attempt;
int select_single_attempt;
bool moving_selection;
int moving_selection_from_key;
Vector2 moving_selection_offset;
bool box_selecting_attempt;
bool box_selecting;
bool box_selecting_add;
Vector2 box_selection_from;
Vector2 box_selection_to;
int moving_handle; //0 no move -1 or +1 out
int moving_handle_key;
Vector2 moving_handle_left;
Vector2 moving_handle_right;
void _clear_selection();
void _clear_selection_for_anim(const Ref<Animation> &p_anim);
void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos);
Vector2 menu_insert_key;
struct AnimMoveRestore {
int track;
float time;
Variant key;
float transition;
};
AnimationTrackEditor *editor;
struct EditPoint {
Rect2 point_rect;
Rect2 in_rect;
Rect2 out_rect;
};
Vector<EditPoint> edit_points;
Set<int> selection;
bool panning_timeline;
float panning_timeline_from;
float panning_timeline_at;
void _draw_line_clipped(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, int p_clip_left, int p_clip_right);
void _draw_track(int p_track, const Color &p_color);
float _bezier_h_to_pixel(float p_h);
protected:
static void _bind_methods();
void _notification(int p_what);
public:
virtual String get_tooltip(const Point2 &p_pos) const;
Ref<Animation> get_animation() const;
void set_animation_and_track(const Ref<Animation> &p_animation, int p_track);
virtual Size2 get_minimum_size() const;
void set_undo_redo(UndoRedo *p_undo_redo);
void set_timeline(AnimationTimelineEdit *p_timeline);
void set_editor(AnimationTrackEditor *p_editor);
void set_root(Node *p_root);
void set_block_animation_update_ptr(bool *p_block_ptr);
void set_play_position(float p_pos);
void update_play_position();
void duplicate_selection();
void delete_selection();
AnimationBezierTrackEdit();
};
#endif // ANIMATION_BEZIER_EDITOR_H

File diff suppressed because it is too large Load diff

View file

@ -1,348 +0,0 @@
/*************************************************************************/
/* animation_editor.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef ANIMATION_EDITOR_H
#define ANIMATION_EDITOR_H
#include "scene/gui/control.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/scroll_bar.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tool_button.h"
#include "editor_data.h"
#include "property_editor.h"
#include "scene/animation/animation_cache.h"
#include "scene/resources/animation.h"
#include "scene_tree_editor.h"
class AnimationKeyEdit;
class AnimationCurveEdit;
class AnimationKeyEditor : public VBoxContainer {
GDCLASS(AnimationKeyEditor, VBoxContainer);
/*
enum {
MENU_NEW_ANIMATION,
MENU_OPEN_ANIMATION,
MENU_EDIT_ANIMATION,
MENU_CLOSE_ANIMATION,
MENU_KEYING_ACTIVE,
MENU_SET_ROOT_NODE,
MENU_SYNC_TO_PLAYER,
MENU_ANIM_BASE=100,
};
*/
enum {
ADD_TRACK_MENU_ADD_VALUE_TRACK,
ADD_TRACK_MENU_ADD_TRANSFORM_TRACK,
ADD_TRACK_MENU_ADD_CALL_TRACK,
TRACK_MENU_SCALE,
TRACK_MENU_SCALE_PIVOT,
TRACK_MENU_MOVE_UP,
TRACK_MENU_MOVE_DOWN,
TRACK_MENU_REMOVE,
TRACK_MENU_DUPLICATE,
TRACK_MENU_DUPLICATE_TRANSPOSE,
TRACK_MENU_SET_ALL_TRANS_LINEAR,
TRACK_MENU_SET_ALL_TRANS_CONSTANT,
TRACK_MENU_SET_ALL_TRANS_OUT,
TRACK_MENU_SET_ALL_TRANS_IN,
TRACK_MENU_SET_ALL_TRANS_INOUT,
TRACK_MENU_SET_ALL_TRANS_OUTIN,
TRACK_MENU_NEXT_STEP,
TRACK_MENU_PREV_STEP,
TRACK_MENU_OPTIMIZE,
TRACK_MENU_CLEAN_UP,
TRACK_MENU_CLEAN_UP_CONFIRM,
CURVE_SET_LINEAR,
CURVE_SET_IN,
CURVE_SET_OUT,
CURVE_SET_INOUT,
CURVE_SET_OUTIN,
CURVE_SET_CONSTANT
};
enum {
RIGHT_MENU_DUPLICATE,
RIGHT_MENU_DUPLICATE_TRANSPOSE,
RIGHT_MENU_REMOVE
};
struct MouseOver {
enum Over {
OVER_NONE,
OVER_NAME,
OVER_KEY,
OVER_VALUE,
OVER_INTERP,
OVER_WRAP,
OVER_UP,
OVER_DOWN,
OVER_REMOVE,
OVER_ADD_KEY,
};
Over over;
int track;
int over_key;
} mouse_over;
struct SelectedKey {
int track;
int key;
bool operator<(const SelectedKey &p_key) const { return track == p_key.track ? key < p_key.key : track < p_key.track; };
};
struct KeyInfo {
float pos;
};
Map<SelectedKey, KeyInfo> selection;
struct ClickOver {
enum Click {
CLICK_NONE,
CLICK_RESIZE_NAMES,
CLICK_DRAG_TIMELINE,
CLICK_MOVE_KEYS,
CLICK_SELECT_KEYS
};
SelectedKey selk;
bool shift;
Click click;
Point2 at;
Point2 to;
} click;
float timeline_pos;
float name_column_ratio;
int track_name_editing;
int interp_editing;
int cont_editing;
int wrap_editing;
int selected_track;
int track_ofs[5];
int last_menu_track_opt;
LineEdit *track_name;
PopupMenu *track_menu;
PopupMenu *type_menu;
Control *ec;
TextureRect *zoomicon;
HSlider *zoom;
//MenuButton *menu;
SpinBox *length;
Button *loop;
bool keying;
ToolButton *edit_button;
ToolButton *move_up_button;
ToolButton *move_down_button;
ToolButton *remove_button;
ToolButton *curve_linear;
ToolButton *curve_in;
ToolButton *curve_out;
ToolButton *curve_inout;
ToolButton *curve_outin;
ToolButton *curve_constant;
ConfirmationDialog *optimize_dialog;
SpinBox *optimize_linear_error;
SpinBox *optimize_angular_error;
SpinBox *optimize_max_angle;
ConfirmationDialog *cleanup_dialog;
CheckButton *cleanup_keys;
CheckButton *cleanup_tracks;
CheckButton *cleanup_all;
SpinBox *step;
MenuButton *menu_add_track;
MenuButton *menu_track;
HScrollBar *h_scroll;
VScrollBar *v_scroll;
Control *track_editor;
Control *track_pos;
TabContainer *key_editor_tab;
ConfirmationDialog *scale_dialog;
SpinBox *scale;
PropertyEditor *key_editor;
SceneTreeDialog *call_select;
Ref<Animation> animation;
void _update_paths();
int last_idx;
Node *root;
UndoRedo *undo_redo;
EditorHistory *history;
ConfirmationDialog *insert_confirm;
AnimationKeyEdit *key_edit;
AnimationCurveEdit *curve_edit;
bool inserting;
bool updating;
bool te_drawing;
void _animation_len_changed(float p_len);
void _animation_loop_changed();
void _step_changed(float p_len);
struct InsertData {
Animation::TrackType type;
NodePath path;
int track_idx;
Variant value;
String query;
bool advance;
}; /* insert_data;*/
bool insert_query;
List<InsertData> insert_data;
uint64_t insert_frame;
int cvi_track;
float cvi_pos;
int right_data_size_cache;
EditorSelection *editor_selection;
Label *select_anim_warning;
float _get_zoom_scale() const;
void _track_editor_draw();
void _track_editor_gui_input(const Ref<InputEvent> &p_input);
void _track_position_draw();
void _track_name_changed(const String &p_name);
void _track_menu_selected(int p_idx);
void _confirm_insert_list();
int _confirm_insert(InsertData p_id, int p_last_track = -1);
void _query_insert(const InsertData &p_id);
void _update_menu();
bool insert_queue;
void _insert_delay();
void _scale();
void _clear_selection();
//void _browse_path();
StringName alc;
void _animation_changed();
void _animation_optimize();
void _cleanup_animation(Ref<Animation> p_animation);
void _scroll_changed(double);
void _menu_add_track(int p_type);
void _menu_track(int p_type);
void _clear_selection_for_anim(const Ref<Animation> &p_anim);
void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos);
void _curve_transition_changed(float p_what);
PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path);
void _create_value_item(int p_type);
void _pane_drag(const Point2 &p_delta);
bool _edit_if_single_selection();
void _toggle_edit_curves();
void _animation_len_update();
void _add_call_track(const NodePath &p_base);
void _anim_duplicate_keys(bool transpose = false);
void _anim_delete_keys();
void _root_removed();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
void set_animation(const Ref<Animation> &p_anim);
Ref<Animation> get_current_animation() const;
void set_root(Node *p_root);
Node *get_root() const;
void update_keying();
bool has_keying() const;
void cleanup();
void set_anim_pos(float p_pos);
void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false);
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
void insert_transform_key(Spatial *p_node, const String &p_sub, const Transform &p_xform);
void show_select_node_warning(bool p_show) { select_anim_warning->set_visible(p_show); }
AnimationKeyEditor();
~AnimationKeyEditor();
};
#endif // ANIMATION_EDITOR_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,483 @@
#ifndef ANIMATION_TRACK_EDITOR_H
#define ANIMATION_TRACK_EDITOR_H
#include "scene/gui/control.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/scroll_bar.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tool_button.h"
#include "editor/property_selector.h"
#include "editor_data.h"
#include "editor_spin_slider.h"
#include "property_editor.h"
#include "scene/animation/animation_cache.h"
#include "scene/resources/animation.h"
#include "scene_tree_editor.h"
class AnimationTimelineEdit : public Range {
GDCLASS(AnimationTimelineEdit, Range)
Ref<Animation> animation;
int name_limit;
Range *zoom;
Range *h_scroll;
float play_position_pos;
HBoxContainer *len_hb;
EditorSpinSlider *length;
ToolButton *loop;
TextureRect *time_icon;
MenuButton *add_track;
Control *play_position; //separate control used to draw so updates for only position changed are much faster
HScrollBar *hscroll;
void _zoom_changed(double);
void _anim_length_changed(double p_new_len);
void _anim_loop_pressed();
void _play_position_draw();
UndoRedo *undo_redo;
Rect2 hsize_rect;
bool editing;
bool *block_animation_update_ptr; //used to block all tracks re-gen (speed up)
bool panning_timeline;
float panning_timeline_from;
float panning_timeline_at;
bool dragging_timeline;
bool dragging_hsize;
float dragging_hsize_from;
float dragging_hsize_at;
void _gui_input(const Ref<InputEvent> &p_event);
void _track_added(int p_track);
protected:
static void _bind_methods();
void _notification(int p_what);
public:
int get_name_limit() const;
int get_buttons_width() const;
float get_zoom_scale() const;
virtual Size2 get_minimum_size() const;
void set_animation(const Ref<Animation> &p_animation);
void set_zoom(Range *p_zoom);
Range *get_zoom() const { return zoom; }
void set_undo_redo(UndoRedo *p_undo_redo);
void set_block_animation_update_ptr(bool *p_block_ptr);
void set_play_position(float p_pos);
float get_play_position() const;
void update_play_position();
void update_values();
void set_hscroll(HScrollBar *p_hscroll);
AnimationTimelineEdit();
};
class AnimationTrackEditor;
class AnimationTrackEdit : public Control {
GDCLASS(AnimationTrackEdit, Control)
enum {
MENU_CALL_MODE_CONTINUOUS,
MENU_CALL_MODE_DISCRETE,
MENU_CALL_MODE_TRIGGER,
MENU_CALL_MODE_CAPTURE,
MENU_INTERPOLATION_NEAREST,
MENU_INTERPOLATION_LINEAR,
MENU_INTERPOLATION_CUBIC,
MENU_LOOP_WRAP,
MENU_LOOP_CLAMP,
MENU_KEY_INSERT,
MENU_KEY_DUPLICATE,
MENU_KEY_DELETE
};
AnimationTimelineEdit *timeline;
UndoRedo *undo_redo;
LineEdit *path;
Node *root;
Control *play_position; //separate control used to draw so updates for only position changed are much faster
float play_position_pos;
Ref<Animation> animation;
int track;
Rect2 check_rect;
Rect2 path_rect;
Rect2 update_mode_rect;
Rect2 interp_mode_rect;
Rect2 loop_mode_rect;
Rect2 remove_rect;
Rect2 bezier_edit_rect;
Ref<Texture> type_icon;
Ref<Texture> selected_icon;
PopupMenu *menu;
bool clicking_on_name;
void _zoom_changed();
Ref<Texture> icon_cache;
String path_cache;
void _menu_selected(int p_index);
bool *block_animation_update_ptr; //used to block all tracks re-gen (speed up)
void _path_entered(const String &p_text);
void _play_position_draw();
mutable int dropping_at;
float insert_at_pos;
bool moving_selection_attempt;
int select_single_attempt;
bool moving_selection;
float moving_selection_from_ofs;
bool in_group;
AnimationTrackEditor *editor;
protected:
static void _bind_methods();
void _notification(int p_what);
virtual void _gui_input(const Ref<InputEvent> &p_event);
public:
virtual Variant get_drag_data(const Point2 &p_point);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
virtual String get_tooltip(const Point2 &p_pos) const;
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual 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);
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
virtual void draw_bg(int p_clip_left, int p_clip_right);
virtual void draw_fg(int p_clip_left, int p_clip_right);
//helper
void draw_texture_clipped(const Ref<Texture> &p_texture, const Vector2 &p_pos);
void draw_texture_region_clipped(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_region);
void draw_rect_clipped(const Rect2 &p_rect, const Color &p_color, bool p_filled = true);
int get_track() const;
Ref<Animation> get_animation() const;
AnimationTimelineEdit *get_timeline() const { return timeline; }
AnimationTrackEditor *get_editor() const { return editor; }
UndoRedo *get_undo_redo() const { return undo_redo; }
bool *get_block_animation_update_ptr() { return block_animation_update_ptr; }
void set_animation_and_track(const Ref<Animation> &p_animation, int p_track);
virtual Size2 get_minimum_size() const;
void set_undo_redo(UndoRedo *p_undo_redo);
void set_timeline(AnimationTimelineEdit *p_timeline);
void set_editor(AnimationTrackEditor *p_editor);
void set_root(Node *p_root);
void set_block_animation_update_ptr(bool *p_block_ptr);
void set_play_position(float p_pos);
void update_play_position();
void cancel_drop();
void set_in_group(bool p_enable);
void append_to_selection(const Rect2 &p_box);
AnimationTrackEdit();
};
class AnimationTrackEditPlugin : public Reference {
GDCLASS(AnimationTrackEditPlugin, Reference)
public:
virtual 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);
virtual AnimationTrackEdit *create_audio_track_edit();
virtual AnimationTrackEdit *create_animation_track_edit(Object *p_object);
};
class AnimationTrackKeyEdit;
class AnimationBezierTrackEdit;
class AnimationTrackEditGroup : public Control {
GDCLASS(AnimationTrackEditGroup, Control)
Ref<Texture> icon;
String node_name;
NodePath node;
Node *root;
AnimationTimelineEdit *timeline;
void _zoom_changed();
protected:
static void _bind_methods();
void _notification(int p_what);
public:
void set_type_and_name(const Ref<Texture> &p_type, const String &p_name, const NodePath &p_node);
virtual Size2 get_minimum_size() const;
void set_timeline(AnimationTimelineEdit *p_timeline);
void set_root(Node *p_root);
AnimationTrackEditGroup();
};
class AnimationTrackEditor : public VBoxContainer {
GDCLASS(AnimationTrackEditor, VBoxContainer)
enum {
EDIT_COPY_TRACKS,
EDIT_COPY_TRACKS_CONFIRM,
EDIT_PASTE_TRACKS,
EDIT_SCALE_SELECTION,
EDIT_SCALE_FROM_CURSOR,
EDIT_SCALE_CONFIRM,
EDIT_DUPLICATE_SELECTION,
EDIT_DUPLICATE_TRANSPOSED,
EDIT_DELETE_SELECTION,
EDIT_GOTO_NEXT_STEP,
EDIT_GOTO_PREV_STEP,
EDIT_OPTIMIZE_ANIMATION,
EDIT_OPTIMIZE_ANIMATION_CONFIRM,
EDIT_CLEAN_UP_ANIMATION,
EDIT_CLEAN_UP_ANIMATION_CONFIRM
};
Ref<Animation> animation;
Node *root;
MenuButton *edit;
HScrollBar *hscroll;
ScrollContainer *scroll;
VBoxContainer *track_vbox;
AnimationBezierTrackEdit *bezier_edit;
AnimationTimelineEdit *timeline;
HSlider *zoom;
EditorSpinSlider *step;
TextureRect *zoom_icon;
ToolButton *snap;
Vector<AnimationTrackEdit *> track_edits;
Vector<AnimationTrackEditGroup *> groups;
bool block_animation_update;
int _get_track_selected();
void _animation_changed();
void _update_tracks();
void _name_limit_changed();
void _timeline_changed(float p_new_pos, bool p_drag);
void _track_remove_request(int p_track);
UndoRedo *undo_redo;
void _update_scroll(double);
void _update_step(double p_new_step);
void _update_length(double p_new_step);
void _dropped_track(int p_from_track, int p_to_track);
void _add_track(int p_type);
void _new_track_node_selected(NodePath p_path);
void _new_track_property_selected(String p_name);
PropertySelector *prop_selector;
PropertySelector *method_selector;
SceneTreeDialog *pick_track;
int adding_track_type;
NodePath adding_track_path;
bool keying;
struct InsertData {
Animation::TrackType type;
NodePath path;
int track_idx;
Variant value;
String query;
bool advance;
}; /* insert_data;*/
Label *insert_confirm_text;
CheckBox *insert_confirm_bezier;
ConfirmationDialog *insert_confirm;
bool insert_queue;
bool inserting;
bool insert_query;
List<InsertData> insert_data;
uint64_t insert_frame;
void _query_insert(const InsertData &p_id);
void _confirm_insert_list();
int _confirm_insert(InsertData p_id, int p_last_track, bool p_create_beziers = false);
void _insert_delay();
void _root_removed(Node *p_root);
PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = NULL);
void _timeline_value_changed(double);
float insert_key_from_track_call_ofs;
int insert_key_from_track_call_track;
void _insert_key_from_track(float p_ofs, int p_track);
void _add_method_key(const String &p_method);
void _clear_selection();
void _clear_selection_for_anim(const Ref<Animation> &p_anim);
void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos);
//selection
struct SelectedKey {
int track;
int key;
bool operator<(const SelectedKey &p_key) const { return track == p_key.track ? key < p_key.key : track < p_key.track; };
};
struct KeyInfo {
float pos;
};
Map<SelectedKey, KeyInfo> selection;
void _key_selected(int p_key, bool p_single, int p_track);
void _key_deselected(int p_key, int p_track);
bool moving_selection;
float moving_selection_offset;
void _move_selection_begin();
void _move_selection(float p_offset);
void _move_selection_commit();
void _move_selection_cancel();
AnimationTrackKeyEdit *key_edit;
void _update_key_edit();
void _clear_key_edit();
Control *box_selection;
void _box_selection_draw();
bool box_selecting;
Vector2 box_selecting_from;
Rect2 box_select_rect;
void _scroll_input(const Ref<InputEvent> &p_event);
Vector<Ref<AnimationTrackEditPlugin> > track_edit_plugins;
void _cancel_bezier_edit();
void _bezier_edit(int p_for_track);
////////////// edit menu stuff
ConfirmationDialog *optimize_dialog;
SpinBox *optimize_linear_error;
SpinBox *optimize_angular_error;
SpinBox *optimize_max_angle;
ConfirmationDialog *cleanup_dialog;
CheckButton *cleanup_keys;
CheckButton *cleanup_tracks;
CheckButton *cleanup_all;
ConfirmationDialog *scale_dialog;
SpinBox *scale;
void _edit_menu_pressed(int p_option);
int last_menu_track_opt;
void _cleanup_animation(Ref<Animation> p_animation);
void _anim_duplicate_keys(bool transpose);
void _view_group_toggle();
ToolButton *view_group;
ToolButton *selected_filter;
void _selection_changed();
ConfirmationDialog *track_copy_dialog;
Tree *track_copy_select;
struct TrackClipboard {
NodePath full_path;
NodePath base_path;
Animation::TrackType track_type;
Animation::InterpolationType interp_type;
Animation::UpdateMode update_mode;
bool loop_wrap;
bool enabled;
struct Key {
float time;
float transition;
Variant value;
};
Vector<Key> keys;
};
Vector<TrackClipboard> track_clipboard;
void _insert_animation_key(NodePath p_path, const Variant &p_value);
protected:
static void _bind_methods();
void _notification(int p_what);
public:
void add_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);
void remove_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);
void set_animation(const Ref<Animation> &p_anim);
Ref<Animation> get_current_animation() const;
void set_root(Node *p_root);
Node *get_root() const;
void update_keying();
bool has_keying() const;
void cleanup();
void set_anim_pos(float p_pos);
void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false);
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
void insert_transform_key(Spatial *p_node, const String &p_sub, const Transform &p_xform);
void show_select_node_warning(bool p_show);
bool is_key_selected(int p_track, int p_key) const;
bool is_selection_active() const;
bool is_moving_selection() const;
float get_moving_selection_offset() const;
bool is_snap_enabled();
float snap_time(float p_value);
MenuButton *get_edit_menu();
AnimationTrackEditor();
~AnimationTrackEditor();
};
#endif // ANIMATION_TRACK_EDITOR_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,139 @@
#ifndef ANIMATION_TRACK_EDITOR_PLUGINS_H
#define ANIMATION_TRACK_EDITOR_PLUGINS_H
#include "editor/animation_track_editor.h"
class AnimationTrackEditBool : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditBool, AnimationTrackEdit)
Ref<Texture> icon_checked;
Ref<Texture> icon_unchecked;
public:
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
};
class AnimationTrackEditColor : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditColor, AnimationTrackEdit)
public:
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
virtual 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);
};
class AnimationTrackEditAudio : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditAudio, AnimationTrackEdit)
ObjectID id;
void _preview_changed(ObjectID p_which);
protected:
static void _bind_methods();
public:
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
void set_node(Object *p_object);
AnimationTrackEditAudio();
};
class AnimationTrackEditSpriteFrame : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditSpriteFrame, AnimationTrackEdit)
ObjectID id;
public:
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
void set_node(Object *p_object);
};
class AnimationTrackEditSubAnim : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditSubAnim, AnimationTrackEdit)
ObjectID id;
public:
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
void set_node(Object *p_object);
};
class AnimationTrackEditTypeAudio : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditTypeAudio, AnimationTrackEdit)
void _preview_changed(ObjectID p_which);
bool len_resizing;
bool len_resizing_start;
int len_resizing_index;
float len_resizing_from_px;
float len_resizing_rel;
protected:
static void _bind_methods();
public:
virtual void _gui_input(const Ref<InputEvent> &p_event);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
AnimationTrackEditTypeAudio();
};
class AnimationTrackEditTypeAnimation : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditTypeAnimation, AnimationTrackEdit)
ObjectID id;
public:
virtual int get_key_height() const;
virtual Rect2 get_key_rect(int p_index, float p_pixels_sec);
virtual bool is_key_selectable_by_distance() const;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right);
void set_node(Object *p_object);
AnimationTrackEditTypeAnimation();
};
class AnimationTrackEditVolumeDB : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditVolumeDB, AnimationTrackEdit)
public:
virtual void draw_bg(int p_clip_left, int p_clip_right);
virtual void draw_fg(int p_clip_left, int p_clip_right);
virtual int get_key_height() const;
virtual 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);
};
class AnimationTrackEditDefaultPlugin : public AnimationTrackEditPlugin {
GDCLASS(AnimationTrackEditDefaultPlugin, AnimationTrackEditPlugin)
public:
virtual 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);
virtual AnimationTrackEdit *create_audio_track_edit();
virtual AnimationTrackEdit *create_animation_track_edit(Object *p_object);
};
#endif // ANIMATION_TRACK_EDITOR_PLUGINS_H

View file

@ -0,0 +1,211 @@
#include "audio_stream_preview.h"
/////////////////////
float AudioStreamPreview::get_length() const {
return length;
}
float AudioStreamPreview::get_max(float p_time, float p_time_next) const {
if (length == 0)
return 0;
int max = preview.size() / 2;
int time_from = p_time / length * max;
int time_to = p_time_next / length * max;
time_from = CLAMP(time_from, 0, max - 1);
time_to = CLAMP(time_to, 0, max - 1);
if (time_to <= time_from) {
time_to = time_from + 1;
}
uint8_t vmax;
for (int i = time_from; i < time_to; i++) {
uint8_t v = preview[i * 2 + 1];
if (i == 0 || v > vmax) {
vmax = v;
}
}
return (vmax / 255.0) * 2.0 - 1.0;
}
float AudioStreamPreview::get_min(float p_time, float p_time_next) const {
if (length == 0)
return 0;
int max = preview.size() / 2;
int time_from = p_time / length * max;
int time_to = p_time_next / length * max;
time_from = CLAMP(time_from, 0, max - 1);
time_to = CLAMP(time_to, 0, max - 1);
if (time_to <= time_from) {
time_to = time_from + 1;
}
uint8_t vmin;
for (int i = time_from; i < time_to; i++) {
uint8_t v = preview[i * 2];
if (i == 0 || v < vmin) {
vmin = v;
}
}
return (vmin / 255.0) * 2.0 - 1.0;
}
AudioStreamPreview::AudioStreamPreview() {
length = 0;
}
////
void AudioStreamPreviewGenerator::_update_emit(ObjectID p_id) {
emit_signal("preview_updated", p_id);
}
void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) {
Preview *preview = (Preview *)p_preview;
float muxbuff_chunk_s = 0.25;
int mixbuff_chunk_frames = AudioServer::get_singleton()->get_mix_rate() * muxbuff_chunk_s;
Vector<AudioFrame> mix_chunk;
mix_chunk.resize(mixbuff_chunk_frames);
int frames_total = AudioServer::get_singleton()->get_mix_rate() * preview->preview->length;
int frames_todo = frames_total;
preview->playback->start();
while (frames_todo) {
int ofs_write = uint64_t(frames_total - frames_todo) * uint64_t(preview->preview->preview.size() / 2) / uint64_t(frames_total);
int to_read = MIN(frames_todo, mixbuff_chunk_frames);
int to_write = uint64_t(to_read) * uint64_t(preview->preview->preview.size() / 2) / uint64_t(frames_total);
to_write = MIN(to_write, (preview->preview->preview.size() / 2) - ofs_write);
preview->playback->mix(mix_chunk.ptrw(), 1.0, to_read);
for (int i = 0; i < to_write; i++) {
float max = -1000;
float min = 1000;
int from = uint64_t(i) * to_read / to_write;
int to = uint64_t(i + 1) * to_read / to_write;
to = MIN(to, to_read);
from = MIN(from, to_read - 1);
if (to == from) {
to = from + 1;
}
for (int j = from; j < to; j++) {
max = MAX(max, mix_chunk[j].l);
max = MAX(max, mix_chunk[j].r);
min = MIN(min, mix_chunk[j].l);
min = MIN(min, mix_chunk[j].r);
}
uint8_t pfrom = CLAMP((min * 0.5 + 0.5) * 255, 0, 255);
uint8_t pto = CLAMP((max * 0.5 + 0.5) * 255, 0, 255);
preview->preview->preview[(ofs_write + i) * 2 + 0] = pfrom;
preview->preview->preview[(ofs_write + i) * 2 + 1] = pto;
}
frames_todo -= to_read;
singleton->call_deferred("_update_emit", preview->id);
}
preview->playback->stop();
preview->generating = false;
}
Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<AudioStream> &p_stream) {
ERR_FAIL_COND_V(p_stream.is_null(), Ref<AudioStreamPreview>());
if (previews.has(p_stream->get_instance_id())) {
return previews[p_stream->get_instance_id()].preview;
}
//no preview exists
previews[p_stream->get_instance_id()] = Preview();
Preview *preview = &previews[p_stream->get_instance_id()];
preview->base_stream = p_stream;
preview->playback = preview->base_stream->instance_playback();
preview->generating = true;
preview->id = p_stream->get_instance_id();
float len_s = preview->base_stream->get_length();
if (len_s == 0) {
len_s = 60 * 5; //five minutes
}
int frames = AudioServer::get_singleton()->get_mix_rate() * len_s;
Vector<uint8_t> maxmin;
int pw = frames / 20;
maxmin.resize(pw * 2);
{
uint8_t *ptr = maxmin.ptrw();
for (int i = 0; i < pw * 2; i++) {
ptr[i] = 127;
}
}
preview->preview.instance();
preview->preview->preview = maxmin;
preview->preview->length = len_s;
preview->thread = Thread::create(_preview_thread, preview);
return preview->preview;
}
void AudioStreamPreviewGenerator::_bind_methods() {
ClassDB::bind_method("_update_emit", &AudioStreamPreviewGenerator::_update_emit);
ClassDB::bind_method(D_METHOD("generate_preview", "stream"), &AudioStreamPreviewGenerator::generate_preview);
ADD_SIGNAL(MethodInfo("preview_updated", PropertyInfo(Variant::INT, "obj_id")));
}
AudioStreamPreviewGenerator *AudioStreamPreviewGenerator::singleton = NULL;
void AudioStreamPreviewGenerator::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
List<ObjectID> to_erase;
for (Map<ObjectID, Preview>::Element *E = previews.front(); E; E = E->next()) {
if (!E->get().generating) {
if (E->get().thread) {
Thread::wait_to_finish(E->get().thread);
E->get().thread = NULL;
}
if (!ObjectDB::get_instance(E->key())) { //no longer in use, get rid of preview
to_erase.push_back(E->key());
}
}
}
while (to_erase.front()) {
previews.erase(to_erase.front()->get());
to_erase.pop_front();
}
}
}
AudioStreamPreviewGenerator::AudioStreamPreviewGenerator() {
singleton = this;
set_process(true);
}

View file

@ -0,0 +1,56 @@
#ifndef AUDIO_STREAM_PREVIEW_H
#define AUDIO_STREAM_PREVIEW_H
#include "os/thread.h"
#include "scene/main/node.h"
#include "servers/audio/audio_stream.h"
class AudioStreamPreview : public Reference {
GDCLASS(AudioStreamPreview, Reference)
friend class AudioStream;
Vector<uint8_t> preview;
float length;
friend class AudioStreamPreviewGenerator;
public:
float get_length() const;
float get_max(float p_time, float p_time_next) const;
float get_min(float p_time, float p_time_next) const;
AudioStreamPreview();
};
class AudioStreamPreviewGenerator : public Node {
GDCLASS(AudioStreamPreviewGenerator, Node)
static AudioStreamPreviewGenerator *singleton;
struct Preview {
Ref<AudioStreamPreview> preview;
Ref<AudioStream> base_stream;
Ref<AudioStreamPlayback> playback;
volatile bool generating;
ObjectID id;
Thread *thread;
};
Map<ObjectID, Preview> previews;
static void _preview_thread(void *p_preview);
void _update_emit(ObjectID p_id);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
static AudioStreamPreviewGenerator *get_singleton() { return singleton; }
Ref<AudioStreamPreview> generate_preview(const Ref<AudioStream> &p_preview);
AudioStreamPreviewGenerator();
};
#endif // AUDIO_STREAM_PREVIEW_H

View file

@ -1331,8 +1331,9 @@ void EditorInspector::update_tree() {
} else if (!(p.usage & PROPERTY_USAGE_EDITOR)) } else if (!(p.usage & PROPERTY_USAGE_EDITOR))
continue; continue;
if (hide_script && p.name == "script") if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) {
continue; continue;
}
String basename = p.name; String basename = p.name;
if (group != "") { if (group != "") {

View file

@ -51,7 +51,6 @@
#include "scene/resources/packed_scene.h" #include "scene/resources/packed_scene.h"
#include "servers/physics_2d_server.h" #include "servers/physics_2d_server.h"
#include "editor/animation_editor.h"
#include "editor/editor_audio_buses.h" #include "editor/editor_audio_buses.h"
#include "editor/editor_file_system.h" #include "editor/editor_file_system.h"
#include "editor/editor_help.h" #include "editor/editor_help.h"
@ -3038,6 +3037,7 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorInspector>(); ClassDB::register_class<EditorInspector>();
ClassDB::register_class<EditorInspectorPlugin>(); ClassDB::register_class<EditorInspectorPlugin>();
ClassDB::register_class<EditorProperty>(); ClassDB::register_class<EditorProperty>();
ClassDB::register_class<AnimationTrackEditPlugin>();
// FIXME: Is this stuff obsolete, or should it be ported to new APIs? // FIXME: Is this stuff obsolete, or should it be ported to new APIs?
ClassDB::register_class<EditorScenePostImport>(); ClassDB::register_class<EditorScenePostImport>();
@ -5300,6 +5300,8 @@ EditorNode::EditorNode() {
file->connect("file_selected", this, "_dialog_action"); file->connect("file_selected", this, "_dialog_action");
file_templates->connect("file_selected", this, "_dialog_action"); file_templates->connect("file_selected", this, "_dialog_action");
preview_gen = memnew(AudioStreamPreviewGenerator);
add_child(preview_gen);
//plugin stuff //plugin stuff
file_server = memnew(EditorFileServer); file_server = memnew(EditorFileServer);
@ -5382,8 +5384,7 @@ EditorNode::EditorNode() {
resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin)));
// FIXME: Needs to be rewritten for AudioStream in Godot 3.0+ resource_preview->add_preview_generator(Ref<EditorAudioStreamPreviewPlugin>(memnew(EditorAudioStreamPreviewPlugin)));
//resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin )));
resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorFontPreviewPlugin>(memnew(EditorFontPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorFontPreviewPlugin>(memnew(EditorFontPreviewPlugin)));

View file

@ -32,6 +32,7 @@
#define EDITOR_NODE_H #define EDITOR_NODE_H
#include "core/print_string.h" #include "core/print_string.h"
#include "editor/audio_stream_preview.h"
#include "editor/connections_dialog.h" #include "editor/connections_dialog.h"
#include "editor/create_dialog.h" #include "editor/create_dialog.h"
#include "editor/editor_about.h" #include "editor/editor_about.h"
@ -81,6 +82,7 @@
#include "scene/gui/tool_button.h" #include "scene/gui/tool_button.h"
#include "scene/gui/tree.h" #include "scene/gui/tree.h"
#include "scene/gui/viewport_container.h" #include "scene/gui/viewport_container.h"
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
@ -298,6 +300,7 @@ private:
Vector<ToolButton *> main_editor_buttons; Vector<ToolButton *> main_editor_buttons;
Vector<EditorPlugin *> editor_table; Vector<EditorPlugin *> editor_table;
AudioStreamPreviewGenerator *preview_gen;
ProgressDialog *progress_dialog; ProgressDialog *progress_dialog;
BackgroundProgress *progress_hb; BackgroundProgress *progress_hb;

View file

@ -37,6 +37,9 @@ String EditorSpinSlider::get_text_value() const {
} }
void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
if (read_only)
return;
Ref<InputEventMouseButton> mb = p_event; Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
@ -301,10 +304,23 @@ void EditorSpinSlider::_grabber_mouse_exited() {
update(); update();
} }
void EditorSpinSlider::set_read_only(bool p_enable) {
read_only = p_enable;
update();
}
bool EditorSpinSlider::is_read_only() const {
return read_only;
}
void EditorSpinSlider::_bind_methods() { void EditorSpinSlider::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_label", "label"), &EditorSpinSlider::set_label); ClassDB::bind_method(D_METHOD("set_label", "label"), &EditorSpinSlider::set_label);
ClassDB::bind_method(D_METHOD("get_label"), &EditorSpinSlider::get_label); ClassDB::bind_method(D_METHOD("get_label"), &EditorSpinSlider::get_label);
ClassDB::bind_method(D_METHOD("set_read_only", "read_only"), &EditorSpinSlider::set_read_only);
ClassDB::bind_method(D_METHOD("is_read_only"), &EditorSpinSlider::is_read_only);
ClassDB::bind_method(D_METHOD("_gui_input"), &EditorSpinSlider::_gui_input); ClassDB::bind_method(D_METHOD("_gui_input"), &EditorSpinSlider::_gui_input);
ClassDB::bind_method(D_METHOD("_grabber_mouse_entered"), &EditorSpinSlider::_grabber_mouse_entered); ClassDB::bind_method(D_METHOD("_grabber_mouse_entered"), &EditorSpinSlider::_grabber_mouse_entered);
ClassDB::bind_method(D_METHOD("_grabber_mouse_exited"), &EditorSpinSlider::_grabber_mouse_exited); ClassDB::bind_method(D_METHOD("_grabber_mouse_exited"), &EditorSpinSlider::_grabber_mouse_exited);
@ -313,6 +329,7 @@ void EditorSpinSlider::_bind_methods() {
ClassDB::bind_method(D_METHOD("_value_input_entered"), &EditorSpinSlider::_value_input_entered); ClassDB::bind_method(D_METHOD("_value_input_entered"), &EditorSpinSlider::_value_input_entered);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only");
} }
EditorSpinSlider::EditorSpinSlider() { EditorSpinSlider::EditorSpinSlider() {
@ -342,4 +359,5 @@ EditorSpinSlider::EditorSpinSlider() {
value_input->connect("modal_closed", this, "_value_input_closed"); value_input->connect("modal_closed", this, "_value_input_closed");
value_input->connect("text_entered", this, "_value_input_entered"); value_input->connect("text_entered", this, "_value_input_entered");
hide_slider = false; hide_slider = false;
read_only = false;
} }

View file

@ -55,6 +55,8 @@ class EditorSpinSlider : public Range {
bool grabbing_spinner_attempt; bool grabbing_spinner_attempt;
bool grabbing_spinner; bool grabbing_spinner;
bool read_only;
Vector2 grabbing_spinner_mouse_pos; Vector2 grabbing_spinner_mouse_pos;
LineEdit *value_input; LineEdit *value_input;
@ -80,6 +82,9 @@ public:
void set_hide_slider(bool p_hide); void set_hide_slider(bool p_hide);
bool is_hiding_slider() const; bool is_hiding_slider() const;
void set_read_only(bool p_enable);
bool is_read_only() const;
virtual Size2 get_minimum_size() const; virtual Size2 get_minimum_size() const;
EditorSpinSlider(); EditorSpinSlider();
}; };

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_animation_filter.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1089"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="10.429825"
inkscape:cx="-5.6414698"
inkscape:cy="10.961343"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="g10" />
<g
transform="matrix(0.02719109,0,0,0.02719109,1.3153462,1.0022864)"
id="g12">
<g
id="g10">
<path
inkscape:connector-curvature="0"
d="M 495.289,20.143 H 16.709 c -14.938,0 -22.344,18.205 -11.666,28.636 l 169.7,165.778 v 260.587 c 0,14.041 16.259,21.739 27.131,13.031 L 331.017,384.743 c 3.956,-3.169 6.258,-7.962 6.258,-13.031 V 214.556 L 506.955,48.779 c 10.688,-10.44 3.259,-28.636 -11.666,-28.636 z"
id="path8"
style="fill:#e0e0e0;fill-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_animation_track_group.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1089"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="10.429825"
inkscape:cx="6.2135985"
inkscape:cy="6.5622523"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
style="fill:#e0e0e0"
inkscape:connector-curvature="0"
id="path2"
d="M 5.0508475,2 V 4 H 14 V 2 Z m -3.322034,-0.016949 v 2 h 2 v -2 z M 8.9830508,7 V 9 H 14 V 7 Z m -3.5254237,5 v 2 h 2 v -2 z m 3.5254237,0 v 2 H 14 v -2 z"
sodipodi:nodetypes="ccccccccccccccccccccccccc" />
<path
style="fill:#e0e0e0"
inkscape:connector-curvature="0"
id="path2-3"
d="m 5.4915255,6.9322039 v 1.999999 h 2 v -1.999999 z"
sodipodi:nodetypes="ccccc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_animation_track_list.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1089"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<g
transform="translate(0 -1036.4)"
id="g4">
<path
transform="translate(0 1036.4)"
d="m2 2v2h2v-2h-2zm4 0v2h8v-2h-8zm-4 5v2h2v-2h-2zm4 0v2h8v-2h-8zm-4 5v2h2v-2h-2zm4 0v2h8v-2h-8z"
fill="#e0e0e0"
id="path2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_bezier_handles_balanced.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1417"
inkscape:window-height="685"
id="namedview8"
showgrid="false"
inkscape:zoom="20.85965"
inkscape:cx="4.2910315"
inkscape:cy="11.857644"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="m 1.7627119,13.627119 c 0,0 1.2881355,-6.847458 6.5762712,-8.1355935 5.0847459,0.9491522 5.9661009,8.1355925 5.9661009,8.1355925"
id="path4526"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846"
cx="1.8983043"
cy="13.491526"
rx="1.2675855"
ry="1.1997888" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3"
cx="14.237288"
cy="13.491526"
rx="1.2675855"
ry="1.1997888" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:0.61799997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 7.4559186,5.1473018 2.7203863,6.7014816"
id="path5878"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:0.61489719;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 10.790357,4.2063094 8.2893822,5.149623"
id="path5878-7"
inkscape:connector-curvature="0" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3-6"
cx="8.2711868"
cy="4.7796612"
rx="1.2675855"
ry="1.1997888" />
<path
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="M 1.7157324,5.8754878 A 1.2675855,1.1997888 0 0 0 0.44815434,7.0747066 1.2675855,1.1997888 0 0 0 1.7157324,8.2739253 1.2675855,1.1997888 0 0 0 2.9833105,7.0747066 1.2675855,1.1997888 0 0 0 1.7157324,5.8754878 Z m 0.00195,0.4238282 A 0.84677333,0.80148375 0 0 1 2.5653417,7.1000972 0.84677333,0.80148375 0 0 1 1.7176855,7.9008784 0.84677333,0.80148375 0 0 1 0.87002934,7.1000972 0.84677333,0.80148375 0 0 1 1.7176855,6.299316 Z"
id="path5846-5"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.7567277;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="M 11.909414,2.4642073 A 1.2836218,1.231838 0 0 0 10.6258,3.6954601 1.2836218,1.231838 0 0 0 11.909414,4.9267128 1.2836218,1.231838 0 0 0 13.193028,3.6954601 1.2836218,1.231838 0 0 0 11.909414,2.4642073 Z m 0.002,0.4351497 a 0.85748593,0.82289328 0 0 1 0.858383,0.8221719 0.85748593,0.82289328 0 0 1 -0.85838,0.822172 0.85748593,0.82289328 0 0 1 -0.858379,-0.822172 0.85748593,0.82289328 0 0 1 0.858379,-0.8221719 z"
id="path5846-5-6" />
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_bezier_handles_separate.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1417"
inkscape:window-height="685"
id="namedview8"
showgrid="false"
inkscape:zoom="20.85965"
inkscape:cx="4.2910315"
inkscape:cy="11.857644"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="m 1.7627119,13.627119 c 0,0 1.2881355,-6.847458 6.5762712,-8.1355935 5.0847459,0.9491522 5.9661009,8.1355925 5.9661009,8.1355925"
id="path4526"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846"
cx="1.8983043"
cy="13.491526"
rx="1.2675855"
ry="1.1997888" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3"
cx="14.237288"
cy="13.491526"
rx="1.2675855"
ry="1.1997888" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:0.80513805;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 7.6850253,4.7560401 3.9088983,5.4168"
id="path5878"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:0.73079807;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 11.695505,2.3941651 8.696384,4.6876729"
id="path5878-7"
inkscape:connector-curvature="0" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3-6"
cx="8.2711868"
cy="4.7796612"
rx="1.2675855"
ry="1.1997888" />
<path
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="M 2.4961199,4.3976698 A 1.1997888,1.2675855 80.074672 0 0 1.4542161,5.7974257 1.1997888,1.2675855 80.074672 0 0 2.9095255,6.7602105 1.1997888,1.2675855 80.074672 0 0 3.9514292,5.3604547 1.1997888,1.2675855 80.074672 0 0 2.4961199,4.3976698 Z m 0.074974,0.4171488 A 0.80148375,0.84677333 80.074672 0 1 3.5440925,5.4575082 0.80148375,0.84677333 80.074672 0 1 2.8471493,6.3924102 0.80148375,0.84677333 80.074672 0 1 1.8741535,5.74972 0.80148375,0.84677333 80.074672 0 1 2.5710967,4.814818 Z"
id="path5846-5"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.7567277;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="m 11.838896,0.64428913 a 1.231838,1.2836218 52.593897 0 0 -0.271701,1.75779027 1.231838,1.2836218 52.593897 0 0 1.767576,0.1983008 1.231838,1.2836218 52.593897 0 0 0.271701,-1.75779027 1.231838,1.2836218 52.593897 0 0 -1.767576,-0.1983008 z m 0.265925,0.3444462 A 0.82289328,0.85748593 52.593897 0 1 13.286115,1.1203938 0.82289328,0.85748593 52.593897 0 1 13.103698,2.2949179 0.82289328,0.85748593 52.593897 0 1 11.922407,2.163257 0.82289328,0.85748593 52.593897 0 1 12.104824,0.98873353 Z"
id="path5846-5-6" />
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_bezier_handles_mirror.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1417"
inkscape:window-height="685"
id="namedview8"
showgrid="false"
inkscape:zoom="20.85965"
inkscape:cx="4.2910315"
inkscape:cy="11.857644"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="m 1.7627119,13.627119 c 0,0 1.2881355,-6.847458 6.5762712,-8.1355935 5.0847459,0.9491522 5.9661009,8.1355925 5.9661009,8.1355925"
id="path4526"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846"
cx="1.8983043"
cy="13.491526"
rx="1.2675855"
ry="1.1997888" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3"
cx="14.237288"
cy="13.491526"
rx="1.2675855"
ry="1.1997888" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:0.80513805;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 8.2033896,4.6779662 H 4.3698875"
id="path5878"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#84c2ff;stroke-width:0.71670938;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 11.931789,4.6440679 H 8.2033896"
id="path5878-7"
inkscape:connector-curvature="0" />
<ellipse
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3-6"
cx="8.2711868"
cy="4.7796612"
rx="1.2675855"
ry="1.1997888" />
<path
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="M 3.1539157,3.4305762 A 1.2675855,1.1997888 0 0 0 1.8863376,4.629795 1.2675855,1.1997888 0 0 0 3.1539157,5.8290137 1.2675855,1.1997888 0 0 0 4.4214938,4.629795 1.2675855,1.1997888 0 0 0 3.1539157,3.4305762 Z m 0.00195,0.4238282 A 0.84677333,0.80148375 0 0 1 4.003525,4.6551856 0.84677333,0.80148375 0 0 1 3.1558688,5.4559668 0.84677333,0.80148375 0 0 1 2.3082126,4.6551856 0.84677333,0.80148375 0 0 1 3.1558688,3.8544044 Z"
id="path5846-5"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="m 13.093969,3.3750567 a 1.2675855,1.1997888 0 0 0 -1.267578,1.1992188 1.2675855,1.1997888 0 0 0 1.267578,1.1992187 1.2675855,1.1997888 0 0 0 1.267578,-1.1992187 1.2675855,1.1997888 0 0 0 -1.267578,-1.1992188 z m 0.002,0.4238282 a 0.84677333,0.80148375 0 0 1 0.847659,0.8007812 0.84677333,0.80148375 0 0 1 -0.847656,0.8007812 0.84677333,0.80148375 0 0 1 -0.847656,-0.8007812 0.84677333,0.80148375 0 0 1 0.847656,-0.8007812 z"
id="path5846-5-6" />
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="24"
version="1.1"
viewBox="0 0 16 24"
id="svg6"
sodipodi:docname="icon_color_track_vu.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10">
<linearGradient
id="linearGradient4583"
inkscape:collect="always">
<stop
id="stop4579"
offset="0"
style="stop-color:#f70000;stop-opacity:1" />
<stop
id="stop4581"
offset="1"
style="stop-color:#eec315;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4549">
<stop
style="stop-color:#288027;stop-opacity:1"
offset="0"
id="stop4545" />
<stop
style="stop-color:#dbee15;stop-opacity:1"
offset="1"
id="stop4547" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4549"
id="linearGradient4551"
x1="7.7288136"
y1="16.474577"
x2="7.7288136"
y2="3.8644071"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0931873,0,0,1.4762899,-0.98021429,0.08553021)" />
<linearGradient
gradientTransform="matrix(1.1036585,0,0,0.47778193,-16.507235,-7.9018165)"
inkscape:collect="always"
xlink:href="#linearGradient4583"
id="linearGradient4551-7"
x1="7.7288136"
y1="16.474577"
x2="7.7288136"
y2="3.8644071"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1170"
inkscape:window-height="712"
id="namedview8"
showgrid="false"
showguides="false"
inkscape:zoom="14.75"
inkscape:cx="5.3261277"
inkscape:cy="13.681053"
inkscape:window-x="397"
inkscape:window-y="233"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<rect
style="fill:url(#linearGradient4551);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
id="rect822"
width="18.232145"
height="18.416088"
x="-1.3507863"
y="5.9906898"
ry="0.84580106" />
<rect
style="fill:url(#linearGradient4551-7);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;paint-order:fill markers stroke"
id="rect822-5"
width="18.406782"
height="5.9601259"
x="-16.881357"
y="-5.9906898"
ry="0.27373245"
transform="scale(-1)" />
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_edit_bezier.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1039"
inkscape:window-height="585"
id="namedview8"
showgrid="false"
inkscape:zoom="20.85965"
inkscape:cx="11.65471"
inkscape:cy="9.0988062"
inkscape:window-x="277"
inkscape:window-y="113"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1036.4)"
id="g4">
<path
style="fill:none;stroke:#84c2ff;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
d="m 1.4758015,1050.3064 c 11.6492855,0.7191 3.1098343,-11.4976 12.2331255,-11.3475"
id="path4526"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<circle
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1"
id="path5846-3"
cy="1038.7133"
cx="13.470984"
r="1.8230016" />
<circle
r="1.8230016"
cx="2.4449117"
cy="1050.1708"
id="circle1374"
style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:5.64574671;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_animation.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1852"
inkscape:window-height="781"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="-10.271186"
inkscape:cy="3.4149032"
inkscape:window-x="68"
inkscape:window-y="117"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#ea686c"
id="rect2"
style="fill:#b76ef0;fill-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_audio.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1053"
inkscape:window-height="591"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="4"
inkscape:cy="4"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#ea686c"
id="rect2"
style="fill:#eae668;fill-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_bezier.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1852"
inkscape:window-height="781"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="-17.152542"
inkscape:cy="3.4149032"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#ea686c"
id="rect2"
style="fill:#5792f6;fill-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_bezier_handle.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1853"
inkscape:window-height="1016"
id="namedview8"
showgrid="false"
inkscape:zoom="59"
inkscape:cx="2.0952442"
inkscape:cy="4.6061633"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1044.4)"
id="g4">
<path
style="fill:#e0e0e0;fill-opacity:1"
d="M 3.9960938 -0.037109375 C 3.8010931 -0.037109375 3.6064535 0.038077731 3.4570312 0.1875 L 0.22070312 3.4238281 C -0.078134343 3.7226656 -0.078141414 4.2050617 0.22070312 4.5039062 L 3.4570312 7.7402344 C 3.7558687 8.0390718 4.2382719 8.0390718 4.5371094 7.7402344 L 7.7734375 4.5039062 C 8.072282 4.2050617 8.072275 3.7226656 7.7734375 3.4238281 L 4.5371094 0.1875 C 4.3876871 0.038077731 4.1910944 -0.037109375 3.9960938 -0.037109375 z M 4.0253906 0.81445312 C 4.1770098 0.81445312 4.3291322 0.87241756 4.4453125 0.98828125 L 6.9609375 3.4960938 C 7.193298 3.7278211 7.193298 4.102257 6.9609375 4.3339844 L 4.4453125 6.84375 C 4.212952 7.0754774 3.8378293 7.0754774 3.6054688 6.84375 L 1.0898438 4.3339844 C 0.85748323 4.102257 0.85748323 3.7278211 1.0898438 3.4960938 L 3.6054688 0.98828125 C 3.721649 0.87241756 3.8737714 0.81445312 4.0253906 0.81445312 z "
transform="translate(0,1044.4)"
id="rect2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_bezier_point.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="836"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="4"
inkscape:cy="4"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#e0e0e0"
id="rect2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_bezier_selected.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="836"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="4"
inkscape:cy="4"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#84c2ff"
id="rect2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,5 +1,64 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<g transform="translate(0 -1044.4)"> <svg
<rect transform="rotate(-45)" x="-741.53" y="741.08" width="6.1027" height="6.1027" ry=".76286" fill="#adf18f"/> xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_call.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="836"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="4"
inkscape:cy="4"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#adf18f"
id="rect2"
style="fill:#66f376;fill-opacity:1" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,5 +1,76 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<g transform="translate(0 -1044.4)"> <svg
<rect transform="rotate(-45)" x="-741.53" y="741.08" width="6.1027" height="6.1027" ry=".76286" fill="#84c2ff"/> xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_selected.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1568"
inkscape:window-height="767"
id="namedview8"
showgrid="false"
inkscape:zoom="41.7193"
inkscape:cx="-0.48848775"
inkscape:cy="3.5639274"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="g4-3" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#84c2ff"
id="rect2" />
</g>
<g
transform="translate(0,-1044.4)"
id="g4-3">
<rect
style="fill:#003e7a;fill-opacity:1;stroke-width:0.56281364"
transform="matrix(0.71728847,-0.69677633,0.71728847,0.69677633,0,0)"
x="-751.20953"
y="753.42743"
width="3.4346831"
height="3.4346831"
ry="0.42934799"
id="rect2-6" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,5 +1,64 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<g transform="translate(0 -1044.4)"> <svg
<rect transform="rotate(-45)" x="-741.53" y="741.08" width="6.1027" height="6.1027" ry=".76286" fill="#ea686c"/> xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="8"
version="1.1"
viewBox="0 0 8 8"
id="svg6"
sodipodi:docname="icon_key_xform.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="836"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="4"
inkscape:cy="4"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1044.4)"
id="g4">
<rect
transform="rotate(-45)"
x="-741.53"
y="741.08"
width="6.1027"
height="6.1027"
ry=".76286"
fill="#ea686c"
id="rect2"
style="fill:#ea9568;fill-opacity:1" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
viewBox="0 0 16 16"
id="svg6"
sodipodi:docname="icon_time.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="836"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="4.4999435"
inkscape:cy="13.04848"
inkscape:window-x="744"
inkscape:window-y="280"
inkscape:window-maximized="0"
inkscape:current-layer="g4" />
<g
transform="translate(0 -1036.4)"
id="g4">
<g
id="g8"
style="fill:#e0e0e0;fill-opacity:1"
transform="matrix(0.0279396,0,0,0.02755726,0.91401567,1037.1343)">
<g
id="g6"
style="fill:#e0e0e0;fill-opacity:1">
<path
d="M 276.193,58.507 V 40.389 h 14.578 c 11.153,0 20.194,-9.042 20.194,-20.194 C 310.965,9.043 301.923,0 290.771,0 h -69.544 c -11.153,0 -20.194,9.042 -20.194,20.194 0,11.152 9.042,20.194 20.194,20.194 h 14.578 V 58.506 C 119.952,68.76 28.799,166.327 28.799,284.799 28.799,410.078 130.721,512 256,512 381.279,512 483.201,410.078 483.201,284.799 483.2,166.327 392.046,68.76 276.193,58.507 Z m 0,412.009 v -20.124 c 0,-11.153 -9.042,-20.194 -20.194,-20.194 -11.153,0 -20.194,9.042 -20.194,20.194 v 20.124 C 148.895,461.131 79.668,391.902 70.283,304.994 h 20.124 c 11.153,0 20.194,-9.042 20.194,-20.194 0,-11.152 -9.042,-20.194 -20.194,-20.194 H 70.282 c 9.385,-86.91 78.614,-156.137 165.522,-165.523 v 20.124 c 0,11.153 9.042,20.194 20.194,20.194 11.153,0 20.194,-9.042 20.194,-20.194 V 99.081 c 86.91,9.385 156.137,78.614 165.522,165.523 H 421.59 c -11.153,0 -20.194,9.042 -20.194,20.194 0,11.152 9.042,20.194 20.194,20.194 h 20.126 c -9.385,86.911 -78.613,156.14 -165.523,165.524 z"
id="path2"
style="fill:#e0e0e0;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="m 317.248,194.99 -58.179,58.18 c -1.011,-0.097 -2.034,-0.151 -3.071,-0.151 -17.552,0 -31.779,14.229 -31.779,31.779 0,17.552 14.228,31.779 31.779,31.779 17.551,0 31.779,-14.229 31.779,-31.779 0,-1.037 -0.054,-2.06 -0.151,-3.07 l 58.178,-58.18 c 7.887,-7.885 7.887,-20.672 0,-28.559 -7.882,-7.886 -20.669,-7.886 -28.556,0.001 z"
id="path4"
style="fill:#e0e0e0;fill-opacity:1"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="8"
version="1.1"
viewBox="0 0 16 8"
id="svg6"
sodipodi:docname="icon_track_capture.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1350"
inkscape:window-height="593"
id="namedview8"
showgrid="false"
inkscape:zoom="27.577164"
inkscape:cx="8.347146"
inkscape:cy="4.4012076"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
style="fill:#e0e0e0;fill-opacity:1"
d="m 2.1665128,0.99764963 c -0.422625,0 -0.763672,0.34104737 -0.763672,0.76367187 v 4.5742187 c 0,0.4226242 0.341047,0.7617192 0.763672,0.7617192 h 4.472656 c 0.422625,0 0.763672,-0.339095 0.763672,-0.7617192 V 5.347259 h -3.300781 c -0.1662,0 -0.298828,-0.3390943 -0.298828,-0.7617188 V 3.3609308 c 0,-0.4226244 0.132628,-0.7636718 0.298828,-0.7636718 h 3.300781 V 1.7613215 c 0,-0.4226245 -0.341047,-0.76367187 -0.763672,-0.76367187 z"
id="rect1389"
inkscape:connector-curvature="0" />
<path
style="fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0.80299997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 9.1827441,4.7953408 C 9.6993662,3.7537783 10.278269,2.5835979 10.469195,2.1949398 l 0.347137,-0.7066511 0.679654,0.00665 0.679654,0.00665 0.956945,2.3125 c 0.526319,1.271875 1.007254,2.4334375 1.068744,2.5812497 l 0.1118,0.26875 H 13.715914 13.1187 L 12.785851,6.0203387 12.453002,5.3765887 H 11.319176 10.185351 L 9.8066761,6.032702 9.4280014,6.6888154 l -0.5922856,1.37e-4 -0.592285,1.36e-4 z m 3.1779349,-0.369483 c 0.0042,-0.00346 -0.233487,-0.4884588 -0.528245,-1.0777779 l -0.535922,-1.0714891 -0.03691,0.0875 c -0.0203,0.048125 -0.183516,0.425 -0.362699,0.8375 -0.179182,0.4125 -0.355738,0.85125 -0.392346,0.975 -0.03661,0.12375 -0.07127,0.2390723 -0.07703,0.2562715 -0.0083,0.024853 0.188215,0.027989 0.957503,0.015278 0.532385,-0.0088 0.971429,-0.018823 0.975651,-0.022283 z"
id="path1424"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -292,14 +292,14 @@ void InspectorDock::_menu_expandall() {
} }
void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) { void InspectorDock::_property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance) {
AnimationPlayerEditor::singleton->get_key_editor()->insert_value_key(p_keyed, p_value, p_advance); AnimationPlayerEditor::singleton->get_track_editor()->insert_value_key(p_keyed, p_value, p_advance);
} }
void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) { void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Transform &p_key) {
Spatial *s = Object::cast_to<Spatial>(sp); Spatial *s = Object::cast_to<Spatial>(sp);
if (!s) if (!s)
return; return;
AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s, p_sub, p_key); AnimationPlayerEditor::singleton->get_track_editor()->insert_transform_key(s, p_sub, p_key);
} }
void InspectorDock::_warning_pressed() { void InspectorDock::_warning_pressed() {
@ -435,10 +435,14 @@ void InspectorDock::update(Object *p_object) {
} }
} }
void InspectorDock::go_back() {
_edit_back();
}
void InspectorDock::update_keying() { void InspectorDock::update_keying() {
bool valid = false; bool valid = false;
if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) { if (AnimationPlayerEditor::singleton->get_track_editor()->has_keying()) {
EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history(); EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
if (editor_history->get_path_size() >= 1) { if (editor_history->get_path_size() >= 1) {

View file

@ -31,7 +31,7 @@
#ifndef INSPECTOR_DOCK_H #ifndef INSPECTOR_DOCK_H
#define INSPECTOR_DOCK_H #define INSPECTOR_DOCK_H
#include "editor/animation_editor.h" #include "editor/animation_track_editor.h"
#include "editor/connections_dialog.h" #include "editor/connections_dialog.h"
#include "editor/create_dialog.h" #include "editor/create_dialog.h"
#include "editor/editor_data.h" #include "editor/editor_data.h"
@ -121,6 +121,7 @@ protected:
static void _bind_methods(); static void _bind_methods();
public: public:
void go_back();
void update_keying(); void update_keying();
void edit_resource(const Ref<Resource> &p_resource); void edit_resource(const Ref<Resource> &p_resource);
void open_resource(const String &p_type); void open_resource(const String &p_type);

View file

@ -30,7 +30,7 @@
#include "animation_player_editor_plugin.h" #include "animation_player_editor_plugin.h"
#include "editor/animation_editor.h" #include "editor/animation_track_editor.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "io/resource_loader.h" #include "io/resource_loader.h"
#include "io/resource_saver.h" #include "io/resource_saver.h"
@ -50,9 +50,9 @@ void AnimationPlayerEditor::_node_removed(Node *p_node) {
set_process(false); set_process(false);
key_editor->set_animation(Ref<Animation>()); track_editor->set_animation(Ref<Animation>());
key_editor->set_root(NULL); track_editor->set_root(NULL);
key_editor->show_select_node_warning(true); track_editor->show_select_node_warning(true);
_update_player(); _update_player();
//editor->animation_editor_make_visible(false); //editor->animation_editor_make_visible(false);
} }
@ -84,7 +84,7 @@ void AnimationPlayerEditor::_notification(int p_what) {
} }
} }
frame->set_value(player->get_current_animation_position()); frame->set_value(player->get_current_animation_position());
key_editor->set_anim_pos(player->get_current_animation_position()); track_editor->set_anim_pos(player->get_current_animation_position());
EditorNode::get_singleton()->get_inspector()->refresh(); EditorNode::get_singleton()->get_inspector()->refresh();
} else if (last_active) { } else if (last_active) {
@ -101,8 +101,6 @@ void AnimationPlayerEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
save_anim->get_popup()->connect("id_pressed", this, "_animation_save_menu");
tool_anim->get_popup()->connect("id_pressed", this, "_animation_tool_menu"); tool_anim->get_popup()->connect("id_pressed", this, "_animation_tool_menu");
onion_skinning->get_popup()->connect("id_pressed", this, "_onion_skinning_menu"); onion_skinning->get_popup()->connect("id_pressed", this, "_onion_skinning_menu");
@ -121,16 +119,8 @@ void AnimationPlayerEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: { case NOTIFICATION_THEME_CHANGED: {
add_anim->set_icon(get_icon("New", "EditorIcons"));
rename_anim->set_icon(get_icon("Rename", "EditorIcons"));
duplicate_anim->set_icon(get_icon("Duplicate", "EditorIcons"));
autoplay->set_icon(get_icon("AutoPlay", "EditorIcons")); autoplay->set_icon(get_icon("AutoPlay", "EditorIcons"));
load_anim->set_icon(get_icon("Folder", "EditorIcons"));
save_anim->set_icon(get_icon("Save", "EditorIcons"));
remove_anim->set_icon(get_icon("Remove", "EditorIcons"));
blend_anim->set_icon(get_icon("Blend", "EditorIcons"));
play->set_icon(get_icon("PlayStart", "EditorIcons")); play->set_icon(get_icon("PlayStart", "EditorIcons"));
play_from->set_icon(get_icon("Play", "EditorIcons")); play_from->set_icon(get_icon("Play", "EditorIcons"));
play_bw->set_icon(get_icon("PlayStartBackwards", "EditorIcons")); play_bw->set_icon(get_icon("PlayStartBackwards", "EditorIcons"));
@ -138,11 +128,26 @@ void AnimationPlayerEditor::_notification(int p_what) {
autoplay_icon = get_icon("AutoPlay", "EditorIcons"); autoplay_icon = get_icon("AutoPlay", "EditorIcons");
stop->set_icon(get_icon("Stop", "EditorIcons")); stop->set_icon(get_icon("Stop", "EditorIcons"));
resource_edit_anim->set_icon(get_icon("EditResource", "EditorIcons"));
pin->set_icon(get_icon("Pin", "EditorIcons")); pin->set_icon(get_icon("Pin", "EditorIcons"));
tool_anim->set_icon(get_icon("Tools", "EditorIcons"));
onion_skinning->set_icon(get_icon("Onion", "EditorIcons")); onion_skinning->set_icon(get_icon("Onion", "EditorIcons"));
tool_anim->add_style_override("normal", get_stylebox("normal", "Button"));
track_editor->get_edit_menu()->add_style_override("normal", get_stylebox("normal", "Button"));
#define ITEM_ICON(m_item, m_icon) tool_anim->get_popup()->set_item_icon(tool_anim->get_popup()->get_item_index(m_item), get_icon(m_icon, "EditorIcons"))
ITEM_ICON(TOOL_NEW_ANIM, "New");
ITEM_ICON(TOOL_LOAD_ANIM, "Load");
ITEM_ICON(TOOL_SAVE_ANIM, "Save");
ITEM_ICON(TOOL_SAVE_AS_ANIM, "Save");
ITEM_ICON(TOOL_DUPLICATE_ANIM, "Duplicate");
ITEM_ICON(TOOL_RENAME_ANIM, "Rename");
ITEM_ICON(TOOL_EDIT_TRANSITIONS, "Blend");
ITEM_ICON(TOOL_REMOVE_ANIM, "Remove");
//ITEM_ICON(TOOL_COPY_ANIM, "Copy");
//ITEM_ICON(TOOL_PASTE_ANIM, "Paste");
} break; } break;
} }
} }
@ -304,10 +309,10 @@ void AnimationPlayerEditor::_animation_selected(int p_which) {
Ref<Animation> anim = player->get_animation(current); Ref<Animation> anim = player->get_animation(current);
{ {
key_editor->set_animation(anim); track_editor->set_animation(anim);
Node *root = player->get_node(player->get_root()); Node *root = player->get_node(player->get_root());
if (root) { if (root) {
key_editor->set_root(root); track_editor->set_root(root);
} }
} }
frame->set_max(anim->get_length()); frame->set_max(anim->get_length());
@ -317,8 +322,8 @@ void AnimationPlayerEditor::_animation_selected(int p_which) {
frame->set_step(0.00001); frame->set_step(0.00001);
} else { } else {
key_editor->set_animation(Ref<Animation>()); track_editor->set_animation(Ref<Animation>());
key_editor->set_root(NULL); track_editor->set_root(NULL);
} }
autoplay->set_pressed(current == player->get_autoplay()); autoplay->set_pressed(current == player->get_autoplay());
@ -704,16 +709,16 @@ void AnimationPlayerEditor::_animation_edit() {
if (animation->get_item_count()) { if (animation->get_item_count()) {
String current = animation->get_item_text(animation->get_selected()); String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim = player->get_animation(current); Ref<Animation> anim = player->get_animation(current);
key_editor->set_animation(anim); track_editor->set_animation(anim);
Node *root = player->get_node(player->get_root()); Node *root = player->get_node(player->get_root());
if (root) { if (root) {
key_editor->set_root(root); track_editor->set_root(root);
} }
} else { } else {
key_editor->set_animation(Ref<Animation>()); track_editor->set_animation(Ref<Animation>());
key_editor->set_root(NULL); track_editor->set_root(NULL);
} }
} }
void AnimationPlayerEditor::_dialog_action(String p_file) { void AnimationPlayerEditor::_dialog_action(String p_file) {
@ -810,8 +815,16 @@ void AnimationPlayerEditor::_update_player() {
animation->clear(); animation->clear();
add_anim->set_disabled(player == NULL); #define ITEM_DISABLED(m_item, m_disabled) tool_anim->get_popup()->set_item_disabled(tool_anim->get_popup()->get_item_index(m_item), m_disabled)
load_anim->set_disabled(player == NULL);
ITEM_DISABLED(TOOL_SAVE_ANIM, animlist.size() == 0);
ITEM_DISABLED(TOOL_SAVE_AS_ANIM, animlist.size() == 0);
ITEM_DISABLED(TOOL_DUPLICATE_ANIM, animlist.size() == 0);
ITEM_DISABLED(TOOL_RENAME_ANIM, animlist.size() == 0);
ITEM_DISABLED(TOOL_EDIT_TRANSITIONS, animlist.size() == 0);
ITEM_DISABLED(TOOL_COPY_ANIM, animlist.size() == 0);
ITEM_DISABLED(TOOL_REMOVE_ANIM, animlist.size() == 0);
stop->set_disabled(animlist.size() == 0); stop->set_disabled(animlist.size() == 0);
play->set_disabled(animlist.size() == 0); play->set_disabled(animlist.size() == 0);
play_bw->set_disabled(animlist.size() == 0); play_bw->set_disabled(animlist.size() == 0);
@ -820,12 +833,6 @@ void AnimationPlayerEditor::_update_player() {
frame->set_editable(animlist.size() != 0); frame->set_editable(animlist.size() != 0);
animation->set_disabled(animlist.size() == 0); animation->set_disabled(animlist.size() == 0);
autoplay->set_disabled(animlist.size() == 0); autoplay->set_disabled(animlist.size() == 0);
duplicate_anim->set_disabled(animlist.size() == 0);
rename_anim->set_disabled(animlist.size() == 0);
blend_anim->set_disabled(animlist.size() == 0);
remove_anim->set_disabled(animlist.size() == 0);
resource_edit_anim->set_disabled(animlist.size() == 0);
save_anim->set_disabled(animlist.size() == 0);
tool_anim->set_disabled(player == NULL); tool_anim->set_disabled(player == NULL);
onion_skinning->set_disabled(player == NULL); onion_skinning->set_disabled(player == NULL);
pin->set_disabled(player == NULL); pin->set_disabled(player == NULL);
@ -863,10 +870,10 @@ void AnimationPlayerEditor::_update_player() {
if (animation->get_item_count()) { if (animation->get_item_count()) {
String current = animation->get_item_text(animation->get_selected()); String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim = player->get_animation(current); Ref<Animation> anim = player->get_animation(current);
key_editor->set_animation(anim); track_editor->set_animation(anim);
Node *root = player->get_node(player->get_root()); Node *root = player->get_node(player->get_root());
if (root) { if (root) {
key_editor->set_root(root); track_editor->set_root(root);
} }
} }
@ -884,9 +891,9 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
if (player) { if (player) {
_update_player(); _update_player();
key_editor->show_select_node_warning(false); track_editor->show_select_node_warning(false);
} else { } else {
key_editor->show_select_node_warning(true); track_editor->show_select_node_warning(true);
//hide(); //hide();
} }
@ -1024,7 +1031,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set) {
player->seek(pos, true); player->seek(pos, true);
} }
key_editor->set_anim_pos(pos); track_editor->set_anim_pos(pos);
updating = true; updating = true;
}; };
@ -1084,16 +1091,55 @@ void AnimationPlayerEditor::_hide_anim_editors() {
hide(); hide();
set_process(false); set_process(false);
key_editor->set_animation(Ref<Animation>()); track_editor->set_animation(Ref<Animation>());
key_editor->set_root(NULL); track_editor->set_root(NULL);
key_editor->show_select_node_warning(true); track_editor->show_select_node_warning(true);
//editor->animation_editor_make_visible(false); //editor->animation_editor_make_visible(false);
} }
void AnimationPlayerEditor::_animation_about_to_show_menu() {
}
void AnimationPlayerEditor::_animation_tool_menu(int p_option) { void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim;
if (current != "") {
anim = player->get_animation(current);
}
switch (p_option) { switch (p_option) {
case TOOL_NEW_ANIM: {
_animation_new();
} break;
case TOOL_LOAD_ANIM: {
_animation_load();
break;
} break;
case TOOL_SAVE_ANIM: {
if (anim.is_valid()) {
_animation_save(anim);
}
} break;
case TOOL_SAVE_AS_ANIM: {
if (anim.is_valid()) {
_animation_save_as(anim);
}
} break;
case TOOL_DUPLICATE_ANIM: {
_animation_duplicate();
} break;
case TOOL_RENAME_ANIM: {
_animation_rename();
} break;
case TOOL_EDIT_TRANSITIONS: {
_animation_blend();
} break;
case TOOL_REMOVE_ANIM: {
_animation_remove();
} break;
case TOOL_COPY_ANIM: { case TOOL_COPY_ANIM: {
if (!animation->get_item_count()) { if (!animation->get_item_count()) {
@ -1156,23 +1202,6 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
} }
} }
void AnimationPlayerEditor::_animation_save_menu(int p_option) {
String current = animation->get_item_text(animation->get_selected());
if (current != "") {
Ref<Animation> anim = player->get_animation(current);
switch (p_option) {
case ANIM_SAVE:
_animation_save(anim);
break;
case ANIM_SAVE_AS:
_animation_save_as(anim);
break;
}
}
}
void AnimationPlayerEditor::_onion_skinning_menu(int p_option) { void AnimationPlayerEditor::_onion_skinning_menu(int p_option) {
PopupMenu *menu = onion_skinning->get_popup(); PopupMenu *menu = onion_skinning->get_popup();
@ -1431,7 +1460,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
float pos = cpos + step_off * anim->get_step(); float pos = cpos + step_off * anim->get_step();
bool valid = anim->has_loop() || pos >= 0 && pos <= anim->get_length(); bool valid = anim->has_loop() || (pos >= 0 && pos <= anim->get_length());
onion.captures_valid[cidx] = valid; onion.captures_valid[cidx] = valid;
if (valid) { if (valid) {
player->seek(pos, true); player->seek(pos, true);
@ -1494,6 +1523,10 @@ void AnimationPlayerEditor::_stop_onion_skinning() {
} }
} }
void AnimationPlayerEditor::_pin_pressed() {
EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->update_tree();
}
void AnimationPlayerEditor::_bind_methods() { void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &AnimationPlayerEditor::_gui_input); ClassDB::bind_method(D_METHOD("_gui_input"), &AnimationPlayerEditor::_gui_input);
@ -1532,11 +1565,13 @@ void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_blend_editor_next_changed"), &AnimationPlayerEditor::_blend_editor_next_changed); ClassDB::bind_method(D_METHOD("_blend_editor_next_changed"), &AnimationPlayerEditor::_blend_editor_next_changed);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &AnimationPlayerEditor::_unhandled_key_input); ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &AnimationPlayerEditor::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_animation_tool_menu"), &AnimationPlayerEditor::_animation_tool_menu); ClassDB::bind_method(D_METHOD("_animation_tool_menu"), &AnimationPlayerEditor::_animation_tool_menu);
ClassDB::bind_method(D_METHOD("_animation_save_menu"), &AnimationPlayerEditor::_animation_save_menu);
ClassDB::bind_method(D_METHOD("_onion_skinning_menu"), &AnimationPlayerEditor::_onion_skinning_menu); ClassDB::bind_method(D_METHOD("_onion_skinning_menu"), &AnimationPlayerEditor::_onion_skinning_menu);
ClassDB::bind_method(D_METHOD("_editor_visibility_changed"), &AnimationPlayerEditor::_editor_visibility_changed); ClassDB::bind_method(D_METHOD("_editor_visibility_changed"), &AnimationPlayerEditor::_editor_visibility_changed);
ClassDB::bind_method(D_METHOD("_prepare_onion_layers_1"), &AnimationPlayerEditor::_prepare_onion_layers_1); ClassDB::bind_method(D_METHOD("_prepare_onion_layers_1"), &AnimationPlayerEditor::_prepare_onion_layers_1);
ClassDB::bind_method(D_METHOD("_prepare_onion_layers_2"), &AnimationPlayerEditor::_prepare_onion_layers_2); ClassDB::bind_method(D_METHOD("_prepare_onion_layers_2"), &AnimationPlayerEditor::_prepare_onion_layers_2);
ClassDB::bind_method(D_METHOD("_pin_pressed"), &AnimationPlayerEditor::_pin_pressed);
} }
AnimationPlayerEditor *AnimationPlayerEditor::singleton = NULL; AnimationPlayerEditor *AnimationPlayerEditor::singleton = NULL;
@ -1606,26 +1641,6 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
scale->set_tooltip(TTR("Scale animation playback globally for the node.")); scale->set_tooltip(TTR("Scale animation playback globally for the node."));
scale->hide(); scale->hide();
add_anim = memnew(ToolButton);
ED_SHORTCUT("animation_player_editor/add_animation", TTR("Create new animation in player."));
add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/add_animation"));
add_anim->set_tooltip(TTR("Create new animation in player."));
hb->add_child(add_anim);
load_anim = memnew(ToolButton);
ED_SHORTCUT("animation_player_editor/load_from_disk", TTR("Load animation from disk."));
add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/load_from_disk"));
load_anim->set_tooltip(TTR("Load an animation from disk."));
hb->add_child(load_anim);
save_anim = memnew(MenuButton);
save_anim->set_tooltip(TTR("Save the current animation."));
save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save", TTR("Save")), ANIM_SAVE);
save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_as", TTR("Save As")), ANIM_SAVE_AS);
save_anim->set_focus_mode(Control::FOCUS_NONE);
hb->add_child(save_anim);
accept = memnew(AcceptDialog); accept = memnew(AcceptDialog);
add_child(accept); add_child(accept);
accept->connect("confirmed", this, "_menu_confirm_current"); accept->connect("confirmed", this, "_menu_confirm_current");
@ -1634,23 +1649,27 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
add_child(delete_dialog); add_child(delete_dialog);
delete_dialog->connect("confirmed", this, "_animation_remove_confirmed"); delete_dialog->connect("confirmed", this, "_animation_remove_confirmed");
duplicate_anim = memnew(ToolButton); tool_anim = memnew(MenuButton);
hb->add_child(duplicate_anim); tool_anim->set_flat(false);
ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate Animation")); //tool_anim->set_flat(false);
duplicate_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/duplicate_animation")); tool_anim->set_tooltip(TTR("Animation Tools"));
duplicate_anim->set_tooltip(TTR("Duplicate Animation")); tool_anim->set_text("Animation");
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/new_animation", TTR("New...")), TOOL_NEW_ANIM);
rename_anim = memnew(ToolButton); tool_anim->get_popup()->add_separator();
hb->add_child(rename_anim); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/open_animation", TTR("Load...")), TOOL_LOAD_ANIM);
ED_SHORTCUT("animation_player_editor/rename_animation", TTR("Rename Animation")); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_animation", TTR("Save")), TOOL_SAVE_ANIM);
rename_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/rename_animation")); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_as_animation", TTR("Save As..")), TOOL_SAVE_AS_ANIM);
rename_anim->set_tooltip(TTR("Rename Animation")); tool_anim->get_popup()->add_separator();
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/copy_animation", TTR("Copy")), TOOL_COPY_ANIM);
remove_anim = memnew(ToolButton); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation", TTR("Paste")), TOOL_PASTE_ANIM);
hb->add_child(remove_anim); tool_anim->get_popup()->add_separator();
ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove Animation")); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate")), TOOL_DUPLICATE_ANIM);
remove_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/remove_animation")); tool_anim->get_popup()->add_separator();
remove_anim->set_tooltip(TTR("Remove Animation")); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/rename_animation", TTR("Rename...")), TOOL_RENAME_ANIM);
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/edit_transitions", TTR("Edit Transitions...")), TOOL_EDIT_TRANSITIONS);
tool_anim->get_popup()->add_separator();
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove")), TOOL_REMOVE_ANIM);
hb->add_child(tool_anim);
animation = memnew(OptionButton); animation = memnew(OptionButton);
hb->add_child(animation); hb->add_child(animation);
@ -1662,18 +1681,12 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
hb->add_child(autoplay); hb->add_child(autoplay);
autoplay->set_tooltip(TTR("Autoplay on Load")); autoplay->set_tooltip(TTR("Autoplay on Load"));
blend_anim = memnew(ToolButton);
hb->add_child(blend_anim);
blend_anim->set_tooltip(TTR("Edit Target Blend Times"));
tool_anim = memnew(MenuButton);
//tool_anim->set_flat(false);
tool_anim->set_tooltip(TTR("Animation Tools"));
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/copy_animation", TTR("Copy Animation")), TOOL_COPY_ANIM);
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation", TTR("Paste Animation")), TOOL_PASTE_ANIM);
//tool_anim->get_popup()->add_separator(); //tool_anim->get_popup()->add_separator();
//tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM); //tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM);
hb->add_child(tool_anim);
track_editor = memnew(AnimationTrackEditor);
hb->add_child(track_editor->get_edit_menu());
onion_skinning = memnew(MenuButton); onion_skinning = memnew(MenuButton);
//onion_skinning->set_flat(false); //onion_skinning->set_flat(false);
@ -1702,10 +1715,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
pin->set_toggle_mode(true); pin->set_toggle_mode(true);
pin->set_tooltip(TTR("Pin AnimationPlayer")); pin->set_tooltip(TTR("Pin AnimationPlayer"));
hb->add_child(pin); hb->add_child(pin);
pin->connect("pressed", this, "_pin_pressed");
resource_edit_anim = memnew(Button);
hb->add_child(resource_edit_anim);
resource_edit_anim->hide();
file = memnew(EditorFileDialog); file = memnew(EditorFileDialog);
add_child(file); add_child(file);
@ -1758,16 +1768,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
play_bw_from->connect("pressed", this, "_play_bw_from_pressed"); play_bw_from->connect("pressed", this, "_play_bw_from_pressed");
stop->connect("pressed", this, "_stop_pressed"); stop->connect("pressed", this, "_stop_pressed");
//pause->connect("pressed", this,"_pause_pressed"); //pause->connect("pressed", this,"_pause_pressed");
add_anim->connect("pressed", this, "_animation_new");
rename_anim->connect("pressed", this, "_animation_rename");
load_anim->connect("pressed", this, "_animation_load");
duplicate_anim->connect("pressed", this, "_animation_duplicate");
//frame->connect("text_entered", this,"_seek_frame_changed"); //frame->connect("text_entered", this,"_seek_frame_changed");
blend_anim->connect("pressed", this, "_animation_blend");
remove_anim->connect("pressed", this, "_animation_remove");
animation->connect("item_selected", this, "_animation_selected", Vector<Variant>(), true); animation->connect("item_selected", this, "_animation_selected", Vector<Variant>(), true);
resource_edit_anim->connect("pressed", this, "_animation_resource_edit");
file->connect("file_selected", this, "_dialog_action"); file->connect("file_selected", this, "_dialog_action");
frame->connect("value_changed", this, "_seek_value_changed", Vector<Variant>(), true); frame->connect("value_changed", this, "_seek_value_changed", Vector<Variant>(), true);
scale->connect("text_entered", this, "_scale_changed", Vector<Variant>(), true); scale->connect("text_entered", this, "_scale_changed", Vector<Variant>(), true);
@ -1777,18 +1781,17 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
set_process_unhandled_key_input(true); set_process_unhandled_key_input(true);
key_editor = memnew(AnimationKeyEditor); add_child(track_editor);
add_child(key_editor); track_editor->set_v_size_flags(SIZE_EXPAND_FILL);
key_editor->set_v_size_flags(SIZE_EXPAND_FILL); track_editor->connect("timeline_changed", this, "_animation_key_editor_seek");
key_editor->connect("timeline_changed", this, "_animation_key_editor_seek"); track_editor->connect("animation_len_changed", this, "_animation_key_editor_anim_len_changed");
key_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");
key_editor->connect("animation_step_changed", this, "_animation_key_editor_anim_step_changed");
_update_player(); _update_player();
// Onion skinning // Onion skinning
key_editor->connect("visibility_changed", this, "_editor_visibility_changed"); track_editor->connect("visibility_changed", this, "_editor_visibility_changed");
onion.enabled = false; onion.enabled = false;
onion.past = true; onion.past = true;

View file

@ -42,8 +42,9 @@
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
class AnimationKeyEditor; class AnimationTrackEditor;
class AnimationPlayerEditorPlugin; class AnimationPlayerEditorPlugin;
class AnimationPlayerEditor : public VBoxContainer { class AnimationPlayerEditor : public VBoxContainer {
GDCLASS(AnimationPlayerEditor, VBoxContainer); GDCLASS(AnimationPlayerEditor, VBoxContainer);
@ -53,6 +54,14 @@ class AnimationPlayerEditor : public VBoxContainer {
AnimationPlayer *player; AnimationPlayer *player;
enum { enum {
TOOL_NEW_ANIM,
TOOL_LOAD_ANIM,
TOOL_SAVE_ANIM,
TOOL_SAVE_AS_ANIM,
TOOL_DUPLICATE_ANIM,
TOOL_RENAME_ANIM,
TOOL_EDIT_TRANSITIONS,
TOOL_REMOVE_ANIM,
TOOL_COPY_ANIM, TOOL_COPY_ANIM,
TOOL_PASTE_ANIM, TOOL_PASTE_ANIM,
TOOL_EDIT_RESOURCE TOOL_EDIT_RESOURCE
@ -72,6 +81,7 @@ class AnimationPlayerEditor : public VBoxContainer {
}; };
enum { enum {
ANIM_OPEN,
ANIM_SAVE, ANIM_SAVE,
ANIM_SAVE_AS ANIM_SAVE_AS
}; };
@ -89,16 +99,8 @@ class AnimationPlayerEditor : public VBoxContainer {
Button *play_bw_from; Button *play_bw_from;
//Button *pause; //Button *pause;
Button *add_anim;
Button *autoplay; Button *autoplay;
Button *rename_anim;
Button *duplicate_anim;
Button *resource_edit_anim;
Button *load_anim;
MenuButton *save_anim;
Button *blend_anim;
Button *remove_anim;
MenuButton *tool_anim; MenuButton *tool_anim;
MenuButton *onion_skinning; MenuButton *onion_skinning;
ToolButton *pin; ToolButton *pin;
@ -130,7 +132,7 @@ class AnimationPlayerEditor : public VBoxContainer {
bool updating; bool updating;
bool updating_blends; bool updating_blends;
AnimationKeyEditor *key_editor; AnimationTrackEditor *track_editor;
// Onion skinning // Onion skinning
struct { struct {
@ -207,8 +209,8 @@ class AnimationPlayerEditor : public VBoxContainer {
void _unhandled_key_input(const Ref<InputEvent> &p_ev); void _unhandled_key_input(const Ref<InputEvent> &p_ev);
void _animation_tool_menu(int p_option); void _animation_tool_menu(int p_option);
void _animation_save_menu(int p_option);
void _onion_skinning_menu(int p_option); void _onion_skinning_menu(int p_option);
void _animation_about_to_show_menu();
void _editor_visibility_changed(); void _editor_visibility_changed();
bool _are_onion_layers_valid(); bool _are_onion_layers_valid();
@ -219,6 +221,8 @@ class AnimationPlayerEditor : public VBoxContainer {
void _start_onion_skinning(); void _start_onion_skinning();
void _stop_onion_skinning(); void _stop_onion_skinning();
void _pin_pressed();
AnimationPlayerEditor(); AnimationPlayerEditor();
~AnimationPlayerEditor(); ~AnimationPlayerEditor();
@ -232,7 +236,9 @@ public:
AnimationPlayer *get_player() const; AnimationPlayer *get_player() const;
static AnimationPlayerEditor *singleton; static AnimationPlayerEditor *singleton;
AnimationKeyEditor *get_key_editor() { return key_editor; } bool is_pinned() const { return pin->is_pressed(); }
void unpin() { pin->set_pressed(false); }
AnimationTrackEditor *get_track_editor() { return track_editor; }
Dictionary get_state() const; Dictionary get_state() const;
void set_state(const Dictionary &p_state); void set_state(const Dictionary &p_state);

View file

@ -30,7 +30,6 @@
#include "canvas_item_editor_plugin.h" #include "canvas_item_editor_plugin.h"
#include "editor/animation_editor.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/animation_player_editor_plugin.h"
@ -365,7 +364,7 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
void CanvasItemEditor::_keying_changed() { void CanvasItemEditor::_keying_changed() {
if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree()) if (AnimationPlayerEditor::singleton->get_track_editor()->is_visible_in_tree())
animation_hb->show(); animation_hb->show();
else else
animation_hb->hide(); animation_hb->hide();
@ -3080,7 +3079,7 @@ void CanvasItemEditor::_notification(int p_what) {
select_sb->set_default_margin(Margin(i), 4); select_sb->set_default_margin(Margin(i), 4);
} }
AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed", this, "_keying_changed"); AnimationPlayerEditor::singleton->get_track_editor()->connect("visibility_changed", this, "_keying_changed");
_keying_changed(); _keying_changed();
get_tree()->connect("node_added", this, "_tree_changed", varray()); get_tree()->connect("node_added", this, "_tree_changed", varray());
get_tree()->connect("node_removed", this, "_tree_changed", varray()); get_tree()->connect("node_removed", this, "_tree_changed", varray());
@ -3692,11 +3691,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
Node2D *n2d = Object::cast_to<Node2D>(canvas_item); Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
if (key_pos) if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), existing);
if (key_rot) if (key_rot)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), existing);
if (key_scale) if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), existing);
if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) { if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) {
//look for an IK chain //look for an IK chain
@ -3723,11 +3722,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for (List<Node2D *>::Element *F = ik_chain.front(); F; F = F->next()) { for (List<Node2D *>::Element *F = ik_chain.front(); F; F = F->next()) {
if (key_pos) if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), existing);
if (key_rot) if (key_rot)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), existing);
if (key_scale) if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), existing);
} }
} }
} }
@ -3737,11 +3736,11 @@ void CanvasItemEditor::_popup_callback(int p_op) {
Control *ctrl = Object::cast_to<Control>(canvas_item); Control *ctrl = Object::cast_to<Control>(canvas_item);
if (key_pos) if (key_pos)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), existing);
if (key_rot) if (key_rot)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), existing);
if (key_scale) if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), existing); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), existing);
} }
} }
@ -3837,7 +3836,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
ctrl->set_position(Point2()); ctrl->set_position(Point2());
/* /*
if (key_scale) if (key_scale)
AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size()); AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
*/ */
} }
} }

View file

@ -554,18 +554,15 @@ EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// FIXME: Needs to be rewritten for AudioStream in Godot 3.0+ bool EditorAudioStreamPreviewPlugin::handles(const String &p_type) const {
#if 0
bool EditorSamplePreviewPlugin::handles(const String& p_type) const {
return ClassDB::is_parent_class(p_type,"Sample"); return ClassDB::is_parent_class(p_type, "AudioStream");
} }
Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) { Ref<Texture> EditorAudioStreamPreviewPlugin::generate(const RES &p_from) {
Ref<Sample> smp =p_from;
ERR_FAIL_COND_V(smp.is_null(),Ref<Texture>());
Ref<AudioStream> stream = p_from;
ERR_FAIL_COND_V(stream.is_null(), Ref<Texture>());
int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
thumbnail_size *= EDSCALE; thumbnail_size *= EDSCALE;
@ -576,252 +573,73 @@ Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
PoolVector<uint8_t>::Write imgdata = img.write(); PoolVector<uint8_t>::Write imgdata = img.write();
uint8_t *imgw = imgdata.ptr(); uint8_t *imgw = imgdata.ptr();
PoolVector<uint8_t> data = smp->get_data();
PoolVector<uint8_t>::Read sampledata = data.read();
const uint8_t *sdata=sampledata.ptr();
bool stereo = smp->is_stereo(); Ref<AudioStreamPlayback> playback = stream->instance_playback();
bool _16=smp->get_format()==Sample::FORMAT_PCM16;
int len = smp->get_length();
if (len<1) float len_s = stream->get_length();
return Ref<Texture>(); if (len_s == 0) {
len_s = 60; //one minute audio if no length specified
}
int frame_length = AudioServer::get_singleton()->get_mix_rate() * len_s;
if (smp->get_format()==Sample::FORMAT_IMA_ADPCM) { Vector<AudioFrame> frames;
frames.resize(frame_length);
struct IMA_ADPCM_State {
int16_t step_index;
int32_t predictor;
/* values at loop point */
int16_t loop_step_index;
int32_t loop_predictor;
int32_t last_nibble;
int32_t loop_pos;
int32_t window_ofs;
const uint8_t *ptr;
} ima_adpcm;
ima_adpcm.step_index=0;
ima_adpcm.predictor=0;
ima_adpcm.loop_step_index=0;
ima_adpcm.loop_predictor=0;
ima_adpcm.last_nibble=-1;
ima_adpcm.loop_pos=0x7FFFFFFF;
ima_adpcm.window_ofs=0;
ima_adpcm.ptr=NULL;
playback->start();
playback->mix(frames.ptrw(), 1, frames.size());
playback->stop();
for (int i = 0; i < w; i++) { for (int i = 0; i < w; i++) {
float max[2]={-1e10,-1e10}; float max = -1000;
float min[2]={1e10,1e10}; float min = 1000;
int from = i*len/w; int from = uint64_t(i) * frame_length / w;
int to = (i+1)*len/w; int to = uint64_t(i + 1) * frame_length / w;
if (to>=len) to = MIN(to, frame_length);
to=len-1; from = MIN(from, frame_length - 1);
if (to == from) {
to = from + 1;
}
for (int j = from; j < to; j++) { for (int j = from; j < to; j++) {
while(j>ima_adpcm.last_nibble) { max = MAX(max, frames[j].l);
max = MAX(max, frames[j].r);
static const int16_t _ima_adpcm_step_table[89] = { min = MIN(min, frames[j].l);
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, min = MIN(min, frames[j].r);
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
static const int8_t _ima_adpcm_index_table[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
int16_t nibble,diff,step;
ima_adpcm.last_nibble++;
const uint8_t *src_ptr=sdata;
int ofs = ima_adpcm.last_nibble>>1;
if (stereo)
ofs*=2;
nibble = (ima_adpcm.last_nibble&1)?
(src_ptr[ofs]>>4):(src_ptr[ofs]&0xF);
step=_ima_adpcm_step_table[ima_adpcm.step_index];
ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
if (ima_adpcm.step_index<0)
ima_adpcm.step_index=0;
if (ima_adpcm.step_index>88)
ima_adpcm.step_index=88;
diff = step >> 3 ;
if (nibble & 1)
diff += step >> 2 ;
if (nibble & 2)
diff += step >> 1 ;
if (nibble & 4)
diff += step ;
if (nibble & 8)
diff = -diff ;
ima_adpcm.predictor+=diff;
if (ima_adpcm.predictor<-0x8000)
ima_adpcm.predictor=-0x8000;
else if (ima_adpcm.predictor>0x7FFF)
ima_adpcm.predictor=0x7FFF;
/* store loop if there */
if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
ima_adpcm.loop_step_index = ima_adpcm.step_index;
ima_adpcm.loop_predictor = ima_adpcm.predictor;
} }
} int pfrom = CLAMP((min * 0.5 + 0.5) * h / 2, 0, h / 2) + h / 4;
int pto = CLAMP((max * 0.5 + 0.5) * h / 2, 0, h / 2) + h / 4;
float v=ima_adpcm.predictor/32767.0;
if (v>max[0])
max[0]=v;
if (v<min[0])
min[0]=v;
}
max[0]*=0.8;
min[0]*=0.8;
for (int j = 0; j < h; j++) { for (int j = 0; j < h; j++) {
float v = (j/(float)h) * 2.0 - 1.0; uint8_t *p = &imgw[(j * w + i) * 3];
uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3]; if (j < pfrom || j > pto) {
if (v>min[0] && v<max[0]) { p[0] = 100;
imgofs[0]=255; p[1] = 100;
imgofs[1]=150; p[2] = 100;
imgofs[2]=80;
} else { } else {
imgofs[0]=0; p[0] = 180;
imgofs[1]=0; p[1] = 180;
imgofs[2]=0; p[2] = 180;
} }
} }
} }
} else {
for(int i=0;i<w;i++) {
// i trust gcc will optimize this loop
float max[2]={-1e10,-1e10};
float min[2]={1e10,1e10};
int c=stereo?2:1;
int from = uint64_t(i)*len/w;
int to = (uint64_t(i)+1)*len/w;
if (to>=len)
to=len-1;
if (_16) {
const int16_t*src =(const int16_t*)sdata;
for(int j=0;j<c;j++) {
for(int k=from;k<=to;k++) {
float v = src[uint64_t(k)*c+j]/32768.0;
if (v>max[j])
max[j]=v;
if (v<min[j])
min[j]=v;
}
}
} else {
const int8_t*src =(const int8_t*)sdata;
for(int j=0;j<c;j++) {
for(int k=from;k<=to;k++) {
float v = src[uint64_t(k)*c+j]/128.0;
if (v>max[j])
max[j]=v;
if (v<min[j])
min[j]=v;
}
}
}
max[0]*=0.8;
max[1]*=0.8;
min[0]*=0.8;
min[1]*=0.8;
if (!stereo) {
for(int j=0;j<h;j++) {
float v = (j/(float)h) * 2.0 - 1.0;
uint8_t* imgofs = &imgw[(j*w+i)*3];
if (v>min[0] && v<max[0]) {
imgofs[0]=255;
imgofs[1]=150;
imgofs[2]=80;
} else {
imgofs[0]=0;
imgofs[1]=0;
imgofs[2]=0;
}
}
} else {
for(int j=0;j<h;j++) {
int half;
float v;
if (j<(h/2)) {
half=0;
v = (j/(float)(h/2)) * 2.0 - 1.0;
} else {
half=1;
if( (float)(h/2) != 0 ) {
v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
} else {
v = ((j-(h/2))/(float)(1/2)) * 2.0 - 1.0;
}
}
uint8_t* imgofs = &imgw[(j*w+i)*3];
if (v>min[half] && v<max[half]) {
imgofs[0]=255;
imgofs[1]=150;
imgofs[2]=80;
} else {
imgofs[0]=0;
imgofs[1]=0;
imgofs[2]=0;
}
}
}
}
}
imgdata = PoolVector<uint8_t>::Write(); imgdata = PoolVector<uint8_t>::Write();
post_process_preview(img); //post_process_preview(img);
Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
ptex->create_from_image(Image(w,h,0,Image::FORMAT_RGB8,img),0); Ref<Image> image;
image.instance();
image->create(w, h, false, Image::FORMAT_RGB8, img);
ptex->create_from_image(image, 0);
return ptex; return ptex;
} }
EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() { EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() {
} }
#endif
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View file

@ -100,17 +100,13 @@ public:
EditorScriptPreviewPlugin(); EditorScriptPreviewPlugin();
}; };
// FIXME: Needs to be rewritten for AudioStream in Godot 3.0+ class EditorAudioStreamPreviewPlugin : public EditorResourcePreviewGenerator {
#if 0
class EditorSamplePreviewPlugin : public EditorResourcePreviewGenerator {
public: public:
virtual bool handles(const String &p_type) const; virtual bool handles(const String &p_type) const;
virtual Ref<Texture> generate(const RES &p_from); virtual Ref<Texture> generate(const RES &p_from);
EditorSamplePreviewPlugin(); EditorAudioStreamPreviewPlugin();
}; };
#endif
class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator { class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {

View file

@ -32,7 +32,7 @@
#include "camera_matrix.h" #include "camera_matrix.h"
#include "core/os/input.h" #include "core/os/input.h"
#include "editor/animation_editor.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/animation_player_editor_plugin.h"
@ -1829,7 +1829,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!get_selected_count() || _edit.mode != TRANSFORM_NONE) if (!get_selected_count() || _edit.mode != TRANSFORM_NONE)
return; return;
if (!AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) { if (!AnimationPlayerEditor::singleton->get_track_editor()->has_keying()) {
set_message(TTR("Keying is disabled (no key inserted).")); set_message(TTR("Keying is disabled (no key inserted)."));
return; return;
} }

View file

@ -120,33 +120,33 @@ void PropertySelector::_update_search() {
bool found = false; bool found = false;
Ref<Texture> type_icons[Variant::VARIANT_MAX] = { Ref<Texture> type_icons[Variant::VARIANT_MAX] = {
Control::get_icon("MiniVariant", "EditorIcons"), Control::get_icon("Variant", "EditorIcons"),
Control::get_icon("MiniBoolean", "EditorIcons"), Control::get_icon("bool", "EditorIcons"),
Control::get_icon("MiniInteger", "EditorIcons"), Control::get_icon("int", "EditorIcons"),
Control::get_icon("MiniFloat", "EditorIcons"), Control::get_icon("float", "EditorIcons"),
Control::get_icon("MiniString", "EditorIcons"), Control::get_icon("String", "EditorIcons"),
Control::get_icon("MiniVector2", "EditorIcons"), Control::get_icon("Vector2", "EditorIcons"),
Control::get_icon("MiniRect2", "EditorIcons"), Control::get_icon("Rect2", "EditorIcons"),
Control::get_icon("MiniVector3", "EditorIcons"), Control::get_icon("Vector3", "EditorIcons"),
Control::get_icon("MiniMatrix2", "EditorIcons"), Control::get_icon("Transform2D", "EditorIcons"),
Control::get_icon("MiniPlane", "EditorIcons"), Control::get_icon("Plane", "EditorIcons"),
Control::get_icon("MiniQuat", "EditorIcons"), Control::get_icon("Quat", "EditorIcons"),
Control::get_icon("MiniAabb", "EditorIcons"), Control::get_icon("AABB", "EditorIcons"),
Control::get_icon("MiniMatrix3", "EditorIcons"), Control::get_icon("Basis", "EditorIcons"),
Control::get_icon("MiniTransform", "EditorIcons"), Control::get_icon("Transform", "EditorIcons"),
Control::get_icon("MiniColor", "EditorIcons"), Control::get_icon("Color", "EditorIcons"),
Control::get_icon("MiniPath", "EditorIcons"), Control::get_icon("Path", "EditorIcons"),
Control::get_icon("MiniRid", "EditorIcons"), Control::get_icon("RID", "EditorIcons"),
Control::get_icon("MiniObject", "EditorIcons"), Control::get_icon("Object", "EditorIcons"),
Control::get_icon("MiniDictionary", "EditorIcons"), Control::get_icon("Dictionary", "EditorIcons"),
Control::get_icon("MiniArray", "EditorIcons"), Control::get_icon("Array", "EditorIcons"),
Control::get_icon("MiniRawArray", "EditorIcons"), Control::get_icon("PoolByteArray", "EditorIcons"),
Control::get_icon("MiniIntArray", "EditorIcons"), Control::get_icon("PoolIntArray", "EditorIcons"),
Control::get_icon("MiniFloatArray", "EditorIcons"), Control::get_icon("PoolRealArray", "EditorIcons"),
Control::get_icon("MiniStringArray", "EditorIcons"), Control::get_icon("PoolStringArray", "EditorIcons"),
Control::get_icon("MiniVector2Array", "EditorIcons"), Control::get_icon("PoolVector2Array", "EditorIcons"),
Control::get_icon("MiniVector3Array", "EditorIcons"), Control::get_icon("PoolVector3Array", "EditorIcons"),
Control::get_icon("MiniColorArray", "EditorIcons") Control::get_icon("PoolColorArray", "EditorIcons")
}; };
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
@ -175,6 +175,10 @@ void PropertySelector::_update_search() {
if (search_box->get_text() != String() && E->get().name.find(search_box->get_text()) == -1) if (search_box->get_text() != String() && E->get().name.find(search_box->get_text()) == -1)
continue; continue;
if (type_filter.size() && type_filter.find(E->get().type) == -1)
continue;
TreeItem *item = search_options->create_item(category ? category : root); TreeItem *item = search_options->create_item(category ? category : root);
item->set_text(0, E->get().name); item->set_text(0, E->get().name);
item->set_metadata(0, E->get().name); item->set_metadata(0, E->get().name);
@ -534,6 +538,10 @@ void PropertySelector::select_property_from_instance(Object *p_instance, const S
_update_search(); _update_search();
} }
void PropertySelector::set_type_filter(const Vector<Variant::Type> &p_type_filter) {
type_filter = p_type_filter;
}
void PropertySelector::_bind_methods() { void PropertySelector::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_changed"), &PropertySelector::_text_changed); ClassDB::bind_method(D_METHOD("_text_changed"), &PropertySelector::_text_changed);

View file

@ -60,6 +60,8 @@ class PropertySelector : public ConfirmationDialog {
void _item_selected(); void _item_selected();
Vector<Variant::Type> type_filter;
protected: protected:
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();
@ -75,6 +77,8 @@ public:
void select_property_from_basic_type(Variant::Type p_type, const String &p_current = ""); void select_property_from_basic_type(Variant::Type p_type, const String &p_current = "");
void select_property_from_instance(Object *p_instance, const String &p_current = ""); void select_property_from_instance(Object *p_instance, const String &p_current = "");
void set_type_filter(const Vector<Variant::Type> &p_type_filter);
PropertySelector(); PropertySelector();
}; };

View file

@ -33,7 +33,7 @@
#include "core/io/resource_saver.h" #include "core/io/resource_saver.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/project_settings.h" #include "core/project_settings.h"
#include "editor/animation_editor.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "editor/multi_node_edit.h" #include "editor/multi_node_edit.h"
@ -1262,8 +1262,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
editor_data->get_undo_redo().add_do_method(this, "_set_owners", edited_scene, owners); editor_data->get_undo_redo().add_do_method(this, "_set_owners", edited_scene, owners);
if (AnimationPlayerEditor::singleton->get_key_editor()->get_root() == node) if (AnimationPlayerEditor::singleton->get_track_editor()->get_root() == node)
editor_data->get_undo_redo().add_do_method(AnimationPlayerEditor::singleton->get_key_editor(), "set_root", node); editor_data->get_undo_redo().add_do_method(AnimationPlayerEditor::singleton->get_track_editor(), "set_root", node);
editor_data->get_undo_redo().add_undo_method(new_parent, "remove_child", node); editor_data->get_undo_redo().add_undo_method(new_parent, "remove_child", node);
editor_data->get_undo_redo().add_undo_method(node, "set_name", former_names[ni]); editor_data->get_undo_redo().add_undo_method(node, "set_name", former_names[ni]);
@ -1290,8 +1290,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node); editor_data->get_undo_redo().add_undo_method(node->get_parent(), "add_child", node);
editor_data->get_undo_redo().add_undo_method(node->get_parent(), "move_child", node, child_pos); editor_data->get_undo_redo().add_undo_method(node->get_parent(), "move_child", node, child_pos);
editor_data->get_undo_redo().add_undo_method(this, "_set_owners", edited_scene, owners); editor_data->get_undo_redo().add_undo_method(this, "_set_owners", edited_scene, owners);
if (AnimationPlayerEditor::singleton->get_key_editor()->get_root() == node) if (AnimationPlayerEditor::singleton->get_track_editor()->get_root() == node)
editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_key_editor(), "set_root", node); editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_track_editor(), "set_root", node);
if (p_keep_global_xform) { if (p_keep_global_xform) {
if (Object::cast_to<Node2D>(node)) if (Object::cast_to<Node2D>(node))
@ -1392,8 +1392,8 @@ void SceneTreeDock::_delete_confirm() {
editor_data->get_undo_redo().add_do_method(n->get_parent(), "remove_child", n); editor_data->get_undo_redo().add_do_method(n->get_parent(), "remove_child", n);
editor_data->get_undo_redo().add_undo_method(n->get_parent(), "add_child", n); editor_data->get_undo_redo().add_undo_method(n->get_parent(), "add_child", n);
editor_data->get_undo_redo().add_undo_method(n->get_parent(), "move_child", n, n->get_index()); editor_data->get_undo_redo().add_undo_method(n->get_parent(), "move_child", n, n->get_index());
if (AnimationPlayerEditor::singleton->get_key_editor()->get_root() == n) if (AnimationPlayerEditor::singleton->get_track_editor()->get_root() == n)
editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_key_editor(), "set_root", n); editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_track_editor(), "set_root", n);
editor_data->get_undo_redo().add_undo_method(this, "_set_owners", edited_scene, owners); editor_data->get_undo_redo().add_undo_method(this, "_set_owners", edited_scene, owners);
editor_data->get_undo_redo().add_undo_reference(n); editor_data->get_undo_redo().add_undo_reference(n);

View file

@ -30,6 +30,7 @@
#include "scene_tree_editor.h" #include "scene_tree_editor.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor_node.h" #include "editor_node.h"
#include "message_queue.h" #include "message_queue.h"
@ -90,6 +91,12 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
_update_tree(); _update_tree();
emit_signal("node_changed"); emit_signal("node_changed");
} }
} else if (p_id == BUTTON_PIN) {
if (n->is_class("AnimationPlayer")) {
AnimationPlayerEditor::singleton->unpin();
_update_tree();
}
} else if (p_id == BUTTON_GROUP) { } else if (p_id == BUTTON_GROUP) {
if (n->is_class("CanvasItem")) { if (n->is_class("CanvasItem")) {
@ -284,6 +291,13 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
p_node->connect("visibility_changed", this, "_node_visibility_changed", varray(p_node)); p_node->connect("visibility_changed", this, "_node_visibility_changed", varray(p_node));
_update_visibility_color(p_node, item); _update_visibility_color(p_node, item);
} else if (p_node->is_class("AnimationPlayer")) {
bool is_pinned = AnimationPlayerEditor::singleton->get_player() == p_node && AnimationPlayerEditor::singleton->is_pinned();
if (is_pinned) {
item->add_button(0, get_icon("Pin", "EditorIcons"), BUTTON_PIN, false, TTR("AnimationPlayer is pinned.\nClick to unpin."));
}
} }
} }

View file

@ -55,6 +55,7 @@ class SceneTreeEditor : public Control {
BUTTON_WARNING = 5, BUTTON_WARNING = 5,
BUTTON_SIGNALS = 6, BUTTON_SIGNALS = 6,
BUTTON_GROUPS = 7, BUTTON_GROUPS = 7,
BUTTON_PIN = 8,
}; };
Tree *tree; Tree *tree;

View file

@ -1,206 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> duplicate,
<manifest xmlns:android="http://schemas.android.com/apk/res/android" delete
package="com.godot.game" options,
android:versionCode="1" unite equal tracks
android:versionName="1.0" fix (harcode) seek
android:installLocation="auto" biziers
> sound tracks
<supports-screens android:smallScreens="true" play icons on key tracks
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false" $$ADD_APPATTRIBUTE_CHUNKS$$ > Siempre quise se parte de un equipo que desarrolle un juego, lo publique en Steam y consiga un Overwhelmingly Positive.
<activity android:name="org.godotengine.godot.Godot"
android:label="@string/godot_project_name_string"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"
android:resizeableActivity="false">
<intent-filter> Posiblemente eso no me de nunca.. pero esto es muchísimo mejor! Gracias a todos por tenerle fé a este proyecto hermoso!
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="org.godotengine.godot.GodotDownloaderService" />
$$ADD_APPLICATION_CHUNKS$$
</application>
<uses-feature android:glEsVersion="0x00030000" android:required="true" />
$$ADD_PERMISSION_CHUNKS$$
<uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/>
<uses-permission android:name="godot.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="godot.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="godot.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="godot.ACCESS_MOCK_LOCATION"/>
<uses-permission android:name="godot.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="godot.ACCESS_SURFACE_FLINGER"/>
<uses-permission android:name="godot.ACCESS_WIFI_STATE"/>
<uses-permission android:name="godot.ACCOUNT_MANAGER"/>
<uses-permission android:name="godot.ADD_VOICEMAIL"/>
<uses-permission android:name="godot.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="godot.BATTERY_STATS"/>
<uses-permission android:name="godot.BIND_ACCESSIBILITY_SERVICE"/>
<uses-permission android:name="godot.BIND_APPWIDGET"/>
<uses-permission android:name="godot.BIND_DEVICE_ADMIN"/>
<uses-permission android:name="godot.BIND_INPUT_METHOD"/>
<uses-permission android:name="godot.BIND_NFC_SERVICE"/>
<uses-permission android:name="godot.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<uses-permission android:name="godot.BIND_PRINT_SERVICE"/>
<uses-permission android:name="godot.BIND_REMOTEVIEWS"/>
<uses-permission android:name="godot.BIND_TEXT_SERVICE"/>
<uses-permission android:name="godot.BIND_VPN_SERVICE"/>
<uses-permission android:name="godot.BIND_WALLPAPER"/>
<uses-permission android:name="godot.BLUETOOTH"/>
<uses-permission android:name="godot.BLUETOOTH_ADMIN"/>
<uses-permission android:name="godot.BLUETOOTH_PRIVILEGED"/>
<uses-permission android:name="godot.BRICK"/>
<uses-permission android:name="godot.BROADCAST_PACKAGE_REMOVED"/>
<uses-permission android:name="godot.BROADCAST_SMS"/>
<uses-permission android:name="godot.BROADCAST_STICKY"/>
<uses-permission android:name="godot.BROADCAST_WAP_PUSH"/>
<uses-permission android:name="godot.CALL_PHONE"/>
<uses-permission android:name="godot.CALL_PRIVILEGED"/>
<uses-permission android:name="godot.CAMERA"/>
<uses-permission android:name="godot.CAPTURE_AUDIO_OUTPUT"/>
<uses-permission android:name="godot.CAPTURE_SECURE_VIDEO_OUTPUT"/>
<uses-permission android:name="godot.CAPTURE_VIDEO_OUTPUT"/>
<uses-permission android:name="godot.CHANGE_COMPONENT_ENABLED_STATE"/>
<uses-permission android:name="godot.CHANGE_CONFIGURATION"/>
<uses-permission android:name="godot.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="godot.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="godot.CHANGE_WIFI_STATE"/>
<uses-permission android:name="godot.CLEAR_APP_CACHE"/>
<uses-permission android:name="godot.CLEAR_APP_USER_DATA"/>
<uses-permission android:name="godot.CONTROL_LOCATION_UPDATES"/>
<uses-permission android:name="godot.DELETE_CACHE_FILES"/>
<uses-permission android:name="godot.DELETE_PACKAGES"/>
<uses-permission android:name="godot.DEVICE_POWER"/>
<uses-permission android:name="godot.DIAGNOSTIC"/>
<uses-permission android:name="godot.DISABLE_KEYGUARD"/>
<uses-permission android:name="godot.DUMP"/>
<uses-permission android:name="godot.EXPAND_STATUS_BAR"/>
<uses-permission android:name="godot.FACTORY_TEST"/>
<uses-permission android:name="godot.FLASHLIGHT"/>
<uses-permission android:name="godot.FORCE_BACK"/>
<uses-permission android:name="godot.GET_ACCOUNTS"/>
<uses-permission android:name="godot.GET_PACKAGE_SIZE"/>
<uses-permission android:name="godot.GET_TASKS"/>
<uses-permission android:name="godot.GET_TOP_ACTIVITY_INFO"/>
<uses-permission android:name="godot.GLOBAL_SEARCH"/>
<uses-permission android:name="godot.HARDWARE_TEST"/>
<uses-permission android:name="godot.INJECT_EVENTS"/>
<uses-permission android:name="godot.INSTALL_LOCATION_PROVIDER"/>
<uses-permission android:name="godot.INSTALL_PACKAGES"/>
<uses-permission android:name="godot.INSTALL_SHORTCUT"/>
<uses-permission android:name="godot.INTERNAL_SYSTEM_WINDOW"/>
<uses-permission android:name="godot.INTERNET"/>
<uses-permission android:name="godot.KILL_BACKGROUND_PROCESSES"/>
<uses-permission android:name="godot.LOCATION_HARDWARE"/>
<uses-permission android:name="godot.MANAGE_ACCOUNTS"/>
<uses-permission android:name="godot.MANAGE_APP_TOKENS"/>
<uses-permission android:name="godot.MANAGE_DOCUMENTS"/>
<uses-permission android:name="godot.MASTER_CLEAR"/>
<uses-permission android:name="godot.MEDIA_CONTENT_CONTROL"/>
<uses-permission android:name="godot.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="godot.MODIFY_PHONE_STATE"/>
<uses-permission android:name="godot.MOUNT_FORMAT_FILESYSTEMS"/>
<uses-permission android:name="godot.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="godot.NFC"/>
<uses-permission android:name="godot.PERSISTENT_ACTIVITY"/>
<uses-permission android:name="godot.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="godot.READ_CALENDAR"/>
<uses-permission android:name="godot.READ_CALL_LOG"/>
<uses-permission android:name="godot.READ_CONTACTS"/>
<uses-permission android:name="godot.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="godot.READ_FRAME_BUFFER"/>
<uses-permission android:name="godot.READ_HISTORY_BOOKMARKS"/>
<uses-permission android:name="godot.READ_INPUT_STATE"/>
<uses-permission android:name="godot.READ_LOGS"/>
<uses-permission android:name="godot.READ_PHONE_STATE"/>
<uses-permission android:name="godot.READ_PROFILE"/>
<uses-permission android:name="godot.READ_SMS"/>
<uses-permission android:name="godot.READ_SOCIAL_STREAM"/>
<uses-permission android:name="godot.READ_SYNC_SETTINGS"/>
<uses-permission android:name="godot.READ_SYNC_STATS"/>
<uses-permission android:name="godot.READ_USER_DICTIONARY"/>
<uses-permission android:name="godot.REBOOT"/>
<uses-permission android:name="godot.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="godot.RECEIVE_MMS"/>
<uses-permission android:name="godot.RECEIVE_SMS"/>
<uses-permission android:name="godot.RECEIVE_WAP_PUSH"/>
<uses-permission android:name="godot.RECORD_AUDIO"/>
<uses-permission android:name="godot.REORDER_TASKS"/>
<uses-permission android:name="godot.RESTART_PACKAGES"/>
<uses-permission android:name="godot.SEND_RESPOND_VIA_MESSAGE"/>
<uses-permission android:name="godot.SEND_SMS"/>
<uses-permission android:name="godot.SET_ACTIVITY_WATCHER"/>
<uses-permission android:name="godot.SET_ALARM"/>
<uses-permission android:name="godot.SET_ALWAYS_FINISH"/>
<uses-permission android:name="godot.SET_ANIMATION_SCALE"/>
<uses-permission android:name="godot.SET_DEBUG_APP"/>
<uses-permission android:name="godot.SET_ORIENTATION"/>
<uses-permission android:name="godot.SET_POINTER_SPEED"/>
<uses-permission android:name="godot.SET_PREFERRED_APPLICATIONS"/>
<uses-permission android:name="godot.SET_PROCESS_LIMIT"/>
<uses-permission android:name="godot.SET_TIME"/>
<uses-permission android:name="godot.SET_TIME_ZONE"/>
<uses-permission android:name="godot.SET_WALLPAPER"/>
<uses-permission android:name="godot.SET_WALLPAPER_HINTS"/>
<uses-permission android:name="godot.SIGNAL_PERSISTENT_PROCESSES"/>
<uses-permission android:name="godot.STATUS_BAR"/>
<uses-permission android:name="godot.SUBSCRIBED_FEEDS_READ"/>
<uses-permission android:name="godot.SUBSCRIBED_FEEDS_WRITE"/>
<uses-permission android:name="godot.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="godot.TRANSMIT_IR"/>
<uses-permission android:name="godot.UNINSTALL_SHORTCUT"/>
<uses-permission android:name="godot.UPDATE_DEVICE_STATS"/>
<uses-permission android:name="godot.USE_CREDENTIALS"/>
<uses-permission android:name="godot.USE_SIP"/>
<uses-permission android:name="godot.VIBRATE"/>
<uses-permission android:name="godot.WAKE_LOCK"/>
<uses-permission android:name="godot.WRITE_APN_SETTINGS"/>
<uses-permission android:name="godot.WRITE_CALENDAR"/>
<uses-permission android:name="godot.WRITE_CALL_LOG"/>
<uses-permission android:name="godot.WRITE_CONTACTS"/>
<uses-permission android:name="godot.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="godot.WRITE_GSERVICES"/>
<uses-permission android:name="godot.WRITE_HISTORY_BOOKMARKS"/>
<uses-permission android:name="godot.WRITE_PROFILE"/>
<uses-permission android:name="godot.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="godot.WRITE_SETTINGS"/>
<uses-permission android:name="godot.WRITE_SMS"/>
<uses-permission android:name="godot.WRITE_SOCIAL_STREAM"/>
<uses-permission android:name="godot.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="godot.WRITE_USER_DICTIONARY"/>
<uses-permission android:name="godot.custom.0"/>
<uses-permission android:name="godot.custom.1"/>
<uses-permission android:name="godot.custom.2"/>
<uses-permission android:name="godot.custom.3"/>
<uses-permission android:name="godot.custom.4"/>
<uses-permission android:name="godot.custom.5"/>
<uses-permission android:name="godot.custom.6"/>
<uses-permission android:name="godot.custom.7"/>
<uses-permission android:name="godot.custom.8"/>
<uses-permission android:name="godot.custom.9"/>
<uses-permission android:name="godot.custom.10"/>
<uses-permission android:name="godot.custom.11"/>
<uses-permission android:name="godot.custom.12"/>
<uses-permission android:name="godot.custom.13"/>
<uses-permission android:name="godot.custom.14"/>
<uses-permission android:name="godot.custom.15"/>
<uses-permission android:name="godot.custom.16"/>
<uses-permission android:name="godot.custom.17"/>
<uses-permission android:name="godot.custom.18"/>
<uses-permission android:name="godot.custom.19"/>
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="27"/>
</manifest>

View file

@ -33,7 +33,7 @@
#include "engine.h" #include "engine.h"
#include "message_queue.h" #include "message_queue.h"
#include "scene/scene_string_names.h" #include "scene/scene_string_names.h"
#include "servers/audio/audio_stream.h"
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
void AnimatedValuesBackup::update_skeletons() { void AnimatedValuesBackup::update_skeletons() {
@ -325,10 +325,27 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
p_anim->node_cache[i]->property_anim[a->track_get_path(i).get_concatenated_subnames()] = pa; p_anim->node_cache[i]->property_anim[a->track_get_path(i).get_concatenated_subnames()] = pa;
} }
} }
if (a->track_get_type(i) == Animation::TYPE_BEZIER && leftover_path.size()) {
if (!p_anim->node_cache[i]->bezier_anim.has(a->track_get_path(i).get_concatenated_subnames())) {
TrackNodeCache::BezierAnim ba;
String path = leftover_path[leftover_path.size() - 1];
Vector<String> index = path.split(".");
for (int j = 0; j < index.size(); j++) {
ba.bezier_property.push_back(index[j]);
}
ba.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child;
ba.owner = p_anim->node_cache[i];
p_anim->node_cache[i]->bezier_anim[a->track_get_path(i).get_concatenated_subnames()] = ba;
}
}
} }
} }
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete) { void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started) {
_ensure_node_caches(p_anim); _ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@ -394,7 +411,39 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
TrackNodeCache::PropertyAnim *pa = &E->get(); TrackNodeCache::PropertyAnim *pa = &E->get();
if (a->value_track_get_update_mode(i) == Animation::UPDATE_CONTINUOUS || (p_delta == 0 && a->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek Animation::UpdateMode update_mode = a->value_track_get_update_mode(i);
if (update_mode == Animation::UPDATE_CAPTURE) {
if (p_started) {
pa->capture = pa->object->get_indexed(pa->subpath);
}
if (a->track_get_key_count(i) == 0)
continue; //eeh not worth it
float first_key_time = a->track_get_key_time(i, 0);
if (p_time < first_key_time) {
float c = p_time / first_key_time;
Variant first_value = a->track_get_key_value(i, 0);
Variant interp_value;
Variant::interpolate(pa->capture, first_value, c, interp_value);
if (pa->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
cache_update_prop[cache_update_prop_size++] = pa;
pa->value_accum = interp_value;
pa->accum_pass = accum_pass;
} else {
Variant::interpolate(pa->value_accum, interp_value, p_interp, pa->value_accum);
}
continue; //handled
}
}
if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE || (p_delta == 0 && update_mode == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek
Variant value = a->value_track_interpolate(i, p_time); Variant value = a->value_track_interpolate(i, p_time);
@ -415,7 +464,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum); Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum);
} }
} else if (p_allow_discrete && p_delta != 0) { } else if (p_is_current && p_delta != 0) {
List<int> indices; List<int> indices;
a->value_track_get_key_indices(i, p_time, p_delta, &indices); a->value_track_get_key_indices(i, p_time, p_delta, &indices);
@ -470,9 +519,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
if (!nc->node) if (!nc->node)
continue; continue;
if (p_delta == 0) if (p_delta == 0) {
continue; continue;
if (!p_allow_discrete) }
if (!p_is_current)
break; break;
List<int> indices; List<int> indices;
@ -500,11 +550,180 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
} }
} break; } break;
case Animation::TYPE_BEZIER: {
if (!nc->node)
continue;
Map<StringName, TrackNodeCache::BezierAnim>::Element *E = nc->bezier_anim.find(a->track_get_path(i).get_concatenated_subnames());
ERR_CONTINUE(!E); //should it continue, or create a new one?
TrackNodeCache::BezierAnim *ba = &E->get();
float bezier = a->bezier_track_interpolate(i, p_time);
if (ba->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX);
cache_update_bezier[cache_update_bezier_size++] = ba;
ba->bezier_accum = bezier;
ba->accum_pass = accum_pass;
} else {
ba->bezier_accum = Math::lerp(ba->bezier_accum, bezier, p_interp);
}
} break;
case Animation::TYPE_AUDIO: {
if (!nc->node)
continue;
if (p_delta == 0) {
continue;
}
if (p_seeked) {
//find whathever should be playing
int idx = a->track_find_key(i, p_time);
if (idx < 0)
continue;
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) {
nc->node->call("stop");
nc->audio_playing = false;
playing_caches.erase(nc);
} else {
float start_ofs = a->audio_track_get_key_start_offset(i, idx);
start_ofs += p_time - a->track_get_key_time(i, idx);
float end_ofs = a->audio_track_get_key_end_offset(i, idx);
float len = stream->get_length();
if (start_ofs > len - end_ofs) {
nc->node->call("stop");
nc->audio_playing = false;
playing_caches.erase(nc);
continue;
}
nc->node->call("set_stream", stream);
nc->node->call("play", start_ofs);
nc->audio_playing = true;
playing_caches.insert(nc);
if (len && end_ofs > 0) { //force a end at a time
nc->audio_len = len - start_ofs - end_ofs;
} else {
nc->audio_len = 0;
}
nc->audio_start = p_time;
}
} else {
//find stuff to play
List<int> to_play;
a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play);
if (to_play.size()) {
int idx = to_play.back()->get();
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) {
nc->node->call("stop");
nc->audio_playing = false;
playing_caches.erase(nc);
} else {
float start_ofs = a->audio_track_get_key_start_offset(i, idx);
float end_ofs = a->audio_track_get_key_end_offset(i, idx);
float len = stream->get_length();
nc->node->call("set_stream", stream);
nc->node->call("play", start_ofs);
nc->audio_playing = true;
playing_caches.insert(nc);
if (len && end_ofs > 0) { //force a end at a time
nc->audio_len = len - start_ofs - end_ofs;
} else {
nc->audio_len = 0;
}
nc->audio_start = p_time;
}
} else if (nc->audio_playing) {
if (nc->audio_start > p_time || (nc->audio_len > 0 && p_time - nc->audio_start < nc->audio_len)) {
//time to stop
nc->node->call("stop");
nc->audio_playing = false;
playing_caches.erase(nc);
} }
} }
} }
void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, float p_blend) { } break;
case Animation::TYPE_ANIMATION: {
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(nc->node);
if (!player)
continue;
if (p_delta == 0 || p_seeked) {
//seek
int idx = a->track_find_key(i, p_time);
if (idx < 0)
continue;
float pos = a->track_get_key_time(i, idx);
StringName anim_name = a->animation_track_get_key_animation(i, idx);
if (String(anim_name) == "[stop]" || !player->has_animation(anim_name))
continue;
Ref<Animation> anim = player->get_animation(anim_name);
float at_anim_pos;
if (anim->has_loop()) {
at_anim_pos = Math::fposmod(p_time - pos, anim->get_length()); //seek to loop
} else {
at_anim_pos = MAX(anim->get_length(), p_time - pos); //seek to end
}
if (player->is_playing() || p_seeked) {
player->play(anim_name);
player->seek(at_anim_pos);
nc->animation_playing = true;
playing_caches.insert(nc);
} else {
player->set_assigned_animation(anim_name);
player->seek(at_anim_pos, true);
}
} else {
//find stuff to play
List<int> to_play;
a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play);
if (to_play.size()) {
int idx = to_play.back()->get();
StringName anim_name = a->animation_track_get_key_animation(i, idx);
if (String(anim_name) == "[stop]" || !player->has_animation(anim_name)) {
if (playing_caches.has(nc)) {
playing_caches.erase(nc);
player->stop();
nc->animation_playing = false;
}
} else {
player->play(anim_name);
nc->animation_playing = true;
playing_caches.insert(nc);
}
}
}
} break;
}
}
}
void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started) {
float delta = p_delta * speed_scale * cd.speed_scale; float delta = p_delta * speed_scale * cd.speed_scale;
float next_pos = cd.pos + delta; float next_pos = cd.pos + delta;
@ -553,22 +772,25 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f
cd.pos = next_pos; cd.pos = next_pos;
_animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current); _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started);
} }
void AnimationPlayer::_animation_process2(float p_delta) { void AnimationPlayer::_animation_process2(float p_delta, bool p_started) {
Playback &c = playback; Playback &c = playback;
accum_pass++; accum_pass++;
_animation_process_data(c.current, p_delta, 1.0f); _animation_process_data(c.current, p_delta, 1.0f, c.seeked && p_delta != 0, p_started);
if (p_delta != 0) {
c.seeked = false;
}
List<Blend>::Element *prev = NULL; List<Blend>::Element *prev = NULL;
for (List<Blend>::Element *E = c.blend.back(); E; E = prev) { for (List<Blend>::Element *E = c.blend.back(); E; E = prev) {
Blend &b = E->get(); Blend &b = E->get();
float blend = b.blend_left / b.blend_time; float blend = b.blend_left / b.blend_time;
_animation_process_data(b.data, p_delta, blend); _animation_process_data(b.data, p_delta, blend, false, false);
b.blend_left -= Math::absf(speed_scale * p_delta); b.blend_left -= Math::absf(speed_scale * p_delta);
@ -652,6 +874,16 @@ void AnimationPlayer::_animation_update_transforms() {
} }
cache_update_prop_size = 0; cache_update_prop_size = 0;
for (int i = 0; i < cache_update_bezier_size; i++) {
TrackNodeCache::BezierAnim *ba = cache_update_bezier[i];
ERR_CONTINUE(ba->accum_pass != accum_pass);
ba->object->set_indexed(ba->bezier_property, ba->bezier_accum);
}
cache_update_bezier_size = 0;
} }
void AnimationPlayer::_animation_process(float p_delta) { void AnimationPlayer::_animation_process(float p_delta) {
@ -660,7 +892,12 @@ void AnimationPlayer::_animation_process(float p_delta) {
end_reached = false; end_reached = false;
end_notify = false; end_notify = false;
_animation_process2(p_delta); _animation_process2(p_delta, playback.started);
if (playback.started) {
playback.started = false;
}
_animation_update_transforms(); _animation_update_transforms();
if (end_reached) { if (end_reached) {
if (queued.size()) { if (queued.size()) {
@ -865,7 +1102,7 @@ void AnimationPlayer::queue(const StringName &p_name) {
void AnimationPlayer::clear_queue() { void AnimationPlayer::clear_queue() {
queued.clear(); queued.clear();
}; }
void AnimationPlayer::play_backwards(const StringName &p_name, float p_custom_blend) { void AnimationPlayer::play_backwards(const StringName &p_name, float p_custom_blend) {
@ -930,10 +1167,14 @@ void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float
} }
} }
_stop_playing_caches();
c.current.from = &animation_set[name]; c.current.from = &animation_set[name];
c.current.pos = p_from_end ? c.current.from->animation->get_length() : 0; c.current.pos = p_from_end ? c.current.from->animation->get_length() : 0;
c.current.speed_scale = p_custom_scale; c.current.speed_scale = p_custom_scale;
c.assigned = p_name; c.assigned = p_name;
c.seeked = false;
c.started = true;
if (!end_reached) if (!end_reached)
queued.clear(); queued.clear();
@ -1004,6 +1245,7 @@ String AnimationPlayer::get_assigned_animation() const {
void AnimationPlayer::stop(bool p_reset) { void AnimationPlayer::stop(bool p_reset) {
_stop_playing_caches();
Playback &c = playback; Playback &c = playback;
c.blend.clear(); c.blend.clear();
if (p_reset) { if (p_reset) {
@ -1042,6 +1284,7 @@ void AnimationPlayer::seek(float p_time, bool p_update) {
} }
playback.current.pos = p_time; playback.current.pos = p_time;
playback.seeked = true;
if (p_update) { if (p_update) {
_animation_process(0); _animation_process(0);
} }
@ -1086,6 +1329,24 @@ void AnimationPlayer::_animation_changed() {
clear_caches(); clear_caches();
} }
void AnimationPlayer::_stop_playing_caches() {
for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
if (E->get()->node && E->get()->audio_playing) {
E->get()->node->call("stop");
}
if (E->get()->node && E->get()->animation_playing) {
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(E->get()->node);
if (!player)
continue;
player->stop();
}
}
playing_caches.clear();
}
void AnimationPlayer::_node_removed(Node *p_node) { void AnimationPlayer::_node_removed(Node *p_node) {
clear_caches(); // nodes contained here ar being removed, clear the caches clear_caches(); // nodes contained here ar being removed, clear the caches
@ -1093,6 +1354,8 @@ void AnimationPlayer::_node_removed(Node *p_node) {
void AnimationPlayer::clear_caches() { void AnimationPlayer::clear_caches() {
_stop_playing_caches();
node_cache_map.clear(); node_cache_map.clear();
for (Map<StringName, AnimationData>::Element *E = animation_set.front(); E; E = E->next()) { for (Map<StringName, AnimationData>::Element *E = animation_set.front(); E; E = E->next()) {
@ -1102,6 +1365,7 @@ void AnimationPlayer::clear_caches() {
cache_update_size = 0; cache_update_size = 0;
cache_update_prop_size = 0; cache_update_prop_size = 0;
cache_update_bezier_size = 0;
} }
void AnimationPlayer::set_active(bool p_active) { void AnimationPlayer::set_active(bool p_active) {
@ -1368,6 +1632,7 @@ AnimationPlayer::AnimationPlayer() {
accum_pass = 1; accum_pass = 1;
cache_update_size = 0; cache_update_size = 0;
cache_update_prop_size = 0; cache_update_prop_size = 0;
cache_update_bezier_size = 0;
speed_scale = 1; speed_scale = 1;
end_reached = false; end_reached = false;
end_notify = false; end_notify = false;
@ -1377,6 +1642,8 @@ AnimationPlayer::AnimationPlayer() {
root = SceneStringNames::get_singleton()->path_pp; root = SceneStringNames::get_singleton()->path_pp;
playing = false; playing = false;
active = true; active = true;
playback.seeked = false;
playback.started = false;
} }
AnimationPlayer::~AnimationPlayer() { AnimationPlayer::~AnimationPlayer() {

View file

@ -98,6 +98,12 @@ private:
Vector3 scale_accum; Vector3 scale_accum;
uint64_t accum_pass; uint64_t accum_pass;
bool audio_playing;
float audio_start;
float audio_len;
bool animation_playing;
struct PropertyAnim { struct PropertyAnim {
TrackNodeCache *owner; TrackNodeCache *owner;
@ -106,6 +112,7 @@ private:
Object *object; Object *object;
Variant value_accum; Variant value_accum;
uint64_t accum_pass; uint64_t accum_pass;
Variant capture;
PropertyAnim() { PropertyAnim() {
accum_pass = 0; accum_pass = 0;
object = NULL; object = NULL;
@ -114,6 +121,22 @@ private:
Map<StringName, PropertyAnim> property_anim; Map<StringName, PropertyAnim> property_anim;
struct BezierAnim {
Vector<StringName> bezier_property;
TrackNodeCache *owner;
float bezier_accum;
Object *object;
uint64_t accum_pass;
BezierAnim() {
accum_pass = 0;
bezier_accum = 0;
object = NULL;
}
};
Map<StringName, BezierAnim> bezier_anim;
TrackNodeCache() { TrackNodeCache() {
skeleton = NULL; skeleton = NULL;
spatial = NULL; spatial = NULL;
@ -121,6 +144,8 @@ private:
accum_pass = 0; accum_pass = 0;
bone_idx = -1; bone_idx = -1;
node_2d = NULL; node_2d = NULL;
audio_playing = false;
animation_playing = false;
} }
}; };
@ -146,6 +171,10 @@ private:
int cache_update_size; int cache_update_size;
TrackNodeCache::PropertyAnim *cache_update_prop[NODE_CACHE_UPDATE_MAX]; TrackNodeCache::PropertyAnim *cache_update_prop[NODE_CACHE_UPDATE_MAX];
int cache_update_prop_size; int cache_update_prop_size;
TrackNodeCache::BezierAnim *cache_update_bezier[NODE_CACHE_UPDATE_MAX];
int cache_update_bezier_size;
Set<TrackNodeCache *> playing_caches;
Map<Ref<Animation>, int> used_anims; Map<Ref<Animation>, int> used_anims;
uint64_t accum_pass; uint64_t accum_pass;
@ -202,6 +231,8 @@ private:
List<Blend> blend; List<Blend> blend;
PlaybackData current; PlaybackData current;
StringName assigned; StringName assigned;
bool seeked;
bool started;
} playback; } playback;
List<StringName> queued; List<StringName> queued;
@ -216,15 +247,16 @@ private:
NodePath root; NodePath root;
void _animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_allow_discrete = true); void _animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false);
void _ensure_node_caches(AnimationData *p_anim); void _ensure_node_caches(AnimationData *p_anim);
void _animation_process_data(PlaybackData &cd, float p_delta, float p_blend); void _animation_process_data(PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started);
void _animation_process2(float p_delta); void _animation_process2(float p_delta, bool p_started);
void _animation_update_transforms(); void _animation_update_transforms();
void _animation_process(float p_delta); void _animation_process(float p_delta);
void _node_removed(Node *p_node); void _node_removed(Node *p_node);
void _stop_playing_caches();
// bind helpers // bind helpers
PoolVector<String> _get_animation_list() const { PoolVector<String> _get_animation_list() const {

View file

@ -440,6 +440,8 @@ void PopupMenu::_notification(int p_what) {
float h; float h;
Size2 icon_size; Size2 icon_size;
Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1);
item_ofs.x += items[i].h_ofs; item_ofs.x += items[i].h_ofs;
if (!items[i].icon.is_null()) { if (!items[i].icon.is_null()) {
@ -463,18 +465,18 @@ void PopupMenu::_notification(int p_what) {
if (items[i].checkable_type) { if (items[i].checkable_type) {
Texture *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr(); Texture *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr();
icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0))); icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)), icon_color);
item_ofs.x += icon->get_width() + hseparation; item_ofs.x += icon->get_width() + hseparation;
} }
if (!items[i].icon.is_null()) { if (!items[i].icon.is_null()) {
items[i].icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon_size.height) / 2.0))); items[i].icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
item_ofs.x += items[i].icon->get_width(); item_ofs.x += items[i].icon->get_width();
item_ofs.x += hseparation; item_ofs.x += hseparation;
} }
if (items[i].submenu != "") { if (items[i].submenu != "") {
submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2)); submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
} }
item_ofs.y += font->get_ascent(); item_ofs.y += font->get_ascent();
@ -913,6 +915,13 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) {
update(); update();
} }
void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, items.size());
items[p_idx].shortcut_is_disabled = p_disabled;
update();
}
void PopupMenu::toggle_item_multistate(int p_idx) { void PopupMenu::toggle_item_multistate(int p_idx) {
ERR_FAIL_INDEX(p_idx, items.size()); ERR_FAIL_INDEX(p_idx, items.size());
@ -937,6 +946,12 @@ bool PopupMenu::is_item_radio_checkable(int p_idx) const {
return items[p_idx].checkable_type == Item::CHECKABLE_TYPE_RADIO_BUTTON; return items[p_idx].checkable_type == Item::CHECKABLE_TYPE_RADIO_BUTTON;
} }
bool PopupMenu::is_item_shortcut_disabled(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), false);
return items[p_idx].shortcut_is_disabled;
}
int PopupMenu::get_item_count() const { int PopupMenu::get_item_count() const {
return items.size(); return items.size();
@ -963,7 +978,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo
int il = items.size(); int il = items.size();
for (int i = 0; i < il; i++) { for (int i = 0; i < il; i++) {
if (is_item_disabled(i)) if (is_item_disabled(i) || items[i].shortcut_is_disabled)
continue; continue;
if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) { if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) {
@ -1248,6 +1263,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip); ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip);
ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_item_multistate", "idx", "state"), &PopupMenu::set_item_multistate); ClassDB::bind_method(D_METHOD("set_item_multistate", "idx", "state"), &PopupMenu::set_item_multistate);
ClassDB::bind_method(D_METHOD("set_item_shortcut_disabled", "idx", "disabled"), &PopupMenu::set_item_shortcut_disabled);
ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked); ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked);
ClassDB::bind_method(D_METHOD("toggle_item_multistate", "idx"), &PopupMenu::toggle_item_multistate); ClassDB::bind_method(D_METHOD("toggle_item_multistate", "idx"), &PopupMenu::toggle_item_multistate);
@ -1264,6 +1280,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &PopupMenu::is_item_separator); ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &PopupMenu::is_item_separator);
ClassDB::bind_method(D_METHOD("is_item_checkable", "idx"), &PopupMenu::is_item_checkable); ClassDB::bind_method(D_METHOD("is_item_checkable", "idx"), &PopupMenu::is_item_checkable);
ClassDB::bind_method(D_METHOD("is_item_radio_checkable", "idx"), &PopupMenu::is_item_radio_checkable); ClassDB::bind_method(D_METHOD("is_item_radio_checkable", "idx"), &PopupMenu::is_item_radio_checkable);
ClassDB::bind_method(D_METHOD("is_item_shortcut_disabled", "idx"), &PopupMenu::is_item_shortcut_disabled);
ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &PopupMenu::get_item_tooltip); ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &PopupMenu::get_item_tooltip);
ClassDB::bind_method(D_METHOD("get_item_shortcut", "idx"), &PopupMenu::get_item_shortcut); ClassDB::bind_method(D_METHOD("get_item_shortcut", "idx"), &PopupMenu::get_item_shortcut);

View file

@ -64,6 +64,7 @@ class PopupMenu : public Popup {
int h_ofs; int h_ofs;
Ref<ShortCut> shortcut; Ref<ShortCut> shortcut;
bool shortcut_is_global; bool shortcut_is_global;
bool shortcut_is_disabled;
Item() { Item() {
checked = false; checked = false;
@ -76,6 +77,7 @@ class PopupMenu : public Popup {
_ofs_cache = 0; _ofs_cache = 0;
h_ofs = 0; h_ofs = 0;
shortcut_is_global = false; shortcut_is_global = false;
shortcut_is_disabled = false;
} }
}; };
@ -149,6 +151,7 @@ public:
void set_item_h_offset(int p_idx, int p_offset); void set_item_h_offset(int p_idx, int p_offset);
void set_item_multistate(int p_idx, int p_state); void set_item_multistate(int p_idx, int p_state);
void toggle_item_multistate(int p_idx); void toggle_item_multistate(int p_idx);
void set_item_shortcut_disabled(int p_idx, bool p_disabled);
void toggle_item_checked(int p_idx); void toggle_item_checked(int p_idx);
@ -165,6 +168,7 @@ public:
bool is_item_separator(int p_idx) const; bool is_item_separator(int p_idx) const;
bool is_item_checkable(int p_idx) const; bool is_item_checkable(int p_idx) const;
bool is_item_radio_checkable(int p_idx) const; bool is_item_radio_checkable(int p_idx) const;
bool is_item_shortcut_disabled(int p_idx) const;
String get_item_tooltip(int p_idx) const; String get_item_tooltip(int p_idx) const;
Ref<ShortCut> get_item_shortcut(int p_idx) const; Ref<ShortCut> get_item_shortcut(int p_idx) const;
int get_item_state(int p_idx) const; int get_item_state(int p_idx) const;

View file

@ -241,10 +241,10 @@ void ScrollContainer::_notification(int p_what) {
size -= sb->get_minimum_size(); size -= sb->get_minimum_size();
ofs += sb->get_offset(); ofs += sb->get_offset();
if (h_scroll->is_visible_in_tree()) if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) //scrolls may have been moved out for reasons
size.y -= h_scroll->get_minimum_size().y; size.y -= h_scroll->get_minimum_size().y;
if (v_scroll->is_visible_in_tree()) if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) //scrolls may have been moved out for reasons
size.x -= h_scroll->get_minimum_size().x; size.x -= h_scroll->get_minimum_size().x;
for (int i = 0; i < get_child_count(); i++) { for (int i = 0; i < get_child_count(); i++) {
@ -482,6 +482,16 @@ String ScrollContainer::get_configuration_warning() const {
return ""; return "";
} }
HScrollBar *ScrollContainer::get_h_scrollbar() {
return h_scroll;
}
VScrollBar *ScrollContainer::get_v_scrollbar() {
return v_scroll;
}
void ScrollContainer::_bind_methods() { void ScrollContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("_scroll_moved"), &ScrollContainer::_scroll_moved); ClassDB::bind_method(D_METHOD("_scroll_moved"), &ScrollContainer::_scroll_moved);
@ -498,6 +508,9 @@ void ScrollContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_deadzone", "deadzone"), &ScrollContainer::set_deadzone); ClassDB::bind_method(D_METHOD("set_deadzone", "deadzone"), &ScrollContainer::set_deadzone);
ClassDB::bind_method(D_METHOD("get_deadzone"), &ScrollContainer::get_deadzone); ClassDB::bind_method(D_METHOD("get_deadzone"), &ScrollContainer::get_deadzone);
ClassDB::bind_method(D_METHOD("get_h_scrollbar"), &ScrollContainer::get_h_scrollbar);
ClassDB::bind_method(D_METHOD("get_v_scrollbar"), &ScrollContainer::get_v_scrollbar);
ADD_SIGNAL(MethodInfo("scroll_started")); ADD_SIGNAL(MethodInfo("scroll_started"));
ADD_SIGNAL(MethodInfo("scroll_ended")); ADD_SIGNAL(MethodInfo("scroll_ended"));

View file

@ -92,6 +92,9 @@ public:
int get_deadzone() const; int get_deadzone() const;
void set_deadzone(int p_deadzone); void set_deadzone(int p_deadzone);
HScrollBar *get_h_scrollbar();
VScrollBar *get_v_scrollbar();
virtual bool clips_input() const; virtual bool clips_input() const;
virtual String get_configuration_warning() const; virtual String get_configuration_warning() const;

View file

@ -1308,13 +1308,37 @@ void Viewport::_gui_cancel_tooltip() {
} }
} }
String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos) {
Vector2 pos = p_pos;
String tooltip;
while (p_control) {
tooltip = p_control->get_tooltip(pos);
if (tooltip != String())
break;
pos = p_control->get_transform().xform(pos);
if (p_control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
break;
if (p_control->is_set_as_toplevel())
break;
p_control = p_control->get_parent_control();
}
return tooltip;
}
void Viewport::_gui_show_tooltip() { void Viewport::_gui_show_tooltip() {
if (!gui.tooltip) { if (!gui.tooltip) {
return; return;
} }
String tooltip = gui.tooltip->get_tooltip(gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos)); String tooltip = _gui_get_tooltip(gui.tooltip, gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos));
if (tooltip.length() == 0) if (tooltip.length() == 0)
return; // bye return; // bye
@ -1388,12 +1412,14 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Control *control = Object::cast_to<Control>(ci); Control *control = Object::cast_to<Control>(ci);
if (control) { if (control) {
control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
if (gui.key_event_accepted) if (gui.key_event_accepted)
break; break;
if (!control->is_inside_tree()) if (!control->is_inside_tree())
break; break;
control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
if (!control->is_inside_tree() || control->is_set_as_toplevel()) if (!control->is_inside_tree() || control->is_set_as_toplevel())
break; break;
if (gui.key_event_accepted) if (gui.key_event_accepted)
@ -1864,7 +1890,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.tooltip_popup) { if (gui.tooltip_popup) {
if (can_tooltip) { if (can_tooltip) {
String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
if (tooltip.length() == 0) if (tooltip.length() == 0)
_gui_cancel_tooltip(); _gui_cancel_tooltip();
@ -1886,7 +1912,23 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
mm->set_position(pos); mm->set_position(pos);
Control::CursorShape cursor_shape = over->get_cursor_shape(pos); Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
{
Control *c = over;
Vector2 cpos = pos;
while (c) {
cursor_shape = c->get_cursor_shape();
cpos = c->get_transform().xform(cpos);
if (cursor_shape != Control::CURSOR_ARROW)
break;
if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
break;
if (c->is_set_as_toplevel())
break;
c = c->get_parent_control();
}
}
OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape); OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape);
if (over->can_process()) { if (over->can_process()) {

View file

@ -312,6 +312,7 @@ private:
void _gui_remove_root_control(List<Control *>::Element *RI); void _gui_remove_root_control(List<Control *>::Element *RI);
void _gui_remove_subwindow_control(List<Control *>::Element *SI); void _gui_remove_subwindow_control(List<Control *>::Element *SI);
String _gui_get_tooltip(Control *p_control, const Vector2 &p_pos);
void _gui_cancel_tooltip(); void _gui_cancel_tooltip();
void _gui_show_tooltip(); void _gui_show_tooltip();

File diff suppressed because it is too large Load diff

View file

@ -45,6 +45,9 @@ public:
TYPE_VALUE, ///< Set a value in a property, can be interpolated. TYPE_VALUE, ///< Set a value in a property, can be interpolated.
TYPE_TRANSFORM, ///< Transform a node or a bone. TYPE_TRANSFORM, ///< Transform a node or a bone.
TYPE_METHOD, ///< Call any method on a specific node. TYPE_METHOD, ///< Call any method on a specific node.
TYPE_BEZIER, ///< Bezier curve
TYPE_AUDIO,
TYPE_ANIMATION,
}; };
enum InterpolationType { enum InterpolationType {
@ -57,6 +60,7 @@ public:
UPDATE_CONTINUOUS, UPDATE_CONTINUOUS,
UPDATE_DISCRETE, UPDATE_DISCRETE,
UPDATE_TRIGGER, UPDATE_TRIGGER,
UPDATE_CAPTURE,
}; };
@ -137,6 +141,55 @@ private:
MethodTrack() { type = TYPE_METHOD; } MethodTrack() { type = TYPE_METHOD; }
}; };
/* BEZIER TRACK */
struct BezierKey {
Vector2 in_handle; //relative (x always <0)
Vector2 out_handle; //relative (x always >0)
float value;
};
struct BezierTrack : public Track {
Vector<TKey<BezierKey> > values;
BezierTrack() {
type = TYPE_BEZIER;
}
};
/* AUDIO TRACK */
struct AudioKey {
RES stream;
float start_offset; //offset from start
float end_offset; //offset from end, if 0 then full length or infinite
AudioKey() {
start_offset = 0;
end_offset = 0;
}
};
struct AudioTrack : public Track {
Vector<TKey<AudioKey> > values;
AudioTrack() {
type = TYPE_AUDIO;
}
};
/* AUDIO TRACK */
struct AnimationTrack : public Track {
Vector<TKey<StringName> > values;
AnimationTrack() {
type = TYPE_ANIMATION;
}
};
Vector<Track *> tracks; Vector<Track *> tracks;
/* /*
@ -168,6 +221,9 @@ private:
template <class T> template <class T>
_FORCE_INLINE_ T _interpolate(const Vector<TKey<T> > &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const; _FORCE_INLINE_ T _interpolate(const Vector<TKey<T> > &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const;
template <class T>
_FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, float from_time, float to_time, List<int> *p_indices) const;
_FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const; _FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const;
_FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, float from_time, float to_time, List<int> *p_indices) const; _FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, float from_time, float to_time, List<int> *p_indices) const;
@ -238,6 +294,7 @@ public:
void track_move_up(int p_track); void track_move_up(int p_track);
void track_move_down(int p_track); void track_move_down(int p_track);
void track_swap(int p_track, int p_with_track);
void track_set_imported(int p_track, bool p_imported); void track_set_imported(int p_track, bool p_imported);
bool track_is_imported(int p_track) const; bool track_is_imported(int p_track) const;
@ -245,7 +302,6 @@ public:
void track_set_enabled(int p_track, bool p_enabled); void track_set_enabled(int p_track, bool p_enabled);
bool track_is_enabled(int p_track) const; bool track_is_enabled(int p_track) const;
int transform_track_insert_key(int p_track, float p_time, const Vector3 p_loc, const Quat &p_rot = Quat(), const Vector3 &p_scale = Vector3());
void track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition = 1); 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_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_value(int p_track, int p_key_idx, const Variant &p_value);
@ -257,10 +313,33 @@ public:
float track_get_key_time(int p_track, int p_key_idx) const; float track_get_key_time(int p_track, int p_key_idx) const;
float track_get_key_transition(int p_track, int p_key_idx) const; float track_get_key_transition(int p_track, int p_key_idx) const;
int transform_track_insert_key(int p_track, float p_time, const Vector3 p_loc, const Quat &p_rot = Quat(), const Vector3 &p_scale = Vector3());
Error transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const; Error transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const;
void track_set_interpolation_type(int p_track, InterpolationType p_interp); void track_set_interpolation_type(int p_track, InterpolationType p_interp);
InterpolationType track_get_interpolation_type(int p_track) const; InterpolationType track_get_interpolation_type(int p_track) const;
int bezier_track_insert_key(int p_track, float p_time, float p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle);
void bezier_track_set_key_value(int p_track, int p_index, float p_value);
void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle);
void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle);
float bezier_track_get_key_value(int p_track, int p_index) const;
Vector2 bezier_track_get_key_in_handle(int p_track, int p_index) const;
Vector2 bezier_track_get_key_out_handle(int p_track, int p_index) const;
float bezier_track_interpolate(int p_track, float p_time) const;
int audio_track_insert_key(int p_track, float p_time, const RES &p_stream, float p_start_offset = 0, float p_end_offset = 0);
void audio_track_set_key_stream(int p_track, int p_key, const RES &p_stream);
void audio_track_set_key_start_offset(int p_track, int p_key, float p_offset);
void audio_track_set_key_end_offset(int p_track, int p_key, float p_offset);
RES audio_track_get_key_stream(int p_track, int p_key) const;
float audio_track_get_key_start_offset(int p_track, int p_key) const;
float audio_track_get_key_end_offset(int p_track, int p_key) const;
int animation_track_insert_key(int p_track, float p_time, const StringName &p_animation);
void animation_track_set_key_animation(int p_track, int p_key, const StringName &p_animation);
StringName animation_track_get_key_animation(int p_track, int p_key) const;
void track_set_interpolation_loop_wrap(int p_track, bool p_enable); void track_set_interpolation_loop_wrap(int p_track, bool p_enable);
bool track_get_interpolation_loop_wrap(int p_track) const; bool track_get_interpolation_loop_wrap(int p_track) const;
@ -277,6 +356,8 @@ public:
void copy_track(int p_track, Ref<Animation> p_to_animation); void copy_track(int p_track, Ref<Animation> p_to_animation);
void track_get_key_indices_in_range(int p_track, float p_time, float p_delta, List<int> *p_indices) const;
void set_length(float p_length); void set_length(float p_length);
float get_length() const; float get_length() const;

View file

@ -89,6 +89,7 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
} }
} }
} }
//////////////////////////////// ////////////////////////////////
void AudioStream::_bind_methods() { void AudioStream::_bind_methods() {

View file

@ -31,6 +31,7 @@
#ifndef AUDIO_STREAM_H #ifndef AUDIO_STREAM_H
#define AUDIO_STREAM_H #define AUDIO_STREAM_H
#include "image.h"
#include "resource.h" #include "resource.h"
#include "servers/audio/audio_filter_sw.h" #include "servers/audio/audio_filter_sw.h"
#include "servers/audio_server.h" #include "servers/audio_server.h"