summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2021-10-25 14:27:58 +0200
committerGitHub <noreply@github.com>2021-10-25 14:27:58 +0200
commit24fdedfe948a918b5a67846f7962f83ba0e59258 (patch)
treef42a4077bbcbc19da0615cccd550f4795c2fb05c /editor
parent82a99951753f0fb48d4b6c99a8385009c7fb8446 (diff)
parenta69541da4cf156ed00de7ed10887a1fc57dcbd14 (diff)
Merge pull request #54050 from reduz/animation-compression
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_track_editor.cpp108
-rw-r--r--editor/import/resource_importer_scene.cpp29
-rw-r--r--editor/import/resource_importer_scene.h1
3 files changed, 85 insertions, 53 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index e773510797..a85a4450a6 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -2039,7 +2039,7 @@ void AnimationTrackEdit::_notification(int p_what) {
update_mode_rect.position.y = int(get_size().height - update_icon->get_height()) / 2;
update_mode_rect.size = update_icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
+ if (!animation->track_is_compressed(track) && animation->track_get_type(track) == Animation::TYPE_VALUE) {
draw_texture(update_icon, update_mode_rect.position);
}
// Make it easier to click.
@@ -2081,7 +2081,7 @@ void AnimationTrackEdit::_notification(int p_what) {
interp_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
interp_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(icon, interp_mode_rect.position);
}
// Make it easier to click.
@@ -2091,7 +2091,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
interp_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
interp_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2114,7 +2114,7 @@ void AnimationTrackEdit::_notification(int p_what) {
loop_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
loop_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(icon, loop_mode_rect.position);
}
@@ -2124,7 +2124,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
loop_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
loop_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2139,7 +2139,7 @@ void AnimationTrackEdit::_notification(int p_what) {
{
// Erase.
- Ref<Texture2D> icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
+ Ref<Texture2D> icon = get_theme_icon(animation->track_is_compressed(track) ? SNAME("Lock") : SNAME("Remove"), SNAME("EditorIcons"));
remove_rect.position.x = ofs + ((get_size().width - ofs) - icon->get_width()) / 2;
remove_rect.position.y = int(get_size().height - icon->get_height()) / 2;
@@ -2711,60 +2711,63 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
// Check keyframes.
- float scale = timeline->get_zoom_scale();
- int limit = timeline->get_name_limit();
- int limit_end = get_size().width - timeline->get_buttons_width();
- // Left Border including space occupied by keyframes on t=0.
- int limit_start_hitbox = limit - type_icon->get_width();
-
- if (pos.x >= limit_start_hitbox && pos.x <= limit_end) {
- int key_idx = -1;
- float key_distance = 1e20;
+ if (!animation->track_is_compressed(track)) { // Selecting compressed keyframes for editing is not possible.
- // Select should happen in the opposite order of drawing for more accurate overlap select.
- for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) {
- Rect2 rect = get_key_rect(i, scale);
- float offset = animation->track_get_key_time(track, i) - timeline->get_value();
- offset = offset * scale + limit;
- rect.position.x += offset;
-
- if (rect.has_point(pos)) {
- if (is_key_selectable_by_distance()) {
- float distance = ABS(offset - pos.x);
- if (key_idx == -1 || distance < key_distance) {
+ float scale = timeline->get_zoom_scale();
+ int limit = timeline->get_name_limit();
+ int limit_end = get_size().width - timeline->get_buttons_width();
+ // Left Border including space occupied by keyframes on t=0.
+ int limit_start_hitbox = limit - type_icon->get_width();
+
+ if (pos.x >= limit_start_hitbox && pos.x <= limit_end) {
+ int key_idx = -1;
+ float key_distance = 1e20;
+
+ // Select should happen in the opposite order of drawing for more accurate overlap select.
+ for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) {
+ Rect2 rect = get_key_rect(i, scale);
+ float offset = animation->track_get_key_time(track, i) - timeline->get_value();
+ offset = offset * scale + limit;
+ rect.position.x += offset;
+
+ if (rect.has_point(pos)) {
+ if (is_key_selectable_by_distance()) {
+ float distance = ABS(offset - pos.x);
+ if (key_idx == -1 || distance < key_distance) {
+ key_idx = i;
+ key_distance = distance;
+ }
+ } else {
+ // First one does it.
key_idx = i;
- key_distance = distance;
+ break;
}
- } else {
- // First one does it.
- key_idx = i;
- break;
}
}
- }
- if (key_idx != -1) {
- if (mb->is_command_pressed() || mb->is_shift_pressed()) {
- if (editor->is_key_selected(track, key_idx)) {
- emit_signal(SNAME("deselect_key"), key_idx);
+ if (key_idx != -1) {
+ if (mb->is_command_pressed() || mb->is_shift_pressed()) {
+ if (editor->is_key_selected(track, key_idx)) {
+ emit_signal(SNAME("deselect_key"), key_idx);
+ } else {
+ emit_signal(SNAME("select_key"), key_idx, false);
+ moving_selection_attempt = true;
+ select_single_attempt = -1;
+ moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
+ }
} else {
- emit_signal(SNAME("select_key"), key_idx, false);
+ if (!editor->is_key_selected(track, key_idx)) {
+ emit_signal(SNAME("select_key"), key_idx, true);
+ select_single_attempt = -1;
+ } else {
+ select_single_attempt = key_idx;
+ }
+
moving_selection_attempt = true;
- select_single_attempt = -1;
moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
}
- } else {
- if (!editor->is_key_selected(track, key_idx)) {
- emit_signal(SNAME("select_key"), key_idx, true);
- select_single_attempt = -1;
- } else {
- select_single_attempt = key_idx;
- }
-
- moving_selection_attempt = true;
- moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
+ accept_event();
}
- accept_event();
}
}
}
@@ -2996,6 +2999,9 @@ void AnimationTrackEdit::set_in_group(bool p_enable) {
}
void AnimationTrackEdit::append_to_selection(const Rect2 &p_box, bool p_deselection) {
+ if (animation->track_is_compressed(track)) {
+ return; // Compressed keyframes can't be edited
+ }
// Left Border including space occupied by keyframes on t=0.
int limit_start_hitbox = timeline->get_name_limit() - type_icon->get_width();
Rect2 select_rect(limit_start_hitbox, 0, get_size().width - timeline->get_name_limit() - timeline->get_buttons_width(), get_size().height);
@@ -3339,6 +3345,10 @@ void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool
}
void AnimationTrackEditor::_track_remove_request(int p_track) {
+ if (animation->track_is_compressed(p_track)) {
+ EditorNode::get_singleton()->show_warning(TTR("Compressed tracks can't be edited or removed. Re-import the animation with compression disabled in order to edit."));
+ return;
+ }
int idx = p_track;
if (idx >= 0 && idx < animation->get_track_count()) {
undo_redo->create_action(TTR("Remove Anim Track"));
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 319e5ee25f..bebf05d481 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -950,6 +950,13 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
}
}
}
+
+ bool use_compression = node_settings["compression/enabled"];
+ int anim_compression_page_size = node_settings["compression/page_size"];
+
+ if (use_compression) {
+ _compress_animations(ap, anim_compression_page_size);
+ }
}
return p_node;
@@ -1149,6 +1156,15 @@ void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_
}
}
+void ResourceImporterScene::_compress_animations(AnimationPlayer *anim, int p_page_size_kb) {
+ List<StringName> anim_names;
+ anim->get_animation_list(&anim_names);
+ for (const StringName &E : anim_names) {
+ Ref<Animation> a = anim->get_animation(E);
+ a->compress(p_page_size_kb * 1024);
+ }
+}
+
void ResourceImporterScene::get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const {
switch (p_category) {
case INTERNAL_IMPORT_CATEGORY_NODE: {
@@ -1212,6 +1228,8 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_linear_error"), 0.05));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angular_error"), 0.01));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angle"), 22));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compression/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compression/page_size", PROPERTY_HINT_RANGE, "4,512,1,suffix:kb"), 8));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/position", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/rotation", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/scale", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1));
@@ -1320,13 +1338,16 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor
}
} break;
case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
- if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) {
+ if (p_option.begins_with("optimizer/") && p_option != "optimizer/enabled" && !bool(p_options["optimizer/enabled"])) {
+ return false;
+ }
+ if (p_option.begins_with("compression/") && p_option != "compression/enabled" && !bool(p_options["compression/enabled"])) {
return false;
}
- if (p_option.begins_with("animation/slice_")) {
- int max_slice = p_options["animation/slices/amount"];
- int slice = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1;
+ if (p_option.begins_with("slice_")) {
+ int max_slice = p_options["slices/amount"];
+ int slice = p_option.get_slice("_", 1).to_int() - 1;
if (slice >= max_slice) {
return false;
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index e1e7046be5..a192921966 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -261,6 +261,7 @@ public:
Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks);
void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all);
void _optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle);
+ void _compress_animations(AnimationPlayer *anim, int p_page_size_kb);
Node *pre_import(const String &p_source_file);
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;