summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_bezier_editor.cpp2
-rw-r--r--editor/animation_track_editor.cpp202
-rw-r--r--editor/animation_track_editor.h19
-rw-r--r--editor/array_property_edit.cpp2
-rw-r--r--editor/code_editor.cpp16
-rw-r--r--editor/connections_dialog.cpp2
-rw-r--r--editor/create_dialog.cpp2
-rw-r--r--editor/debugger/editor_debugger_node.cpp12
-rw-r--r--editor/debugger/editor_debugger_tree.cpp2
-rw-r--r--editor/debugger/editor_performance_profiler.cpp6
-rw-r--r--editor/debugger/editor_profiler.cpp2
-rw-r--r--editor/debugger/script_editor_debugger.cpp8
-rw-r--r--editor/dependency_editor.cpp4
-rw-r--r--editor/dependency_editor.h4
-rw-r--r--editor/doc_tools.cpp4
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_autoload_settings.cpp4
-rw-r--r--editor/editor_data.cpp10
-rw-r--r--editor/editor_export.cpp12
-rw-r--r--editor/editor_feature_profile.cpp4
-rw-r--r--editor/editor_file_dialog.cpp14
-rw-r--r--editor/editor_help.cpp38
-rw-r--r--editor/editor_inspector.cpp10
-rw-r--r--editor/editor_layouts_dialog.cpp18
-rw-r--r--editor/editor_node.cpp108
-rw-r--r--editor/editor_node.h6
-rw-r--r--editor/editor_plugin.cpp8
-rw-r--r--editor/editor_plugin.h2
-rw-r--r--editor/editor_properties.cpp16
-rw-r--r--editor/editor_properties_array_dict.cpp4
-rw-r--r--editor/editor_run_native.cpp2
-rw-r--r--editor/editor_sectioned_inspector.cpp2
-rw-r--r--editor/editor_settings.cpp6
-rw-r--r--editor/editor_spin_slider.cpp6
-rw-r--r--editor/editor_themes.cpp128
-rw-r--r--editor/filesystem_dock.cpp34
-rw-r--r--editor/find_in_files.cpp20
-rw-r--r--editor/groups_editor.cpp8
-rw-r--r--editor/icons/GuiToggleOn.svg2
-rw-r--r--editor/icons/GuiToggleOnMirrored.svg2
-rw-r--r--editor/import/collada.cpp4
-rw-r--r--editor/import/collada.h2
-rw-r--r--editor/import/editor_import_collada.cpp13
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp3254
-rw-r--r--editor/import/editor_scene_importer_gltf.h384
-rw-r--r--editor/import/resource_importer_layered_texture.cpp2
-rw-r--r--editor/import/resource_importer_obj.cpp4
-rw-r--r--editor/import/resource_importer_scene.cpp379
-rw-r--r--editor/import/resource_importer_scene.h86
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--editor/import/scene_importer_mesh.cpp326
-rw-r--r--editor/import/scene_importer_mesh.h96
-rw-r--r--editor/import/scene_importer_mesh_node_3d.cpp83
-rw-r--r--editor/import/scene_importer_mesh_node_3d.h64
-rw-r--r--editor/input_map_editor.cpp14
-rw-r--r--editor/inspector_dock.cpp2
-rw-r--r--editor/node_3d_editor_gizmos.cpp6
-rw-r--r--editor/plugin_config_dialog.cpp2
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp6
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp35
-rw-r--r--editor/plugins/animation_player_editor_plugin.h2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp10
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp24
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp4
-rw-r--r--editor/plugins/camera_3d_editor_plugin.cpp24
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp304
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h78
-rw-r--r--editor/plugins/editor_preview_plugins.cpp4
-rw-r--r--editor/plugins/font_editor_plugin.cpp2
-rw-r--r--editor/plugins/material_editor_plugin.cpp4
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp2
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp69
-rw-r--r--editor/plugins/packed_scene_translation_parser_plugin.cpp4
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp8
-rw-r--r--editor/plugins/script_editor_plugin.cpp22
-rw-r--r--editor/plugins/script_text_editor.cpp18
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp4
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp6
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_editor.cpp6
-rw-r--r--editor/plugins/texture_3d_editor_plugin.cpp12
-rw-r--r--editor/plugins/texture_layered_editor_plugin.cpp12
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp62
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp10
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp14
-rw-r--r--editor/plugins/version_control_editor_plugin.h1
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp44
-rw-r--r--editor/pot_generator.cpp6
-rw-r--r--editor/progress_dialog.cpp16
-rw-r--r--editor/project_export.cpp4
-rw-r--r--editor/project_manager.cpp18
-rw-r--r--editor/project_settings_editor.cpp4
-rw-r--r--editor/property_editor.cpp52
-rw-r--r--editor/rename_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp26
-rw-r--r--editor/scene_tree_editor.cpp12
-rw-r--r--editor/script_create_dialog.cpp4
-rw-r--r--editor/settings_config_dialog.cpp6
103 files changed, 1548 insertions, 4881 deletions
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 25ff7f884a..6530e27dcd 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -1164,7 +1164,7 @@ AnimationBezierTrackEdit::AnimationBezierTrackEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_margins_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
play_position->connect("draw", callable_mp(this, &AnimationBezierTrackEdit::_play_position_draw));
set_focus_mode(FOCUS_CLICK);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 492a9f2a2f..9a2d7b1e6d 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -37,6 +37,7 @@
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor_node.h"
#include "editor_scale.h"
+#include "scene/animation/animation_player.h"
#include "scene/main/window.h"
#include "servers/audio/audio_stream.h"
@@ -1744,7 +1745,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_margins_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
play_position->connect("draw", callable_mp(this, &AnimationTimelineEdit::_play_position_draw));
add_track = memnew(MenuButton);
@@ -2719,7 +2720,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
add_child(path_popup);
path = memnew(LineEdit);
path_popup->add_child(path);
- path->set_anchors_and_margins_preset(PRESET_WIDE);
+ path->set_anchors_and_offsets_preset(PRESET_WIDE);
path->connect("text_entered", callable_mp(this, &AnimationTrackEdit::_path_entered));
}
@@ -2972,7 +2973,7 @@ AnimationTrackEdit::AnimationTrackEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_margins_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
play_position->connect("draw", callable_mp(this, &AnimationTrackEdit::_play_position_draw));
set_focus_mode(FOCUS_CLICK);
set_mouse_filter(MOUSE_FILTER_PASS); //scroll has to work too for selection
@@ -3299,6 +3300,19 @@ void AnimationTrackEditor::set_anim_pos(float p_pos) {
bezier_edit->set_play_position(p_pos);
}
+static bool track_type_is_resettable(Animation::TrackType p_type) {
+ switch (p_type) {
+ case Animation::TYPE_VALUE:
+ [[fallthrough]];
+ case Animation::TYPE_BEZIER:
+ [[fallthrough]];
+ case Animation::TYPE_TRANSFORM:
+ return true;
+ default:
+ return false;
+ }
+}
+
void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
if (insert_frame != Engine::get_singleton()->get_frames_drawn()) {
//clear insert list for the frame if frame changed
@@ -3319,40 +3333,58 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
insert_data.push_back(p_id);
+ bool reset_allowed = true;
+ AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ if (player->has_animation("RESET") && player->get_animation("RESET") == animation) {
+ // Avoid messing with the reset animation itself
+ reset_allowed = false;
+ } else {
+ bool some_resettable = false;
+ for (int i = 0; i < insert_data.size(); i++) {
+ if (track_type_is_resettable(insert_data[i].type)) {
+ some_resettable = true;
+ break;
+ }
+ }
+ if (!some_resettable) {
+ reset_allowed = false;
+ }
+ }
+
if (p_id.track_idx == -1) {
- if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true))) {
- //potential new key, does not exist
- int num_tracks = 0;
- bool all_bezier = true;
- for (int i = 0; i < insert_data.size(); i++) {
- if (insert_data[i].type != Animation::TYPE_VALUE && insert_data[i].type != Animation::TYPE_BEZIER) {
- all_bezier = false;
- }
+ int num_tracks = 0;
+ bool all_bezier = true;
+ for (int i = 0; i < insert_data.size(); i++) {
+ if (insert_data[i].type != Animation::TYPE_VALUE && insert_data[i].type != Animation::TYPE_BEZIER) {
+ all_bezier = false;
+ }
- if (insert_data[i].track_idx == -1) {
- ++num_tracks;
- }
+ if (insert_data[i].track_idx == -1) {
+ ++num_tracks;
+ }
- if (insert_data[i].type != Animation::TYPE_VALUE) {
- continue;
- }
+ if (insert_data[i].type != Animation::TYPE_VALUE) {
+ continue;
+ }
- switch (insert_data[i].value.get_type()) {
- case Variant::INT:
- case Variant::FLOAT:
- case Variant::VECTOR2:
- case Variant::VECTOR3:
- case Variant::QUAT:
- case Variant::PLANE:
- case Variant::COLOR: {
- // Valid.
- } break;
- default: {
- all_bezier = false;
- }
+ switch (insert_data[i].value.get_type()) {
+ case Variant::INT:
+ case Variant::FLOAT:
+ case Variant::VECTOR2:
+ case Variant::VECTOR3:
+ case Variant::QUAT:
+ case Variant::PLANE:
+ case Variant::COLOR: {
+ // Valid.
+ } break;
+ default: {
+ all_bezier = false;
}
}
+ }
+ if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true))) {
+ //potential new key, does not exist
if (num_tracks == 1) {
insert_confirm_text->set_text(vformat(TTR("Create new track for %s and insert key?"), p_id.query));
} else {
@@ -3360,23 +3392,26 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
}
insert_confirm_bezier->set_visible(all_bezier);
+ insert_confirm_reset->set_visible(reset_allowed);
+
insert_confirm->get_ok_button()->set_text(TTR("Create"));
insert_confirm->popup_centered();
insert_query = true;
} else {
- call_deferred("_insert_delay");
+ call_deferred("_insert_delay", reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
insert_queue = true;
}
} else {
if (!insert_query && !insert_queue) {
- call_deferred("_insert_delay");
+ // Create Beziers wouldn't make sense in this case, where no tracks are being created
+ call_deferred("_insert_delay", reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), false);
insert_queue = true;
}
}
}
-void AnimationTrackEditor::_insert_delay() {
+void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_beziers) {
if (insert_query) {
//discard since it's entered into query mode
insert_queue = false;
@@ -3385,13 +3420,18 @@ void AnimationTrackEditor::_insert_delay() {
undo_redo->create_action(TTR("Anim Insert"));
- int last_track = animation->get_track_count();
+ Ref<Animation> reset_anim;
+ if (p_create_reset) {
+ reset_anim = _create_and_get_reset_animation();
+ }
+
+ TrackIndices next_tracks(animation.ptr(), reset_anim.ptr());
bool advance = false;
while (insert_data.size()) {
if (insert_data.front()->get().advance) {
advance = true;
}
- last_track = _confirm_insert(insert_data.front()->get(), last_track);
+ next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, p_create_reset, p_create_beziers);
insert_data.pop_front();
}
@@ -3682,12 +3722,34 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
}
}
+Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
+ AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ if (player->has_animation("RESET")) {
+ return player->get_animation("RESET");
+ } else {
+ Ref<Animation> reset_anim;
+ reset_anim.instance();
+ reset_anim->set_length(ANIM_MIN_LENGTH);
+ undo_redo->add_do_method(player, "add_animation", "RESET", reset_anim);
+ undo_redo->add_do_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
+ undo_redo->add_undo_method(player, "remove_animation", "RESET");
+ undo_redo->add_undo_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
+ return reset_anim;
+ }
+}
+
void AnimationTrackEditor::_confirm_insert_list() {
undo_redo->create_action(TTR("Anim Create & Insert"));
- int last_track = animation->get_track_count();
+ bool create_reset = insert_confirm_reset->is_visible() && insert_confirm_reset->is_pressed();
+ Ref<Animation> reset_anim;
+ if (create_reset) {
+ reset_anim = _create_and_get_reset_animation();
+ }
+
+ TrackIndices next_tracks(animation.ptr(), reset_anim.ptr());
while (insert_data.size()) {
- last_track = _confirm_insert(insert_data.front()->get(), last_track, insert_confirm_bezier->is_pressed());
+ next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, create_reset, insert_confirm_bezier->is_pressed());
insert_data.pop_front();
}
@@ -3717,7 +3779,7 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b
r_base_path = node->get_path();
}
- if (leftover_path.empty()) {
+ if (leftover_path.is_empty()) {
if (r_current_val) {
if (res.is_valid()) {
*r_current_val = res;
@@ -3807,11 +3869,7 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool
return subindices;
}
-int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, bool p_create_beziers) {
- if (p_last_track == -1) {
- p_last_track = animation->get_track_count();
- }
-
+AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, bool p_create_beziers) {
bool created = false;
if (p_id.track_idx < 0) {
if (p_create_beziers) {
@@ -3823,10 +3881,10 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
id.type = Animation::TYPE_BEZIER;
id.value = p_id.value.get(subindices[i].substr(1, subindices[i].length()));
id.path = String(p_id.path) + subindices[i];
- _confirm_insert(id, p_last_track + i);
+ p_next_tracks = _confirm_insert(id, p_next_tracks, p_create_reset, false);
}
- return p_last_track + subindices.size();
+ return p_next_tracks;
}
}
created = true;
@@ -3863,7 +3921,7 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
}
}
- p_id.track_idx = p_last_track;
+ p_id.track_idx = p_next_tracks.normal;
undo_redo->add_do_method(animation.ptr(), "add_track", p_id.type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", p_id.track_idx, p_id.path);
@@ -3915,7 +3973,7 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
// Just remove the track.
undo_redo->add_undo_method(this, "_clear_selection", false);
undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count());
- p_last_track++;
+ p_next_tracks.normal++;
} else {
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_id.track_idx, time);
int existing = animation->track_find_key(p_id.track_idx, time, true);
@@ -3926,9 +3984,27 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
}
}
+ if (p_create_reset && track_type_is_resettable(p_id.type)) {
+ bool create_reset_track = true;
+ Animation *reset_anim = AnimationPlayerEditor::singleton->get_player()->get_animation("RESET").ptr();
+ for (int i = 0; i < reset_anim->get_track_count(); i++) {
+ if (reset_anim->track_get_path(i) == p_id.path) {
+ create_reset_track = false;
+ break;
+ }
+ }
+ if (create_reset_track) {
+ undo_redo->add_do_method(reset_anim, "add_track", p_id.type);
+ undo_redo->add_do_method(reset_anim, "track_set_path", p_next_tracks.reset, p_id.path);
+ undo_redo->add_do_method(reset_anim, "track_insert_key", p_next_tracks.reset, 0.0f, value);
+ undo_redo->add_undo_method(reset_anim, "remove_track", reset_anim->get_track_count());
+ p_next_tracks.reset++;
+ }
+ }
+
undo_redo->commit_action();
- return p_last_track;
+ return p_next_tracks;
}
void AnimationTrackEditor::show_select_node_warning(bool p_show) {
@@ -4004,8 +4080,8 @@ void AnimationTrackEditor::_update_tracks() {
object = res.ptr();
}
- if (object && !leftover_path.empty()) {
- if (pinfo.name.empty()) {
+ if (object && !leftover_path.is_empty()) {
+ if (pinfo.name.is_empty()) {
pinfo.name = leftover_path[leftover_path.size() - 1];
}
@@ -4224,6 +4300,7 @@ void AnimationTrackEditor::_notification(int p_what) {
selected_filter->set_icon(get_theme_icon("AnimationFilter", "EditorIcons"));
imported_anim_warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
main_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
+ edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_theme_icon("Reload", "EditorIcons"));
}
if (p_what == NOTIFICATION_READY) {
@@ -5056,6 +5133,11 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
}
}
+void AnimationTrackEditor::_edit_menu_about_to_popup() {
+ AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
+}
+
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
last_menu_track_opt = p_option;
switch (p_option) {
@@ -5203,7 +5285,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
scale_dialog->popup_centered(Size2(200, 100) * EDSCALE);
} break;
case EDIT_SCALE_CONFIRM: {
- if (selection.empty()) {
+ if (selection.is_empty()) {
return;
}
@@ -5378,6 +5460,10 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
emit_signal("timeline_changed", pos, true);
} break;
+ case EDIT_APPLY_RESET: {
+ AnimationPlayerEditor::singleton->get_player()->apply_reset(true);
+
+ } break;
case EDIT_OPTIMIZE_ANIMATION: {
optimize_dialog->popup_centered(Size2(250, 180) * EDSCALE);
@@ -5575,7 +5661,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
info_message->set_align(Label::ALIGN_CENTER);
info_message->set_autowrap(true);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
main_panel->add_child(info_message);
timeline = memnew(AnimationTimelineEdit);
@@ -5710,10 +5796,13 @@ AnimationTrackEditor::AnimationTrackEditor() {
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KEY_MASK_CMD | KEY_RIGHT), EDIT_GOTO_NEXT_STEP);
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KEY_MASK_CMD | KEY_LEFT), EDIT_GOTO_PREV_STEP);
edit->get_popup()->add_separator();
+ edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET);
+ edit->get_popup()->add_separator();
edit->get_popup()->add_item(TTR("Optimize Animation"), EDIT_OPTIMIZE_ANIMATION);
edit->get_popup()->add_item(TTR("Clean-Up Animation"), EDIT_CLEAN_UP_ANIMATION);
edit->get_popup()->connect("id_pressed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed));
+ edit->get_popup()->connect("about_to_popup", callable_mp(this, &AnimationTrackEditor::_edit_menu_about_to_popup));
pick_track = memnew(SceneTreeDialog);
add_child(pick_track);
@@ -5739,9 +5828,16 @@ AnimationTrackEditor::AnimationTrackEditor() {
insert_confirm->add_child(icvb);
insert_confirm_text = memnew(Label);
icvb->add_child(insert_confirm_text);
+ HBoxContainer *ichb = memnew(HBoxContainer);
+ icvb->add_child(ichb);
insert_confirm_bezier = memnew(CheckBox);
insert_confirm_bezier->set_text(TTR("Use Bezier Curves"));
- icvb->add_child(insert_confirm_bezier);
+ insert_confirm_bezier->set_pressed(EDITOR_GET("editors/animation/default_create_bezier_tracks"));
+ ichb->add_child(insert_confirm_bezier);
+ insert_confirm_reset = memnew(CheckBox);
+ insert_confirm_reset->set_text(TTR("Create RESET Track(s)", ""));
+ insert_confirm_reset->set_pressed(EDITOR_GET("editors/animation/default_create_reset_tracks"));
+ ichb->add_child(insert_confirm_reset);
keying = false;
moving_selection = false;
key_edit = nullptr;
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 3cb31fe21e..7006959187 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -47,6 +47,8 @@
#include "scene/resources/animation.h"
#include "scene_tree_editor.h"
+class AnimationPlayer;
+
class AnimationTimelineEdit : public Range {
GDCLASS(AnimationTimelineEdit, Range);
@@ -285,6 +287,7 @@ class AnimationTrackEditor : public VBoxContainer {
EDIT_DELETE_SELECTION,
EDIT_GOTO_NEXT_STEP,
EDIT_GOTO_PREV_STEP,
+ EDIT_APPLY_RESET,
EDIT_OPTIMIZE_ANIMATION,
EDIT_OPTIMIZE_ANIMATION_CONFIRM,
EDIT_CLEAN_UP_ANIMATION,
@@ -361,6 +364,7 @@ class AnimationTrackEditor : public VBoxContainer {
Label *insert_confirm_text;
CheckBox *insert_confirm_bezier;
+ CheckBox *insert_confirm_reset;
ConfirmationDialog *insert_confirm;
bool insert_queue;
bool inserting;
@@ -369,9 +373,19 @@ class AnimationTrackEditor : public VBoxContainer {
uint64_t insert_frame;
void _query_insert(const InsertData &p_id);
+ Ref<Animation> _create_and_get_reset_animation();
void _confirm_insert_list();
- int _confirm_insert(InsertData p_id, int p_last_track, bool p_create_beziers = false);
- void _insert_delay();
+ struct TrackIndices {
+ int normal;
+ int reset;
+
+ TrackIndices(const Animation *p_anim = nullptr, const Animation *p_reset_anim = nullptr) {
+ normal = p_anim ? p_anim->get_track_count() : 0;
+ reset = p_reset_anim ? p_reset_anim->get_track_count() : 0;
+ }
+ };
+ TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, bool p_create_beziers);
+ void _insert_delay(bool p_create_reset, bool p_create_beziers);
void _root_removed(Node *p_root);
@@ -447,6 +461,7 @@ class AnimationTrackEditor : public VBoxContainer {
void _select_all_tracks_for_copy();
+ void _edit_menu_about_to_popup();
void _edit_menu_pressed(int p_option);
int last_menu_track_opt;
diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp
index 0b6b1ef6a7..25a67d0041 100644
--- a/editor/array_property_edit.cpp
+++ b/editor/array_property_edit.cpp
@@ -259,7 +259,7 @@ void ArrayPropertyEdit::edit(Object *p_obj, const StringName &p_prop, const Stri
obj = p_obj->get_instance_id();
default_type = p_deftype;
- if (!p_hint_string.empty()) {
+ if (!p_hint_string.is_empty()) {
int hint_subtype_separator = p_hint_string.find(":");
if (hint_subtype_separator >= 0) {
String subtype_string = p_hint_string.substr(0, hint_subtype_separator);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 3dd0977478..a634b87366 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -66,10 +66,10 @@ GotoLineDialog::GotoLineDialog() {
set_title(TTR("Go to Line"));
VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE);
add_child(vbc);
Label *l = memnew(Label);
@@ -325,7 +325,7 @@ void FindReplaceBar::_update_results_count() {
results_count = 0;
String searched = get_search_text();
- if (searched.empty()) {
+ if (searched.is_empty()) {
return;
}
@@ -356,7 +356,7 @@ void FindReplaceBar::_update_results_count() {
}
void FindReplaceBar::_update_matches_label() {
- if (search_text->get_text().empty() || results_count == -1) {
+ if (search_text->get_text().is_empty() || results_count == -1) {
matches_label->hide();
} else {
matches_label->show();
@@ -483,7 +483,7 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) {
search_text->set_text(text_editor->get_selection_text());
}
- if (!get_search_text().empty()) {
+ if (!get_search_text().is_empty()) {
if (p_focus_replace) {
replace_text->select_all();
replace_text->set_cursor_position(replace_text->get_text().length());
@@ -1309,7 +1309,7 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
for (int i = begin; i <= end; i++) {
String line_text = text_editor->get_line(i);
- if (line_text.strip_edges().empty()) {
+ if (line_text.strip_edges().is_empty()) {
line_text = delimiter;
} else {
if (is_commented) {
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 473597b9b3..c4ab226b28 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -1008,7 +1008,7 @@ void ConnectionsDock::update_tree() {
break;
}
}
- if (!F->get().inherits.empty()) {
+ if (!F->get().inherits.is_empty()) {
F = dd->class_list.find(F->get().inherits);
} else {
break;
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 75d57b040f..b28fe400e6 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -492,7 +492,7 @@ void CreateDialog::_favorite_selected() {
}
search_box->set_text(item->get_text(0).get_slicec(' ', 0));
- recent->unselect_all();
+ recent->deselect_all();
_update_search();
}
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index 276df45972..5b2dc3fc32 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -55,8 +55,8 @@ EditorDebuggerNode::EditorDebuggerNode() {
singleton = this;
}
- add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT));
- add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT));
+ add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_LEFT));
+ add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_RIGHT));
tabs = memnew(TabContainer);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
@@ -115,7 +115,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
}
- if (!debugger_plugins.empty()) {
+ if (!debugger_plugins.is_empty()) {
for (Set<Ref<Script>>::Element *i = debugger_plugins.front(); i; i = i->next()) {
node->add_debugger_plugin(i->get());
}
@@ -140,7 +140,7 @@ void EditorDebuggerNode::_error_selected(const String &p_file, int p_line, int p
void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_debugger) {
const String file = p_debugger->get_stack_script_file();
- if (file.empty()) {
+ if (file.is_empty()) {
return;
}
stack_script = ResourceLoader::load(file);
@@ -226,8 +226,8 @@ void EditorDebuggerNode::_notification(int p_what) {
switch (p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
if (tabs->get_tab_count() > 1) {
- add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT));
- add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT));
+ add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_LEFT));
+ add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(SIDE_RIGHT));
tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles"));
}
diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp
index ebac9b3482..e36f11ae1d 100644
--- a/editor/debugger/editor_debugger_tree.cpp
+++ b/editor/debugger/editor_debugger_tree.cpp
@@ -242,7 +242,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) {
} break;
case ITEM_MENU_COPY_NODE_PATH: {
String text = get_selected_path();
- if (text.empty()) {
+ if (text.is_empty()) {
return;
} else if (text == "/root") {
text = ".";
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index 44c5f83e9a..f73165881c 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -102,7 +102,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
}
}
- if (active.empty()) {
+ if (active.is_empty()) {
info_message->show();
return;
}
@@ -217,7 +217,7 @@ void EditorPerformanceProfiler::_build_monitor_tree() {
TreeItem *item = _create_monitor_item(i.value().name, base);
item->set_checked(0, monitor_checked.has(i.key()));
i.value().item = item;
- if (!i.value().history.empty()) {
+ if (!i.value().history.is_empty()) {
i.value().update_value(i.value().history.front()->get());
}
}
@@ -382,7 +382,7 @@ EditorPerformanceProfiler::EditorPerformanceProfiler() {
info_message->set_align(Label::ALIGN_CENTER);
info_message->set_autowrap(true);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
monitor_draw->add_child(info_message);
for (int i = 0; i < Performance::MONITOR_MAX; i++) {
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 930aca6e5a..4871c35ea4 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -596,7 +596,7 @@ bool EditorProfiler::is_profiling() {
Vector<Vector<String>> EditorProfiler::get_data_as_csv() const {
Vector<Vector<String>> res;
- if (frame_metrics.empty()) {
+ if (frame_metrics.is_empty()) {
return res;
}
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 45b9d68158..6f0d537fa2 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -490,17 +490,17 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
if (oe.callstack.size() > 0) {
// If available, use the script's stack in the error title.
error_title = oe.callstack[oe.callstack.size() - 1].func + ": ";
- } else if (!oe.source_func.empty()) {
+ } else if (!oe.source_func.is_empty()) {
// Otherwise try to use the C++ source function.
error_title += oe.source_func + ": ";
}
// If we have a (custom) error message, use it as title, and add a C++ Error
// item with the original error condition.
- error_title += oe.error_descr.empty() ? oe.error : oe.error_descr;
+ error_title += oe.error_descr.is_empty() ? oe.error : oe.error_descr;
error->set_text(1, error_title);
tooltip += " " + error_title + "\n";
- if (!oe.error_descr.empty()) {
+ if (!oe.error_descr.is_empty()) {
// Add item for C++ error condition.
TreeItem *cpp_cond = error_tree->create_item(error);
cpp_cond->set_text(0, "<" + TTR("C++ Error") + ">");
@@ -516,7 +516,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
// Source of the error.
String source_txt = (source_is_project_file ? oe.source_file.get_file() : oe.source_file) + ":" + itos(oe.source_line);
- if (!oe.source_func.empty()) {
+ if (!oe.source_func.is_empty()) {
source_txt += " @ " + oe.source_func + "()";
}
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index a27f196d49..208d390134 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -448,7 +448,7 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<
Vector<RemovedDependency> removed_deps;
_find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps);
removed_deps.sort();
- if (removed_deps.empty()) {
+ if (removed_deps.is_empty()) {
owners->hide();
text->set_text(TTR("Remove selected files from the project? (no undo)\nYou can find the removed files in the system trash to restore them."));
set_size(Size2());
@@ -639,7 +639,7 @@ void OrphanResourcesDialog::ok_pressed() {
paths.clear();
_find_to_delete(files->get_root(), paths);
- if (paths.empty()) {
+ if (paths.is_empty()) {
return;
}
diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h
index 5d2ae582e6..008194bbd6 100644
--- a/editor/dependency_editor.h
+++ b/editor/dependency_editor.h
@@ -111,8 +111,8 @@ class DependencyRemoveDialog : public ConfirmationDialog {
String dependency_folder;
bool operator<(const RemovedDependency &p_other) const {
- if (dependency_folder.empty() != p_other.dependency_folder.empty()) {
- return p_other.dependency_folder.empty();
+ if (dependency_folder.is_empty() != p_other.dependency_folder.is_empty()) {
+ return p_other.dependency_folder.is_empty();
} else {
return dependency < p_other.dependency;
}
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index 5ee9abb183..c21c957799 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -813,7 +813,7 @@ void DocTools::generate(bool p_basic_types) {
}
// Skip adding the lang if it doesn't expose anything (e.g. C#).
- if (c.methods.empty() && c.constants.empty()) {
+ if (c.methods.is_empty() && c.constants.is_empty()) {
continue;
}
@@ -1165,7 +1165,7 @@ Error DocTools::save_classes(const String &p_default_path, const Map<String, Str
_write_string(f, 1, "<tutorials>");
for (int i = 0; i < c.tutorials.size(); i++) {
DocData::TutorialDoc tutorial = c.tutorials.get(i);
- String title_attribute = (!tutorial.title.empty()) ? " title=\"" + tutorial.title.xml_escape() + "\"" : "";
+ String title_attribute = (!tutorial.title.is_empty()) ? " title=\"" + tutorial.title.xml_escape() + "\"" : "";
_write_string(f, 2, "<link" + title_attribute + ">" + tutorial.link.xml_escape() + "</link>");
}
_write_string(f, 1, "</tutorials>");
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index d81dc05a75..d768f00c3b 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -922,7 +922,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
bus_options = memnew(MenuButton);
bus_options->set_shortcut_context(this);
bus_options->set_h_size_flags(SIZE_SHRINK_END);
- bus_options->set_anchor(MARGIN_RIGHT, 0.0);
+ bus_options->set_anchor(SIDE_RIGHT, 0.0);
bus_options->set_tooltip(TTR("Bus options"));
hbc->add_child(bus_options);
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 2251440544..5f429e7034 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -402,7 +402,7 @@ void EditorAutoloadSettings::update_autoload() {
String name = pi.name.get_slice("/", 1);
String path = ProjectSettings::get_singleton()->get(pi.name);
- if (name.empty()) {
+ if (name.is_empty()) {
continue;
}
@@ -774,7 +774,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
String name = pi.name.get_slice("/", 1);
String path = ProjectSettings::get_singleton()->get(pi.name);
- if (name.empty()) {
+ if (name.is_empty()) {
continue;
}
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index eab1ecf373..05c7b58c72 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -331,7 +331,7 @@ Dictionary EditorData::get_editor_states() const {
Dictionary metadata;
for (int i = 0; i < editor_plugins.size(); i++) {
Dictionary state = editor_plugins[i]->get_state();
- if (state.empty()) {
+ if (state.is_empty()) {
continue;
}
metadata[editor_plugins[i]->get_name()] = state;
@@ -493,7 +493,7 @@ void EditorData::remove_custom_type(const String &p_type) {
for (int i = 0; i < E->get().size(); i++) {
if (E->get()[i].name == p_type) {
E->get().remove(i);
- if (E->get().empty()) {
+ if (E->get().is_empty()) {
custom_types.erase(E->key());
}
return;
@@ -901,7 +901,7 @@ String EditorData::script_class_get_icon_path(const String &p_class) const {
String current = p_class;
String ret = _script_class_icon_paths[current];
- while (ret.empty()) {
+ while (ret.is_empty()) {
current = script_class_get_base(current);
if (!ScriptServer::is_global_class(current)) {
return String();
@@ -931,7 +931,7 @@ void EditorData::script_class_save_icon_paths() {
}
}
- if (d.empty()) {
+ if (d.is_empty()) {
if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) {
ProjectSettings::get_singleton()->clear("_global_script_class_icons");
}
@@ -1125,7 +1125,7 @@ List<Node *> EditorSelection::get_full_selected_node_list() {
}
void EditorSelection::clear() {
- while (!selection.empty()) {
+ while (!selection.is_empty()) {
remove_node(selection.front()->key());
}
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 07318c14bc..231c143c05 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -398,7 +398,7 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat
Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
ERR_FAIL_COND_V(theme.is_null(), Ref<ImageTexture>());
- if (EditorNode::get_singleton()->get_viewport()->is_layout_rtl()) {
+ if (EditorNode::get_singleton()->get_main_control()->is_layout_rtl()) {
return theme->get_icon("PlayBackwards", "EditorIcons");
} else {
return theme->get_icon("Play", "EditorIcons");
@@ -521,7 +521,7 @@ void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String &
Vector<String> filters;
for (int i = 0; i < split.size(); i++) {
String f = split[i].strip_edges();
- if (f.empty()) {
+ if (f.is_empty()) {
continue;
}
filters.push_back(f);
@@ -754,7 +754,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
Vector<String> enc_in_split = p_preset->get_enc_in_filter().split(",");
for (int i = 0; i < enc_in_split.size(); i++) {
String f = enc_in_split[i].strip_edges();
- if (f.empty()) {
+ if (f.is_empty()) {
continue;
}
enc_in_filters.push_back(f);
@@ -763,7 +763,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
Vector<String> enc_ex_split = p_preset->get_enc_ex_filter().split(",");
for (int i = 0; i < enc_ex_split.size(); i++) {
String f = enc_ex_split[i].strip_edges();
- if (f.empty()) {
+ if (f.is_empty()) {
continue;
}
enc_ex_filters.push_back(f);
@@ -1696,7 +1696,7 @@ bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset,
valid = dvalid || rvalid;
r_missing_templates = !valid;
- if (!err.empty()) {
+ if (!err.is_empty()) {
r_error = err;
}
return valid;
@@ -1783,7 +1783,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
}
}
- if (err == OK && !so_files.empty()) {
+ if (err == OK && !so_files.is_empty()) {
//if shared object files, copy them
da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < so_files.size() && err == OK; i++) {
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 05bc2edefb..280c13ec9d 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -96,7 +96,7 @@ void EditorFeatureProfile::set_disable_class_property(const StringName &p_class,
} else {
ERR_FAIL_COND(!disabled_properties.has(p_class));
disabled_properties[p_class].erase(p_property);
- if (disabled_properties[p_class].empty()) {
+ if (disabled_properties[p_class].is_empty()) {
disabled_properties.erase(p_class);
}
}
@@ -876,7 +876,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
no_profile_selected_help = memnew(Label(TTR("Create or import a profile to edit available classes and properties.")));
// Add some spacing above the help label.
Ref<StyleBoxEmpty> sb = memnew(StyleBoxEmpty);
- sb->set_default_margin(MARGIN_TOP, 20 * EDSCALE);
+ sb->set_default_margin(SIDE_TOP, 20 * EDSCALE);
no_profile_selected_help->add_theme_style_override("normal", sb);
no_profile_selected_help->set_align(Label::ALIGN_CENTER);
no_profile_selected_help->set_v_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 8ded47605c..55373c47a4 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -499,7 +499,7 @@ void EditorFileDialog::_multi_selected(int p_item, bool p_selected) {
}
void EditorFileDialog::_items_clear_selection() {
- item_list->unselect_all();
+ item_list->deselect_all();
// If nothing is selected, then block Open button.
switch (mode) {
@@ -595,7 +595,7 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p
void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) {
// Right click on folder background. Deselect all files so that actions are applied on the current folder.
for (int i = 0; i < item_list->get_item_count(); i++) {
- item_list->unselect(i);
+ item_list->deselect(i);
}
item_menu->clear();
@@ -758,7 +758,7 @@ void EditorFileDialog::update_file_list() {
dirs.sort_custom<NaturalNoCaseComparator>();
files.sort_custom<NaturalNoCaseComparator>();
- while (!dirs.empty()) {
+ while (!dirs.is_empty()) {
const String &dir_name = dirs.front()->get();
item_list->add_item(dir_name);
@@ -806,8 +806,8 @@ void EditorFileDialog::update_file_list() {
}
}
- while (!files.empty()) {
- bool match = patterns.empty();
+ while (!files.is_empty()) {
+ bool match = patterns.is_empty();
for (List<String>::Element *E = patterns.front(); E; E = E->next()) {
if (files.front()->get().matchn(E->get())) {
@@ -849,7 +849,7 @@ void EditorFileDialog::update_file_list() {
}
if (favorites->get_current() >= 0) {
- favorites->unselect(favorites->get_current());
+ favorites->deselect(favorites->get_current());
}
favorite->set_pressed(false);
@@ -1226,7 +1226,7 @@ void EditorFileDialog::_update_favorites() {
if (setthis) {
favorite->set_pressed(true);
favorites->set_current(favorites->get_item_count() - 1);
- recent->unselect_all();
+ recent->deselect_all();
}
}
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 41010b6a86..5eff0f2e4a 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -160,19 +160,19 @@ void EditorHelp::_class_desc_resized() {
const int display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5;
Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "RichTextLabel")->duplicate();
- class_desc_stylebox->set_default_margin(MARGIN_LEFT, display_margin);
- class_desc_stylebox->set_default_margin(MARGIN_RIGHT, display_margin);
+ class_desc_stylebox->set_default_margin(SIDE_LEFT, display_margin);
+ class_desc_stylebox->set_default_margin(SIDE_RIGHT, display_margin);
class_desc->add_theme_style_override("normal", class_desc_stylebox);
}
void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
String t = p_type;
- if (t.empty()) {
+ if (t.is_empty()) {
t = "void";
}
- bool can_ref = (t != "void") || !p_enum.empty();
+ bool can_ref = (t != "void") || !p_enum.is_empty();
- if (!p_enum.empty()) {
+ if (!p_enum.is_empty()) {
if (p_enum.get_slice_count(".") > 1) {
t = p_enum.get_slice(".", 1);
} else {
@@ -188,7 +188,7 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
add_array = true;
t = t.replace("[]", "");
}
- if (p_enum.empty()) {
+ if (p_enum.is_empty()) {
class_desc->push_meta("#" + t); //class
} else {
class_desc->push_meta("$" + p_enum); //class
@@ -472,7 +472,7 @@ void EditorHelp::_update_doc() {
for (int i = 0; i < cd.tutorials.size(); i++) {
const String link = DTR(cd.tutorials[i].link);
- String linktxt = (cd.tutorials[i].title.empty()) ? link : DTR(cd.tutorials[i].title);
+ String linktxt = (cd.tutorials[i].title.is_empty()) ? link : DTR(cd.tutorials[i].title);
const int seppos = linktxt.find("//");
if (seppos != -1) {
linktxt = link.right(seppos + 2);
@@ -498,7 +498,7 @@ void EditorHelp::_update_doc() {
if (cd.is_script_doc) {
has_properties = false;
for (int i = 0; i < cd.properties.size(); i++) {
- if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.empty()) {
+ if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.is_empty()) {
continue;
}
has_properties = true;
@@ -522,7 +522,7 @@ void EditorHelp::_update_doc() {
for (int i = 0; i < cd.properties.size(); i++) {
// Ignore undocumented private.
- if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.empty()) {
+ if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.is_empty()) {
continue;
}
property_line[cd.properties[i].name] = class_desc->get_line_count() - 2; //gets overridden if description
@@ -633,7 +633,7 @@ void EditorHelp::_update_doc() {
}
}
// Ignore undocumented private.
- if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.empty()) {
+ if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty()) {
continue;
}
methods.push_back(cd.methods[i]);
@@ -668,7 +668,7 @@ void EditorHelp::_update_doc() {
}
}
- if (any_previous && !m.empty()) {
+ if (any_previous && !m.is_empty()) {
class_desc->push_cell();
class_desc->pop(); //cell
class_desc->push_cell();
@@ -702,7 +702,7 @@ void EditorHelp::_update_doc() {
_add_method(m[i], true);
}
- any_previous = !m.empty();
+ any_previous = !m.is_empty();
}
class_desc->pop(); //table
@@ -848,7 +848,7 @@ void EditorHelp::_update_doc() {
Vector<DocData::ConstantDoc> constants;
for (int i = 0; i < cd.constants.size(); i++) {
- if (!cd.constants[i].enumeration.empty()) {
+ if (!cd.constants[i].enumeration.is_empty()) {
if (!enums.has(cd.constants[i].enumeration)) {
enums[cd.constants[i].enumeration] = Vector<DocData::ConstantDoc>();
}
@@ -856,7 +856,7 @@ void EditorHelp::_update_doc() {
enums[cd.constants[i].enumeration].push_back(cd.constants[i]);
} else {
// Ignore undocumented private.
- if (cd.constants[i].name.begins_with("_") && cd.constants[i].description.empty()) {
+ if (cd.constants[i].name.begins_with("_") && cd.constants[i].description.is_empty()) {
continue;
}
constants.push_back(cd.constants[i]);
@@ -1174,7 +1174,7 @@ void EditorHelp::_update_doc() {
class_desc->push_color(text_color);
class_desc->push_font(doc_font);
class_desc->push_indent(1);
- if (!cd.properties[i].description.strip_edges().empty()) {
+ if (!cd.properties[i].description.strip_edges().is_empty()) {
_add_text(DTR(cd.properties[i].description));
} else {
class_desc->add_image(get_theme_icon("Error", "EditorIcons"));
@@ -1229,7 +1229,7 @@ void EditorHelp::_update_doc() {
class_desc->push_color(text_color);
class_desc->push_font(doc_font);
class_desc->push_indent(1);
- if (!methods_filtered[i].description.strip_edges().empty()) {
+ if (!methods_filtered[i].description.strip_edges().is_empty()) {
_add_text(DTR(methods_filtered[i].description));
} else {
class_desc->add_image(get_theme_icon("Error", "EditorIcons"));
@@ -1838,7 +1838,7 @@ void FindBar::popup_search() {
grabbed_focus = true;
}
- if (!search_text->get_text().empty()) {
+ if (!search_text->get_text().is_empty()) {
search_text->select_all();
search_text->set_cursor_position(search_text->get_text().length());
if (grabbed_focus) {
@@ -1908,7 +1908,7 @@ void FindBar::_update_results_count() {
results_count = 0;
String searched = search_text->get_text();
- if (searched.empty()) {
+ if (searched.is_empty()) {
return;
}
@@ -1928,7 +1928,7 @@ void FindBar::_update_results_count() {
}
void FindBar::_update_matches_label() {
- if (search_text->get_text().empty() || results_count == -1) {
+ if (search_text->get_text().is_empty() || results_count == -1) {
matches_label->hide();
} else {
matches_label->show();
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index dd136c046f..4d975512d4 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -220,7 +220,7 @@ void EditorProperty::_notification(int p_what) {
Size2 size = get_size();
if (bottom_editor) {
- size.height = bottom_editor->get_margin(MARGIN_TOP);
+ size.height = bottom_editor->get_offset(SIDE_TOP);
} else if (label_reference) {
size.height = label_reference->get_size().height;
}
@@ -865,7 +865,7 @@ Control *EditorProperty::make_custom_tooltip(const String &p_text) const {
String text;
PackedStringArray slices = p_text.split("::", false);
- if (!slices.empty()) {
+ if (!slices.is_empty()) {
String property_name = slices[0].strip_edges();
text = TTR("Property:") + " [u][b]" + property_name + "[/b][/u]";
@@ -1098,7 +1098,7 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
PackedStringArray slices = p_text.split("::", false);
- if (!slices.empty()) {
+ if (!slices.is_empty()) {
String property_name = slices[0].strip_edges();
String text = "[u][b]" + property_name + "[/b][/u]";
@@ -1901,7 +1901,7 @@ void EditorInspector::update_tree() {
}
}
- if (!F->get().inherits.empty()) {
+ if (!F->get().inherits.is_empty()) {
F = dd->class_list.find(F->get().inherits);
} else {
break;
@@ -2525,7 +2525,7 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li
script = script->get_base_script();
}
- if (classes.empty()) {
+ if (classes.is_empty()) {
return;
}
diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp
index c50fe81217..71d369be1f 100644
--- a/editor/editor_layouts_dialog.cpp
+++ b/editor/editor_layouts_dialog.cpp
@@ -100,26 +100,26 @@ void EditorLayoutsDialog::_post_popup() {
EditorLayoutsDialog::EditorLayoutsDialog() {
makevb = memnew(VBoxContainer);
add_child(makevb);
- makevb->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5);
- makevb->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5);
+ makevb->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5);
+ makevb->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5);
layout_names = memnew(ItemList);
makevb->add_child(layout_names);
layout_names->set_visible(true);
- layout_names->set_margin(MARGIN_TOP, 5);
- layout_names->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5);
- layout_names->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5);
+ layout_names->set_offset(SIDE_TOP, 5);
+ layout_names->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5);
+ layout_names->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5);
layout_names->set_v_size_flags(Control::SIZE_EXPAND_FILL);
layout_names->set_select_mode(ItemList::SELECT_MULTI);
layout_names->set_allow_rmb_select(true);
name = memnew(LineEdit);
makevb->add_child(name);
- name->set_margin(MARGIN_TOP, 5);
- name->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5);
- name->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5);
+ name->set_offset(SIDE_TOP, 5);
+ name->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5);
+ name->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5);
name->connect("gui_input", callable_mp(this, &EditorLayoutsDialog::_line_gui_input));
- name->connect("focus_entered", callable_mp(layout_names, &ItemList::unselect_all));
+ name->connect("focus_entered", callable_mp(layout_names, &ItemList::deselect_all));
}
void EditorLayoutsDialog::set_name_line_enabled(bool p_enabled) {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index dfe5d64784..4fb34f58bf 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -91,7 +91,6 @@
#include "editor/export_template_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/import/editor_import_collada.h"
-#include "editor/import/editor_scene_importer_gltf.h"
#include "editor/import/resource_importer_bitmask.h"
#include "editor/import/resource_importer_csv.h"
#include "editor/import/resource_importer_csv_translation.h"
@@ -103,6 +102,7 @@
#include "editor/import/resource_importer_texture.h"
#include "editor/import/resource_importer_texture_atlas.h"
#include "editor/import/resource_importer_wav.h"
+#include "editor/import/scene_importer_mesh_node_3d.h"
#include "editor/import_dock.h"
#include "editor/multi_node_edit.h"
#include "editor/node_dock.h"
@@ -377,9 +377,9 @@ void EditorNode::_version_control_menu_option(int p_idx) {
void EditorNode::_update_title() {
String appname = ProjectSettings::get_singleton()->get("application/config/name");
- String title = appname.empty() ? String(VERSION_FULL_NAME) : String(VERSION_NAME + String(" - ") + appname);
+ String title = appname.is_empty() ? String(VERSION_FULL_NAME) : String(VERSION_NAME + String(" - ") + appname);
String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_filename() : String();
- if (!edited.empty()) {
+ if (!edited.is_empty()) {
title += " - " + String(edited.get_file());
}
if (unsaved_cache) {
@@ -485,7 +485,7 @@ void EditorNode::_notification(int p_what) {
RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality")));
bool dof_jitter = GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter");
RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter);
- RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"));
+ RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"), GLOBAL_GET("rendering/quality/ssao/adaptive_target"), GLOBAL_GET("rendering/quality/ssao/blur_passes"), GLOBAL_GET("rendering/quality/ssao/fadeout_from"), GLOBAL_GET("rendering/quality/ssao/fadeout_to"));
RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"));
bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic);
@@ -782,8 +782,8 @@ void EditorNode::_fs_changed() {
preset_name);
} else {
Ref<EditorExportPlatform> platform = preset->get_platform();
- const String export_path = export_defer.path.empty() ? preset->get_export_path() : export_defer.path;
- if (export_path.empty()) {
+ const String export_path = export_defer.path.is_empty() ? preset->get_export_path() : export_defer.path;
+ if (export_path.is_empty()) {
export_error = vformat("Export preset '%s' doesn't have a default export path, and none was specified.", preset_name);
} else if (platform.is_null()) {
export_error = vformat("Export preset '%s' doesn't have a matching platform.", preset_name);
@@ -821,7 +821,7 @@ void EditorNode::_fs_changed() {
}
}
- if (!export_error.empty()) {
+ if (!export_error.is_empty()) {
ERR_PRINT(export_error);
OS::get_singleton()->set_exit_code(EXIT_FAILURE);
}
@@ -1419,6 +1419,17 @@ int EditorNode::_save_external_resources() {
return saved;
}
+static void _reset_animation_players(Node *p_node, List<Ref<AnimatedValuesBackup>> *r_anim_backups) {
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ AnimationPlayer *player = Object::cast_to<AnimationPlayer>(p_node->get_child(i));
+ if (player && player->is_reset_on_save_enabled() && player->can_apply_reset()) {
+ Ref<AnimatedValuesBackup> old_values = player->apply_reset();
+ r_anim_backups->push_back(old_values);
+ }
+ _reset_animation_players(p_node->get_child(i), r_anim_backups);
+ }
+}
+
void EditorNode::_save_scene(String p_file, int idx) {
Node *scene = editor_data.get_edited_scene_root(idx);
@@ -1433,6 +1444,8 @@ void EditorNode::_save_scene(String p_file, int idx) {
}
editor_data.apply_changes_in_editors();
+ List<Ref<AnimatedValuesBackup>> anim_backups;
+ _reset_animation_players(scene, &anim_backups);
_save_default_environment();
_set_scene_metadata(p_file, idx);
@@ -1480,6 +1493,11 @@ void EditorNode::_save_scene(String p_file, int idx) {
_save_external_resources();
editor_data.save_editor_external_data();
+
+ for (List<Ref<AnimatedValuesBackup>>::Element *E = anim_backups.front(); E; E = E->next()) {
+ E->get()->restore();
+ }
+
if (err == OK) {
scene->set_filename(ProjectSettings::get_singleton()->localize_path(p_file));
if (idx < 0 || idx == editor_data.get_edited_scene()) {
@@ -1693,7 +1711,7 @@ void EditorNode::_dialog_action(String p_file) {
current_obj->_change_notify();
} break;
case SETTINGS_LAYOUT_SAVE: {
- if (p_file.empty()) {
+ if (p_file.is_empty()) {
return;
}
@@ -1721,7 +1739,7 @@ void EditorNode::_dialog_action(String p_file) {
} break;
case SETTINGS_LAYOUT_DELETE: {
- if (p_file.empty()) {
+ if (p_file.is_empty()) {
return;
}
@@ -1804,7 +1822,7 @@ void EditorNode::edit_item(Object *p_object) {
sub_plugins = editor_data.get_subeditors(p_object);
}
- if (!sub_plugins.empty()) {
+ if (!sub_plugins.is_empty()) {
bool same = true;
if (sub_plugins.size() == editor_plugins_over->get_plugins_list().size()) {
for (int i = 0; i < sub_plugins.size(); i++) {
@@ -1980,7 +1998,7 @@ void EditorNode::_edit_current() {
multi_nodes.push_back(node);
}
}
- if (!multi_nodes.empty()) {
+ if (!multi_nodes.is_empty()) {
// Pick the top-most node
multi_nodes.sort_custom<Node::Comparator>();
selected_node = multi_nodes.front()->get();
@@ -2062,13 +2080,13 @@ void EditorNode::_edit_current() {
sub_plugins = editor_data.get_subeditors(current_obj);
}
- if (!sub_plugins.empty()) {
+ if (!sub_plugins.is_empty()) {
_display_top_editors(false);
_set_top_editors(sub_plugins);
_set_editing_top_editors(current_obj);
_display_top_editors(true);
- } else if (!editor_plugins_over->get_plugins_list().empty()) {
+ } else if (!editor_plugins_over->get_plugins_list().is_empty()) {
hide_top_editors();
}
}
@@ -2238,7 +2256,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case FILE_OPEN_PREV: {
- if (previous_scenes.empty()) {
+ if (previous_scenes.is_empty()) {
break;
}
opening_prev = true;
@@ -2509,7 +2527,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case RUN_PLAY_CUSTOM_SCENE: {
- if (run_custom_filename.empty() || editor_run.get_status() == EditorRun::STATUS_STOP) {
+ if (run_custom_filename.is_empty() || editor_run.get_status() == EditorRun::STATUS_STOP) {
_menu_option_confirm(RUN_STOP, true);
quick_run->popup_dialog("PackedScene", true);
quick_run->set_title(TTR("Quick Run Scene..."));
@@ -2727,14 +2745,14 @@ void EditorNode::_screenshot(bool p_use_utc) {
}
void EditorNode::_save_screenshot(NodePath p_path) {
- Control *editor_viewport = EditorInterface::get_singleton()->get_editor_viewport();
- ERR_FAIL_COND_MSG(!editor_viewport, "Cannot get editor viewport.");
- Viewport *viewport = editor_viewport->get_viewport();
- ERR_FAIL_COND_MSG(!viewport, "Cannot get editor viewport.");
+ Control *editor_main_control = EditorInterface::get_singleton()->get_editor_main_control();
+ ERR_FAIL_COND_MSG(!editor_main_control, "Cannot get editor main control.");
+ Viewport *viewport = editor_main_control->get_viewport();
+ ERR_FAIL_COND_MSG(!viewport, "Cannot get editor main control viewport.");
Ref<ViewportTexture> texture = viewport->get_texture();
- ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get editor viewport texture.");
+ ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get editor main control viewport texture.");
Ref<Image> img = texture->get_data();
- ERR_FAIL_COND_MSG(img.is_null(), "Cannot get editor viewport texture image.");
+ ERR_FAIL_COND_MSG(img.is_null(), "Cannot get editor main control viewport texture image.");
Error error = img->save_png(p_path);
ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'.");
}
@@ -2858,7 +2876,7 @@ void EditorNode::_update_file_menu_opened() {
Ref<Shortcut> reopen_closed_scene_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene");
reopen_closed_scene_sc->set_name(TTR("Reopen Closed Scene"));
PopupMenu *pop = file_menu->get_popup();
- pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), previous_scenes.empty());
+ pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), previous_scenes.is_empty());
}
void EditorNode::_update_file_menu_closed() {
@@ -2866,8 +2884,8 @@ void EditorNode::_update_file_menu_closed() {
pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), false);
}
-Control *EditorNode::get_viewport() {
- return viewport;
+Control *EditorNode::get_main_control() {
+ return main_control;
}
void EditorNode::_editor_select(int p_which) {
@@ -3655,7 +3673,7 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorFeatureProfile>();
ClassDB::register_class<EditorSpinSlider>();
ClassDB::register_class<EditorSceneImporterMesh>();
- ClassDB::register_class<EditorSceneImporterMeshNode>();
+ ClassDB::register_class<EditorSceneImporterMeshNode3D>();
ClassDB::register_virtual_class<FileSystemDock>();
@@ -3805,7 +3823,7 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String
}
Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const {
- ERR_FAIL_COND_V_MSG(p_class.empty(), nullptr, "Class name cannot be empty.");
+ ERR_FAIL_COND_V_MSG(p_class.is_empty(), nullptr, "Class name cannot be empty.");
if (ScriptServer::is_global_class(p_class)) {
Ref<ImageTexture> icon;
@@ -4000,16 +4018,16 @@ void EditorNode::_dock_make_float() {
window->set_title(dock->get_name());
Panel *p = memnew(Panel);
p->set_mode(Panel::MODE_FOREGROUND);
- p->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ p->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
window->add_child(p);
MarginContainer *margin = memnew(MarginContainer);
- margin->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ margin->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
margin->add_theme_constant_override("margin_right", borders.width);
margin->add_theme_constant_override("margin_top", borders.height);
margin->add_theme_constant_override("margin_left", borders.width);
margin->add_theme_constant_override("margin_bottom", borders.height);
window->add_child(margin);
- dock->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ dock->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
margin->add_child(dock);
window->set_wrap_controls(true);
window->set_size(dock_size);
@@ -4537,7 +4555,7 @@ bool EditorNode::has_scenes_in_session() {
return false;
}
Array scenes = config->get_value("EditorNode", "open_scenes");
- return !scenes.empty();
+ return !scenes.is_empty();
}
bool EditorNode::ensure_main_scene(bool p_from_native) {
@@ -4763,7 +4781,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) {
Ref<Shortcut> undo_close_tab_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene");
undo_close_tab_sc->set_name(TTR("Undo Close Tab"));
scene_tabs_context_menu->add_shortcut(undo_close_tab_sc, FILE_OPEN_PREV);
- if (previous_scenes.empty()) {
+ if (previous_scenes.is_empty()) {
scene_tabs_context_menu->set_item_disabled(scene_tabs_context_menu->get_item_index(FILE_OPEN_PREV), true);
}
scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), FILE_CLOSE_OTHERS);
@@ -5167,7 +5185,7 @@ void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, Str
next_file = sub_dir->get_next();
}
- if (!sub_files.empty()) {
+ if (!sub_files.is_empty()) {
dir->make_dir(to);
_add_dropped_files_recursive(sub_files, to);
}
@@ -5694,10 +5712,6 @@ EditorNode::EditorNode() {
import_obj2.instance();
import_scene->add_importer(import_obj2);
- Ref<EditorSceneImporterGLTF> import_gltf;
- import_gltf.instance();
- import_scene->add_importer(import_gltf);
-
Ref<EditorSceneImporterESCN> import_escn;
import_escn.instance();
import_scene->add_importer(import_escn);
@@ -5777,11 +5791,11 @@ EditorNode::EditorNode() {
theme_base = memnew(Control);
add_child(theme_base);
- theme_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ theme_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
gui_base = memnew(Panel);
theme_base->add_child(gui_base);
- gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ gui_base->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
theme_base->set_theme(theme);
gui_base->set_theme(theme);
@@ -5793,13 +5807,13 @@ EditorNode::EditorNode() {
gui_base->add_child(progress_dialog);
// take up all screen
- gui_base->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
- gui_base->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END);
+ gui_base->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
+ gui_base->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
gui_base->set_end(Point2(0, 0));
main_vbox = memnew(VBoxContainer);
gui_base->add_child(main_vbox);
- main_vbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8);
+ main_vbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8);
main_vbox->add_theme_constant_override("separation", 8 * EDSCALE);
menu_hb = memnew(HBoxContainer);
@@ -6027,10 +6041,10 @@ EditorNode::EditorNode() {
scene_root->set_disable_input(true);
scene_root->set_as_audio_listener_2d(true);
- viewport = memnew(VBoxContainer);
- viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- viewport->add_theme_constant_override("separation", 0);
- scene_root_parent->add_child(viewport);
+ main_control = memnew(VBoxContainer);
+ main_control->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ main_control->add_theme_constant_override("separation", 0);
+ scene_root_parent->add_child(main_control);
HBoxContainer *left_menu_hb = memnew(HBoxContainer);
menu_hb->add_child(left_menu_hb);
@@ -6936,8 +6950,8 @@ void EditorPluginList::remove_plugin(EditorPlugin *p_plugin) {
plugins_list.erase(p_plugin);
}
-bool EditorPluginList::empty() {
- return plugins_list.empty();
+bool EditorPluginList::is_empty() {
+ return plugins_list.is_empty();
}
void EditorPluginList::clear() {
diff --git a/editor/editor_node.h b/editor/editor_node.h
index ab8d268801..9ebc0f522c 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -255,7 +255,7 @@ private:
Control *vp_base;
HBoxContainer *menu_hb;
- Control *viewport;
+ Control *main_control;
MenuButton *file_menu;
MenuButton *project_menu;
MenuButton *debug_menu;
@@ -728,7 +728,7 @@ public:
bool is_changing_scene() const;
static EditorLog *get_log() { return singleton->log; }
- Control *get_viewport();
+ Control *get_main_control();
void set_edited_scene(Node *p_scene);
@@ -903,7 +903,7 @@ public:
void add_plugin(EditorPlugin *p_plugin);
void remove_plugin(EditorPlugin *p_plugin);
void clear();
- bool empty();
+ bool is_empty();
EditorPluginList();
~EditorPluginList();
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index f974ba9998..76912c8925 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -128,7 +128,7 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
Main::iteration();
Main::iteration();
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
- ERR_CONTINUE(!img.is_valid() || img->empty());
+ ERR_CONTINUE(!img.is_valid() || img->is_empty());
Ref<ImageTexture> it(memnew(ImageTexture));
it->create_from_image(img);
@@ -152,8 +152,8 @@ void EditorInterface::set_main_screen_editor(const String &p_name) {
EditorNode::get_singleton()->select_editor_by_name(p_name);
}
-Control *EditorInterface::get_editor_viewport() {
- return EditorNode::get_singleton()->get_viewport();
+Control *EditorInterface::get_editor_main_control() {
+ return EditorNode::get_singleton()->get_main_control();
}
void EditorInterface::edit_resource(const Ref<Resource> &p_resource) {
@@ -319,7 +319,7 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &EditorInterface::get_edited_scene_root);
ClassDB::bind_method(D_METHOD("get_resource_previewer"), &EditorInterface::get_resource_previewer);
ClassDB::bind_method(D_METHOD("get_resource_filesystem"), &EditorInterface::get_resource_file_system);
- ClassDB::bind_method(D_METHOD("get_editor_viewport"), &EditorInterface::get_editor_viewport);
+ ClassDB::bind_method(D_METHOD("get_editor_main_control"), &EditorInterface::get_editor_main_control);
ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
ClassDB::bind_method(D_METHOD("select_file", "file"), &EditorInterface::select_file);
ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 03908b43ca..1697b79216 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -69,7 +69,7 @@ protected:
public:
static EditorInterface *get_singleton() { return singleton; }
- Control *get_editor_viewport();
+ Control *get_editor_main_control();
void edit_resource(const Ref<Resource> &p_resource);
void open_scene_from_path(const String &scene_path);
void reload_scene_from_path(const String &scene_path);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 523e65babe..972fd0723a 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -2356,7 +2356,7 @@ void EditorPropertyResource::_file_selected(const String &p_path) {
property_types = E->get().hint_string;
}
}
- if (!property_types.empty()) {
+ if (!property_types.is_empty()) {
bool any_type_matches = false;
const Vector<String> split_property_types = property_types.split(",");
for (int i = 0; i < split_property_types.size(); ++i) {
@@ -2514,7 +2514,7 @@ void EditorPropertyResource::_menu_option(int p_which) {
update_property();
break;
}
- ERR_FAIL_COND(inheritors_array.empty());
+ ERR_FAIL_COND(inheritors_array.is_empty());
String intype = inheritors_array[p_which - TYPE_BASE_ID];
@@ -2590,7 +2590,7 @@ void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<T
}
if (p_preview.is_valid()) {
- preview->set_margin(MARGIN_LEFT, assign->get_icon()->get_width() + assign->get_theme_stylebox("normal")->get_default_margin(MARGIN_LEFT) + get_theme_constant("hseparation", "Button"));
+ preview->set_offset(SIDE_LEFT, assign->get_icon()->get_width() + assign->get_theme_stylebox("normal")->get_default_margin(SIDE_LEFT) + get_theme_constant("hseparation", "Button"));
if (type == "GradientTexture") {
preview->set_stretch_mode(TextureRect::STRETCH_SCALE);
assign->set_custom_minimum_size(Size2(1, 1));
@@ -2658,7 +2658,7 @@ void EditorPropertyResource::_update_menu_items() {
bool is_custom_resource = false;
Ref<Texture2D> icon;
- if (!custom_resources.empty()) {
+ if (!custom_resources.is_empty()) {
for (int j = 0; j < custom_resources.size(); j++) {
if (custom_resources[j].name == t) {
is_custom_resource = true;
@@ -3167,10 +3167,10 @@ EditorPropertyResource::EditorPropertyResource() {
preview = memnew(TextureRect);
preview->set_expand(true);
- preview->set_anchors_and_margins_preset(PRESET_WIDE);
- preview->set_margin(MARGIN_TOP, 1);
- preview->set_margin(MARGIN_BOTTOM, -1);
- preview->set_margin(MARGIN_RIGHT, -1);
+ preview->set_anchors_and_offsets_preset(PRESET_WIDE);
+ preview->set_offset(SIDE_TOP, 1);
+ preview->set_offset(SIDE_BOTTOM, -1);
+ preview->set_offset(SIDE_RIGHT, -1);
assign->add_child(preview);
assign->connect("gui_input", callable_mp(this, &EditorPropertyResource::_button_input));
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 56fbfbd0c2..774c08c4f0 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -550,7 +550,7 @@ void EditorPropertyArray::_length_changed(double p_page) {
void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint_string) {
array_type = p_array_type;
- if (array_type == Variant::ARRAY && !p_hint_string.empty()) {
+ if (array_type == Variant::ARRAY && !p_hint_string.is_empty()) {
int hint_subtype_separator = p_hint_string.find(":");
if (hint_subtype_separator >= 0) {
String subtype_string = p_hint_string.substr(0, hint_subtype_separator);
@@ -975,7 +975,7 @@ void EditorPropertyDictionary::update_property() {
Ref<StyleBoxFlat> flat;
flat.instance();
for (int j = 0; j < 4; j++) {
- flat->set_default_margin(Margin(j), 2 * EDSCALE);
+ flat->set_default_margin(Side(j), 2 * EDSCALE);
}
flat->set_bg_color(get_theme_color("prop_subsection", "Editor"));
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 639da371bd..3ebcd16275 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -46,7 +46,7 @@ void EditorRunNative::_notification(int p_what) {
Ref<Image> im = icon->get_data();
im = im->duplicate();
im->clear_mipmaps();
- if (!im->empty()) {
+ if (!im->is_empty()) {
im->resize(16 * EDSCALE, 16 * EDSCALE);
Ref<ImageTexture> small_icon;
small_icon.instance();
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index bc9ca15467..691f2e8228 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -234,7 +234,7 @@ void SectionedInspector::update_category_list() {
continue;
}
- if (!filter.empty() && pi.name.findn(filter) == -1 && pi.name.replace("/", " ").capitalize().findn(filter) == -1) {
+ if (!filter.is_empty() && pi.name.findn(filter) == -1 && pi.name.replace("/", " ").capitalize().findn(filter) == -1) {
continue;
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index e88f27c857..3d131d373a 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -281,7 +281,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
locales_to_skip.push_back("te"); // Telugu
}
- if (!locales_to_skip.empty()) {
+ if (!locales_to_skip.is_empty()) {
WARN_PRINT("Some locales are not properly supported by selected Text Server and are disabled.");
}
@@ -628,6 +628,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Animation
_initial_set("editors/animation/autorename_animation_tracks", true);
_initial_set("editors/animation/confirm_insert_track", true);
+ _initial_set("editors/animation/default_create_bezier_tracks", false);
+ _initial_set("editors/animation/default_create_reset_tracks", true);
_initial_set("editors/animation/onion_layers_past_color", Color(1, 0, 0));
_initial_set("editors/animation/onion_layers_future_color", Color(0, 1, 0));
@@ -1474,7 +1476,7 @@ bool EditorSettings::is_default_text_editor_theme() {
Vector<String> EditorSettings::get_script_templates(const String &p_extension, const String &p_custom_path) {
Vector<String> templates;
String template_dir = get_script_templates_dir();
- if (!p_custom_path.empty()) {
+ if (!p_custom_path.is_empty()) {
template_dir = p_custom_path;
}
DirAccess *d = DirAccess::open(template_dir);
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index d72510d40d..4a37d26a26 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -202,7 +202,7 @@ void EditorSpinSlider::_notification(int p_what) {
// EditorSpinSliders with a label have more space on the left, so add an
// higher margin to match the location where the text begins.
// The margin values below were determined by empirical testing.
- stylebox->set_default_margin(MARGIN_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE);
+ stylebox->set_default_margin(SIDE_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE);
value_input->add_theme_style_override("normal", stylebox);
}
@@ -256,7 +256,7 @@ void EditorSpinSlider::_notification(int p_what) {
if (get_step() == 1) {
Ref<Texture2D> updown2 = get_theme_icon("updown", "SpinBox");
int updown_vofs = (get_size().height - updown2->get_height()) / 2;
- updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown2->get_width();
+ updown_offset = get_size().width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
Color c(1, 1, 1);
if (hover_updown) {
c *= Color(1.2, 1.2, 1.2);
@@ -500,7 +500,7 @@ EditorSpinSlider::EditorSpinSlider() {
value_input = memnew(LineEdit);
value_input_popup->add_child(value_input);
value_input_popup->set_wrap_controls(true);
- value_input->set_anchors_and_margins_preset(PRESET_WIDE);
+ value_input->set_anchors_and_offsets_preset(PRESET_WIDE);
value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
value_input->connect("text_entered", callable_mp(this, &EditorSpinSlider::_value_input_entered));
value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 35de38fad2..7582c2073f 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -44,34 +44,34 @@
static Ref<StyleBoxTexture> make_stylebox(Ref<Texture2D> p_texture, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) {
Ref<StyleBoxTexture> style(memnew(StyleBoxTexture));
style->set_texture(p_texture);
- style->set_margin_size(MARGIN_LEFT, p_left * EDSCALE);
- style->set_margin_size(MARGIN_RIGHT, p_right * EDSCALE);
- style->set_margin_size(MARGIN_BOTTOM, p_botton * EDSCALE);
- style->set_margin_size(MARGIN_TOP, p_top * EDSCALE);
- style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE);
- style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE);
- style->set_default_margin(MARGIN_BOTTOM, p_margin_botton * EDSCALE);
- style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE);
+ style->set_margin_size(SIDE_LEFT, p_left * EDSCALE);
+ style->set_margin_size(SIDE_RIGHT, p_right * EDSCALE);
+ style->set_margin_size(SIDE_BOTTOM, p_botton * EDSCALE);
+ style->set_margin_size(SIDE_TOP, p_top * EDSCALE);
+ style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE);
+ style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE);
+ style->set_default_margin(SIDE_BOTTOM, p_margin_botton * EDSCALE);
+ style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE);
style->set_draw_center(p_draw_center);
return style;
}
static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
- style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE);
- style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE);
- style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE);
- style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE);
+ style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE);
+ style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE);
+ style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE);
+ style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE);
return style;
}
static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
style->set_bg_color(p_color);
- style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE);
- style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE);
- style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE);
- style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE);
+ style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE);
+ style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE);
+ style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE);
+ style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE);
return style;
}
@@ -477,10 +477,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing");
Ref<StyleBoxFlat> style_widget = style_default->duplicate();
- style_widget->set_default_margin(MARGIN_LEFT, (extra_spacing + 6) * EDSCALE);
- style_widget->set_default_margin(MARGIN_TOP, (extra_spacing + default_margin_size) * EDSCALE);
- style_widget->set_default_margin(MARGIN_RIGHT, (extra_spacing + 6) * EDSCALE);
- style_widget->set_default_margin(MARGIN_BOTTOM, (extra_spacing + default_margin_size) * EDSCALE);
+ style_widget->set_default_margin(SIDE_LEFT, (extra_spacing + 6) * EDSCALE);
+ style_widget->set_default_margin(SIDE_TOP, (extra_spacing + default_margin_size) * EDSCALE);
+ style_widget->set_default_margin(SIDE_RIGHT, (extra_spacing + 6) * EDSCALE);
+ style_widget->set_default_margin(SIDE_BOTTOM, (extra_spacing + default_margin_size) * EDSCALE);
style_widget->set_bg_color(dark_color_1);
style_widget->set_border_color(dark_color_2);
@@ -500,10 +500,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// style for windows, popups, etc..
Ref<StyleBoxFlat> style_popup = style_default->duplicate();
const int popup_margin_size = default_margin_size * EDSCALE * 2;
- style_popup->set_default_margin(MARGIN_LEFT, popup_margin_size);
- style_popup->set_default_margin(MARGIN_TOP, popup_margin_size);
- style_popup->set_default_margin(MARGIN_RIGHT, popup_margin_size);
- style_popup->set_default_margin(MARGIN_BOTTOM, popup_margin_size);
+ style_popup->set_default_margin(SIDE_LEFT, popup_margin_size);
+ style_popup->set_default_margin(SIDE_TOP, popup_margin_size);
+ style_popup->set_default_margin(SIDE_RIGHT, popup_margin_size);
+ style_popup->set_default_margin(SIDE_BOTTOM, popup_margin_size);
style_popup->set_border_color(contrast_color_1);
style_popup->set_border_width_all(MAX(EDSCALE, border_width));
const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1);
@@ -536,13 +536,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_tab_selected = style_widget->duplicate();
style_tab_selected->set_border_width_all(border_width);
- style_tab_selected->set_border_width(MARGIN_BOTTOM, 0);
+ style_tab_selected->set_border_width(SIDE_BOTTOM, 0);
style_tab_selected->set_border_color(dark_color_3);
- style_tab_selected->set_expand_margin_size(MARGIN_BOTTOM, border_width);
- style_tab_selected->set_default_margin(MARGIN_LEFT, tab_default_margin_side);
- style_tab_selected->set_default_margin(MARGIN_RIGHT, tab_default_margin_side);
- style_tab_selected->set_default_margin(MARGIN_BOTTOM, tab_default_margin_vertical);
- style_tab_selected->set_default_margin(MARGIN_TOP, tab_default_margin_vertical);
+ style_tab_selected->set_expand_margin_size(SIDE_BOTTOM, border_width);
+ style_tab_selected->set_default_margin(SIDE_LEFT, tab_default_margin_side);
+ style_tab_selected->set_default_margin(SIDE_RIGHT, tab_default_margin_side);
+ style_tab_selected->set_default_margin(SIDE_BOTTOM, tab_default_margin_vertical);
+ style_tab_selected->set_default_margin(SIDE_TOP, tab_default_margin_vertical);
style_tab_selected->set_bg_color(tab_color);
Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate();
@@ -580,7 +580,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxFlat> style_menu_hover_border = style_widget->duplicate();
style_menu_hover_border->set_draw_center(false);
style_menu_hover_border->set_border_width_all(0);
- style_menu_hover_border->set_border_width(MARGIN_BOTTOM, border_width);
+ style_menu_hover_border->set_border_width(SIDE_BOTTOM, border_width);
style_menu_hover_border->set_border_color(accent_color);
Ref<StyleBoxFlat> style_menu_hover_bg = style_widget->duplicate();
@@ -668,10 +668,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Checkbox
Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
- sb_checkbox->set_default_margin(MARGIN_LEFT, default_margin_size * EDSCALE);
- sb_checkbox->set_default_margin(MARGIN_RIGHT, default_margin_size * EDSCALE);
- sb_checkbox->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
- sb_checkbox->set_default_margin(MARGIN_BOTTOM, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(SIDE_LEFT, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(SIDE_RIGHT, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE);
+ sb_checkbox->set_default_margin(SIDE_BOTTOM, default_margin_size * EDSCALE);
theme->set_stylebox("normal", "CheckBox", sb_checkbox);
theme->set_stylebox("pressed", "CheckBox", sb_checkbox);
@@ -697,10 +697,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// PopupMenu
const int popup_menu_margin_size = default_margin_size * 1.5 * EDSCALE;
Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate();
- style_popup_menu->set_default_margin(MARGIN_LEFT, popup_menu_margin_size);
- style_popup_menu->set_default_margin(MARGIN_TOP, popup_menu_margin_size);
- style_popup_menu->set_default_margin(MARGIN_RIGHT, popup_menu_margin_size);
- style_popup_menu->set_default_margin(MARGIN_BOTTOM, popup_menu_margin_size);
+ style_popup_menu->set_default_margin(SIDE_LEFT, popup_menu_margin_size);
+ style_popup_menu->set_default_margin(SIDE_TOP, popup_menu_margin_size);
+ style_popup_menu->set_default_margin(SIDE_RIGHT, popup_menu_margin_size);
+ style_popup_menu->set_default_margin(SIDE_BOTTOM, popup_menu_margin_size);
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
theme->set_stylebox("separator", "PopupMenu", style_popup_separator);
@@ -724,9 +724,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size + 1) * EDSCALE);
Ref<StyleBoxFlat> sub_inspector_bg = make_flat_stylebox(dark_color_1.lerp(accent_color, 0.08), 2, 0, 2, 2);
- sub_inspector_bg->set_border_width(MARGIN_LEFT, 2);
- sub_inspector_bg->set_border_width(MARGIN_RIGHT, 2);
- sub_inspector_bg->set_border_width(MARGIN_BOTTOM, 2);
+ sub_inspector_bg->set_border_width(SIDE_LEFT, 2);
+ sub_inspector_bg->set_border_width(SIDE_RIGHT, 2);
+ sub_inspector_bg->set_border_width(SIDE_BOTTOM, 2);
sub_inspector_bg->set_border_color(accent_color * Color(1, 1, 1, 0.3));
sub_inspector_bg->set_draw_center(true);
@@ -866,17 +866,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_content_panel->set_border_color(dark_color_3);
style_content_panel->set_border_width_all(border_width);
// compensate the border
- style_content_panel->set_default_margin(MARGIN_TOP, margin_size_extra * EDSCALE);
- style_content_panel->set_default_margin(MARGIN_RIGHT, margin_size_extra * EDSCALE);
- style_content_panel->set_default_margin(MARGIN_BOTTOM, margin_size_extra * EDSCALE);
- style_content_panel->set_default_margin(MARGIN_LEFT, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(SIDE_TOP, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(SIDE_RIGHT, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(SIDE_BOTTOM, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(SIDE_LEFT, margin_size_extra * EDSCALE);
// this is the stylebox used in 3d and 2d viewports (no borders)
Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
- style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width * 2);
- style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
- style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width * 2);
- style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width * 2);
+ style_content_panel_vp->set_default_margin(SIDE_LEFT, border_width * 2);
+ style_content_panel_vp->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE);
+ style_content_panel_vp->set_default_margin(SIDE_RIGHT, border_width * 2);
+ style_content_panel_vp->set_default_margin(SIDE_BOTTOM, border_width * 2);
theme->set_stylebox("panel", "TabContainer", style_content_panel);
theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp);
@@ -887,13 +887,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Debugger
Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate();
- style_panel_debugger->set_border_width(MARGIN_BOTTOM, 0);
+ style_panel_debugger->set_border_width(SIDE_BOTTOM, 0);
theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger);
Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
- int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height(theme->get_font_size("tab_fg", "TabContainer")) + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(MARGIN_TOP);
- style_panel_invisible_top->set_expand_margin_size(MARGIN_TOP, -stylebox_offset);
- style_panel_invisible_top->set_default_margin(MARGIN_TOP, 0);
+ int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height(theme->get_font_size("tab_fg", "TabContainer")) + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(SIDE_TOP);
+ style_panel_invisible_top->set_expand_margin_size(SIDE_TOP, -stylebox_offset);
+ style_panel_invisible_top->set_default_margin(SIDE_TOP, 0);
theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top);
// LineEdit
@@ -958,8 +958,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// WindowDialog
Ref<StyleBoxFlat> style_window = style_popup->duplicate();
style_window->set_border_color(tab_color);
- style_window->set_border_width(MARGIN_TOP, 24 * EDSCALE);
- style_window->set_expand_margin_size(MARGIN_TOP, 24 * EDSCALE);
+ style_window->set_border_width(SIDE_TOP, 24 * EDSCALE);
+ style_window->set_expand_margin_size(SIDE_TOP, 24 * EDSCALE);
theme->set_stylebox("panel", "Window", style_default);
theme->set_stylebox("panel_window", "Window", style_window);
@@ -1055,10 +1055,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// TooltipPanel
Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate();
float v = MAX(border_size * EDSCALE, 1.0);
- style_tooltip->set_default_margin(MARGIN_LEFT, v);
- style_tooltip->set_default_margin(MARGIN_TOP, v);
- style_tooltip->set_default_margin(MARGIN_RIGHT, v);
- style_tooltip->set_default_margin(MARGIN_BOTTOM, v);
+ style_tooltip->set_default_margin(SIDE_LEFT, v);
+ style_tooltip->set_default_margin(SIDE_TOP, v);
+ style_tooltip->set_default_margin(SIDE_RIGHT, v);
+ style_tooltip->set_default_margin(SIDE_BOTTOM, v);
style_tooltip->set_bg_color(Color(mono_color.r, mono_color.g, mono_color.b, 0.9));
style_tooltip->set_border_width_all(border_width);
style_tooltip->set_border_color(mono_color);
@@ -1155,10 +1155,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
smgraphsbselected->set_shadow_color(shadow_color);
if (use_gn_headers) {
- graphsb->set_border_width(MARGIN_TOP, 24 * EDSCALE);
- graphsbselected->set_border_width(MARGIN_TOP, 24 * EDSCALE);
- graphsbcomment->set_border_width(MARGIN_TOP, 24 * EDSCALE);
- graphsbcommentselected->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsb->set_border_width(SIDE_TOP, 24 * EDSCALE);
+ graphsbselected->set_border_width(SIDE_TOP, 24 * EDSCALE);
+ graphsbcomment->set_border_width(SIDE_TOP, 24 * EDSCALE);
+ graphsbcommentselected->set_border_width(SIDE_TOP, 24 * EDSCALE);
}
theme->set_stylebox("frame", "GraphNode", graphsb);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 6c8bd1901e..e7a621eee6 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -531,7 +531,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
}
String file_name = p_path.get_file();
- if (!file_name.empty()) {
+ if (!file_name.is_empty()) {
for (int i = 0; i < files->get_item_count(); i++) {
if (files->get_item_text(i) == file_name) {
files->select(i, true);
@@ -1528,7 +1528,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove
if (!p_overwrite) {
to_move_path = p_to_path;
Vector<String> conflicting_items = _check_existing();
- if (!conflicting_items.empty()) {
+ if (!conflicting_items.is_empty()) {
// Ask to do something.
overwrite_dialog->set_text(vformat(
TTR("The following files or folders conflict with items in the target location '%s':\n\n%s\n\nDo you wish to overwrite them?"),
@@ -1721,7 +1721,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
paths.push_back(fpath);
}
}
- if (!paths.empty()) {
+ if (!paths.is_empty()) {
emit_signal("instance", paths);
}
} break;
@@ -1753,7 +1753,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
case FILE_DEPENDENCIES: {
// Checkout the file dependencies.
- if (!p_selected.empty()) {
+ if (!p_selected.is_empty()) {
String fpath = p_selected[0];
deps_editor->edit(fpath);
}
@@ -1761,7 +1761,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
case FILE_OWNERS: {
// Checkout the file owners.
- if (!p_selected.empty()) {
+ if (!p_selected.is_empty()) {
String fpath = p_selected[0];
owners_editor->show(fpath);
}
@@ -1784,7 +1784,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
case FILE_RENAME: {
// Rename the active file.
- if (!p_selected.empty()) {
+ if (!p_selected.is_empty()) {
to_rename.path = p_selected[0];
if (to_rename.path != "res://") {
to_rename.is_file = !to_rename.path.ends_with("/");
@@ -1885,7 +1885,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_COPY_PATH: {
- if (!p_selected.empty()) {
+ if (!p_selected.is_empty()) {
String fpath = p_selected[0];
DisplayServer::get_singleton()->clipboard_set(fpath);
}
@@ -2013,7 +2013,7 @@ Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from)
all_not_favorites = true;
}
- if (paths.empty()) {
+ if (paths.is_empty()) {
return Variant();
}
@@ -2061,7 +2061,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
- return !to_dir.empty();
+ return !to_dir.is_empty();
}
if (drag_data.has("type") && (String(drag_data["type"]) == "files" || String(drag_data["type"]) == "files_and_dirs")) {
@@ -2074,7 +2074,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
return true;
}
- if (to_dir.empty()) {
+ if (to_dir.is_empty()) {
return false;
}
@@ -2169,7 +2169,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
- if (res.is_valid() && !to_dir.empty()) {
+ if (res.is_valid() && !to_dir.is_empty()) {
EditorNode::get_singleton()->push_item(res.ptr());
EditorNode::get_singleton()->save_resource_as(res, to_dir);
}
@@ -2180,7 +2180,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
String to_dir;
bool favorite;
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
- if (!to_dir.empty()) {
+ if (!to_dir.is_empty()) {
Vector<String> fnames = drag_data["files"];
to_move.clear();
for (int i = 0; i < fnames.size(); i++) {
@@ -2188,7 +2188,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
to_move.push_back(FileOrFolder(fnames[i], !fnames[i].ends_with("/")));
}
}
- if (!to_move.empty()) {
+ if (!to_move.is_empty()) {
if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
for (int i = 0; i < to_move.size(); i++) {
String new_path;
@@ -2291,7 +2291,7 @@ void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favori
void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<String> p_paths, bool p_display_path_dependent_options) {
// Add options for files and folders.
- ERR_FAIL_COND_MSG(p_paths.empty(), "Path cannot be empty.");
+ ERR_FAIL_COND_MSG(p_paths.is_empty(), "Path cannot be empty.");
Vector<String> filenames;
Vector<String> foldernames;
@@ -2414,7 +2414,7 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) {
}
// Popup.
- if (!paths.empty()) {
+ if (!paths.is_empty()) {
tree_popup->set_size(Size2(1, 1));
_file_and_folders_fill_popup(tree_popup, paths);
tree_popup->set_position(tree->get_screen_position() + p_pos);
@@ -2447,14 +2447,14 @@ void FileSystemDock::_file_list_rmb_select(int p_item, const Vector2 &p_pos) {
continue;
}
if (files->get_item_text(p_item) == "..") {
- files->unselect(i);
+ files->deselect(i);
continue;
}
paths.push_back(files->get_item_metadata(i));
}
// Popup.
- if (!paths.empty()) {
+ if (!paths.is_empty()) {
file_list_popup->clear();
file_list_popup->set_size(Size2(1, 1));
_file_and_folders_fill_popup(file_list_popup, paths, searched_string.length() == 0);
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index 076b873eac..ac4acc613f 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -294,10 +294,10 @@ FindInFilesDialog::FindInFilesDialog() {
set_title(TTR("Find in Files"));
VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE);
add_child(vbc);
GridContainer *gc = memnew(GridContainer);
@@ -499,8 +499,8 @@ void FindInFilesDialog::_on_search_text_modified(String text) {
ERR_FAIL_COND(!_find_button);
ERR_FAIL_COND(!_replace_button);
- _find_button->set_disabled(get_search_text().empty());
- _replace_button->set_disabled(get_search_text().empty());
+ _find_button->set_disabled(get_search_text().is_empty());
+ _replace_button->set_disabled(get_search_text().is_empty());
}
void FindInFilesDialog::_on_search_text_entered(String text) {
@@ -551,10 +551,10 @@ FindInFilesPanel::FindInFilesPanel() {
add_child(_finder);
VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0);
- vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
- vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
- vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);
+ vbc->set_anchor_and_offset(SIDE_LEFT, ANCHOR_BEGIN, 0);
+ vbc->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 0);
+ vbc->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, 0);
+ vbc->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0);
add_child(vbc);
{
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 32c50321d7..55bd475543 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -198,7 +198,7 @@ void GroupDialog::_add_group(String p_name) {
}
String name = p_name.strip_edges();
- if (name.empty() || groups->get_item_with_text(name)) {
+ if (name.is_empty() || groups->get_item_with_text(name)) {
return;
}
@@ -413,7 +413,7 @@ GroupDialog::GroupDialog() {
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
- vbc->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ vbc->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
HBoxContainer *hbc = memnew(HBoxContainer);
vbc->add_child(hbc);
@@ -534,7 +534,7 @@ GroupDialog::GroupDialog() {
group_empty->set_autowrap(true);
group_empty->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
nodes_to_remove->add_child(group_empty);
- group_empty->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ group_empty->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
set_title(TTR("Group Editor"));
@@ -551,7 +551,7 @@ void GroupsEditor::_add_group(const String &p_group) {
}
const String name = group_name->get_text().strip_edges();
- if (name.empty()) {
+ if (name.is_empty()) {
return;
}
diff --git a/editor/icons/GuiToggleOn.svg b/editor/icons/GuiToggleOn.svg
index 8ab0998f71..37b47e8de4 100644
--- a/editor/icons/GuiToggleOn.svg
+++ b/editor/icons/GuiToggleOn.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 38 15.999999" width="38" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.878 0-7 3.122-7 7s3.122 7 7 7h22c3.878 0 7-3.122 7-7s-3.122-7-7-7zm22 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5-5 5 5 0 0 1 5-5z" fill="#e0e0e0" stroke-width="55.8958"/></svg>
+<svg height="16" viewBox="0 0 38 15.999999" width="38" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-4 0-7 3.0000002-7 7.0000002 0 3.9999998 3 6.9999998 7 6.9999998h22c4 0 7-3 7-6.9999998 0-4-3-7.0000002-7-7.0000002-7.333334 0-14.55609 0-22 0z" fill="#699ce8"/><circle cx="30" cy="8" fill="#fefefe" r="5"/></svg>
diff --git a/editor/icons/GuiToggleOnMirrored.svg b/editor/icons/GuiToggleOnMirrored.svg
index 7339b6efd2..fa7f602ee7 100644
--- a/editor/icons/GuiToggleOnMirrored.svg
+++ b/editor/icons/GuiToggleOnMirrored.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="42" height="26"><path fill="#e0e0e0" d="M31 5c4.986 0 9 3.568 9 8s-4.014 8-9 8H11c-4.986 0-9-3.568-9-8s4.014-8 9-8zM10 8a-5 5 0 0 0-5 5-5 5 0 0 0 5 5-5 5 0 0 0 5-5-5 5 0 0 0-5-5z"/></svg>
+<svg height="26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m31 5c4.986 0 9 3.568 9 8s-4.014 8-9 8h-20c-4.986 0-9-3.568-9-8s4.014-8 9-8z" fill="#699ce8"/><circle cx="10" cy="13" fill="#fefefe" r="5"/></svg>
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp
index 8eb68ecdcf..91c4e3afd2 100644
--- a/editor/import/collada.cpp
+++ b/editor/import/collada.cpp
@@ -1365,7 +1365,7 @@ Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) {
}
if (geom->controller) {
- if (geom->skeletons.empty()) {
+ if (geom->skeletons.is_empty()) {
//XSI style
if (state.skin_controller_data_map.has(geom->source)) {
@@ -2321,7 +2321,7 @@ void Collada::_optimize() {
i--;
}
- while (!mgeom.empty()) {
+ while (!mgeom.is_empty()) {
Node *n = mgeom.front()->get();
n->parent->children.push_back(n);
mgeom.pop_front();
diff --git a/editor/import/collada.h b/editor/import/collada.h
index 29d49d4aa7..354a3e697a 100644
--- a/editor/import/collada.h
+++ b/editor/import/collada.h
@@ -274,7 +274,7 @@ public:
if (normal == p_vert.normal) {
if (uv == p_vert.uv) {
if (uv2 == p_vert.uv2) {
- if (!weights.empty() || !p_vert.weights.empty()) {
+ if (!weights.is_empty() || !p_vert.weights.is_empty()) {
if (weights.size() == p_vert.weights.size()) {
for (int i = 0; i < weights.size(); i++) {
if (weights[i].bone_idx != p_vert.weights[i].bone_idx) {
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 4e93fe6f12..19a846bf37 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -33,6 +33,7 @@
#include "core/os/os.h"
#include "editor/editor_node.h"
#include "editor/import/collada.h"
+#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -278,8 +279,8 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) {
node = memnew(Path3D);
} else {
//mesh since nothing else
- node = memnew(EditorSceneImporterMeshNode);
- //Object::cast_to<EditorSceneImporterMeshNode>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true);
+ node = memnew(EditorSceneImporterMeshNode3D);
+ //Object::cast_to<EditorSceneImporterMeshNode3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true);
}
} break;
case Collada::Node::TYPE_SKELETON: {
@@ -1003,10 +1004,10 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
}
}
- if (Object::cast_to<EditorSceneImporterMeshNode>(node)) {
+ if (Object::cast_to<EditorSceneImporterMeshNode3D>(node)) {
Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node);
- EditorSceneImporterMeshNode *mi = Object::cast_to<EditorSceneImporterMeshNode>(node);
+ EditorSceneImporterMeshNode3D *mi = Object::cast_to<EditorSceneImporterMeshNode3D>(node);
ERR_FAIL_COND_V(!mi, ERR_BUG);
@@ -1026,7 +1027,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres
Vector<String> skeletons = ng2->skeletons;
- ERR_FAIL_COND_V(skeletons.empty(), ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(skeletons.is_empty(), ERR_INVALID_DATA);
String skname = skeletons[0];
ERR_FAIL_COND_V(!node_map.has(skname), ERR_INVALID_DATA);
@@ -1470,7 +1471,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
}
Vector<float> data = at.get_value_at_time(snapshots[i]);
- ERR_CONTINUE(data.empty());
+ ERR_CONTINUE(data.is_empty());
Collada::Node::XForm &xf = cn->xform_list.write[xform_idx];
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
deleted file mode 100644
index 1059692ca0..0000000000
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ /dev/null
@@ -1,3254 +0,0 @@
-/*************************************************************************/
-/* editor_scene_importer_gltf.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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. */
-/*************************************************************************/
-
-#include "editor_scene_importer_gltf.h"
-
-#include "core/crypto/crypto_core.h"
-#include "core/io/json.h"
-#include "core/math/disjoint_set.h"
-#include "core/math/math_defs.h"
-#include "core/os/file_access.h"
-#include "core/os/os.h"
-#include "modules/regex/regex.h"
-#include "scene/3d/bone_attachment_3d.h"
-#include "scene/3d/camera_3d.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/surface_tool.h"
-
-uint32_t EditorSceneImporterGLTF::get_import_flags() const {
- return IMPORT_SCENE | IMPORT_ANIMATION;
-}
-
-void EditorSceneImporterGLTF::get_extensions(List<String> *r_extensions) const {
- r_extensions->push_back("gltf");
- r_extensions->push_back("glb");
-}
-
-Error EditorSceneImporterGLTF::_parse_json(const String &p_path, GLTFState &state) {
- Error err;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
- return err;
- }
-
- Vector<uint8_t> array;
- array.resize(f->get_len());
- f->get_buffer(array.ptrw(), array.size());
- String text;
- text.parse_utf8((const char *)array.ptr(), array.size());
-
- String err_txt;
- int err_line;
- Variant v;
- err = JSON::parse(text, v, err_txt, err_line);
- if (err != OK) {
- _err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT);
- return err;
- }
- state.json = v;
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_glb(const String &p_path, GLTFState &state) {
- Error err;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
- return err;
- }
-
- uint32_t magic = f->get_32();
- ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF
- f->get_32(); // version
- f->get_32(); // length
-
- uint32_t chunk_length = f->get_32();
- uint32_t chunk_type = f->get_32();
-
- ERR_FAIL_COND_V(chunk_type != 0x4E4F534A, ERR_PARSE_ERROR); //JSON
- Vector<uint8_t> json_data;
- json_data.resize(chunk_length);
- uint32_t len = f->get_buffer(json_data.ptrw(), chunk_length);
- ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
-
- String text;
- text.parse_utf8((const char *)json_data.ptr(), json_data.size());
-
- String err_txt;
- int err_line;
- Variant v;
- err = JSON::parse(text, v, err_txt, err_line);
- if (err != OK) {
- _err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT);
- return err;
- }
-
- state.json = v;
-
- //data?
-
- chunk_length = f->get_32();
- chunk_type = f->get_32();
-
- if (f->eof_reached()) {
- return OK; //all good
- }
-
- ERR_FAIL_COND_V(chunk_type != 0x004E4942, ERR_PARSE_ERROR); //BIN
-
- state.glb_data.resize(chunk_length);
- len = f->get_buffer(state.glb_data.ptrw(), chunk_length);
- ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
-
- return OK;
-}
-
-static Vector3 _arr_to_vec3(const Array &p_array) {
- ERR_FAIL_COND_V(p_array.size() != 3, Vector3());
- return Vector3(p_array[0], p_array[1], p_array[2]);
-}
-
-static Quat _arr_to_quat(const Array &p_array) {
- ERR_FAIL_COND_V(p_array.size() != 4, Quat());
- return Quat(p_array[0], p_array[1], p_array[2], p_array[3]);
-}
-
-static Transform _arr_to_xform(const Array &p_array) {
- ERR_FAIL_COND_V(p_array.size() != 16, Transform());
-
- Transform xform;
- xform.basis.set_axis(Vector3::AXIS_X, Vector3(p_array[0], p_array[1], p_array[2]));
- xform.basis.set_axis(Vector3::AXIS_Y, Vector3(p_array[4], p_array[5], p_array[6]));
- xform.basis.set_axis(Vector3::AXIS_Z, Vector3(p_array[8], p_array[9], p_array[10]));
- xform.set_origin(Vector3(p_array[12], p_array[13], p_array[14]));
-
- return xform;
-}
-
-String EditorSceneImporterGLTF::_sanitize_scene_name(const String &name) {
- RegEx regex("([^a-zA-Z0-9_ -]+)");
- String p_name = regex.sub(name, "", true);
- return p_name;
-}
-
-String EditorSceneImporterGLTF::_gen_unique_name(GLTFState &state, const String &p_name) {
- const String s_name = _sanitize_scene_name(p_name);
-
- String name;
- int index = 1;
- while (true) {
- name = s_name;
-
- if (index > 1) {
- name += " " + itos(index);
- }
- if (!state.unique_names.has(name)) {
- break;
- }
- index++;
- }
-
- state.unique_names.insert(name);
-
- return name;
-}
-
-String EditorSceneImporterGLTF::_sanitize_bone_name(const String &name) {
- String p_name = name.camelcase_to_underscore(true);
-
- RegEx pattern_nocolon(":");
- p_name = pattern_nocolon.sub(p_name, "_", true);
-
- RegEx pattern_noslash("/");
- p_name = pattern_noslash.sub(p_name, "_", true);
-
- RegEx pattern_nospace(" +");
- p_name = pattern_nospace.sub(p_name, "_", true);
-
- RegEx pattern_multiple("_+");
- p_name = pattern_multiple.sub(p_name, "_", true);
-
- RegEx pattern_padded("0+(\\d+)");
- p_name = pattern_padded.sub(p_name, "$1", true);
-
- return p_name;
-}
-
-String EditorSceneImporterGLTF::_gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name) {
- String s_name = _sanitize_bone_name(p_name);
- if (s_name.empty()) {
- s_name = "bone";
- }
- String name;
- int index = 1;
- while (true) {
- name = s_name;
-
- if (index > 1) {
- name += "_" + itos(index);
- }
- if (!state.skeletons[skel_i].unique_names.has(name)) {
- break;
- }
- index++;
- }
-
- state.skeletons.write[skel_i].unique_names.insert(name);
-
- return name;
-}
-
-Error EditorSceneImporterGLTF::_parse_scenes(GLTFState &state) {
- ERR_FAIL_COND_V(!state.json.has("scenes"), ERR_FILE_CORRUPT);
- const Array &scenes = state.json["scenes"];
- int loaded_scene = 0;
- if (state.json.has("scene")) {
- loaded_scene = state.json["scene"];
- } else {
- WARN_PRINT("The load-time scene is not defined in the glTF2 file. Picking the first scene.");
- }
-
- if (scenes.size()) {
- ERR_FAIL_COND_V(loaded_scene >= scenes.size(), ERR_FILE_CORRUPT);
- const Dictionary &s = scenes[loaded_scene];
- ERR_FAIL_COND_V(!s.has("nodes"), ERR_UNAVAILABLE);
- const Array &nodes = s["nodes"];
- for (int j = 0; j < nodes.size(); j++) {
- state.root_nodes.push_back(nodes[j]);
- }
-
- if (s.has("name") && s["name"] != "") {
- state.scene_name = _gen_unique_name(state, s["name"]);
- } else {
- state.scene_name = _gen_unique_name(state, "Scene");
- }
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) {
- ERR_FAIL_COND_V(!state.json.has("nodes"), ERR_FILE_CORRUPT);
- const Array &nodes = state.json["nodes"];
- for (int i = 0; i < nodes.size(); i++) {
- GLTFNode *node = memnew(GLTFNode);
- const Dictionary &n = nodes[i];
-
- if (n.has("name")) {
- node->name = n["name"];
- }
- if (n.has("camera")) {
- node->camera = n["camera"];
- }
- if (n.has("mesh")) {
- node->mesh = n["mesh"];
- }
- if (n.has("skin")) {
- node->skin = n["skin"];
- }
- if (n.has("matrix")) {
- node->xform = _arr_to_xform(n["matrix"]);
-
- } else {
- if (n.has("translation")) {
- node->translation = _arr_to_vec3(n["translation"]);
- }
- if (n.has("rotation")) {
- node->rotation = _arr_to_quat(n["rotation"]);
- }
- if (n.has("scale")) {
- node->scale = _arr_to_vec3(n["scale"]);
- }
-
- node->xform.basis.set_quat_scale(node->rotation, node->scale);
- node->xform.origin = node->translation;
- }
- if (n.has("extensions")) {
- Dictionary extensions = n["extensions"];
- if (extensions.has("KHR_lights_punctual")) {
- Dictionary lights_punctual = extensions["KHR_lights_punctual"];
- if (lights_punctual.has("light")) {
- GLTFLightIndex light = lights_punctual["light"];
- node->light = light;
- }
- }
- }
- if (n.has("children")) {
- const Array &children = n["children"];
- for (int j = 0; j < children.size(); j++) {
- node->children.push_back(children[j]);
- }
- }
-
- state.nodes.push_back(node);
- }
-
- // build the hierarchy
- for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); node_i++) {
- for (int j = 0; j < state.nodes[node_i]->children.size(); j++) {
- GLTFNodeIndex child_i = state.nodes[node_i]->children[j];
-
- ERR_FAIL_INDEX_V(child_i, state.nodes.size(), ERR_FILE_CORRUPT);
- ERR_CONTINUE(state.nodes[child_i]->parent != -1); //node already has a parent, wtf.
-
- state.nodes[child_i]->parent = node_i;
- }
- }
-
- _compute_node_heights(state);
-
- return OK;
-}
-
-void EditorSceneImporterGLTF::_compute_node_heights(GLTFState &state) {
- state.root_nodes.clear();
- for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); ++node_i) {
- GLTFNode *node = state.nodes[node_i];
- node->height = 0;
-
- GLTFNodeIndex current_i = node_i;
- while (current_i >= 0) {
- const GLTFNodeIndex parent_i = state.nodes[current_i]->parent;
- if (parent_i >= 0) {
- ++node->height;
- }
- current_i = parent_i;
- }
-
- if (node->height == 0) {
- state.root_nodes.push_back(node_i);
- }
- }
-}
-
-static Vector<uint8_t> _parse_base64_uri(const String &uri) {
- int start = uri.find(",");
- ERR_FAIL_COND_V(start == -1, Vector<uint8_t>());
-
- CharString substr = uri.right(start + 1).ascii();
-
- int strlen = substr.length();
-
- Vector<uint8_t> buf;
- buf.resize(strlen / 4 * 3 + 1 + 1);
-
- size_t len = 0;
- ERR_FAIL_COND_V(CryptoCore::b64_decode(buf.ptrw(), buf.size(), &len, (unsigned char *)substr.get_data(), strlen) != OK, Vector<uint8_t>());
-
- buf.resize(len);
-
- return buf;
-}
-
-Error EditorSceneImporterGLTF::_parse_buffers(GLTFState &state, const String &p_base_path) {
- if (!state.json.has("buffers")) {
- return OK;
- }
-
- const Array &buffers = state.json["buffers"];
- for (GLTFBufferIndex i = 0; i < buffers.size(); i++) {
- if (i == 0 && state.glb_data.size()) {
- state.buffers.push_back(state.glb_data);
-
- } else {
- const Dictionary &buffer = buffers[i];
- if (buffer.has("uri")) {
- Vector<uint8_t> buffer_data;
- String uri = buffer["uri"];
-
- if (uri.begins_with("data:")) { // Embedded data using base64.
- // Validate data MIME types and throw an error if it's one we don't know/support.
- if (!uri.begins_with("data:application/octet-stream;base64") &&
- !uri.begins_with("data:application/gltf-buffer;base64")) {
- ERR_PRINT("glTF: Got buffer with an unknown URI data type: " + uri);
- }
- buffer_data = _parse_base64_uri(uri);
- } else { // Relative path to an external image file.
- uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
- buffer_data = FileAccess::get_file_as_array(uri);
- ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri);
- }
-
- ERR_FAIL_COND_V(!buffer.has("byteLength"), ERR_PARSE_ERROR);
- int byteLength = buffer["byteLength"];
- ERR_FAIL_COND_V(byteLength < buffer_data.size(), ERR_PARSE_ERROR);
- state.buffers.push_back(buffer_data);
- }
- }
- }
-
- print_verbose("glTF: Total buffers: " + itos(state.buffers.size()));
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_buffer_views(GLTFState &state) {
- ERR_FAIL_COND_V(!state.json.has("bufferViews"), ERR_FILE_CORRUPT);
- const Array &buffers = state.json["bufferViews"];
- for (GLTFBufferViewIndex i = 0; i < buffers.size(); i++) {
- const Dictionary &d = buffers[i];
-
- GLTFBufferView buffer_view;
-
- ERR_FAIL_COND_V(!d.has("buffer"), ERR_PARSE_ERROR);
- buffer_view.buffer = d["buffer"];
- ERR_FAIL_COND_V(!d.has("byteLength"), ERR_PARSE_ERROR);
- buffer_view.byte_length = d["byteLength"];
-
- if (d.has("byteOffset")) {
- buffer_view.byte_offset = d["byteOffset"];
- }
-
- if (d.has("byteStride")) {
- buffer_view.byte_stride = d["byteStride"];
- }
-
- if (d.has("target")) {
- const int target = d["target"];
- buffer_view.indices = target == ELEMENT_ARRAY_BUFFER;
- }
-
- state.buffer_views.push_back(buffer_view);
- }
-
- print_verbose("glTF: Total buffer views: " + itos(state.buffer_views.size()));
-
- return OK;
-}
-
-EditorSceneImporterGLTF::GLTFType EditorSceneImporterGLTF::_get_type_from_str(const String &p_string) {
- if (p_string == "SCALAR") {
- return TYPE_SCALAR;
- }
-
- if (p_string == "VEC2") {
- return TYPE_VEC2;
- }
- if (p_string == "VEC3") {
- return TYPE_VEC3;
- }
- if (p_string == "VEC4") {
- return TYPE_VEC4;
- }
-
- if (p_string == "MAT2") {
- return TYPE_MAT2;
- }
- if (p_string == "MAT3") {
- return TYPE_MAT3;
- }
- if (p_string == "MAT4") {
- return TYPE_MAT4;
- }
-
- ERR_FAIL_V(TYPE_SCALAR);
-}
-
-Error EditorSceneImporterGLTF::_parse_accessors(GLTFState &state) {
- ERR_FAIL_COND_V(!state.json.has("accessors"), ERR_FILE_CORRUPT);
- const Array &accessors = state.json["accessors"];
- for (GLTFAccessorIndex i = 0; i < accessors.size(); i++) {
- const Dictionary &d = accessors[i];
-
- GLTFAccessor accessor;
-
- ERR_FAIL_COND_V(!d.has("componentType"), ERR_PARSE_ERROR);
- accessor.component_type = d["componentType"];
- ERR_FAIL_COND_V(!d.has("count"), ERR_PARSE_ERROR);
- accessor.count = d["count"];
- ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR);
- accessor.type = _get_type_from_str(d["type"]);
-
- if (d.has("bufferView")) {
- accessor.buffer_view = d["bufferView"]; //optional because it may be sparse...
- }
-
- if (d.has("byteOffset")) {
- accessor.byte_offset = d["byteOffset"];
- }
-
- if (d.has("max")) {
- accessor.max = d["max"];
- }
-
- if (d.has("min")) {
- accessor.min = d["min"];
- }
-
- if (d.has("sparse")) {
- //eeh..
-
- const Dictionary &s = d["sparse"];
-
- ERR_FAIL_COND_V(!s.has("count"), ERR_PARSE_ERROR);
- accessor.sparse_count = s["count"];
- ERR_FAIL_COND_V(!s.has("indices"), ERR_PARSE_ERROR);
- const Dictionary &si = s["indices"];
-
- ERR_FAIL_COND_V(!si.has("bufferView"), ERR_PARSE_ERROR);
- accessor.sparse_indices_buffer_view = si["bufferView"];
- ERR_FAIL_COND_V(!si.has("componentType"), ERR_PARSE_ERROR);
- accessor.sparse_indices_component_type = si["componentType"];
-
- if (si.has("byteOffset")) {
- accessor.sparse_indices_byte_offset = si["byteOffset"];
- }
-
- ERR_FAIL_COND_V(!s.has("values"), ERR_PARSE_ERROR);
- const Dictionary &sv = s["values"];
-
- ERR_FAIL_COND_V(!sv.has("bufferView"), ERR_PARSE_ERROR);
- accessor.sparse_values_buffer_view = sv["bufferView"];
- if (sv.has("byteOffset")) {
- accessor.sparse_values_byte_offset = sv["byteOffset"];
- }
- }
-
- state.accessors.push_back(accessor);
- }
-
- print_verbose("glTF: Total accessors: " + itos(state.accessors.size()));
-
- return OK;
-}
-
-String EditorSceneImporterGLTF::_get_component_type_name(const uint32_t p_component) {
- switch (p_component) {
- case COMPONENT_TYPE_BYTE:
- return "Byte";
- case COMPONENT_TYPE_UNSIGNED_BYTE:
- return "UByte";
- case COMPONENT_TYPE_SHORT:
- return "Short";
- case COMPONENT_TYPE_UNSIGNED_SHORT:
- return "UShort";
- case COMPONENT_TYPE_INT:
- return "Int";
- case COMPONENT_TYPE_FLOAT:
- return "Float";
- }
-
- return "<Error>";
-}
-
-String EditorSceneImporterGLTF::_get_type_name(const GLTFType p_component) {
- static const char *names[] = {
- "float",
- "vec2",
- "vec3",
- "vec4",
- "mat2",
- "mat3",
- "mat4"
- };
-
- return names[p_component];
-}
-
-Error EditorSceneImporterGLTF::_decode_buffer_view(GLTFState &state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex) {
- const GLTFBufferView &bv = state.buffer_views[p_buffer_view];
-
- int stride = bv.byte_stride ? bv.byte_stride : element_size;
- if (for_vertex && stride % 4) {
- stride += 4 - (stride % 4); //according to spec must be multiple of 4
- }
-
- ERR_FAIL_INDEX_V(bv.buffer, state.buffers.size(), ERR_PARSE_ERROR);
-
- const uint32_t offset = bv.byte_offset + byte_offset;
- Vector<uint8_t> buffer = state.buffers[bv.buffer]; //copy on write, so no performance hit
- const uint8_t *bufptr = buffer.ptr();
-
- //use to debug
- print_verbose("glTF: type " + _get_type_name(type) + " component type: " + _get_component_type_name(component_type) + " stride: " + itos(stride) + " amount " + itos(count));
- print_verbose("glTF: accessor offset" + itos(byte_offset) + " view offset: " + itos(bv.byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv.byte_length));
-
- const int buffer_end = (stride * (count - 1)) + element_size;
- ERR_FAIL_COND_V(buffer_end > bv.byte_length, ERR_PARSE_ERROR);
-
- ERR_FAIL_COND_V((int)(offset + buffer_end) > buffer.size(), ERR_PARSE_ERROR);
-
- //fill everything as doubles
-
- for (int i = 0; i < count; i++) {
- const uint8_t *src = &bufptr[offset + i * stride];
-
- for (int j = 0; j < component_count; j++) {
- if (skip_every && j > 0 && (j % skip_every) == 0) {
- src += skip_bytes;
- }
-
- double d = 0;
-
- switch (component_type) {
- case COMPONENT_TYPE_BYTE: {
- int8_t b = int8_t(*src);
- if (normalized) {
- d = (double(b) / 128.0);
- } else {
- d = double(b);
- }
- } break;
- case COMPONENT_TYPE_UNSIGNED_BYTE: {
- uint8_t b = *src;
- if (normalized) {
- d = (double(b) / 255.0);
- } else {
- d = double(b);
- }
- } break;
- case COMPONENT_TYPE_SHORT: {
- int16_t s = *(int16_t *)src;
- if (normalized) {
- d = (double(s) / 32768.0);
- } else {
- d = double(s);
- }
- } break;
- case COMPONENT_TYPE_UNSIGNED_SHORT: {
- uint16_t s = *(uint16_t *)src;
- if (normalized) {
- d = (double(s) / 65535.0);
- } else {
- d = double(s);
- }
-
- } break;
- case COMPONENT_TYPE_INT: {
- d = *(int *)src;
- } break;
- case COMPONENT_TYPE_FLOAT: {
- d = *(float *)src;
- } break;
- }
-
- *dst++ = d;
- src += component_size;
- }
- }
-
- return OK;
-}
-
-int EditorSceneImporterGLTF::_get_component_type_size(const int component_type) {
- switch (component_type) {
- case COMPONENT_TYPE_BYTE:
- return 1;
- break;
- case COMPONENT_TYPE_UNSIGNED_BYTE:
- return 1;
- break;
- case COMPONENT_TYPE_SHORT:
- return 2;
- break;
- case COMPONENT_TYPE_UNSIGNED_SHORT:
- return 2;
- break;
- case COMPONENT_TYPE_INT:
- return 4;
- break;
- case COMPONENT_TYPE_FLOAT:
- return 4;
- break;
- default: {
- ERR_FAIL_V(0);
- }
- }
- return 0;
-}
-
-Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- //spec, for reference:
- //https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
-
- ERR_FAIL_INDEX_V(p_accessor, state.accessors.size(), Vector<double>());
-
- const GLTFAccessor &a = state.accessors[p_accessor];
-
- const int component_count_for_type[7] = {
- 1, 2, 3, 4, 4, 9, 16
- };
-
- const int component_count = component_count_for_type[a.type];
- const int component_size = _get_component_type_size(a.component_type);
- ERR_FAIL_COND_V(component_size == 0, Vector<double>());
- int element_size = component_count * component_size;
-
- int skip_every = 0;
- int skip_bytes = 0;
- //special case of alignments, as described in spec
- switch (a.component_type) {
- case COMPONENT_TYPE_BYTE:
- case COMPONENT_TYPE_UNSIGNED_BYTE: {
- if (a.type == TYPE_MAT2) {
- skip_every = 2;
- skip_bytes = 2;
- element_size = 8; //override for this case
- }
- if (a.type == TYPE_MAT3) {
- skip_every = 3;
- skip_bytes = 1;
- element_size = 12; //override for this case
- }
-
- } break;
- case COMPONENT_TYPE_SHORT:
- case COMPONENT_TYPE_UNSIGNED_SHORT: {
- if (a.type == TYPE_MAT3) {
- skip_every = 6;
- skip_bytes = 4;
- element_size = 16; //override for this case
- }
- } break;
- default: {
- }
- }
-
- Vector<double> dst_buffer;
- dst_buffer.resize(component_count * a.count);
- double *dst = dst_buffer.ptrw();
-
- if (a.buffer_view >= 0) {
- ERR_FAIL_INDEX_V(a.buffer_view, state.buffer_views.size(), Vector<double>());
-
- const Error err = _decode_buffer_view(state, dst, a.buffer_view, skip_every, skip_bytes, element_size, a.count, a.type, component_count, a.component_type, component_size, a.normalized, a.byte_offset, p_for_vertex);
- if (err != OK) {
- return Vector<double>();
- }
-
- } else {
- //fill with zeros, as bufferview is not defined.
- for (int i = 0; i < (a.count * component_count); i++) {
- dst_buffer.write[i] = 0;
- }
- }
-
- if (a.sparse_count > 0) {
- // I could not find any file using this, so this code is so far untested
- Vector<double> indices;
- indices.resize(a.sparse_count);
- const int indices_component_size = _get_component_type_size(a.sparse_indices_component_type);
-
- Error err = _decode_buffer_view(state, indices.ptrw(), a.sparse_indices_buffer_view, 0, 0, indices_component_size, a.sparse_count, TYPE_SCALAR, 1, a.sparse_indices_component_type, indices_component_size, false, a.sparse_indices_byte_offset, false);
- if (err != OK) {
- return Vector<double>();
- }
-
- Vector<double> data;
- data.resize(component_count * a.sparse_count);
- err = _decode_buffer_view(state, data.ptrw(), a.sparse_values_buffer_view, skip_every, skip_bytes, element_size, a.sparse_count, a.type, component_count, a.component_type, component_size, a.normalized, a.sparse_values_byte_offset, p_for_vertex);
- if (err != OK) {
- return Vector<double>();
- }
-
- for (int i = 0; i < indices.size(); i++) {
- const int write_offset = int(indices[i]) * component_count;
-
- for (int j = 0; j < component_count; j++) {
- dst[write_offset + j] = data[i * component_count + j];
- }
- }
- }
-
- return dst_buffer;
-}
-
-Vector<int> EditorSceneImporterGLTF::_decode_accessor_as_ints(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<int> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size();
- ret.resize(ret_size);
- {
- int *w = ret.ptrw();
- for (int i = 0; i < ret_size; i++) {
- w[i] = int(attribs_ptr[i]);
- }
- }
- return ret;
-}
-
-Vector<float> EditorSceneImporterGLTF::_decode_accessor_as_floats(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<float> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size();
- ret.resize(ret_size);
- {
- float *w = ret.ptrw();
- for (int i = 0; i < ret_size; i++) {
- w[i] = float(attribs_ptr[i]);
- }
- }
- return ret;
-}
-
-Vector<Vector2> EditorSceneImporterGLTF::_decode_accessor_as_vec2(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Vector2> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- ERR_FAIL_COND_V(attribs.size() % 2 != 0, ret);
- const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / 2;
- ret.resize(ret_size);
- {
- Vector2 *w = ret.ptrw();
- for (int i = 0; i < ret_size; i++) {
- w[i] = Vector2(attribs_ptr[i * 2 + 0], attribs_ptr[i * 2 + 1]);
- }
- }
- return ret;
-}
-
-Vector<Vector3> EditorSceneImporterGLTF::_decode_accessor_as_vec3(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Vector3> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- ERR_FAIL_COND_V(attribs.size() % 3 != 0, ret);
- const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / 3;
- ret.resize(ret_size);
- {
- Vector3 *w = ret.ptrw();
- for (int i = 0; i < ret_size; i++) {
- w[i] = Vector3(attribs_ptr[i * 3 + 0], attribs_ptr[i * 3 + 1], attribs_ptr[i * 3 + 2]);
- }
- }
- return ret;
-}
-
-Vector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Color> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- const int type = state.accessors[p_accessor].type;
- ERR_FAIL_COND_V(!(type == TYPE_VEC3 || type == TYPE_VEC4), ret);
- int vec_len = 3;
- if (type == TYPE_VEC4) {
- vec_len = 4;
- }
-
- ERR_FAIL_COND_V(attribs.size() % vec_len != 0, ret);
- const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / vec_len;
- ret.resize(ret_size);
- {
- Color *w = ret.ptrw();
- for (int i = 0; i < ret_size; i++) {
- w[i] = Color(attribs_ptr[i * vec_len + 0], attribs_ptr[i * vec_len + 1], attribs_ptr[i * vec_len + 2], vec_len == 4 ? attribs_ptr[i * 4 + 3] : 1.0);
- }
- }
- return ret;
-}
-
-Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Quat> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret);
- const double *attribs_ptr = attribs.ptr();
- const int ret_size = attribs.size() / 4;
- ret.resize(ret_size);
- {
- for (int i = 0; i < ret_size; i++) {
- ret.write[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]).normalized();
- }
- }
- return ret;
-}
-
-Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Transform2D> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret);
- ret.resize(attribs.size() / 4);
- for (int i = 0; i < ret.size(); i++) {
- ret.write[i][0] = Vector2(attribs[i * 4 + 0], attribs[i * 4 + 1]);
- ret.write[i][1] = Vector2(attribs[i * 4 + 2], attribs[i * 4 + 3]);
- }
- return ret;
-}
-
-Vector<Basis> EditorSceneImporterGLTF::_decode_accessor_as_basis(GLTFState &state, const GLTFAccessorIndex p_accessor, bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Basis> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- ERR_FAIL_COND_V(attribs.size() % 9 != 0, ret);
- ret.resize(attribs.size() / 9);
- for (int i = 0; i < ret.size(); i++) {
- ret.write[i].set_axis(0, Vector3(attribs[i * 9 + 0], attribs[i * 9 + 1], attribs[i * 9 + 2]));
- ret.write[i].set_axis(1, Vector3(attribs[i * 9 + 3], attribs[i * 9 + 4], attribs[i * 9 + 5]));
- ret.write[i].set_axis(2, Vector3(attribs[i * 9 + 6], attribs[i * 9 + 7], attribs[i * 9 + 8]));
- }
- return ret;
-}
-
-Vector<Transform> EditorSceneImporterGLTF::_decode_accessor_as_xform(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
- Vector<Transform> ret;
-
- if (attribs.size() == 0) {
- return ret;
- }
-
- ERR_FAIL_COND_V(attribs.size() % 16 != 0, ret);
- ret.resize(attribs.size() / 16);
- for (int i = 0; i < ret.size(); i++) {
- ret.write[i].basis.set_axis(0, Vector3(attribs[i * 16 + 0], attribs[i * 16 + 1], attribs[i * 16 + 2]));
- ret.write[i].basis.set_axis(1, Vector3(attribs[i * 16 + 4], attribs[i * 16 + 5], attribs[i * 16 + 6]));
- ret.write[i].basis.set_axis(2, Vector3(attribs[i * 16 + 8], attribs[i * 16 + 9], attribs[i * 16 + 10]));
- ret.write[i].set_origin(Vector3(attribs[i * 16 + 12], attribs[i * 16 + 13], attribs[i * 16 + 14]));
- }
- return ret;
-}
-
-Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
- if (!state.json.has("meshes")) {
- return OK;
- }
-
- Array meshes = state.json["meshes"];
- for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {
- print_verbose("glTF: Parsing mesh: " + itos(i));
- Dictionary d = meshes[i];
-
- GLTFMesh mesh;
- mesh.mesh.instance();
- bool has_vertex_color = false;
-
- ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR);
-
- Array primitives = d["primitives"];
- const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary();
-
- for (int j = 0; j < primitives.size(); j++) {
- Dictionary p = primitives[j];
-
- Array array;
- array.resize(Mesh::ARRAY_MAX);
-
- ERR_FAIL_COND_V(!p.has("attributes"), ERR_PARSE_ERROR);
-
- Dictionary a = p["attributes"];
-
- Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
- if (p.has("mode")) {
- const int mode = p["mode"];
- ERR_FAIL_INDEX_V(mode, 7, ERR_FILE_CORRUPT);
- static const Mesh::PrimitiveType primitives2[7] = {
- Mesh::PRIMITIVE_POINTS,
- Mesh::PRIMITIVE_LINES,
- Mesh::PRIMITIVE_LINES, //loop not supported, should ce converted
- Mesh::PRIMITIVE_LINES,
- Mesh::PRIMITIVE_TRIANGLES,
- Mesh::PRIMITIVE_TRIANGLE_STRIP,
- Mesh::PRIMITIVE_TRIANGLES, //fan not supported, should be converted
-#ifndef _MSC_VER
-#warning line loop and triangle fan are not supported and need to be converted to lines and triangles
-#endif
-
- };
-
- primitive = primitives2[mode];
- }
-
- ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR);
- if (a.has("POSITION")) {
- array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true);
- }
- if (a.has("NORMAL")) {
- array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
- }
- if (a.has("TANGENT")) {
- array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(state, a["TANGENT"], true);
- }
- if (a.has("TEXCOORD_0")) {
- array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(state, a["TEXCOORD_0"], true);
- }
- if (a.has("TEXCOORD_1")) {
- array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(state, a["TEXCOORD_1"], true);
- }
- if (a.has("COLOR_0")) {
- array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true);
- has_vertex_color = true;
- }
- if (a.has("JOINTS_0")) {
- array[Mesh::ARRAY_BONES] = _decode_accessor_as_ints(state, a["JOINTS_0"], true);
- }
- if (a.has("WEIGHTS_0")) {
- Vector<float> weights = _decode_accessor_as_floats(state, a["WEIGHTS_0"], true);
- { //gltf does not seem to normalize the weights for some reason..
- int wc = weights.size();
- float *w = weights.ptrw();
-
- for (int k = 0; k < wc; k += 4) {
- float total = 0.0;
- total += w[k + 0];
- total += w[k + 1];
- total += w[k + 2];
- total += w[k + 3];
- if (total > 0.0) {
- w[k + 0] /= total;
- w[k + 1] /= total;
- w[k + 2] /= total;
- w[k + 3] /= total;
- }
- }
- }
- array[Mesh::ARRAY_WEIGHTS] = weights;
- }
-
- if (p.has("indices")) {
- Vector<int> indices = _decode_accessor_as_ints(state, p["indices"], false);
-
- if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
- //swap around indices, convert ccw to cw for front face
-
- const int is = indices.size();
- int *w = indices.ptrw();
- for (int k = 0; k < is; k += 3) {
- SWAP(w[k + 1], w[k + 2]);
- }
- }
- array[Mesh::ARRAY_INDEX] = indices;
-
- } else if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
- //generate indices because they need to be swapped for CW/CCW
- const Vector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
- ERR_FAIL_COND_V(vertices.size() == 0, ERR_PARSE_ERROR);
- Vector<int> indices;
- const int vs = vertices.size();
- indices.resize(vs);
- {
- int *w = indices.ptrw();
- for (int k = 0; k < vs; k += 3) {
- w[k] = k;
- w[k + 1] = k + 2;
- w[k + 2] = k + 1;
- }
- }
- array[Mesh::ARRAY_INDEX] = indices;
- }
-
- bool generate_tangents = (primitive == Mesh::PRIMITIVE_TRIANGLES && !a.has("TANGENT") && a.has("TEXCOORD_0") && a.has("NORMAL"));
-
- if (generate_tangents) {
- //must generate mikktspace tangents.. ergh..
- Ref<SurfaceTool> st;
- st.instance();
- st->create_from_triangle_arrays(array);
- st->generate_tangents();
- array = st->commit_to_arrays();
- }
-
- Array morphs;
- //blend shapes
- if (p.has("targets")) {
- print_verbose("glTF: Mesh has targets");
- const Array &targets = p["targets"];
-
- //ideally BLEND_SHAPE_MODE_RELATIVE since gltf2 stores in displacement
- //but it could require a larger refactor?
- mesh.mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
-
- if (j == 0) {
- const Array &target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array();
- for (int k = 0; k < targets.size(); k++) {
- const String name = k < target_names.size() ? (String)target_names[k] : String("morph_") + itos(k);
- mesh.mesh->add_blend_shape(name);
- }
- }
-
- for (int k = 0; k < targets.size(); k++) {
- const Dictionary &t = targets[k];
-
- Array array_copy;
- array_copy.resize(Mesh::ARRAY_MAX);
-
- for (int l = 0; l < Mesh::ARRAY_MAX; l++) {
- array_copy[l] = array[l];
- }
-
- array_copy[Mesh::ARRAY_INDEX] = Variant();
-
- if (t.has("POSITION")) {
- Vector<Vector3> varr = _decode_accessor_as_vec3(state, t["POSITION"], true);
- const Vector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
- const int size = src_varr.size();
- ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
- {
- const int max_idx = varr.size();
- varr.resize(size);
-
- Vector3 *w_varr = varr.ptrw();
- const Vector3 *r_varr = varr.ptr();
- const Vector3 *r_src_varr = src_varr.ptr();
- for (int l = 0; l < size; l++) {
- if (l < max_idx) {
- w_varr[l] = r_varr[l] + r_src_varr[l];
- } else {
- w_varr[l] = r_src_varr[l];
- }
- }
- }
- array_copy[Mesh::ARRAY_VERTEX] = varr;
- }
- if (t.has("NORMAL")) {
- Vector<Vector3> narr = _decode_accessor_as_vec3(state, t["NORMAL"], true);
- const Vector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
- int size = src_narr.size();
- ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
- {
- int max_idx = narr.size();
- narr.resize(size);
-
- Vector3 *w_narr = narr.ptrw();
- const Vector3 *r_narr = narr.ptr();
- const Vector3 *r_src_narr = src_narr.ptr();
- for (int l = 0; l < size; l++) {
- if (l < max_idx) {
- w_narr[l] = r_narr[l] + r_src_narr[l];
- } else {
- w_narr[l] = r_src_narr[l];
- }
- }
- }
- array_copy[Mesh::ARRAY_NORMAL] = narr;
- }
- if (t.has("TANGENT")) {
- const Vector<Vector3> tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true);
- const Vector<float> src_tangents = array[Mesh::ARRAY_TANGENT];
- ERR_FAIL_COND_V(src_tangents.size() == 0, ERR_PARSE_ERROR);
-
- Vector<float> tangents_v4;
-
- {
- int max_idx = tangents_v3.size();
-
- int size4 = src_tangents.size();
- tangents_v4.resize(size4);
- float *w4 = tangents_v4.ptrw();
-
- const Vector3 *r3 = tangents_v3.ptr();
- const float *r4 = src_tangents.ptr();
-
- for (int l = 0; l < size4 / 4; l++) {
- if (l < max_idx) {
- w4[l * 4 + 0] = r3[l].x + r4[l * 4 + 0];
- w4[l * 4 + 1] = r3[l].y + r4[l * 4 + 1];
- w4[l * 4 + 2] = r3[l].z + r4[l * 4 + 2];
- } else {
- w4[l * 4 + 0] = r4[l * 4 + 0];
- w4[l * 4 + 1] = r4[l * 4 + 1];
- w4[l * 4 + 2] = r4[l * 4 + 2];
- }
- w4[l * 4 + 3] = r4[l * 4 + 3]; //copy flip value
- }
- }
-
- array_copy[Mesh::ARRAY_TANGENT] = tangents_v4;
- }
-
- if (generate_tangents) {
- Ref<SurfaceTool> st;
- st.instance();
- st->create_from_triangle_arrays(array_copy);
- st->deindex();
- st->generate_tangents();
- array_copy = st->commit_to_arrays();
- }
-
- morphs.push_back(array_copy);
- }
- }
-
- //just add it
-
- Ref<Material> mat;
- if (p.has("material")) {
- const int material = p["material"];
- ERR_FAIL_INDEX_V(material, state.materials.size(), ERR_FILE_CORRUPT);
- Ref<StandardMaterial3D> mat3d = state.materials[material];
- if (has_vertex_color) {
- mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- }
- mat = mat3d;
-
- } else if (has_vertex_color) {
- Ref<StandardMaterial3D> mat3d;
- mat3d.instance();
- mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- mat = mat3d;
- }
-
- mesh.mesh->add_surface(primitive, array, morphs, Dictionary(), mat);
- }
-
- mesh.blend_weights.resize(mesh.mesh->get_blend_shape_count());
- for (int32_t weight_i = 0; weight_i < mesh.blend_weights.size(); weight_i++) {
- mesh.blend_weights.write[weight_i] = 0.0f;
- }
-
- if (d.has("weights")) {
- const Array &weights = d["weights"];
- ERR_FAIL_COND_V(mesh.blend_weights.size() != weights.size(), ERR_PARSE_ERROR);
- for (int j = 0; j < weights.size(); j++) {
- mesh.blend_weights.write[j] = weights[j];
- }
- }
-
- state.meshes.push_back(mesh);
- }
-
- print_verbose("glTF: Total meshes: " + itos(state.meshes.size()));
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_base_path) {
- if (!state.json.has("images")) {
- return OK;
- }
-
- // Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images
-
- const Array &images = state.json["images"];
- for (int i = 0; i < images.size(); i++) {
- const Dictionary &d = images[i];
-
- // glTF 2.0 supports PNG and JPEG types, which can be specified as (from spec):
- // "- a URI to an external file in one of the supported images formats, or
- // - a URI with embedded base64-encoded data, or
- // - a reference to a bufferView; in that case mimeType must be defined."
- // Since mimeType is optional for external files and base64 data, we'll have to
- // fall back on letting Godot parse the data to figure out if it's PNG or JPEG.
-
- // We'll assume that we use either URI or bufferView, so let's warn the user
- // if their image somehow uses both. And fail if it has neither.
- ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specific an 'uri' or 'bufferView'.");
- if (d.has("uri") && d.has("bufferView")) {
- WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'bufferView' will take precedence.");
- }
-
- String mimetype;
- if (d.has("mimeType")) { // Should be "image/png" or "image/jpeg".
- mimetype = d["mimeType"];
- }
-
- Vector<uint8_t> data;
- const uint8_t *data_ptr = nullptr;
- int data_size = 0;
-
- if (d.has("uri")) {
- // Handles the first two bullet points from the spec (embedded data, or external file).
- String uri = d["uri"];
-
- if (uri.begins_with("data:")) { // Embedded data using base64.
- // Validate data MIME types and throw a warning if it's one we don't know/support.
- if (!uri.begins_with("data:application/octet-stream;base64") &&
- !uri.begins_with("data:application/gltf-buffer;base64") &&
- !uri.begins_with("data:image/png;base64") &&
- !uri.begins_with("data:image/jpeg;base64")) {
- WARN_PRINT(vformat("glTF: Image index '%d' uses an unsupported URI data type: %s. Skipping it.", i, uri));
- state.images.push_back(Ref<Texture2D>()); // Placeholder to keep count.
- continue;
- }
- data = _parse_base64_uri(uri);
- data_ptr = data.ptr();
- data_size = data.size();
- // mimeType is optional, but if we have it defined in the URI, let's use it.
- if (mimetype.empty()) {
- if (uri.begins_with("data:image/png;base64")) {
- mimetype = "image/png";
- } else if (uri.begins_with("data:image/jpeg;base64")) {
- mimetype = "image/jpeg";
- }
- }
- } else { // Relative path to an external image file.
- uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
- // The spec says that if mimeType is defined, we should enforce it.
- // So we should only rely on ResourceLoader::load if mimeType is not defined,
- // otherwise we should use the same logic as for buffers.
- if (mimetype == "image/png" || mimetype == "image/jpeg") {
- // Load data buffer and rely on PNG and JPEG-specific logic below to load the image.
- // This makes it possible to load a file with a wrong extension but correct MIME type,
- // e.g. "foo.jpg" containing PNG data and with MIME type "image/png". ResourceLoader would fail.
- data = FileAccess::get_file_as_array(uri);
- ERR_FAIL_COND_V_MSG(data.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load image file as an array: " + uri);
- data_ptr = data.ptr();
- data_size = data.size();
- } else {
- // Good old ResourceLoader will rely on file extension.
- Ref<Texture2D> texture = ResourceLoader::load(uri);
- state.images.push_back(texture);
- continue;
- }
- }
- } else if (d.has("bufferView")) {
- // Handles the third bullet point from the spec (bufferView).
- ERR_FAIL_COND_V_MSG(mimetype.empty(), ERR_FILE_CORRUPT,
- vformat("glTF: Image index '%d' specifies 'bufferView' but no 'mimeType', which is invalid.", i));
-
- const GLTFBufferViewIndex bvi = d["bufferView"];
-
- ERR_FAIL_INDEX_V(bvi, state.buffer_views.size(), ERR_PARAMETER_RANGE_ERROR);
-
- const GLTFBufferView &bv = state.buffer_views[bvi];
-
- const GLTFBufferIndex bi = bv.buffer;
- ERR_FAIL_INDEX_V(bi, state.buffers.size(), ERR_PARAMETER_RANGE_ERROR);
-
- ERR_FAIL_COND_V(bv.byte_offset + bv.byte_length > state.buffers[bi].size(), ERR_FILE_CORRUPT);
-
- data_ptr = &state.buffers[bi][bv.byte_offset];
- data_size = bv.byte_length;
- }
-
- Ref<Image> img;
-
- if (mimetype == "image/png") { // Load buffer as PNG.
- ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE);
- img = Image::_png_mem_loader_func(data_ptr, data_size);
- } else if (mimetype == "image/jpeg") { // Loader buffer as JPEG.
- ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE);
- img = Image::_jpg_mem_loader_func(data_ptr, data_size);
- } else {
- // We can land here if we got an URI with base64-encoded data with application/* MIME type,
- // and the optional mimeType property was not defined to tell us how to handle this data (or was invalid).
- // So let's try PNG first, then JPEG.
- ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE);
- img = Image::_png_mem_loader_func(data_ptr, data_size);
- if (img.is_null()) {
- ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE);
- img = Image::_jpg_mem_loader_func(data_ptr, data_size);
- }
- }
-
- ERR_FAIL_COND_V_MSG(img.is_null(), ERR_FILE_CORRUPT,
- vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype));
-
- Ref<ImageTexture> t;
- t.instance();
- t->create_from_image(img);
-
- state.images.push_back(t);
- }
-
- print_verbose("glTF: Total images: " + itos(state.images.size()));
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_textures(GLTFState &state) {
- if (!state.json.has("textures")) {
- return OK;
- }
-
- const Array &textures = state.json["textures"];
- for (GLTFTextureIndex i = 0; i < textures.size(); i++) {
- const Dictionary &d = textures[i];
-
- ERR_FAIL_COND_V(!d.has("source"), ERR_PARSE_ERROR);
-
- GLTFTexture t;
- t.src_image = d["source"];
- state.textures.push_back(t);
- }
-
- return OK;
-}
-
-Ref<Texture2D> EditorSceneImporterGLTF::_get_texture(GLTFState &state, const GLTFTextureIndex p_texture) {
- ERR_FAIL_INDEX_V(p_texture, state.textures.size(), Ref<Texture2D>());
- const GLTFImageIndex image = state.textures[p_texture].src_image;
-
- ERR_FAIL_INDEX_V(image, state.images.size(), Ref<Texture2D>());
-
- return state.images[image];
-}
-
-Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
- if (!state.json.has("materials")) {
- return OK;
- }
-
- const Array &materials = state.json["materials"];
- for (GLTFMaterialIndex i = 0; i < materials.size(); i++) {
- const Dictionary &d = materials[i];
-
- Ref<StandardMaterial3D> material;
- material.instance();
- if (d.has("name")) {
- material->set_name(d["name"]);
- }
- //don't do this here only if vertex color exists
- //material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
-
- if (d.has("pbrMetallicRoughness")) {
- const Dictionary &mr = d["pbrMetallicRoughness"];
- if (mr.has("baseColorFactor")) {
- const Array &arr = mr["baseColorFactor"];
- ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
-
- material->set_albedo(c);
- }
-
- if (mr.has("baseColorTexture")) {
- const Dictionary &bct = mr["baseColorTexture"];
- if (bct.has("index")) {
- material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, _get_texture(state, bct["index"]));
- }
- if (!mr.has("baseColorFactor")) {
- material->set_albedo(Color(1, 1, 1));
- }
- }
-
- if (mr.has("metallicFactor")) {
- material->set_metallic(mr["metallicFactor"]);
- } else {
- material->set_metallic(1.0);
- }
-
- if (mr.has("roughnessFactor")) {
- material->set_roughness(mr["roughnessFactor"]);
- } else {
- material->set_roughness(1.0);
- }
-
- if (mr.has("metallicRoughnessTexture")) {
- const Dictionary &bct = mr["metallicRoughnessTexture"];
- if (bct.has("index")) {
- const Ref<Texture2D> t = _get_texture(state, bct["index"]);
- material->set_texture(StandardMaterial3D::TEXTURE_METALLIC, t);
- material->set_metallic_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_BLUE);
- material->set_texture(StandardMaterial3D::TEXTURE_ROUGHNESS, t);
- material->set_roughness_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_GREEN);
- if (!mr.has("metallicFactor")) {
- material->set_metallic(1);
- }
- if (!mr.has("roughnessFactor")) {
- material->set_roughness(1);
- }
- }
- }
- }
-
- if (d.has("normalTexture")) {
- const Dictionary &bct = d["normalTexture"];
- if (bct.has("index")) {
- material->set_texture(StandardMaterial3D::TEXTURE_NORMAL, _get_texture(state, bct["index"]));
- material->set_feature(StandardMaterial3D::FEATURE_NORMAL_MAPPING, true);
- }
- if (bct.has("scale")) {
- material->set_normal_scale(bct["scale"]);
- }
- }
- if (d.has("occlusionTexture")) {
- const Dictionary &bct = d["occlusionTexture"];
- if (bct.has("index")) {
- material->set_texture(StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"]));
- material->set_ao_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_RED);
- material->set_feature(StandardMaterial3D::FEATURE_AMBIENT_OCCLUSION, true);
- }
- }
-
- if (d.has("emissiveFactor")) {
- const Array &arr = d["emissiveFactor"];
- ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
- material->set_feature(StandardMaterial3D::FEATURE_EMISSION, true);
-
- material->set_emission(c);
- }
-
- if (d.has("emissiveTexture")) {
- const Dictionary &bct = d["emissiveTexture"];
- if (bct.has("index")) {
- material->set_texture(StandardMaterial3D::TEXTURE_EMISSION, _get_texture(state, bct["index"]));
- material->set_feature(StandardMaterial3D::FEATURE_EMISSION, true);
- material->set_emission(Color(0, 0, 0));
- }
- }
-
- if (d.has("doubleSided")) {
- const bool ds = d["doubleSided"];
- if (ds) {
- material->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
- }
- }
-
- if (d.has("alphaMode")) {
- const String &am = d["alphaMode"];
- if (am == "BLEND") {
- material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
- } else if (am == "MASK") {
- material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_SCISSOR);
- if (d.has("alphaCutoff")) {
- material->set_alpha_scissor_threshold(d["alphaCutoff"]);
- } else {
- material->set_alpha_scissor_threshold(0.5f);
- }
- }
- }
-
- state.materials.push_back(material);
- }
-
- print_verbose("glTF: Total materials: " + itos(state.materials.size()));
-
- return OK;
-}
-
-EditorSceneImporterGLTF::GLTFNodeIndex EditorSceneImporterGLTF::_find_highest_node(GLTFState &state, const Vector<GLTFNodeIndex> &subset) {
- int highest = -1;
- GLTFNodeIndex best_node = -1;
-
- for (int i = 0; i < subset.size(); ++i) {
- const GLTFNodeIndex node_i = subset[i];
- const GLTFNode *node = state.nodes[node_i];
-
- if (highest == -1 || node->height < highest) {
- highest = node->height;
- best_node = node_i;
- }
- }
-
- return best_node;
-}
-
-bool EditorSceneImporterGLTF::_capture_nodes_in_skin(GLTFState &state, GLTFSkin &skin, const GLTFNodeIndex node_index) {
- bool found_joint = false;
-
- for (int i = 0; i < state.nodes[node_index]->children.size(); ++i) {
- found_joint |= _capture_nodes_in_skin(state, skin, state.nodes[node_index]->children[i]);
- }
-
- if (found_joint) {
- // Mark it if we happen to find another skins joint...
- if (state.nodes[node_index]->joint && skin.joints.find(node_index) < 0) {
- skin.joints.push_back(node_index);
- } else if (skin.non_joints.find(node_index) < 0) {
- skin.non_joints.push_back(node_index);
- }
- }
-
- if (skin.joints.find(node_index) > 0) {
- return true;
- }
-
- return false;
-}
-
-void EditorSceneImporterGLTF::_capture_nodes_for_multirooted_skin(GLTFState &state, GLTFSkin &skin) {
- DisjointSet<GLTFNodeIndex> disjoint_set;
-
- for (int i = 0; i < skin.joints.size(); ++i) {
- const GLTFNodeIndex node_index = skin.joints[i];
- const GLTFNodeIndex parent = state.nodes[node_index]->parent;
- disjoint_set.insert(node_index);
-
- if (skin.joints.find(parent) >= 0) {
- disjoint_set.create_union(parent, node_index);
- }
- }
-
- Vector<GLTFNodeIndex> roots;
- disjoint_set.get_representatives(roots);
-
- if (roots.size() <= 1) {
- return;
- }
-
- int maxHeight = -1;
-
- // Determine the max height rooted tree
- for (int i = 0; i < roots.size(); ++i) {
- const GLTFNodeIndex root = roots[i];
-
- if (maxHeight == -1 || state.nodes[root]->height < maxHeight) {
- maxHeight = state.nodes[root]->height;
- }
- }
-
- // Go up the tree till all of the multiple roots of the skin are at the same hierarchy level.
- // This sucks, but 99% of all game engines (not just Godot) would have this same issue.
- for (int i = 0; i < roots.size(); ++i) {
- GLTFNodeIndex current_node = roots[i];
- while (state.nodes[current_node]->height > maxHeight) {
- GLTFNodeIndex parent = state.nodes[current_node]->parent;
-
- if (state.nodes[parent]->joint && skin.joints.find(parent) < 0) {
- skin.joints.push_back(parent);
- } else if (skin.non_joints.find(parent) < 0) {
- skin.non_joints.push_back(parent);
- }
-
- current_node = parent;
- }
-
- // replace the roots
- roots.write[i] = current_node;
- }
-
- // Climb up the tree until they all have the same parent
- bool all_same;
-
- do {
- all_same = true;
- const GLTFNodeIndex first_parent = state.nodes[roots[0]]->parent;
-
- for (int i = 1; i < roots.size(); ++i) {
- all_same &= (first_parent == state.nodes[roots[i]]->parent);
- }
-
- if (!all_same) {
- for (int i = 0; i < roots.size(); ++i) {
- const GLTFNodeIndex current_node = roots[i];
- const GLTFNodeIndex parent = state.nodes[current_node]->parent;
-
- if (state.nodes[parent]->joint && skin.joints.find(parent) < 0) {
- skin.joints.push_back(parent);
- } else if (skin.non_joints.find(parent) < 0) {
- skin.non_joints.push_back(parent);
- }
-
- roots.write[i] = parent;
- }
- }
-
- } while (!all_same);
-}
-
-Error EditorSceneImporterGLTF::_expand_skin(GLTFState &state, GLTFSkin &skin) {
- _capture_nodes_for_multirooted_skin(state, skin);
-
- // Grab all nodes that lay in between skin joints/nodes
- DisjointSet<GLTFNodeIndex> disjoint_set;
-
- Vector<GLTFNodeIndex> all_skin_nodes;
- all_skin_nodes.append_array(skin.joints);
- all_skin_nodes.append_array(skin.non_joints);
-
- for (int i = 0; i < all_skin_nodes.size(); ++i) {
- const GLTFNodeIndex node_index = all_skin_nodes[i];
- const GLTFNodeIndex parent = state.nodes[node_index]->parent;
- disjoint_set.insert(node_index);
-
- if (all_skin_nodes.find(parent) >= 0) {
- disjoint_set.create_union(parent, node_index);
- }
- }
-
- Vector<GLTFNodeIndex> out_owners;
- disjoint_set.get_representatives(out_owners);
-
- Vector<GLTFNodeIndex> out_roots;
-
- for (int i = 0; i < out_owners.size(); ++i) {
- Vector<GLTFNodeIndex> set;
- disjoint_set.get_members(set, out_owners[i]);
-
- const GLTFNodeIndex root = _find_highest_node(state, set);
- ERR_FAIL_COND_V(root < 0, FAILED);
- out_roots.push_back(root);
- }
-
- out_roots.sort();
-
- for (int i = 0; i < out_roots.size(); ++i) {
- _capture_nodes_in_skin(state, skin, out_roots[i]);
- }
-
- skin.roots = out_roots;
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_verify_skin(GLTFState &state, GLTFSkin &skin) {
- // This may seem duplicated from expand_skins, but this is really a sanity check! (so it kinda is)
- // In case additional interpolating logic is added to the skins, this will help ensure that you
- // do not cause it to self implode into a fiery blaze
-
- // We are going to re-calculate the root nodes and compare them to the ones saved in the skin,
- // then ensure the multiple trees (if they exist) are on the same sublevel
-
- // Grab all nodes that lay in between skin joints/nodes
- DisjointSet<GLTFNodeIndex> disjoint_set;
-
- Vector<GLTFNodeIndex> all_skin_nodes;
- all_skin_nodes.append_array(skin.joints);
- all_skin_nodes.append_array(skin.non_joints);
-
- for (int i = 0; i < all_skin_nodes.size(); ++i) {
- const GLTFNodeIndex node_index = all_skin_nodes[i];
- const GLTFNodeIndex parent = state.nodes[node_index]->parent;
- disjoint_set.insert(node_index);
-
- if (all_skin_nodes.find(parent) >= 0) {
- disjoint_set.create_union(parent, node_index);
- }
- }
-
- Vector<GLTFNodeIndex> out_owners;
- disjoint_set.get_representatives(out_owners);
-
- Vector<GLTFNodeIndex> out_roots;
-
- for (int i = 0; i < out_owners.size(); ++i) {
- Vector<GLTFNodeIndex> set;
- disjoint_set.get_members(set, out_owners[i]);
-
- const GLTFNodeIndex root = _find_highest_node(state, set);
- ERR_FAIL_COND_V(root < 0, FAILED);
- out_roots.push_back(root);
- }
-
- out_roots.sort();
-
- ERR_FAIL_COND_V(out_roots.size() == 0, FAILED);
-
- // Make sure the roots are the exact same (they better be)
- ERR_FAIL_COND_V(out_roots.size() != skin.roots.size(), FAILED);
- for (int i = 0; i < out_roots.size(); ++i) {
- ERR_FAIL_COND_V(out_roots[i] != skin.roots[i], FAILED);
- }
-
- // Single rooted skin? Perfectly ok!
- if (out_roots.size() == 1) {
- return OK;
- }
-
- // Make sure all parents of a multi-rooted skin are the SAME
- const GLTFNodeIndex parent = state.nodes[out_roots[0]]->parent;
- for (int i = 1; i < out_roots.size(); ++i) {
- if (state.nodes[out_roots[i]]->parent != parent) {
- return FAILED;
- }
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_skins(GLTFState &state) {
- if (!state.json.has("skins")) {
- return OK;
- }
-
- const Array &skins = state.json["skins"];
-
- // Create the base skins, and mark nodes that are joints
- for (int i = 0; i < skins.size(); i++) {
- const Dictionary &d = skins[i];
-
- GLTFSkin skin;
-
- ERR_FAIL_COND_V(!d.has("joints"), ERR_PARSE_ERROR);
-
- const Array &joints = d["joints"];
-
- if (d.has("inverseBindMatrices")) {
- skin.inverse_binds = _decode_accessor_as_xform(state, d["inverseBindMatrices"], false);
- ERR_FAIL_COND_V(skin.inverse_binds.size() != joints.size(), ERR_PARSE_ERROR);
- }
-
- for (int j = 0; j < joints.size(); j++) {
- const GLTFNodeIndex node = joints[j];
- ERR_FAIL_INDEX_V(node, state.nodes.size(), ERR_PARSE_ERROR);
-
- skin.joints.push_back(node);
- skin.joints_original.push_back(node);
-
- state.nodes[node]->joint = true;
- }
-
- if (d.has("name")) {
- skin.name = d["name"];
- }
-
- if (d.has("skeleton")) {
- skin.skin_root = d["skeleton"];
- }
-
- state.skins.push_back(skin);
- }
-
- for (GLTFSkinIndex i = 0; i < state.skins.size(); ++i) {
- GLTFSkin &skin = state.skins.write[i];
-
- // Expand the skin to capture all the extra non-joints that lie in between the actual joints,
- // and expand the hierarchy to ensure multi-rooted trees lie on the same height level
- ERR_FAIL_COND_V(_expand_skin(state, skin), ERR_PARSE_ERROR);
- ERR_FAIL_COND_V(_verify_skin(state, skin), ERR_PARSE_ERROR);
- }
-
- print_verbose("glTF: Total skins: " + itos(state.skins.size()));
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_determine_skeletons(GLTFState &state) {
- // Using a disjoint set, we are going to potentially combine all skins that are actually branches
- // of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton.
- // This is another unclear issue caused by the current glTF specification.
-
- DisjointSet<GLTFNodeIndex> skeleton_sets;
-
- for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
- const GLTFSkin &skin = state.skins[skin_i];
-
- Vector<GLTFNodeIndex> all_skin_nodes;
- all_skin_nodes.append_array(skin.joints);
- all_skin_nodes.append_array(skin.non_joints);
-
- for (int i = 0; i < all_skin_nodes.size(); ++i) {
- const GLTFNodeIndex node_index = all_skin_nodes[i];
- const GLTFNodeIndex parent = state.nodes[node_index]->parent;
- skeleton_sets.insert(node_index);
-
- if (all_skin_nodes.find(parent) >= 0) {
- skeleton_sets.create_union(parent, node_index);
- }
- }
-
- // We are going to connect the separate skin subtrees in each skin together
- // so that the final roots are entire sets of valid skin trees
- for (int i = 1; i < skin.roots.size(); ++i) {
- skeleton_sets.create_union(skin.roots[0], skin.roots[i]);
- }
- }
-
- { // attempt to joint all touching subsets (siblings/parent are part of another skin)
- Vector<GLTFNodeIndex> groups_representatives;
- skeleton_sets.get_representatives(groups_representatives);
-
- Vector<GLTFNodeIndex> highest_group_members;
- Vector<Vector<GLTFNodeIndex>> groups;
- for (int i = 0; i < groups_representatives.size(); ++i) {
- Vector<GLTFNodeIndex> group;
- skeleton_sets.get_members(group, groups_representatives[i]);
- highest_group_members.push_back(_find_highest_node(state, group));
- groups.push_back(group);
- }
-
- for (int i = 0; i < highest_group_members.size(); ++i) {
- const GLTFNodeIndex node_i = highest_group_members[i];
-
- // Attach any siblings together (this needs to be done n^2/2 times)
- for (int j = i + 1; j < highest_group_members.size(); ++j) {
- const GLTFNodeIndex node_j = highest_group_members[j];
-
- // Even if they are siblings under the root! :)
- if (state.nodes[node_i]->parent == state.nodes[node_j]->parent) {
- skeleton_sets.create_union(node_i, node_j);
- }
- }
-
- // Attach any parenting going on together (we need to do this n^2 times)
- const GLTFNodeIndex node_i_parent = state.nodes[node_i]->parent;
- if (node_i_parent >= 0) {
- for (int j = 0; j < groups.size() && i != j; ++j) {
- const Vector<GLTFNodeIndex> &group = groups[j];
-
- if (group.find(node_i_parent) >= 0) {
- const GLTFNodeIndex node_j = highest_group_members[j];
- skeleton_sets.create_union(node_i, node_j);
- }
- }
- }
- }
- }
-
- // At this point, the skeleton groups should be finalized
- Vector<GLTFNodeIndex> skeleton_owners;
- skeleton_sets.get_representatives(skeleton_owners);
-
- // Mark all the skins actual skeletons, after we have merged them
- for (GLTFSkeletonIndex skel_i = 0; skel_i < skeleton_owners.size(); ++skel_i) {
- const GLTFNodeIndex skeleton_owner = skeleton_owners[skel_i];
- GLTFSkeleton skeleton;
-
- Vector<GLTFNodeIndex> skeleton_nodes;
- skeleton_sets.get_members(skeleton_nodes, skeleton_owner);
-
- for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
- GLTFSkin &skin = state.skins.write[skin_i];
-
- // If any of the the skeletons nodes exist in a skin, that skin now maps to the skeleton
- for (int i = 0; i < skeleton_nodes.size(); ++i) {
- GLTFNodeIndex skel_node_i = skeleton_nodes[i];
- if (skin.joints.find(skel_node_i) >= 0 || skin.non_joints.find(skel_node_i) >= 0) {
- skin.skeleton = skel_i;
- continue;
- }
- }
- }
-
- Vector<GLTFNodeIndex> non_joints;
- for (int i = 0; i < skeleton_nodes.size(); ++i) {
- const GLTFNodeIndex node_i = skeleton_nodes[i];
-
- if (state.nodes[node_i]->joint) {
- skeleton.joints.push_back(node_i);
- } else {
- non_joints.push_back(node_i);
- }
- }
-
- state.skeletons.push_back(skeleton);
-
- _reparent_non_joint_skeleton_subtrees(state, state.skeletons.write[skel_i], non_joints);
- }
-
- for (GLTFSkeletonIndex skel_i = 0; skel_i < state.skeletons.size(); ++skel_i) {
- GLTFSkeleton &skeleton = state.skeletons.write[skel_i];
-
- for (int i = 0; i < skeleton.joints.size(); ++i) {
- const GLTFNodeIndex node_i = skeleton.joints[i];
- GLTFNode *node = state.nodes[node_i];
-
- ERR_FAIL_COND_V(!node->joint, ERR_PARSE_ERROR);
- ERR_FAIL_COND_V(node->skeleton >= 0, ERR_PARSE_ERROR);
- node->skeleton = skel_i;
- }
-
- ERR_FAIL_COND_V(_determine_skeleton_roots(state, skel_i), ERR_PARSE_ERROR);
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_reparent_non_joint_skeleton_subtrees(GLTFState &state, GLTFSkeleton &skeleton, const Vector<GLTFNodeIndex> &non_joints) {
- DisjointSet<GLTFNodeIndex> subtree_set;
-
- // Populate the disjoint set with ONLY non joints that are in the skeleton hierarchy (non_joints vector)
- // This way we can find any joints that lie in between joints, as the current glTF specification
- // mentions nothing about non-joints being in between joints of the same skin. Hopefully one day we
- // can remove this code.
-
- // skinD depicted here explains this issue:
- // https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Animation_Skin
-
- for (int i = 0; i < non_joints.size(); ++i) {
- const GLTFNodeIndex node_i = non_joints[i];
-
- subtree_set.insert(node_i);
-
- const GLTFNodeIndex parent_i = state.nodes[node_i]->parent;
- if (parent_i >= 0 && non_joints.find(parent_i) >= 0 && !state.nodes[parent_i]->joint) {
- subtree_set.create_union(parent_i, node_i);
- }
- }
-
- // Find all the non joint subtrees and re-parent them to a new "fake" joint
-
- Vector<GLTFNodeIndex> non_joint_subtree_roots;
- subtree_set.get_representatives(non_joint_subtree_roots);
-
- for (int root_i = 0; root_i < non_joint_subtree_roots.size(); ++root_i) {
- const GLTFNodeIndex subtree_root = non_joint_subtree_roots[root_i];
-
- Vector<GLTFNodeIndex> subtree_nodes;
- subtree_set.get_members(subtree_nodes, subtree_root);
-
- for (int subtree_i = 0; subtree_i < subtree_nodes.size(); ++subtree_i) {
- ERR_FAIL_COND_V(_reparent_to_fake_joint(state, skeleton, subtree_nodes[subtree_i]), FAILED);
-
- // We modified the tree, recompute all the heights
- _compute_node_heights(state);
- }
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_reparent_to_fake_joint(GLTFState &state, GLTFSkeleton &skeleton, const GLTFNodeIndex node_index) {
- GLTFNode *node = state.nodes[node_index];
-
- // Can we just "steal" this joint if it is just a spatial node?
- if (node->skin < 0 && node->mesh < 0 && node->camera < 0) {
- node->joint = true;
- // Add the joint to the skeletons joints
- skeleton.joints.push_back(node_index);
- return OK;
- }
-
- GLTFNode *fake_joint = memnew(GLTFNode);
- const GLTFNodeIndex fake_joint_index = state.nodes.size();
- state.nodes.push_back(fake_joint);
-
- // We better not be a joint, or we messed up in our logic
- if (node->joint) {
- return FAILED;
- }
-
- fake_joint->translation = node->translation;
- fake_joint->rotation = node->rotation;
- fake_joint->scale = node->scale;
- fake_joint->xform = node->xform;
- fake_joint->joint = true;
-
- // We can use the exact same name here, because the joint will be inside a skeleton and not the scene
- fake_joint->name = node->name;
-
- // Clear the nodes transforms, since it will be parented to the fake joint
- node->translation = Vector3(0, 0, 0);
- node->rotation = Quat();
- node->scale = Vector3(1, 1, 1);
- node->xform = Transform();
-
- // Transfer the node children to the fake joint
- for (int child_i = 0; child_i < node->children.size(); ++child_i) {
- GLTFNode *child = state.nodes[node->children[child_i]];
- child->parent = fake_joint_index;
- }
-
- fake_joint->children = node->children;
- node->children.clear();
-
- // add the fake joint to the parent and remove the original joint
- if (node->parent >= 0) {
- GLTFNode *parent = state.nodes[node->parent];
- parent->children.erase(node_index);
- parent->children.push_back(fake_joint_index);
- fake_joint->parent = node->parent;
- }
-
- // Add the node to the fake joint
- fake_joint->children.push_back(node_index);
- node->parent = fake_joint_index;
- node->fake_joint_parent = fake_joint_index;
-
- // Add the fake joint to the skeletons joints
- skeleton.joints.push_back(fake_joint_index);
-
- // Replace skin_skeletons with fake joints if we must.
- for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
- GLTFSkin &skin = state.skins.write[skin_i];
- if (skin.skin_root == node_index) {
- skin.skin_root = fake_joint_index;
- }
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_determine_skeleton_roots(GLTFState &state, const GLTFSkeletonIndex skel_i) {
- DisjointSet<GLTFNodeIndex> disjoint_set;
-
- for (GLTFNodeIndex i = 0; i < state.nodes.size(); ++i) {
- const GLTFNode *node = state.nodes[i];
-
- if (node->skeleton != skel_i) {
- continue;
- }
-
- disjoint_set.insert(i);
-
- if (node->parent >= 0 && state.nodes[node->parent]->skeleton == skel_i) {
- disjoint_set.create_union(node->parent, i);
- }
- }
-
- GLTFSkeleton &skeleton = state.skeletons.write[skel_i];
-
- Vector<GLTFNodeIndex> owners;
- disjoint_set.get_representatives(owners);
-
- Vector<GLTFNodeIndex> roots;
-
- for (int i = 0; i < owners.size(); ++i) {
- Vector<GLTFNodeIndex> set;
- disjoint_set.get_members(set, owners[i]);
- const GLTFNodeIndex root = _find_highest_node(state, set);
- ERR_FAIL_COND_V(root < 0, FAILED);
- roots.push_back(root);
- }
-
- roots.sort();
-
- skeleton.roots = roots;
-
- if (roots.size() == 0) {
- return FAILED;
- } else if (roots.size() == 1) {
- return OK;
- }
-
- // Check that the subtrees have the same parent root
- const GLTFNodeIndex parent = state.nodes[roots[0]]->parent;
- for (int i = 1; i < roots.size(); ++i) {
- if (state.nodes[roots[i]]->parent != parent) {
- return FAILED;
- }
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_create_skeletons(GLTFState &state) {
- for (GLTFSkeletonIndex skel_i = 0; skel_i < state.skeletons.size(); ++skel_i) {
- GLTFSkeleton &gltf_skeleton = state.skeletons.write[skel_i];
-
- Skeleton3D *skeleton = memnew(Skeleton3D);
- gltf_skeleton.godot_skeleton = skeleton;
-
- // Make a unique name, no gltf node represents this skeleton
- skeleton->set_name(_gen_unique_name(state, "Skeleton"));
-
- List<GLTFNodeIndex> bones;
-
- for (int i = 0; i < gltf_skeleton.roots.size(); ++i) {
- bones.push_back(gltf_skeleton.roots[i]);
- }
-
- // Make the skeleton creation deterministic by going through the roots in
- // a sorted order, and DEPTH FIRST
- bones.sort();
-
- while (!bones.empty()) {
- const GLTFNodeIndex node_i = bones.front()->get();
- bones.pop_front();
-
- GLTFNode *node = state.nodes[node_i];
- ERR_FAIL_COND_V(node->skeleton != skel_i, FAILED);
-
- { // Add all child nodes to the stack (deterministically)
- Vector<GLTFNodeIndex> child_nodes;
- for (int i = 0; i < node->children.size(); ++i) {
- const GLTFNodeIndex child_i = node->children[i];
- if (state.nodes[child_i]->skeleton == skel_i) {
- child_nodes.push_back(child_i);
- }
- }
-
- // Depth first insertion
- child_nodes.sort();
- for (int i = child_nodes.size() - 1; i >= 0; --i) {
- bones.push_front(child_nodes[i]);
- }
- }
-
- const int bone_index = skeleton->get_bone_count();
-
- if (node->name.empty()) {
- node->name = "bone";
- }
-
- node->name = _gen_unique_bone_name(state, skel_i, node->name);
-
- skeleton->add_bone(node->name);
- skeleton->set_bone_rest(bone_index, node->xform);
-
- if (node->parent >= 0 && state.nodes[node->parent]->skeleton == skel_i) {
- const int bone_parent = skeleton->find_bone(state.nodes[node->parent]->name);
- ERR_FAIL_COND_V(bone_parent < 0, FAILED);
- skeleton->set_bone_parent(bone_index, skeleton->find_bone(state.nodes[node->parent]->name));
- }
-
- state.scene_nodes.insert(node_i, skeleton);
- }
- }
-
- ERR_FAIL_COND_V(_map_skin_joints_indices_to_skeleton_bone_indices(state), ERR_PARSE_ERROR);
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_map_skin_joints_indices_to_skeleton_bone_indices(GLTFState &state) {
- for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
- GLTFSkin &skin = state.skins.write[skin_i];
-
- const GLTFSkeleton &skeleton = state.skeletons[skin.skeleton];
-
- for (int joint_index = 0; joint_index < skin.joints_original.size(); ++joint_index) {
- const GLTFNodeIndex node_i = skin.joints_original[joint_index];
- const GLTFNode *node = state.nodes[node_i];
-
- skin.joint_i_to_name.insert(joint_index, node->name);
-
- const int bone_index = skeleton.godot_skeleton->find_bone(node->name);
- ERR_FAIL_COND_V(bone_index < 0, FAILED);
-
- skin.joint_i_to_bone_i.insert(joint_index, bone_index);
- }
- }
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_create_skins(GLTFState &state) {
- for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
- GLTFSkin &gltf_skin = state.skins.write[skin_i];
-
- Ref<Skin> skin;
- skin.instance();
-
- // Some skins don't have IBM's! What absolute monsters!
- const bool has_ibms = !gltf_skin.inverse_binds.empty();
-
- for (int joint_i = 0; joint_i < gltf_skin.joints_original.size(); ++joint_i) {
- Transform xform;
- if (has_ibms) {
- xform = gltf_skin.inverse_binds[joint_i];
- }
-
- if (state.use_named_skin_binds) {
- StringName name = gltf_skin.joint_i_to_name[joint_i];
- skin->add_named_bind(name, xform);
- } else {
- int bone_i = gltf_skin.joint_i_to_bone_i[joint_i];
- skin->add_bind(bone_i, xform);
- }
- }
-
- gltf_skin.godot_skin = skin;
- }
-
- // Purge the duplicates!
- _remove_duplicate_skins(state);
-
- // Create unique names now, after removing duplicates
- for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
- Ref<Skin> skin = state.skins[skin_i].godot_skin;
- if (skin->get_name().empty()) {
- // Make a unique name, no gltf node represents this skin
- skin->set_name(_gen_unique_name(state, "Skin"));
- }
- }
-
- return OK;
-}
-
-bool EditorSceneImporterGLTF::_skins_are_same(const Ref<Skin> &skin_a, const Ref<Skin> &skin_b) {
- if (skin_a->get_bind_count() != skin_b->get_bind_count()) {
- return false;
- }
-
- for (int i = 0; i < skin_a->get_bind_count(); ++i) {
- if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) {
- return false;
- }
-
- Transform a_xform = skin_a->get_bind_pose(i);
- Transform b_xform = skin_b->get_bind_pose(i);
-
- if (a_xform != b_xform) {
- return false;
- }
- }
-
- return true;
-}
-
-void EditorSceneImporterGLTF::_remove_duplicate_skins(GLTFState &state) {
- for (int i = 0; i < state.skins.size(); ++i) {
- for (int j = i + 1; j < state.skins.size(); ++j) {
- const Ref<Skin> &skin_i = state.skins[i].godot_skin;
- const Ref<Skin> &skin_j = state.skins[j].godot_skin;
-
- if (_skins_are_same(skin_i, skin_j)) {
- // replace it and delete the old
- state.skins.write[j].godot_skin = skin_i;
- }
- }
- }
-}
-
-Error EditorSceneImporterGLTF::_parse_lights(GLTFState &state) {
- if (!state.json.has("extensions")) {
- return OK;
- }
- Dictionary extensions = state.json["extensions"];
- if (!extensions.has("KHR_lights_punctual")) {
- return OK;
- }
- Dictionary lights_punctual = extensions["KHR_lights_punctual"];
- if (!lights_punctual.has("lights")) {
- return OK;
- }
-
- const Array &lights = lights_punctual["lights"];
-
- for (GLTFLightIndex light_i = 0; light_i < lights.size(); light_i++) {
- const Dictionary &d = lights[light_i];
-
- GLTFLight light;
- ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR);
- const String &type = d["type"];
- light.type = type;
-
- if (d.has("color")) {
- const Array &arr = d["color"];
- ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
- light.color = c;
- }
- if (d.has("intensity")) {
- light.intensity = d["intensity"];
- }
- if (d.has("range")) {
- light.range = d["range"];
- }
- if (type == "spot") {
- const Dictionary &spot = d["spot"];
- light.inner_cone_angle = spot["innerConeAngle"];
- light.outer_cone_angle = spot["outerConeAngle"];
- ERR_FAIL_COND_V_MSG(light.inner_cone_angle >= light.outer_cone_angle, ERR_PARSE_ERROR, "The inner angle must be smaller than the outer angle.");
- } else if (type != "point" && type != "directional") {
- ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "Light type is unknown.");
- }
-
- state.lights.push_back(light);
- }
-
- print_verbose("glTF: Total lights: " + itos(state.lights.size()));
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) {
- if (!state.json.has("cameras")) {
- return OK;
- }
-
- const Array &cameras = state.json["cameras"];
-
- for (GLTFCameraIndex i = 0; i < cameras.size(); i++) {
- const Dictionary &d = cameras[i];
-
- GLTFCamera camera;
- ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR);
- const String &type = d["type"];
- if (type == "orthographic") {
- camera.perspective = false;
- if (d.has("orthographic")) {
- const Dictionary &og = d["orthographic"];
- camera.fov_size = og["ymag"];
- camera.zfar = og["zfar"];
- camera.znear = og["znear"];
- } else {
- camera.fov_size = 10;
- }
-
- } else if (type == "perspective") {
- camera.perspective = true;
- if (d.has("perspective")) {
- const Dictionary &ppt = d["perspective"];
- // GLTF spec is in radians, Godot's camera is in degrees.
- camera.fov_size = (double)ppt["yfov"] * 180.0 / Math_PI;
- camera.zfar = ppt["zfar"];
- camera.znear = ppt["znear"];
- } else {
- camera.fov_size = 10;
- }
- } else {
- ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "Camera should be in 'orthographic' or 'perspective'");
- }
-
- state.cameras.push_back(camera);
- }
-
- print_verbose("glTF: Total cameras: " + itos(state.cameras.size()));
-
- return OK;
-}
-
-Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
- if (!state.json.has("animations")) {
- return OK;
- }
-
- const Array &animations = state.json["animations"];
-
- for (GLTFAnimationIndex i = 0; i < animations.size(); i++) {
- const Dictionary &d = animations[i];
-
- GLTFAnimation animation;
-
- if (!d.has("channels") || !d.has("samplers")) {
- continue;
- }
-
- Array channels = d["channels"];
- Array samplers = d["samplers"];
-
- if (d.has("name")) {
- String name = d["name"];
- if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
- animation.loop = true;
- }
- animation.name = _sanitize_scene_name(name);
- }
-
- for (int j = 0; j < channels.size(); j++) {
- const Dictionary &c = channels[j];
- if (!c.has("target")) {
- continue;
- }
-
- const Dictionary &t = c["target"];
- if (!t.has("node") || !t.has("path")) {
- continue;
- }
-
- ERR_FAIL_COND_V(!c.has("sampler"), ERR_PARSE_ERROR);
- const int sampler = c["sampler"];
- ERR_FAIL_INDEX_V(sampler, samplers.size(), ERR_PARSE_ERROR);
-
- GLTFNodeIndex node = t["node"];
- String path = t["path"];
-
- ERR_FAIL_INDEX_V(node, state.nodes.size(), ERR_PARSE_ERROR);
-
- GLTFAnimation::Track *track = nullptr;
-
- if (!animation.tracks.has(node)) {
- animation.tracks[node] = GLTFAnimation::Track();
- }
-
- track = &animation.tracks[node];
-
- const Dictionary &s = samplers[sampler];
-
- ERR_FAIL_COND_V(!s.has("input"), ERR_PARSE_ERROR);
- ERR_FAIL_COND_V(!s.has("output"), ERR_PARSE_ERROR);
-
- const int input = s["input"];
- const int output = s["output"];
-
- GLTFAnimation::Interpolation interp = GLTFAnimation::INTERP_LINEAR;
- int output_count = 1;
- if (s.has("interpolation")) {
- const String &in = s["interpolation"];
- if (in == "STEP") {
- interp = GLTFAnimation::INTERP_STEP;
- } else if (in == "LINEAR") {
- interp = GLTFAnimation::INTERP_LINEAR;
- } else if (in == "CATMULLROMSPLINE") {
- interp = GLTFAnimation::INTERP_CATMULLROMSPLINE;
- output_count = 3;
- } else if (in == "CUBICSPLINE") {
- interp = GLTFAnimation::INTERP_CUBIC_SPLINE;
- output_count = 3;
- }
- }
-
- const Vector<float> times = _decode_accessor_as_floats(state, input, false);
- if (path == "translation") {
- const Vector<Vector3> translations = _decode_accessor_as_vec3(state, output, false);
- track->translation_track.interpolation = interp;
- track->translation_track.times = Variant(times); //convert via variant
- track->translation_track.values = Variant(translations); //convert via variant
- } else if (path == "rotation") {
- const Vector<Quat> rotations = _decode_accessor_as_quat(state, output, false);
- track->rotation_track.interpolation = interp;
- track->rotation_track.times = Variant(times); //convert via variant
- track->rotation_track.values = rotations; //convert via variant
- } else if (path == "scale") {
- const Vector<Vector3> scales = _decode_accessor_as_vec3(state, output, false);
- track->scale_track.interpolation = interp;
- track->scale_track.times = Variant(times); //convert via variant
- track->scale_track.values = Variant(scales); //convert via variant
- } else if (path == "weights") {
- const Vector<float> weights = _decode_accessor_as_floats(state, output, false);
-
- ERR_FAIL_INDEX_V(state.nodes[node]->mesh, state.meshes.size(), ERR_PARSE_ERROR);
- const GLTFMesh *mesh = &state.meshes[state.nodes[node]->mesh];
- ERR_FAIL_COND_V(mesh->blend_weights.size() == 0, ERR_PARSE_ERROR);
- const int wc = mesh->blend_weights.size();
-
- track->weight_tracks.resize(wc);
-
- const int expected_value_count = times.size() * output_count * wc;
- ERR_FAIL_COND_V_MSG(weights.size() != expected_value_count, ERR_PARSE_ERROR, "Invalid weight data, expected " + itos(expected_value_count) + " weight values, got " + itos(weights.size()) + " instead.");
-
- const int wlen = weights.size() / wc;
- const float *r = weights.ptr();
- for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea
- GLTFAnimation::Channel<float> cf;
- cf.interpolation = interp;
- cf.times = Variant(times);
- Vector<float> wdata;
- wdata.resize(wlen);
- for (int l = 0; l < wlen; l++) {
- wdata.write[l] = r[l * wc + k];
- }
-
- cf.values = wdata;
- track->weight_tracks.write[k] = cf;
- }
- } else {
- WARN_PRINT("Invalid path '" + path + "'.");
- }
- }
-
- state.animations.push_back(animation);
- }
-
- print_verbose("glTF: Total animations '" + itos(state.animations.size()) + "'.");
-
- return OK;
-}
-
-void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) {
- for (int i = 0; i < state.nodes.size(); i++) {
- GLTFNode *n = state.nodes[i];
-
- // Any joints get unique names generated when the skeleton is made, unique to the skeleton
- if (n->skeleton >= 0) {
- continue;
- }
-
- if (n->name.empty()) {
- if (n->mesh >= 0) {
- n->name = "Mesh";
- } else if (n->camera >= 0) {
- n->name = "Camera";
- } else {
- n->name = "Node";
- }
- }
-
- n->name = _gen_unique_name(state, n->name);
- }
-}
-
-BoneAttachment3D *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index) {
- const GLTFNode *gltf_node = state.nodes[node_index];
- const GLTFNode *bone_node = state.nodes[gltf_node->parent];
-
- BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
- print_verbose("glTF: Creating bone attachment for: " + gltf_node->name);
-
- ERR_FAIL_COND_V(!bone_node->joint, nullptr);
-
- bone_attachment->set_bone_name(bone_node->name);
-
- return bone_attachment;
-}
-
-EditorSceneImporterMeshNode *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
- const GLTFNode *gltf_node = state.nodes[node_index];
-
- ERR_FAIL_INDEX_V(gltf_node->mesh, state.meshes.size(), nullptr);
-
- EditorSceneImporterMeshNode *mi = memnew(EditorSceneImporterMeshNode);
- print_verbose("glTF: Creating mesh for: " + gltf_node->name);
-
- GLTFMesh &mesh = state.meshes.write[gltf_node->mesh];
- mi->set_mesh(mesh.mesh);
-
- if (mesh.mesh->get_name() == "") {
- mesh.mesh->set_name(gltf_node->name);
- }
-
- for (int i = 0; i < mesh.blend_weights.size(); i++) {
- mi->set("blend_shapes/" + mesh.mesh->get_blend_shape_name(i), mesh.blend_weights[i]);
- }
-
- return mi;
-}
-
-Light3D *EditorSceneImporterGLTF::_generate_light(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
- const GLTFNode *gltf_node = state.nodes[node_index];
-
- ERR_FAIL_INDEX_V(gltf_node->light, state.lights.size(), nullptr);
-
- print_verbose("glTF: Creating light for: " + gltf_node->name);
-
- const GLTFLight &l = state.lights[gltf_node->light];
-
- float intensity = l.intensity;
- if (intensity > 10) {
- // GLTF spec has the default around 1, but Blender defaults lights to 100.
- // The only sane way to handle this is to check where it came from and
- // handle it accordingly. If it's over 10, it probably came from Blender.
- intensity /= 100;
- }
-
- if (l.type == "directional") {
- DirectionalLight3D *light = memnew(DirectionalLight3D);
- light->set_param(Light3D::PARAM_ENERGY, intensity);
- light->set_color(l.color);
- return light;
- }
-
- const float range = CLAMP(l.range, 0, 4096);
- // Doubling the range will double the effective brightness, so we need double attenuation (half brightness).
- // We want to have double intensity give double brightness, so we need half the attenuation.
- const float attenuation = range / intensity;
- if (l.type == "point") {
- OmniLight3D *light = memnew(OmniLight3D);
- light->set_param(OmniLight3D::PARAM_ATTENUATION, attenuation);
- light->set_param(OmniLight3D::PARAM_RANGE, range);
- light->set_color(l.color);
- return light;
- }
- if (l.type == "spot") {
- SpotLight3D *light = memnew(SpotLight3D);
- light->set_param(SpotLight3D::PARAM_ATTENUATION, attenuation);
- light->set_param(SpotLight3D::PARAM_RANGE, range);
- light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad2deg(l.outer_cone_angle));
- light->set_color(l.color);
-
- // Line of best fit derived from guessing, see https://www.desmos.com/calculator/biiflubp8b
- // The points in desmos are not exact, except for (1, infinity).
- float angle_ratio = l.inner_cone_angle / l.outer_cone_angle;
- float angle_attenuation = 0.2 / (1 - angle_ratio) - 0.1;
- light->set_param(SpotLight3D::PARAM_SPOT_ATTENUATION, angle_attenuation);
- return light;
- }
- return nullptr;
-}
-
-Camera3D *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
- const GLTFNode *gltf_node = state.nodes[node_index];
-
- ERR_FAIL_INDEX_V(gltf_node->camera, state.cameras.size(), nullptr);
-
- Camera3D *camera = memnew(Camera3D);
- print_verbose("glTF: Creating camera for: " + gltf_node->name);
-
- const GLTFCamera &c = state.cameras[gltf_node->camera];
- if (c.perspective) {
- camera->set_perspective(c.fov_size, c.znear, c.zfar);
- } else {
- camera->set_orthogonal(c.fov_size, c.znear, c.zfar);
- }
-
- return camera;
-}
-
-Node3D *EditorSceneImporterGLTF::_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
- const GLTFNode *gltf_node = state.nodes[node_index];
-
- Node3D *spatial = memnew(Node3D);
- print_verbose("glTF: Creating spatial for: " + gltf_node->name);
-
- return spatial;
-}
-
-void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) {
- const GLTFNode *gltf_node = state.nodes[node_index];
-
- Node3D *current_node = nullptr;
-
- // Is our parent a skeleton
- Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent);
-
- if (gltf_node->skeleton >= 0) {
- Skeleton3D *skeleton = state.skeletons[gltf_node->skeleton].godot_skeleton;
-
- if (active_skeleton != skeleton) {
- ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons");
-
- // Add it to the scene if it has not already been added
- if (skeleton->get_parent() == nullptr) {
- scene_parent->add_child(skeleton);
- skeleton->set_owner(scene_root);
- }
- }
-
- active_skeleton = skeleton;
- current_node = skeleton;
- }
-
- // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment
- if (current_node == nullptr && active_skeleton != nullptr && gltf_node->skin < 0) {
- BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index);
-
- scene_parent->add_child(bone_attachment);
- bone_attachment->set_owner(scene_root);
-
- // There is no gltf_node that represent this, so just directly create a unique name
- bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment"));
-
- // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
- // and attach it to the bone_attachment
- scene_parent = bone_attachment;
- }
-
- // We still have not managed to make a node
- if (current_node == nullptr) {
- if (gltf_node->mesh >= 0) {
- current_node = _generate_mesh_instance(state, scene_parent, node_index);
- } else if (gltf_node->camera >= 0) {
- current_node = _generate_camera(state, scene_parent, node_index);
- } else if (gltf_node->light >= 0) {
- current_node = _generate_light(state, scene_parent, node_index);
- } else {
- current_node = _generate_spatial(state, scene_parent, node_index);
- }
-
- scene_parent->add_child(current_node);
- current_node->set_owner(scene_root);
- current_node->set_transform(gltf_node->xform);
- current_node->set_name(gltf_node->name);
- }
-
- state.scene_nodes.insert(node_index, current_node);
-
- for (int i = 0; i < gltf_node->children.size(); ++i) {
- _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]);
- }
-}
-
-template <class T>
-struct EditorSceneImporterGLTFInterpolate {
- T lerp(const T &a, const T &b, float c) const {
- return a + (b - a) * c;
- }
-
- T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
- const float t2 = t * t;
- const float t3 = t2 * t;
-
- return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
- }
-
- T bezier(T start, T control_1, T control_2, T end, float t) {
- /* Formula from Wikipedia article on Bezier curves. */
- const real_t omt = (1.0 - t);
- const real_t omt2 = omt * omt;
- const real_t omt3 = omt2 * omt;
- const real_t t2 = t * t;
- const real_t t3 = t2 * t;
-
- return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
- }
-};
-
-// thank you for existing, partial specialization
-template <>
-struct EditorSceneImporterGLTFInterpolate<Quat> {
- Quat lerp(const Quat &a, const Quat &b, const float c) const {
- ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized.");
- ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized.");
-
- return a.slerp(b, c).normalized();
- }
-
- Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, const float c) {
- ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quat(), "The quaternion \"p1\" must be normalized.");
- ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quat(), "The quaternion \"p2\" must be normalized.");
-
- return p1.slerp(p2, c).normalized();
- }
-
- Quat bezier(const Quat start, const Quat control_1, const Quat control_2, const Quat end, const float t) {
- ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quat(), "The start quaternion must be normalized.");
- ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quat(), "The end quaternion must be normalized.");
-
- return start.slerp(end, t).normalized();
- }
-};
-
-template <class T>
-T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
- //could use binary search, worth it?
- int idx = -1;
- for (int i = 0; i < p_times.size(); i++) {
- if (p_times[i] > p_time) {
- break;
- }
- idx++;
- }
-
- EditorSceneImporterGLTFInterpolate<T> interp;
-
- switch (p_interp) {
- case GLTFAnimation::INTERP_LINEAR: {
- if (idx == -1) {
- return p_values[0];
- } else if (idx >= p_times.size() - 1) {
- return p_values[p_times.size() - 1];
- }
-
- const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
-
- return interp.lerp(p_values[idx], p_values[idx + 1], c);
-
- } break;
- case GLTFAnimation::INTERP_STEP: {
- if (idx == -1) {
- return p_values[0];
- } else if (idx >= p_times.size() - 1) {
- return p_values[p_times.size() - 1];
- }
-
- return p_values[idx];
-
- } break;
- case GLTFAnimation::INTERP_CATMULLROMSPLINE: {
- if (idx == -1) {
- return p_values[1];
- } else if (idx >= p_times.size() - 1) {
- return p_values[1 + p_times.size() - 1];
- }
-
- const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
-
- return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
-
- } break;
- case GLTFAnimation::INTERP_CUBIC_SPLINE: {
- if (idx == -1) {
- return p_values[1];
- } else if (idx >= p_times.size() - 1) {
- return p_values[(p_times.size() - 1) * 3 + 1];
- }
-
- const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
-
- const T from = p_values[idx * 3 + 1];
- const T c1 = from + p_values[idx * 3 + 2];
- const T to = p_values[idx * 3 + 4];
- const T c2 = to + p_values[idx * 3 + 3];
-
- return interp.bezier(from, c1, c2, to, c);
-
- } break;
- }
-
- ERR_FAIL_V(p_values[0]);
-}
-
-void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) {
- const GLTFAnimation &anim = state.animations[index];
-
- String name = anim.name;
- if (name.empty()) {
- // No node represent these, and they are not in the hierarchy, so just make a unique name
- name = _gen_unique_name(state, "Animation");
- }
-
- Ref<Animation> animation;
- animation.instance();
- animation->set_name(name);
-
- if (anim.loop) {
- animation->set_loop(true);
- }
-
- float length = 0;
-
- for (Map<int, GLTFAnimation::Track>::Element *E = anim.tracks.front(); E; E = E->next()) {
- const GLTFAnimation::Track &track = E->get();
- //need to find the path
- NodePath node_path;
-
- GLTFNodeIndex node_index = E->key();
- if (state.nodes[node_index]->fake_joint_parent >= 0) {
- // Should be same as parent
- node_index = state.nodes[node_index]->fake_joint_parent;
- }
-
- const GLTFNode *node = state.nodes[E->key()];
-
- if (node->skeleton >= 0) {
- const Skeleton3D *sk = Object::cast_to<Skeleton3D>(state.scene_nodes.find(node_index)->get());
- ERR_FAIL_COND(sk == nullptr);
-
- const String path = ap->get_parent()->get_path_to(sk);
- const String bone = node->name;
- node_path = path + ":" + bone;
- } else {
- node_path = ap->get_parent()->get_path_to(state.scene_nodes.find(node_index)->get());
- }
-
- for (int i = 0; i < track.rotation_track.times.size(); i++) {
- length = MAX(length, track.rotation_track.times[i]);
- }
- for (int i = 0; i < track.translation_track.times.size(); i++) {
- length = MAX(length, track.translation_track.times[i]);
- }
- for (int i = 0; i < track.scale_track.times.size(); i++) {
- length = MAX(length, track.scale_track.times[i]);
- }
-
- for (int i = 0; i < track.weight_tracks.size(); i++) {
- for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
- length = MAX(length, track.weight_tracks[i].times[j]);
- }
- }
-
- if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) {
- //make transform track
- int track_idx = animation->get_track_count();
- animation->add_track(Animation::TYPE_TRANSFORM);
- animation->track_set_path(track_idx, node_path);
- animation->track_set_imported(track_idx, true);
- //first determine animation length
-
- const float increment = 1.0 / float(bake_fps);
- float time = 0.0;
-
- Vector3 base_pos;
- Quat base_rot;
- Vector3 base_scale = Vector3(1, 1, 1);
-
- if (!track.rotation_track.values.size()) {
- base_rot = state.nodes[E->key()]->rotation.normalized();
- }
-
- if (!track.translation_track.values.size()) {
- base_pos = state.nodes[E->key()]->translation;
- }
-
- if (!track.scale_track.values.size()) {
- base_scale = state.nodes[E->key()]->scale;
- }
-
- bool last = false;
- while (true) {
- Vector3 pos = base_pos;
- Quat rot = base_rot;
- Vector3 scale = base_scale;
-
- if (track.translation_track.times.size()) {
- pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
- }
-
- if (track.rotation_track.times.size()) {
- rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
- }
-
- if (track.scale_track.times.size()) {
- scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
- }
-
- if (node->skeleton >= 0) {
- Transform xform;
- xform.basis.set_quat_scale(rot, scale);
- xform.origin = pos;
-
- const Skeleton3D *skeleton = state.skeletons[node->skeleton].godot_skeleton;
- const int bone_idx = skeleton->find_bone(node->name);
- xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform;
-
- rot = xform.basis.get_rotation_quat();
- rot.normalize();
- scale = xform.basis.get_scale();
- pos = xform.origin;
- }
-
- animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
-
- if (last) {
- break;
- }
- time += increment;
- if (time >= length) {
- last = true;
- time = length;
- }
- }
- }
-
- for (int i = 0; i < track.weight_tracks.size(); i++) {
- ERR_CONTINUE(node->mesh < 0 || node->mesh >= state.meshes.size());
- const GLTFMesh &mesh = state.meshes[node->mesh];
- const String prop = "blend_shapes/" + mesh.mesh->get_blend_shape_name(i);
-
- const String blend_path = String(node_path) + ":" + prop;
-
- const int track_idx = animation->get_track_count();
- animation->add_track(Animation::TYPE_VALUE);
- animation->track_set_path(track_idx, blend_path);
-
- // Only LINEAR and STEP (NEAREST) can be supported out of the box by Godot's Animation,
- // the other modes have to be baked.
- GLTFAnimation::Interpolation gltf_interp = track.weight_tracks[i].interpolation;
- if (gltf_interp == GLTFAnimation::INTERP_LINEAR || gltf_interp == GLTFAnimation::INTERP_STEP) {
- animation->track_set_interpolation_type(track_idx, gltf_interp == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_LINEAR);
- for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
- const float t = track.weight_tracks[i].times[j];
- const float w = track.weight_tracks[i].values[j];
- animation->track_insert_key(track_idx, t, w);
- }
- } else {
- // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
- const float increment = 1.0 / float(bake_fps);
- float time = 0.0;
- bool last = false;
- while (true) {
- _interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
- if (last) {
- break;
- }
- time += increment;
- if (time >= length) {
- last = true;
- time = length;
- }
- }
- }
- }
- }
-
- animation->set_length(length);
-
- ap->add_animation(name, animation);
-}
-
-void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Node3D *scene_root) {
- for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); ++node_i) {
- const GLTFNode *node = state.nodes[node_i];
-
- if (node->skin >= 0 && node->mesh >= 0) {
- const GLTFSkinIndex skin_i = node->skin;
-
- Map<GLTFNodeIndex, Node *>::Element *mi_element = state.scene_nodes.find(node_i);
- EditorSceneImporterMeshNode *mi = Object::cast_to<EditorSceneImporterMeshNode>(mi_element->get());
- ERR_FAIL_COND(mi == nullptr);
-
- const GLTFSkeletonIndex skel_i = state.skins[node->skin].skeleton;
- const GLTFSkeleton &gltf_skeleton = state.skeletons[skel_i];
- Skeleton3D *skeleton = gltf_skeleton.godot_skeleton;
- ERR_FAIL_COND(skeleton == nullptr);
-
- mi->get_parent()->remove_child(mi);
- skeleton->add_child(mi);
- mi->set_owner(scene_root);
-
- mi->set_skin(state.skins[skin_i].godot_skin);
- mi->set_skeleton_path(mi->get_path_to(skeleton));
- mi->set_transform(Transform());
- }
- }
-}
-
-Node3D *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_bake_fps) {
- Node3D *root = memnew(Node3D);
-
- // scene_name is already unique
- root->set_name(state.scene_name);
-
- for (int i = 0; i < state.root_nodes.size(); ++i) {
- _generate_scene_node(state, root, root, state.root_nodes[i]);
- }
-
- _process_mesh_instances(state, root);
-
- if (state.animations.size()) {
- AnimationPlayer *ap = memnew(AnimationPlayer);
- ap->set_name("AnimationPlayer");
- root->add_child(ap);
- ap->set_owner(root);
-
- for (int i = 0; i < state.animations.size(); i++) {
- _import_animation(state, ap, i, p_bake_fps);
- }
- }
-
- return root;
-}
-
-Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
- print_verbose(vformat("glTF: Importing file %s as scene.", p_path));
-
- GLTFState state;
-
- if (p_path.to_lower().ends_with("glb")) {
- //binary file
- //text file
- Error err = _parse_glb(p_path, state);
- if (err) {
- return nullptr;
- }
- } else {
- //text file
- Error err = _parse_json(p_path, state);
- if (err) {
- return nullptr;
- }
- }
-
- ERR_FAIL_COND_V(!state.json.has("asset"), nullptr);
-
- Dictionary asset = state.json["asset"];
-
- ERR_FAIL_COND_V(!asset.has("version"), nullptr);
-
- String version = asset["version"];
-
- state.import_flags = p_flags;
- state.major_version = version.get_slice(".", 0).to_int();
- state.minor_version = version.get_slice(".", 1).to_int();
- state.use_named_skin_binds = p_flags & IMPORT_USE_NAMED_SKIN_BINDS;
-
- /* STEP 0 PARSE SCENE */
- Error err = _parse_scenes(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 1 PARSE NODES */
- err = _parse_nodes(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 2 PARSE BUFFERS */
- err = _parse_buffers(state, p_path.get_base_dir());
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 3 PARSE BUFFER VIEWS */
- err = _parse_buffer_views(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 4 PARSE ACCESSORS */
- err = _parse_accessors(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 5 PARSE IMAGES */
- err = _parse_images(state, p_path.get_base_dir());
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 6 PARSE TEXTURES */
- err = _parse_textures(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 7 PARSE TEXTURES */
- err = _parse_materials(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 9 PARSE SKINS */
- err = _parse_skins(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 10 DETERMINE SKELETONS */
- err = _determine_skeletons(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 11 CREATE SKELETONS */
- err = _create_skeletons(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 12 CREATE SKINS */
- err = _create_skins(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 13 PARSE MESHES (we have enough info now) */
- err = _parse_meshes(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 14 PARSE LIGHTS */
- err = _parse_lights(state);
- if (err != OK) {
- return NULL;
- }
-
- /* STEP 15 PARSE CAMERAS */
- err = _parse_cameras(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 16 PARSE ANIMATIONS */
- err = _parse_animations(state);
- if (err != OK) {
- return nullptr;
- }
-
- /* STEP 17 ASSIGN SCENE NAMES */
- _assign_scene_names(state);
-
- /* STEP 18 MAKE SCENE! */
- Node3D *scene = _generate_scene(state, p_bake_fps);
-
- return scene;
-}
-
-Ref<Animation> EditorSceneImporterGLTF::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
- return Ref<Animation>();
-}
-
-EditorSceneImporterGLTF::EditorSceneImporterGLTF() {
-}
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
deleted file mode 100644
index e6163a46be..0000000000
--- a/editor/import/editor_scene_importer_gltf.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*************************************************************************/
-/* editor_scene_importer_gltf.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 EDITOR_SCENE_IMPORTER_GLTF_H
-#define EDITOR_SCENE_IMPORTER_GLTF_H
-
-#include "editor/import/resource_importer_scene.h"
-#include "scene/3d/light_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-
-class AnimationPlayer;
-class BoneAttachment3D;
-class EditorSceneImporterMeshNode;
-
-class EditorSceneImporterGLTF : public EditorSceneImporter {
- GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter);
-
- typedef int GLTFAccessorIndex;
- typedef int GLTFAnimationIndex;
- typedef int GLTFBufferIndex;
- typedef int GLTFBufferViewIndex;
- typedef int GLTFCameraIndex;
- typedef int GLTFImageIndex;
- typedef int GLTFMaterialIndex;
- typedef int GLTFMeshIndex;
- typedef int GLTFLightIndex;
- typedef int GLTFNodeIndex;
- typedef int GLTFSkeletonIndex;
- typedef int GLTFSkinIndex;
- typedef int GLTFTextureIndex;
-
- enum {
- ARRAY_BUFFER = 34962,
- ELEMENT_ARRAY_BUFFER = 34963,
-
- TYPE_BYTE = 5120,
- TYPE_UNSIGNED_BYTE = 5121,
- TYPE_SHORT = 5122,
- TYPE_UNSIGNED_SHORT = 5123,
- TYPE_UNSIGNED_INT = 5125,
- TYPE_FLOAT = 5126,
-
- COMPONENT_TYPE_BYTE = 5120,
- COMPONENT_TYPE_UNSIGNED_BYTE = 5121,
- COMPONENT_TYPE_SHORT = 5122,
- COMPONENT_TYPE_UNSIGNED_SHORT = 5123,
- COMPONENT_TYPE_INT = 5125,
- COMPONENT_TYPE_FLOAT = 5126,
-
- };
-
- String _get_component_type_name(const uint32_t p_component);
- int _get_component_type_size(const int component_type);
-
- enum GLTFType {
- TYPE_SCALAR,
- TYPE_VEC2,
- TYPE_VEC3,
- TYPE_VEC4,
- TYPE_MAT2,
- TYPE_MAT3,
- TYPE_MAT4,
- };
-
- String _get_type_name(const GLTFType p_component);
-
- struct GLTFNode {
- //matrices need to be transformed to this
- GLTFNodeIndex parent = -1;
- int height = -1;
-
- Transform xform;
- String name;
-
- GLTFMeshIndex mesh = -1;
- GLTFCameraIndex camera = -1;
- GLTFSkinIndex skin = -1;
-
- GLTFSkeletonIndex skeleton = -1;
- bool joint = false;
-
- Vector3 translation;
- Quat rotation;
- Vector3 scale = Vector3(1, 1, 1);
-
- Vector<int> children;
-
- GLTFNodeIndex fake_joint_parent = -1;
-
- GLTFLightIndex light = -1;
- };
-
- struct GLTFBufferView {
- GLTFBufferIndex buffer = -1;
- int byte_offset = 0;
- int byte_length = 0;
- int byte_stride = 0;
- bool indices = false;
- //matrices need to be transformed to this
- };
-
- struct GLTFAccessor {
- GLTFBufferViewIndex buffer_view = 0;
- int byte_offset = 0;
- int component_type = 0;
- bool normalized = false;
- int count = 0;
- GLTFType type = GLTFType::TYPE_SCALAR;
- float min = 0;
- float max = 0;
- int sparse_count = 0;
- int sparse_indices_buffer_view = 0;
- int sparse_indices_byte_offset = 0;
- int sparse_indices_component_type = 0;
- int sparse_values_buffer_view = 0;
- int sparse_values_byte_offset = 0;
- };
- struct GLTFTexture {
- GLTFImageIndex src_image;
- };
-
- struct GLTFSkeleton {
- // The *synthesized* skeletons joints
- Vector<GLTFNodeIndex> joints;
-
- // The roots of the skeleton. If there are multiple, each root must have the same parent
- // (ie roots are siblings)
- Vector<GLTFNodeIndex> roots;
-
- // The created Skeleton for the scene
- Skeleton3D *godot_skeleton = nullptr;
-
- // Set of unique bone names for the skeleton
- Set<String> unique_names;
- };
-
- struct GLTFSkin {
- String name;
-
- // The "skeleton" property defined in the gltf spec. -1 = Scene Root
- GLTFNodeIndex skin_root = -1;
-
- Vector<GLTFNodeIndex> joints_original;
- Vector<Transform> inverse_binds;
-
- // Note: joints + non_joints should form a complete subtree, or subtrees with a common parent
-
- // All nodes that are skins that are caught in-between the original joints
- // (inclusive of joints_original)
- Vector<GLTFNodeIndex> joints;
-
- // All Nodes that are caught in-between skin joint nodes, and are not defined
- // as joints by any skin
- Vector<GLTFNodeIndex> non_joints;
-
- // The roots of the skin. In the case of multiple roots, their parent *must*
- // be the same (the roots must be siblings)
- Vector<GLTFNodeIndex> roots;
-
- // The GLTF Skeleton this Skin points to (after we determine skeletons)
- GLTFSkeletonIndex skeleton = -1;
-
- // A mapping from the joint indices (in the order of joints_original) to the
- // Godot Skeleton's bone_indices
- Map<int, int> joint_i_to_bone_i;
- Map<int, StringName> joint_i_to_name;
-
- // The Actual Skin that will be created as a mapping between the IBM's of this skin
- // to the generated skeleton for the mesh instances.
- Ref<Skin> godot_skin;
- };
-
- struct GLTFMesh {
- Ref<EditorSceneImporterMesh> mesh;
- Vector<float> blend_weights;
- };
-
- struct GLTFCamera {
- bool perspective = true;
- float fov_size = 75;
- float zfar = 4000;
- float znear = 0.05;
- };
-
- struct GLTFLight {
- Color color = Color(1.0f, 1.0f, 1.0f);
- float intensity = 1.0f;
- String type = "";
- float range = Math_INF;
- float inner_cone_angle = 0.0f;
- float outer_cone_angle = Math_PI / 4.0;
- };
-
- struct GLTFAnimation {
- bool loop = false;
-
- enum Interpolation {
- INTERP_LINEAR,
- INTERP_STEP,
- INTERP_CATMULLROMSPLINE,
- INTERP_CUBIC_SPLINE
- };
-
- template <class T>
- struct Channel {
- Interpolation interpolation;
- Vector<float> times;
- Vector<T> values;
- };
-
- struct Track {
- Channel<Vector3> translation_track;
- Channel<Quat> rotation_track;
- Channel<Vector3> scale_track;
- Vector<Channel<float>> weight_tracks;
- };
-
- String name;
-
- Map<int, Track> tracks;
- };
-
- struct GLTFState {
- Dictionary json;
- int major_version = 0;
- int minor_version = 0;
- Vector<uint8_t> glb_data;
-
- bool use_named_skin_binds = false;
-
- Vector<GLTFNode *> nodes;
- Vector<Vector<uint8_t>> buffers;
- Vector<GLTFBufferView> buffer_views;
- Vector<GLTFAccessor> accessors;
-
- Vector<GLTFMesh> meshes; //meshes are loaded directly, no reason not to.
- Vector<Ref<StandardMaterial3D>> materials;
-
- String scene_name;
- Vector<int> root_nodes;
-
- Vector<GLTFTexture> textures;
- Vector<Ref<Texture2D>> images;
-
- Vector<GLTFSkin> skins;
- Vector<GLTFCamera> cameras;
- Vector<GLTFLight> lights;
-
- Set<String> unique_names;
-
- Vector<GLTFSkeleton> skeletons;
- Vector<GLTFAnimation> animations;
-
- Map<GLTFNodeIndex, Node *> scene_nodes;
-
- // EditorSceneImporter::ImportFlags
- uint32_t import_flags;
-
- ~GLTFState() {
- for (int i = 0; i < nodes.size(); i++) {
- memdelete(nodes[i]);
- }
- }
- };
-
- String _sanitize_scene_name(const String &name);
- String _gen_unique_name(GLTFState &state, const String &p_name);
-
- String _sanitize_bone_name(const String &name);
- String _gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name);
-
- Ref<Texture2D> _get_texture(GLTFState &state, const GLTFTextureIndex p_texture);
-
- Error _parse_json(const String &p_path, GLTFState &state);
- Error _parse_glb(const String &p_path, GLTFState &state);
-
- Error _parse_scenes(GLTFState &state);
- Error _parse_nodes(GLTFState &state);
-
- void _compute_node_heights(GLTFState &state);
-
- Error _parse_buffers(GLTFState &state, const String &p_base_path);
- Error _parse_buffer_views(GLTFState &state);
- GLTFType _get_type_from_str(const String &p_string);
- Error _parse_accessors(GLTFState &state);
- Error _decode_buffer_view(GLTFState &state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex);
-
- Vector<double> _decode_accessor(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<float> _decode_accessor_as_floats(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<int> _decode_accessor_as_ints(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Vector2> _decode_accessor_as_vec2(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Vector3> _decode_accessor_as_vec3(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Color> _decode_accessor_as_color(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Quat> _decode_accessor_as_quat(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Transform2D> _decode_accessor_as_xform2d(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Basis> _decode_accessor_as_basis(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
- Vector<Transform> _decode_accessor_as_xform(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
-
- Error _parse_meshes(GLTFState &state);
- Error _parse_images(GLTFState &state, const String &p_base_path);
- Error _parse_textures(GLTFState &state);
-
- Error _parse_materials(GLTFState &state);
-
- GLTFNodeIndex _find_highest_node(GLTFState &state, const Vector<GLTFNodeIndex> &subset);
-
- bool _capture_nodes_in_skin(GLTFState &state, GLTFSkin &skin, const GLTFNodeIndex node_index);
- void _capture_nodes_for_multirooted_skin(GLTFState &state, GLTFSkin &skin);
- Error _expand_skin(GLTFState &state, GLTFSkin &skin);
- Error _verify_skin(GLTFState &state, GLTFSkin &skin);
- Error _parse_skins(GLTFState &state);
-
- Error _determine_skeletons(GLTFState &state);
- Error _reparent_non_joint_skeleton_subtrees(GLTFState &state, GLTFSkeleton &skeleton, const Vector<GLTFNodeIndex> &non_joints);
- Error _reparent_to_fake_joint(GLTFState &state, GLTFSkeleton &skeleton, const GLTFNodeIndex node_index);
- Error _determine_skeleton_roots(GLTFState &state, const GLTFSkeletonIndex skel_i);
-
- Error _create_skeletons(GLTFState &state);
- Error _map_skin_joints_indices_to_skeleton_bone_indices(GLTFState &state);
-
- Error _create_skins(GLTFState &state);
- bool _skins_are_same(const Ref<Skin> &skin_a, const Ref<Skin> &skin_b);
- void _remove_duplicate_skins(GLTFState &state);
-
- Error _parse_cameras(GLTFState &state);
- Error _parse_lights(GLTFState &state);
- Error _parse_animations(GLTFState &state);
-
- BoneAttachment3D *_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index);
- EditorSceneImporterMeshNode *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
- Camera3D *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
- Light3D *_generate_light(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
- Node3D *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
-
- void _generate_scene_node(GLTFState &state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index);
- Node3D *_generate_scene(GLTFState &state, const int p_bake_fps);
-
- void _process_mesh_instances(GLTFState &state, Node3D *scene_root);
-
- void _assign_scene_names(GLTFState &state);
-
- template <class T>
- T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp);
-
- void _import_animation(GLTFState &state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps);
-
-public:
- virtual uint32_t get_import_flags() const override;
- virtual void get_extensions(List<String> *r_extensions) const override;
- virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) override;
-
- EditorSceneImporterGLTF();
-};
-
-#endif // EDITOR_SCENE_IMPORTER_GLTF_H
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index ac068c05cf..6166b83ae0 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -373,7 +373,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
int x = slice_w * j;
int y = slice_h * i;
Ref<Image> slice = image->get_rect(Rect2(x, y, slice_w, slice_h));
- ERR_CONTINUE(slice.is_null() || slice->empty());
+ ERR_CONTINUE(slice.is_null() || slice->is_empty());
if (slice->get_width() != slice_w || slice->get_height() != slice_h) {
slice->resize(slice_w, slice_h);
}
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 30c7b2920a..e7170ef61c 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -32,6 +32,8 @@
#include "core/io/resource_saver.h"
#include "core/os/file_access.h"
+#include "editor/import/scene_importer_mesh.h"
+#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/node_3d.h"
#include "scene/resources/mesh.h"
@@ -444,7 +446,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i));
}
- EditorSceneImporterMeshNode *mi = memnew(EditorSceneImporterMeshNode);
+ EditorSceneImporterMeshNode3D *mi = memnew(EditorSceneImporterMeshNode3D);
mi->set_mesh(mesh);
mi->set_name(E->get()->get_name());
scene->add_child(mi);
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index b591627660..ea16551f18 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -32,6 +32,7 @@
#include "core/io/resource_saver.h"
#include "editor/editor_node.h"
+#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_3d.h"
@@ -120,345 +121,6 @@ void EditorSceneImporter::_bind_methods() {
BIND_CONSTANT(IMPORT_USE_COMPRESSION);
}
-////////////////////////////////////////////////
-
-void EditorSceneImporterMesh::add_blend_shape(const String &p_name) {
- ERR_FAIL_COND(surfaces.size() > 0);
- blend_shapes.push_back(p_name);
-}
-
-int EditorSceneImporterMesh::get_blend_shape_count() const {
- return blend_shapes.size();
-}
-
-String EditorSceneImporterMesh::get_blend_shape_name(int p_blend_shape) const {
- ERR_FAIL_INDEX_V(p_blend_shape, blend_shapes.size(), String());
- return blend_shapes[p_blend_shape];
-}
-
-void EditorSceneImporterMesh::set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode) {
- blend_shape_mode = p_blend_shape_mode;
-}
-Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const {
- return blend_shape_mode;
-}
-
-void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) {
- ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size());
- ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX);
- Surface s;
- s.primitive = p_primitive;
- s.arrays = p_arrays;
- s.name = p_name;
-
- for (int i = 0; i < blend_shapes.size(); i++) {
- Array bsdata = p_blend_shapes[i];
- ERR_FAIL_COND(bsdata.size() != Mesh::ARRAY_MAX);
- Surface::BlendShape bs;
- bs.arrays = bsdata;
- s.blend_shape_data.push_back(bs);
- }
-
- List<Variant> lods;
- p_lods.get_key_list(&lods);
- for (List<Variant>::Element *E = lods.front(); E; E = E->next()) {
- ERR_CONTINUE(!E->get().is_num());
- Surface::LOD lod;
- lod.distance = E->get();
- lod.indices = p_lods[E->get()];
- ERR_CONTINUE(lod.indices.size() == 0);
- s.lods.push_back(lod);
- }
-
- s.material = p_material;
-
- surfaces.push_back(s);
- mesh.unref();
-}
-int EditorSceneImporterMesh::get_surface_count() const {
- return surfaces.size();
-}
-
-Mesh::PrimitiveType EditorSceneImporterMesh::get_surface_primitive_type(int p_surface) {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Mesh::PRIMITIVE_MAX);
- return surfaces[p_surface].primitive;
-}
-Array EditorSceneImporterMesh::get_surface_arrays(int p_surface) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
- return surfaces[p_surface].arrays;
-}
-String EditorSceneImporterMesh::get_surface_name(int p_surface) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), String());
- return surfaces[p_surface].name;
-}
-Array EditorSceneImporterMesh::get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
- ERR_FAIL_INDEX_V(p_blend_shape, surfaces[p_surface].blend_shape_data.size(), Array());
- return surfaces[p_surface].blend_shape_data[p_blend_shape].arrays;
-}
-int EditorSceneImporterMesh::get_surface_lod_count(int p_surface) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
- return surfaces[p_surface].lods.size();
-}
-Vector<int> EditorSceneImporterMesh::get_surface_lod_indices(int p_surface, int p_lod) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Vector<int>());
- ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), Vector<int>());
-
- return surfaces[p_surface].lods[p_lod].indices;
-}
-
-float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
- ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), 0);
- return surfaces[p_surface].lods[p_lod].distance;
-}
-
-Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const {
- ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>());
- return surfaces[p_surface].material;
-}
-
-void EditorSceneImporterMesh::generate_lods() {
- if (!SurfaceTool::simplify_func) {
- return;
- }
-
- for (int i = 0; i < surfaces.size(); i++) {
- if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) {
- continue;
- }
-
- surfaces.write[i].lods.clear();
- Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX];
- Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX];
- if (indices.size() == 0) {
- continue; //no lods if no indices
- }
- uint32_t vertex_count = vertices.size();
- const Vector3 *vertices_ptr = vertices.ptr();
-
- int min_indices = 10;
- int index_target = indices.size() / 2;
- print_line("total: " + itos(indices.size()));
- while (index_target > min_indices) {
- float error;
- Vector<int> new_indices;
- new_indices.resize(indices.size());
- size_t new_len = SurfaceTool::simplify_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, 1e20, &error);
- print_line("shoot for " + itos(index_target) + ", got " + itos(new_len) + " distance " + rtos(error));
- if ((int)new_len > (index_target * 120 / 100)) {
- break; // 20 percent tolerance
- }
- new_indices.resize(new_len);
- Surface::LOD lod;
- lod.distance = error;
- lod.indices = new_indices;
- surfaces.write[i].lods.push_back(lod);
- index_target /= 2;
- }
- }
-}
-
-bool EditorSceneImporterMesh::has_mesh() const {
- return mesh.is_valid();
-}
-
-Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() {
- ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>());
-
- if (mesh.is_null()) {
- mesh.instance();
- for (int i = 0; i < blend_shapes.size(); i++) {
- mesh->add_blend_shape(blend_shapes[i]);
- }
- mesh->set_blend_shape_mode(blend_shape_mode);
- for (int i = 0; i < surfaces.size(); i++) {
- Array bs_data;
- if (surfaces[i].blend_shape_data.size()) {
- for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) {
- bs_data.push_back(surfaces[i].blend_shape_data[j].arrays);
- }
- }
- Dictionary lods;
- if (surfaces[i].lods.size()) {
- for (int j = 0; j < surfaces[i].lods.size(); j++) {
- lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices;
- }
- }
-
- mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods);
- if (surfaces[i].material.is_valid()) {
- mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material);
- }
- if (surfaces[i].name != String()) {
- mesh->surface_set_name(mesh->get_surface_count() - 1, surfaces[i].name);
- }
- }
- }
-
- return mesh;
-}
-
-void EditorSceneImporterMesh::clear() {
- surfaces.clear();
- blend_shapes.clear();
- mesh.unref();
-}
-
-void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) {
- clear();
- if (p_data.has("blend_shape_names")) {
- blend_shapes = p_data["blend_shape_names"];
- }
- if (p_data.has("surfaces")) {
- Array surface_arr = p_data["surfaces"];
- for (int i = 0; i < surface_arr.size(); i++) {
- Dictionary s = surface_arr[i];
- ERR_CONTINUE(!s.has("primitive"));
- ERR_CONTINUE(!s.has("arrays"));
- Mesh::PrimitiveType prim = Mesh::PrimitiveType(int(s["primitive"]));
- ERR_CONTINUE(prim >= Mesh::PRIMITIVE_MAX);
- Array arr = s["arrays"];
- Dictionary lods;
- String name;
- if (s.has("name")) {
- name = s["name"];
- }
- if (s.has("lods")) {
- lods = s["lods"];
- }
- Array blend_shapes;
- if (s.has("blend_shapes")) {
- blend_shapes = s["blend_shapes"];
- }
- Ref<Material> material;
- if (s.has("material")) {
- material = s["material"];
- }
- add_surface(prim, arr, blend_shapes, lods, material, name);
- }
- }
-}
-Dictionary EditorSceneImporterMesh::_get_data() const {
- Dictionary data;
- if (blend_shapes.size()) {
- data["blend_shape_names"] = blend_shapes;
- }
- Array surface_arr;
- for (int i = 0; i < surfaces.size(); i++) {
- Dictionary d;
- d["primitive"] = surfaces[i].primitive;
- d["arrays"] = surfaces[i].arrays;
- if (surfaces[i].blend_shape_data.size()) {
- Array bs_data;
- for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) {
- bs_data.push_back(surfaces[i].blend_shape_data[j].arrays);
- }
- d["blend_shapes"] = bs_data;
- }
- if (surfaces[i].lods.size()) {
- Dictionary lods;
- for (int j = 0; j < surfaces[i].lods.size(); j++) {
- lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices;
- }
- d["lods"] = lods;
- }
-
- if (surfaces[i].material.is_valid()) {
- d["material"] = surfaces[i].material;
- }
-
- if (surfaces[i].name != String()) {
- d["name"] = surfaces[i].name;
- }
-
- surface_arr.push_back(d);
- }
- data["surfaces"] = surface_arr;
- return data;
-}
-
-void EditorSceneImporterMesh::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape);
- ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count);
- ClassDB::bind_method(D_METHOD("get_blend_shape_name", "blend_shape_idx"), &EditorSceneImporterMesh::get_blend_shape_name);
-
- ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode);
- ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode);
-
- ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()));
-
- ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count);
- ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type);
- ClassDB::bind_method(D_METHOD("get_surface_name", "surface_idx"), &EditorSceneImporterMesh::get_surface_name);
- ClassDB::bind_method(D_METHOD("get_surface_arrays", "surface_idx"), &EditorSceneImporterMesh::get_surface_arrays);
- ClassDB::bind_method(D_METHOD("get_surface_blend_shape_arrays", "surface_idx", "blend_shape_idx"), &EditorSceneImporterMesh::get_surface_blend_shape_arrays);
- ClassDB::bind_method(D_METHOD("get_surface_lod_count", "surface_idx"), &EditorSceneImporterMesh::get_surface_lod_count);
- ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size);
- ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices);
- ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material);
-
- ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMesh::get_mesh);
- ClassDB::bind_method(D_METHOD("clear"), &EditorSceneImporterMesh::clear);
-
- ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data);
- ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data);
-
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data");
-}
-
-void EditorSceneImporterMeshNode::set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh) {
- mesh = p_mesh;
-}
-Ref<EditorSceneImporterMesh> EditorSceneImporterMeshNode::get_mesh() const {
- return mesh;
-}
-
-void EditorSceneImporterMeshNode::set_skin(const Ref<Skin> &p_skin) {
- skin = p_skin;
-}
-Ref<Skin> EditorSceneImporterMeshNode::get_skin() const {
- return skin;
-}
-
-void EditorSceneImporterMeshNode::set_surface_material(int p_idx, const Ref<Material> &p_material) {
- ERR_FAIL_COND(p_idx < 0);
- if (p_idx >= surface_materials.size()) {
- surface_materials.resize(p_idx + 1);
- }
-
- surface_materials.write[p_idx] = p_material;
-}
-Ref<Material> EditorSceneImporterMeshNode::get_surface_material(int p_idx) const {
- ERR_FAIL_COND_V(p_idx < 0, Ref<Material>());
- if (p_idx >= surface_materials.size()) {
- return Ref<Material>();
- }
- return surface_materials[p_idx];
-}
-
-void EditorSceneImporterMeshNode::set_skeleton_path(const NodePath &p_path) {
- skeleton_path = p_path;
-}
-NodePath EditorSceneImporterMeshNode::get_skeleton_path() const {
- return skeleton_path;
-}
-
-void EditorSceneImporterMeshNode::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &EditorSceneImporterMeshNode::set_mesh);
- ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMeshNode::get_mesh);
-
- ClassDB::bind_method(D_METHOD("set_skin", "skin"), &EditorSceneImporterMeshNode::set_skin);
- ClassDB::bind_method(D_METHOD("get_skin"), &EditorSceneImporterMeshNode::get_skin);
-
- ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &EditorSceneImporterMeshNode::set_skeleton_path);
- ClassDB::bind_method(D_METHOD("get_skeleton_path"), &EditorSceneImporterMeshNode::get_skeleton_path);
-
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "EditorSceneImporterMesh"), "set_mesh", "get_mesh");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
-}
-
/////////////////////////////////
void EditorScenePostImport::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::OBJECT, "post_import", PropertyInfo(Variant::OBJECT, "scene")));
@@ -1560,27 +1222,30 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito
}
void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods) {
- EditorSceneImporterMeshNode *src_mesh = Object::cast_to<EditorSceneImporterMeshNode>(p_node);
- if (src_mesh != nullptr) {
+ EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node);
+ if (src_mesh_node) {
//is mesh
MeshInstance3D *mesh_node = memnew(MeshInstance3D);
- mesh_node->set_transform(src_mesh->get_transform());
- mesh_node->set_skin(src_mesh->get_skin());
- mesh_node->set_skeleton_path(src_mesh->get_skeleton_path());
-
- Ref<ArrayMesh> mesh;
- if (!src_mesh->get_mesh()->has_mesh()) {
- if (p_generate_lods) {
- src_mesh->get_mesh()->generate_lods();
+ mesh_node->set_name(src_mesh_node->get_name());
+ mesh_node->set_transform(src_mesh_node->get_transform());
+ mesh_node->set_skin(src_mesh_node->get_skin());
+ mesh_node->set_skeleton_path(src_mesh_node->get_skeleton_path());
+ if (src_mesh_node->get_mesh().is_valid()) {
+ Ref<ArrayMesh> mesh;
+ if (!src_mesh_node->get_mesh()->has_mesh()) {
+ //do mesh processing
+ if (p_generate_lods) {
+ src_mesh_node->get_mesh()->generate_lods();
+ }
+ }
+ mesh = src_mesh_node->get_mesh()->get_mesh();
+ if (mesh.is_valid()) {
+ mesh_node->set_mesh(mesh);
+ for (int i = 0; i < mesh->get_surface_count(); i++) {
+ mesh_node->set_surface_material(i, src_mesh_node->get_surface_material(i));
+ }
}
- //do mesh processing
- }
- mesh = src_mesh->get_mesh()->get_mesh();
- mesh_node->set_mesh(mesh);
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- mesh_node->set_surface_material(i, src_mesh->get_surface_material(i));
}
-
p_node->replace_by(mesh_node);
memdelete(p_node);
p_node = mesh_node;
@@ -1803,7 +1468,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
if (!ret_used_cache) {
// Cache was not used, add the generated entry to the current cache
- if (cache_data.empty()) {
+ if (cache_data.is_empty()) {
cache_data.resize(4 + ret_cache_size);
int *data = (int *)cache_data.ptrw();
data[0] = 1;
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index aef6c0ac50..5b70f5bd81 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -90,92 +90,6 @@ public:
EditorScenePostImport();
};
-// The following classes are used by importers instead of ArrayMesh and MeshInstance3D
-// so the data is not reginstered (hence, quality loss), importing happens faster and
-// its easier to modify before saving
-
-class EditorSceneImporterMesh : public Resource {
- GDCLASS(EditorSceneImporterMesh, Resource)
-
- struct Surface {
- Mesh::PrimitiveType primitive;
- Array arrays;
- struct BlendShape {
- Array arrays;
- };
- Vector<BlendShape> blend_shape_data;
- struct LOD {
- Vector<int> indices;
- float distance;
- };
- Vector<LOD> lods;
- Ref<Material> material;
- String name;
- };
- Vector<Surface> surfaces;
- Vector<String> blend_shapes;
- Mesh::BlendShapeMode blend_shape_mode = Mesh::BLEND_SHAPE_MODE_NORMALIZED;
-
- Ref<ArrayMesh> mesh;
-
-protected:
- void _set_data(const Dictionary &p_data);
- Dictionary _get_data() const;
-
- static void _bind_methods();
-
-public:
- void add_blend_shape(const String &p_name);
- int get_blend_shape_count() const;
- String get_blend_shape_name(int p_blend_shape) const;
-
- void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String());
- int get_surface_count() const;
-
- void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode);
- Mesh::BlendShapeMode get_blend_shape_mode() const;
-
- Mesh::PrimitiveType get_surface_primitive_type(int p_surface);
- String get_surface_name(int p_surface) const;
- Array get_surface_arrays(int p_surface) const;
- Array get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const;
- int get_surface_lod_count(int p_surface) const;
- Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const;
- float get_surface_lod_size(int p_surface, int p_lod) const;
- Ref<Material> get_surface_material(int p_surface) const;
-
- void generate_lods();
-
- bool has_mesh() const;
- Ref<ArrayMesh> get_mesh();
- void clear();
-};
-
-class EditorSceneImporterMeshNode : public Node3D {
- GDCLASS(EditorSceneImporterMeshNode, Node3D)
-
- Ref<EditorSceneImporterMesh> mesh;
- Ref<Skin> skin;
- NodePath skeleton_path;
- Vector<Ref<Material>> surface_materials;
-
-protected:
- static void _bind_methods();
-
-public:
- void set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh);
- Ref<EditorSceneImporterMesh> get_mesh() const;
-
- void set_skin(const Ref<Skin> &p_skin);
- Ref<Skin> get_skin() const;
-
- void set_surface_material(int p_idx, const Ref<Material> &p_material);
- Ref<Material> get_surface_material(int p_idx) const;
-
- void set_skeleton_path(const NodePath &p_path);
- NodePath get_skeleton_path() const;
-};
-
class ResourceImporterScene : public ResourceImporter {
GDCLASS(ResourceImporterScene, ResourceImporter);
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index c8dae53722..0bffc4a2d0 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -82,7 +82,7 @@ void ResourceImporterTexture::update_imports() {
MutexLock lock(mutex);
Vector<String> to_reimport;
{
- if (make_flags.empty()) {
+ if (make_flags.is_empty()) {
return;
}
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
new file mode 100644
index 0000000000..d7c3b60d5a
--- /dev/null
+++ b/editor/import/scene_importer_mesh.cpp
@@ -0,0 +1,326 @@
+/*************************************************************************/
+/* scene_importer_mesh.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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. */
+/*************************************************************************/
+
+#include "scene_importer_mesh.h"
+
+#include "scene/resources/surface_tool.h"
+
+void EditorSceneImporterMesh::add_blend_shape(const String &p_name) {
+ ERR_FAIL_COND(surfaces.size() > 0);
+ blend_shapes.push_back(p_name);
+}
+
+int EditorSceneImporterMesh::get_blend_shape_count() const {
+ return blend_shapes.size();
+}
+
+String EditorSceneImporterMesh::get_blend_shape_name(int p_blend_shape) const {
+ ERR_FAIL_INDEX_V(p_blend_shape, blend_shapes.size(), String());
+ return blend_shapes[p_blend_shape];
+}
+
+void EditorSceneImporterMesh::set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode) {
+ blend_shape_mode = p_blend_shape_mode;
+}
+
+Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const {
+ return blend_shape_mode;
+}
+
+void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) {
+ ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size());
+ ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX);
+ Surface s;
+ s.primitive = p_primitive;
+ s.arrays = p_arrays;
+ s.name = p_name;
+
+ Vector<Vector3> vertex_array = p_arrays[Mesh::ARRAY_VERTEX];
+ int vertex_count = vertex_array.size();
+ ERR_FAIL_COND(vertex_count == 0);
+
+ for (int i = 0; i < blend_shapes.size(); i++) {
+ Array bsdata = p_blend_shapes[i];
+ ERR_FAIL_COND(bsdata.size() != Mesh::ARRAY_MAX);
+ Vector<Vector3> vertex_data = bsdata[Mesh::ARRAY_VERTEX];
+ ERR_FAIL_COND(vertex_data.size() != vertex_count);
+ Surface::BlendShape bs;
+ bs.arrays = bsdata;
+ s.blend_shape_data.push_back(bs);
+ }
+
+ List<Variant> lods;
+ p_lods.get_key_list(&lods);
+ for (List<Variant>::Element *E = lods.front(); E; E = E->next()) {
+ ERR_CONTINUE(!E->get().is_num());
+ Surface::LOD lod;
+ lod.distance = E->get();
+ lod.indices = p_lods[E->get()];
+ ERR_CONTINUE(lod.indices.size() == 0);
+ s.lods.push_back(lod);
+ }
+
+ s.material = p_material;
+
+ surfaces.push_back(s);
+ mesh.unref();
+}
+
+int EditorSceneImporterMesh::get_surface_count() const {
+ return surfaces.size();
+}
+
+Mesh::PrimitiveType EditorSceneImporterMesh::get_surface_primitive_type(int p_surface) {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Mesh::PRIMITIVE_MAX);
+ return surfaces[p_surface].primitive;
+}
+Array EditorSceneImporterMesh::get_surface_arrays(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
+ return surfaces[p_surface].arrays;
+}
+String EditorSceneImporterMesh::get_surface_name(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), String());
+ return surfaces[p_surface].name;
+}
+Array EditorSceneImporterMesh::get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array());
+ ERR_FAIL_INDEX_V(p_blend_shape, surfaces[p_surface].blend_shape_data.size(), Array());
+ return surfaces[p_surface].blend_shape_data[p_blend_shape].arrays;
+}
+int EditorSceneImporterMesh::get_surface_lod_count(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
+ return surfaces[p_surface].lods.size();
+}
+Vector<int> EditorSceneImporterMesh::get_surface_lod_indices(int p_surface, int p_lod) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Vector<int>());
+ ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), Vector<int>());
+
+ return surfaces[p_surface].lods[p_lod].indices;
+}
+
+float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
+ ERR_FAIL_INDEX_V(p_lod, surfaces[p_surface].lods.size(), 0);
+ return surfaces[p_surface].lods[p_lod].distance;
+}
+
+Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const {
+ ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>());
+ return surfaces[p_surface].material;
+}
+
+void EditorSceneImporterMesh::generate_lods() {
+ if (!SurfaceTool::simplify_func) {
+ return;
+ }
+
+ for (int i = 0; i < surfaces.size(); i++) {
+ if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) {
+ continue;
+ }
+
+ surfaces.write[i].lods.clear();
+ Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX];
+ Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX];
+ if (indices.size() == 0) {
+ continue; //no lods if no indices
+ }
+ uint32_t vertex_count = vertices.size();
+ const Vector3 *vertices_ptr = vertices.ptr();
+
+ int min_indices = 10;
+ int index_target = indices.size() / 2;
+ print_line("total: " + itos(indices.size()));
+ while (index_target > min_indices) {
+ float error;
+ Vector<int> new_indices;
+ new_indices.resize(indices.size());
+ size_t new_len = SurfaceTool::simplify_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, 1e20, &error);
+ print_line("shoot for " + itos(index_target) + ", got " + itos(new_len) + " distance " + rtos(error));
+ if ((int)new_len > (index_target * 120 / 100)) {
+ break; // 20 percent tolerance
+ }
+ new_indices.resize(new_len);
+ Surface::LOD lod;
+ lod.distance = error;
+ lod.indices = new_indices;
+ surfaces.write[i].lods.push_back(lod);
+ index_target /= 2;
+ }
+ }
+}
+
+bool EditorSceneImporterMesh::has_mesh() const {
+ return mesh.is_valid();
+}
+
+Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh() {
+ ERR_FAIL_COND_V(surfaces.size() == 0, Ref<ArrayMesh>());
+
+ if (mesh.is_null()) {
+ mesh.instance();
+ for (int i = 0; i < blend_shapes.size(); i++) {
+ mesh->add_blend_shape(blend_shapes[i]);
+ }
+ mesh->set_blend_shape_mode(blend_shape_mode);
+ for (int i = 0; i < surfaces.size(); i++) {
+ Array bs_data;
+ if (surfaces[i].blend_shape_data.size()) {
+ for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) {
+ bs_data.push_back(surfaces[i].blend_shape_data[j].arrays);
+ }
+ }
+ Dictionary lods;
+ if (surfaces[i].lods.size()) {
+ for (int j = 0; j < surfaces[i].lods.size(); j++) {
+ lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices;
+ }
+ }
+
+ mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods);
+ if (surfaces[i].material.is_valid()) {
+ mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material);
+ }
+ if (surfaces[i].name != String()) {
+ mesh->surface_set_name(mesh->get_surface_count() - 1, surfaces[i].name);
+ }
+ }
+ }
+
+ return mesh;
+}
+
+void EditorSceneImporterMesh::clear() {
+ surfaces.clear();
+ blend_shapes.clear();
+ mesh.unref();
+}
+
+void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) {
+ clear();
+ if (p_data.has("blend_shape_names")) {
+ blend_shapes = p_data["blend_shape_names"];
+ }
+ if (p_data.has("surfaces")) {
+ Array surface_arr = p_data["surfaces"];
+ for (int i = 0; i < surface_arr.size(); i++) {
+ Dictionary s = surface_arr[i];
+ ERR_CONTINUE(!s.has("primitive"));
+ ERR_CONTINUE(!s.has("arrays"));
+ Mesh::PrimitiveType prim = Mesh::PrimitiveType(int(s["primitive"]));
+ ERR_CONTINUE(prim >= Mesh::PRIMITIVE_MAX);
+ Array arr = s["arrays"];
+ Dictionary lods;
+ String name;
+ if (s.has("name")) {
+ name = s["name"];
+ }
+ if (s.has("lods")) {
+ lods = s["lods"];
+ }
+ Array blend_shapes;
+ if (s.has("blend_shapes")) {
+ blend_shapes = s["blend_shapes"];
+ }
+ Ref<Material> material;
+ if (s.has("material")) {
+ material = s["material"];
+ }
+ add_surface(prim, arr, blend_shapes, lods, material, name);
+ }
+ }
+}
+Dictionary EditorSceneImporterMesh::_get_data() const {
+ Dictionary data;
+ if (blend_shapes.size()) {
+ data["blend_shape_names"] = blend_shapes;
+ }
+ Array surface_arr;
+ for (int i = 0; i < surfaces.size(); i++) {
+ Dictionary d;
+ d["primitive"] = surfaces[i].primitive;
+ d["arrays"] = surfaces[i].arrays;
+ if (surfaces[i].blend_shape_data.size()) {
+ Array bs_data;
+ for (int j = 0; j < surfaces[i].blend_shape_data.size(); j++) {
+ bs_data.push_back(surfaces[i].blend_shape_data[j].arrays);
+ }
+ d["blend_shapes"] = bs_data;
+ }
+ if (surfaces[i].lods.size()) {
+ Dictionary lods;
+ for (int j = 0; j < surfaces[i].lods.size(); j++) {
+ lods[surfaces[i].lods[j].distance] = surfaces[i].lods[j].indices;
+ }
+ d["lods"] = lods;
+ }
+
+ if (surfaces[i].material.is_valid()) {
+ d["material"] = surfaces[i].material;
+ }
+
+ if (surfaces[i].name != String()) {
+ d["name"] = surfaces[i].name;
+ }
+
+ surface_arr.push_back(d);
+ }
+ data["surfaces"] = surface_arr;
+ return data;
+}
+
+void EditorSceneImporterMesh::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &EditorSceneImporterMesh::add_blend_shape);
+ ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &EditorSceneImporterMesh::get_blend_shape_count);
+ ClassDB::bind_method(D_METHOD("get_blend_shape_name", "blend_shape_idx"), &EditorSceneImporterMesh::get_blend_shape_name);
+
+ ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode);
+
+ ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()));
+
+ ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count);
+ ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type);
+ ClassDB::bind_method(D_METHOD("get_surface_name", "surface_idx"), &EditorSceneImporterMesh::get_surface_name);
+ ClassDB::bind_method(D_METHOD("get_surface_arrays", "surface_idx"), &EditorSceneImporterMesh::get_surface_arrays);
+ ClassDB::bind_method(D_METHOD("get_surface_blend_shape_arrays", "surface_idx", "blend_shape_idx"), &EditorSceneImporterMesh::get_surface_blend_shape_arrays);
+ ClassDB::bind_method(D_METHOD("get_surface_lod_count", "surface_idx"), &EditorSceneImporterMesh::get_surface_lod_count);
+ ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size);
+ ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices);
+ ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material);
+
+ ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMesh::get_mesh);
+ ClassDB::bind_method(D_METHOD("clear"), &EditorSceneImporterMesh::clear);
+
+ ClassDB::bind_method(D_METHOD("_set_data", "data"), &EditorSceneImporterMesh::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"), &EditorSceneImporterMesh::_get_data);
+
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data");
+}
diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h
new file mode 100644
index 0000000000..7efe2f2ffb
--- /dev/null
+++ b/editor/import/scene_importer_mesh.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* scene_importer_mesh.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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 EDITOR_SCENE_IMPORTER_MESH_H
+#define EDITOR_SCENE_IMPORTER_MESH_H
+
+#include "core/io/resource.h"
+#include "scene/resources/mesh.h"
+// The following classes are used by importers instead of ArrayMesh and MeshInstance3D
+// so the data is not registered (hence, quality loss), importing happens faster and
+// its easier to modify before saving
+
+class EditorSceneImporterMesh : public Resource {
+ GDCLASS(EditorSceneImporterMesh, Resource)
+
+ struct Surface {
+ Mesh::PrimitiveType primitive;
+ Array arrays;
+ struct BlendShape {
+ Array arrays;
+ };
+ Vector<BlendShape> blend_shape_data;
+ struct LOD {
+ Vector<int> indices;
+ float distance;
+ };
+ Vector<LOD> lods;
+ Ref<Material> material;
+ String name;
+ };
+ Vector<Surface> surfaces;
+ Vector<String> blend_shapes;
+ Mesh::BlendShapeMode blend_shape_mode = Mesh::BLEND_SHAPE_MODE_NORMALIZED;
+
+ Ref<ArrayMesh> mesh;
+
+protected:
+ void _set_data(const Dictionary &p_data);
+ Dictionary _get_data() const;
+
+ static void _bind_methods();
+
+public:
+ void add_blend_shape(const String &p_name);
+ int get_blend_shape_count() const;
+ String get_blend_shape_name(int p_blend_shape) const;
+
+ void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String());
+ int get_surface_count() const;
+
+ void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode);
+ Mesh::BlendShapeMode get_blend_shape_mode() const;
+
+ Mesh::PrimitiveType get_surface_primitive_type(int p_surface);
+ String get_surface_name(int p_surface) const;
+ Array get_surface_arrays(int p_surface) const;
+ Array get_surface_blend_shape_arrays(int p_surface, int p_blend_shape) const;
+ int get_surface_lod_count(int p_surface) const;
+ Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const;
+ float get_surface_lod_size(int p_surface, int p_lod) const;
+ Ref<Material> get_surface_material(int p_surface) const;
+
+ void generate_lods();
+
+ bool has_mesh() const;
+ Ref<ArrayMesh> get_mesh();
+ void clear();
+};
+#endif // EDITOR_SCENE_IMPORTER_MESH_H
diff --git a/editor/import/scene_importer_mesh_node_3d.cpp b/editor/import/scene_importer_mesh_node_3d.cpp
new file mode 100644
index 0000000000..53929f77b0
--- /dev/null
+++ b/editor/import/scene_importer_mesh_node_3d.cpp
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* scene_importer_mesh_node_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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. */
+/*************************************************************************/
+
+#include "scene_importer_mesh_node_3d.h"
+
+void EditorSceneImporterMeshNode3D::set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh) {
+ mesh = p_mesh;
+}
+Ref<EditorSceneImporterMesh> EditorSceneImporterMeshNode3D::get_mesh() const {
+ return mesh;
+}
+
+void EditorSceneImporterMeshNode3D::set_skin(const Ref<Skin> &p_skin) {
+ skin = p_skin;
+}
+Ref<Skin> EditorSceneImporterMeshNode3D::get_skin() const {
+ return skin;
+}
+
+void EditorSceneImporterMeshNode3D::set_surface_material(int p_idx, const Ref<Material> &p_material) {
+ ERR_FAIL_COND(p_idx < 0);
+ if (p_idx >= surface_materials.size()) {
+ surface_materials.resize(p_idx + 1);
+ }
+
+ surface_materials.write[p_idx] = p_material;
+}
+Ref<Material> EditorSceneImporterMeshNode3D::get_surface_material(int p_idx) const {
+ ERR_FAIL_COND_V(p_idx < 0, Ref<Material>());
+ if (p_idx >= surface_materials.size()) {
+ return Ref<Material>();
+ }
+ return surface_materials[p_idx];
+}
+
+void EditorSceneImporterMeshNode3D::set_skeleton_path(const NodePath &p_path) {
+ skeleton_path = p_path;
+}
+NodePath EditorSceneImporterMeshNode3D::get_skeleton_path() const {
+ return skeleton_path;
+}
+
+void EditorSceneImporterMeshNode3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &EditorSceneImporterMeshNode3D::set_mesh);
+ ClassDB::bind_method(D_METHOD("get_mesh"), &EditorSceneImporterMeshNode3D::get_mesh);
+
+ ClassDB::bind_method(D_METHOD("set_skin", "skin"), &EditorSceneImporterMeshNode3D::set_skin);
+ ClassDB::bind_method(D_METHOD("get_skin"), &EditorSceneImporterMeshNode3D::get_skin);
+
+ ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &EditorSceneImporterMeshNode3D::set_skeleton_path);
+ ClassDB::bind_method(D_METHOD("get_skeleton_path"), &EditorSceneImporterMeshNode3D::get_skeleton_path);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "EditorSceneImporterMesh"), "set_mesh", "get_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
+}
diff --git a/editor/import/scene_importer_mesh_node_3d.h b/editor/import/scene_importer_mesh_node_3d.h
new file mode 100644
index 0000000000..9540e3b886
--- /dev/null
+++ b/editor/import/scene_importer_mesh_node_3d.h
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* scene_importer_mesh_node_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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 EDITOR_SCENE_IMPORTER_MESH_NODE_3D_H
+#define EDITOR_SCENE_IMPORTER_MESH_NODE_3D_H
+
+#include "editor/import/scene_importer_mesh.h"
+#include "scene/3d/node_3d.h"
+#include "scene/resources/skin.h"
+
+class EditorSceneImporterMesh;
+
+class EditorSceneImporterMeshNode3D : public Node3D {
+ GDCLASS(EditorSceneImporterMeshNode3D, Node3D)
+
+ Ref<EditorSceneImporterMesh> mesh;
+ Ref<Skin> skin;
+ NodePath skeleton_path;
+ Vector<Ref<Material>> surface_materials;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_mesh(const Ref<EditorSceneImporterMesh> &p_mesh);
+ Ref<EditorSceneImporterMesh> get_mesh() const;
+
+ void set_skin(const Ref<Skin> &p_skin);
+ Ref<Skin> get_skin() const;
+
+ void set_surface_material(int p_idx, const Ref<Material> &p_material);
+ Ref<Material> get_surface_material(int p_idx) const;
+
+ void set_skeleton_path(const NodePath &p_path);
+ NodePath get_skeleton_path() const;
+};
+#endif
diff --git a/editor/input_map_editor.cpp b/editor/input_map_editor.cpp
index 83adccb752..249b9770b1 100644
--- a/editor/input_map_editor.cpp
+++ b/editor/input_map_editor.cpp
@@ -921,10 +921,10 @@ InputMapEditor::InputMapEditor() {
inputmap_changed = "inputmap_changed";
VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 0);
- vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, 0);
- vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 0);
- vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, 0);
+ vbc->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 0);
+ vbc->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, 0);
+ vbc->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 0);
+ vbc->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, 0);
add_child(vbc);
HBoxContainer *hbc = memnew(HBoxContainer);
@@ -986,10 +986,10 @@ InputMapEditor::InputMapEditor() {
l = memnew(Label);
l->set_text(TTR("Press a Key..."));
- l->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ l->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
l->set_align(Label::ALIGN_CENTER);
- l->set_margin(MARGIN_TOP, 20);
- l->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_BEGIN, 30);
+ l->set_offset(SIDE_TOP, 20);
+ l->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_BEGIN, 30);
press_a_key->add_child(l);
press_a_key_label = l;
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index e0ba50fe4f..0620d572e3 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -452,7 +452,7 @@ void InspectorDock::update(Object *p_object) {
List<MethodInfo> methods;
p_object->get_method_list(&methods);
- if (!methods.empty()) {
+ if (!methods.is_empty()) {
bool found = false;
List<MethodInfo>::Element *I = methods.front();
int i = 0;
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp
index 45fea20594..71ceff7fee 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/node_3d_editor_gizmos.cpp
@@ -198,7 +198,7 @@ void EditorNode3DGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard,
}
void EditorNode3DGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard, const Color &p_modulate) {
- if (p_lines.empty()) {
+ if (p_lines.is_empty()) {
return;
}
@@ -4205,7 +4205,7 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
}
- if (faces.empty()) {
+ if (faces.is_empty()) {
return;
}
@@ -4521,7 +4521,7 @@ Joint3DGizmoPlugin::Joint3DGizmoPlugin() {
}
void Joint3DGizmoPlugin::incremental_update_gizmos() {
- if (!current_gizmos.empty()) {
+ if (!current_gizmos.is_empty()) {
update_idx++;
update_idx = update_idx % current_gizmos.size();
redraw(current_gizmos[update_idx]);
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index a780750633..c63f51c512 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -126,7 +126,7 @@ void PluginConfigDialog::_on_cancelled() {
void PluginConfigDialog::_on_required_text_changed(const String &) {
int lang_idx = script_option_edit->get_selected();
String ext = ScriptServer::get_language(lang_idx)->get_extension();
- get_ok_button()->set_disabled(script_edit->get_text().get_basename().empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().empty());
+ get_ok_button()->set_disabled(script_edit->get_text().get_basename().is_empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().is_empty());
}
void PluginConfigDialog::_notification(int p_what) {
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 38648b5f0a..d301e8ff7b 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -127,7 +127,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
Ref<AnimationNode> agnode = blend_tree->get_node(E->get());
- node->set_offset(blend_tree->get_node_position(E->get()) * EDSCALE);
+ node->set_position_offset(blend_tree->get_node_position(E->get()) * EDSCALE);
node->set_title(agnode->get_caption());
node->set_name(E->get());
@@ -416,7 +416,7 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request() {
}
}
- if (to_erase.empty()) {
+ if (to_erase.is_empty()) {
return;
}
@@ -537,7 +537,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
default: {
} break;
}
- if (!track_type_name.empty()) {
+ if (!track_type_name.is_empty()) {
types[track_path].insert(track_type_name);
}
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 7e376eee57..491aab1258 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -116,6 +116,19 @@ void AnimationPlayerEditor::_notification(int p_what) {
play_bw_from->set_icon(get_theme_icon("PlayBackwards", "EditorIcons"));
autoplay_icon = get_theme_icon("AutoPlay", "EditorIcons");
+ reset_icon = get_theme_icon("Reload", "EditorIcons");
+ {
+ Ref<Image> autoplay_img = autoplay_icon->get_data();
+ Ref<Image> reset_img = reset_icon->get_data();
+ Ref<Image> autoplay_reset_img;
+ Size2 icon_size = Size2(autoplay_img->get_width(), autoplay_img->get_height());
+ autoplay_reset_img.instance();
+ autoplay_reset_img->create(icon_size.x * 2, icon_size.y, false, autoplay_img->get_format());
+ autoplay_reset_img->blit_rect(autoplay_img, Rect2(Point2(), icon_size), Point2());
+ autoplay_reset_img->blit_rect(reset_img, Rect2(Point2(), icon_size), Point2(icon_size.x, 0));
+ autoplay_reset_icon.instance();
+ autoplay_reset_icon->create_from_image(autoplay_reset_img);
+ }
stop->set_icon(get_theme_icon("Stop", "EditorIcons"));
onion_toggle->set_icon(get_theme_icon("Onion", "EditorIcons"));
@@ -667,7 +680,7 @@ void AnimationPlayerEditor::set_state(const Dictionary &p_state) {
if (p_state.has("animation")) {
String anim = p_state["animation"];
- if (!anim.empty() && player->has_animation(anim)) {
+ if (!anim.is_empty() && player->has_animation(anim)) {
_select_anim_by_name(anim);
_animation_edit();
}
@@ -817,11 +830,17 @@ void AnimationPlayerEditor::_update_player() {
int active_idx = -1;
for (List<StringName>::Element *E = animlist.front(); E; E = E->next()) {
- if (player->get_autoplay() == E->get()) {
- animation->add_icon_item(autoplay_icon, E->get());
- } else {
- animation->add_item(E->get());
+ Ref<Texture2D> icon;
+ if (E->get() == player->get_autoplay()) {
+ if (E->get() == "RESET") {
+ icon = autoplay_reset_icon;
+ } else {
+ icon = autoplay_icon;
+ }
+ } else if (E->get() == "RESET") {
+ icon = reset_icon;
}
+ animation->add_icon_item(icon, E->get());
if (player->get_assigned_animation() == E->get()) {
active_idx = animation->get_item_count() - 1;
@@ -1375,7 +1394,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
}
// Backup current animation state.
- AnimatedValuesBackup values_backup = player->backup_animated_values();
+ Ref<AnimatedValuesBackup> values_backup = player->backup_animated_values();
float cpos = player->get_current_animation_position();
// Render every past/future step with the capture shader.
@@ -1405,7 +1424,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
if (valid) {
player->seek(pos, true);
get_tree()->flush_transform_notifications(); // Needed for transforms of Node3Ds.
- values_backup.update_skeletons(); // Needed for Skeletons (2D & 3D).
+ values_backup->update_skeletons(); // Needed for Skeletons (2D & 3D).
RS::get_singleton()->viewport_set_active(onion.captures[cidx], true);
RS::get_singleton()->viewport_set_parent_viewport(root_vp, onion.captures[cidx]);
@@ -1425,7 +1444,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
// (Seeking with update=true wouldn't do the trick because the current value of the properties
// may not match their value for the current point in the animation).
player->seek(cpos, false);
- player->restore_animated_values(values_backup);
+ values_backup->restore();
// Restore state of main editors.
if (Node3DEditor::get_singleton()->is_visible()) {
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 17e554ee0d..ab3feb115f 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -105,6 +105,8 @@ class AnimationPlayerEditor : public VBoxContainer {
Label *name_title;
UndoRedo *undo_redo;
Ref<Texture2D> autoplay_icon;
+ Ref<Texture2D> reset_icon;
+ Ref<ImageTexture> autoplay_reset_icon;
bool last_active;
float timeline_position;
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index c59e056f4f..6fa1792c67 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1291,18 +1291,18 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
state_machine_play_pos = memnew(Control);
state_machine_draw->add_child(state_machine_play_pos);
state_machine_play_pos->set_mouse_filter(MOUSE_FILTER_PASS); //pass all to parent
- state_machine_play_pos->set_anchors_and_margins_preset(PRESET_WIDE);
+ state_machine_play_pos->set_anchors_and_offsets_preset(PRESET_WIDE);
state_machine_play_pos->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_pos_draw));
v_scroll = memnew(VScrollBar);
state_machine_draw->add_child(v_scroll);
- v_scroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
+ v_scroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
v_scroll->connect("value_changed", callable_mp(this, &AnimationNodeStateMachineEditor::_scroll_changed));
h_scroll = memnew(HScrollBar);
state_machine_draw->add_child(h_scroll);
- h_scroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
- h_scroll->set_margin(MARGIN_RIGHT, -v_scroll->get_size().x * EDSCALE);
+ h_scroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
+ h_scroll->set_offset(SIDE_RIGHT, -v_scroll->get_size().x * EDSCALE);
h_scroll->connect("value_changed", callable_mp(this, &AnimationNodeStateMachineEditor::_scroll_changed));
error_panel = memnew(PanelContainer);
@@ -1328,7 +1328,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
add_child(name_edit_popup);
name_edit = memnew(LineEdit);
name_edit_popup->add_child(name_edit);
- name_edit->set_anchors_and_margins_preset(PRESET_WIDE);
+ name_edit->set_anchors_and_offsets_preset(PRESET_WIDE);
name_edit->connect("text_entered", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited));
name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out));
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index ba798a7826..6420a28d50 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -87,10 +87,10 @@ void EditorAssetLibraryItem::_bind_methods() {
EditorAssetLibraryItem::EditorAssetLibraryItem() {
Ref<StyleBoxEmpty> border;
border.instance();
- border->set_default_margin(MARGIN_LEFT, 5 * EDSCALE);
- border->set_default_margin(MARGIN_RIGHT, 5 * EDSCALE);
- border->set_default_margin(MARGIN_BOTTOM, 5 * EDSCALE);
- border->set_default_margin(MARGIN_TOP, 5 * EDSCALE);
+ border->set_default_margin(SIDE_LEFT, 5 * EDSCALE);
+ border->set_default_margin(SIDE_RIGHT, 5 * EDSCALE);
+ border->set_default_margin(SIDE_BOTTOM, 5 * EDSCALE);
+ border->set_default_margin(SIDE_TOP, 5 * EDSCALE);
add_theme_style_override("panel", border);
HBoxContainer *hb = memnew(HBoxContainer);
@@ -702,7 +702,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
}
}
- if (!image->empty()) {
+ if (!image->is_empty()) {
switch (image_queue[p_queue_id].image_type) {
case IMAGE_QUEUE_ICON:
@@ -1151,7 +1151,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
asset_bottom_page = _make_pages(page, pages, page_len, total_items, result.size());
library_vb->add_child(asset_bottom_page);
- if (result.empty()) {
+ if (result.is_empty()) {
if (filter->get_text() != String()) {
library_error->set_text(
vformat(TTR("No results for \"%s\"."), filter->get_text()));
@@ -1188,7 +1188,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
}
}
- if (!result.empty()) {
+ if (!result.is_empty()) {
library_scroll->set_v_scroll(0);
}
} break;
@@ -1400,10 +1400,10 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
Ref<StyleBoxEmpty> border2;
border2.instance();
- border2->set_default_margin(MARGIN_LEFT, 15 * EDSCALE);
- border2->set_default_margin(MARGIN_RIGHT, 35 * EDSCALE);
- border2->set_default_margin(MARGIN_BOTTOM, 15 * EDSCALE);
- border2->set_default_margin(MARGIN_TOP, 15 * EDSCALE);
+ border2->set_default_margin(SIDE_LEFT, 15 * EDSCALE);
+ border2->set_default_margin(SIDE_RIGHT, 35 * EDSCALE);
+ border2->set_default_margin(SIDE_BOTTOM, 15 * EDSCALE);
+ border2->set_default_margin(SIDE_TOP, 15 * EDSCALE);
PanelContainer *library_vb_border = memnew(PanelContainer);
library_scroll->add_child(library_vb_border);
@@ -1493,7 +1493,7 @@ AssetLibraryEditorPlugin::AssetLibraryEditorPlugin(EditorNode *p_node) {
addon_library = memnew(EditorAssetLibrary);
addon_library->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->get_viewport()->add_child(addon_library);
- addon_library->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ addon_library->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
addon_library->hide();
}
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index 998916349c..5041cf9f32 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -202,7 +202,7 @@ AudioStreamEditor::AudioStreamEditor() {
add_child(_player);
VBoxContainer *vbox = memnew(VBoxContainer);
- vbox->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_MINSIZE, 0);
+ vbox->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_MINSIZE, 0);
add_child(vbox);
_preview = memnew(ColorRect);
@@ -211,7 +211,7 @@ AudioStreamEditor::AudioStreamEditor() {
vbox->add_child(_preview);
_indicator = memnew(Control);
- _indicator->set_anchors_and_margins_preset(PRESET_WIDE);
+ _indicator->set_anchors_and_offsets_preset(PRESET_WIDE);
_indicator->connect("draw", callable_mp(this, &AudioStreamEditor::_draw_indicator));
_indicator->connect("gui_input", callable_mp(this, &AudioStreamEditor::_on_input_indicator));
_preview->add_child(_indicator);
diff --git a/editor/plugins/camera_3d_editor_plugin.cpp b/editor/plugins/camera_3d_editor_plugin.cpp
index 48f9f208a5..9a5cfd35cd 100644
--- a/editor/plugins/camera_3d_editor_plugin.cpp
+++ b/editor/plugins/camera_3d_editor_plugin.cpp
@@ -69,12 +69,12 @@ Camera3DEditor::Camera3DEditor() {
preview->set_text(TTR("Preview"));
preview->set_toggle_mode(true);
- preview->set_anchor(MARGIN_LEFT, Control::ANCHOR_END);
- preview->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
- preview->set_margin(MARGIN_LEFT, -60);
- preview->set_margin(MARGIN_RIGHT, 0);
- preview->set_margin(MARGIN_TOP, 0);
- preview->set_margin(MARGIN_BOTTOM, 10);
+ preview->set_anchor(SIDE_LEFT, Control::ANCHOR_END);
+ preview->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
+ preview->set_offset(SIDE_LEFT, -60);
+ preview->set_offset(SIDE_RIGHT, 0);
+ preview->set_offset(SIDE_TOP, 0);
+ preview->set_offset(SIDE_BOTTOM, 10);
preview->connect("pressed", callable_mp(this, &Camera3DEditor::_pressed));
}
@@ -100,12 +100,12 @@ Camera3DEditorPlugin::Camera3DEditorPlugin(EditorNode *p_node) {
/* camera_editor = memnew( CameraEditor );
editor->get_viewport()->add_child(camera_editor);
- camera_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- camera_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- camera_editor->set_margin(MARGIN_LEFT,60);
- camera_editor->set_margin(MARGIN_RIGHT,0);
- camera_editor->set_margin(MARGIN_TOP,0);
- camera_editor->set_margin(MARGIN_BOTTOM,10);
+ camera_editor->set_anchor(SIDE_LEFT,Control::ANCHOR_END);
+ camera_editor->set_anchor(SIDE_RIGHT,Control::ANCHOR_END);
+ camera_editor->set_offset(SIDE_LEFT,60);
+ camera_editor->set_offset(SIDE_RIGHT,0);
+ camera_editor->set_offset(SIDE_TOP,0);
+ camera_editor->set_offset(SIDE_BOTTOM,10);
camera_editor->hide();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 2a4cc691c3..ecd0a20c1a 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -366,8 +366,8 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
// Self anchors
if ((is_snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) {
if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
- Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
- Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
+ Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(SIDE_LEFT), c->get_anchor(SIDE_TOP))));
+ Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(SIDE_RIGHT), c->get_anchor(SIDE_BOTTOM))));
_snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF_ANCHORS, rotation);
_snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF_ANCHORS, rotation);
}
@@ -518,7 +518,7 @@ void CanvasItemEditor::_keying_changed() {
}
Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_list) {
- ERR_FAIL_COND_V(p_list.empty(), Rect2());
+ ERR_FAIL_COND_V(p_list.is_empty(), Rect2());
// Handles the first element
CanvasItem *canvas_item = p_list.front()->get();
@@ -1147,7 +1147,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
if (dragged_guide_index >= 0) {
vguides.remove(dragged_guide_index);
undo_redo->create_action(TTR("Remove Vertical Guide"));
- if (vguides.empty()) {
+ if (vguides.is_empty()) {
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_vertical_guides_");
} else {
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
@@ -1180,7 +1180,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
if (dragged_guide_index >= 0) {
hguides.remove(dragged_guide_index);
undo_redo->create_action(TTR("Remove Horizontal Guide"));
- if (hguides.empty()) {
+ if (hguides.is_empty()) {
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_horizontal_guides_");
} else {
undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
@@ -1628,10 +1628,10 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
Control *control = Object::cast_to<Control>(selection[0]);
if (control && _is_node_movable(control)) {
Vector2 anchor_pos[4];
- anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP));
- anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP));
- anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM));
- anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM));
+ anchor_pos[0] = Vector2(control->get_anchor(SIDE_LEFT), control->get_anchor(SIDE_TOP));
+ anchor_pos[1] = Vector2(control->get_anchor(SIDE_RIGHT), control->get_anchor(SIDE_TOP));
+ anchor_pos[2] = Vector2(control->get_anchor(SIDE_RIGHT), control->get_anchor(SIDE_BOTTOM));
+ anchor_pos[3] = Vector2(control->get_anchor(SIDE_LEFT), control->get_anchor(SIDE_BOTTOM));
Rect2 anchor_rects[4];
for (int i = 0; i < 4; i++) {
@@ -1681,8 +1681,8 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
Transform2D xform = control->get_global_transform_with_canvas().affine_inverse();
Point2 previous_anchor;
- previous_anchor.x = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT) ? control->get_anchor(MARGIN_LEFT) : control->get_anchor(MARGIN_RIGHT);
- previous_anchor.y = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT) ? control->get_anchor(MARGIN_TOP) : control->get_anchor(MARGIN_BOTTOM);
+ previous_anchor.x = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_BOTTOM_LEFT) ? control->get_anchor(SIDE_LEFT) : control->get_anchor(SIDE_RIGHT);
+ previous_anchor.y = (drag_type == DRAG_ANCHOR_TOP_LEFT || drag_type == DRAG_ANCHOR_TOP_RIGHT) ? control->get_anchor(SIDE_TOP) : control->get_anchor(SIDE_BOTTOM);
previous_anchor = xform.affine_inverse().xform(_anchor_to_position(control, previous_anchor));
Vector2 new_anchor = xform.xform(snap_point(previous_anchor + (drag_to - drag_from), SNAP_GRID | SNAP_OTHER_NODES, SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER, control));
@@ -1695,44 +1695,44 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
switch (drag_type) {
case DRAG_ANCHOR_TOP_LEFT:
if (!use_single_axis || !use_y) {
- control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
+ control->set_anchor(SIDE_LEFT, new_anchor.x, false, false);
}
if (!use_single_axis || use_y) {
- control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
+ control->set_anchor(SIDE_TOP, new_anchor.y, false, false);
}
break;
case DRAG_ANCHOR_TOP_RIGHT:
if (!use_single_axis || !use_y) {
- control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
+ control->set_anchor(SIDE_RIGHT, new_anchor.x, false, false);
}
if (!use_single_axis || use_y) {
- control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
+ control->set_anchor(SIDE_TOP, new_anchor.y, false, false);
}
break;
case DRAG_ANCHOR_BOTTOM_RIGHT:
if (!use_single_axis || !use_y) {
- control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
+ control->set_anchor(SIDE_RIGHT, new_anchor.x, false, false);
}
if (!use_single_axis || use_y) {
- control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
+ control->set_anchor(SIDE_BOTTOM, new_anchor.y, false, false);
}
break;
case DRAG_ANCHOR_BOTTOM_LEFT:
if (!use_single_axis || !use_y) {
- control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
+ control->set_anchor(SIDE_LEFT, new_anchor.x, false, false);
}
if (!use_single_axis || use_y) {
- control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
+ control->set_anchor(SIDE_BOTTOM, new_anchor.y, false, false);
}
break;
case DRAG_ANCHOR_ALL:
if (!use_single_axis || !use_y) {
- control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
- control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
+ control->set_anchor(SIDE_LEFT, new_anchor.x, false, true);
+ control->set_anchor(SIDE_RIGHT, new_anchor.x, false, true);
}
if (!use_single_axis || use_y) {
- control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
- control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
+ control->set_anchor(SIDE_TOP, new_anchor.y, false, true);
+ control->set_anchor(SIDE_BOTTOM, new_anchor.y, false, true);
}
break;
default:
@@ -2400,7 +2400,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
_select_click_on_item(item, click, b->get_shift());
return true;
- } else if (!selection_results.empty()) {
+ } else if (!selection_results.is_empty()) {
// Sorts items according the their z-index
selection_results.sort();
@@ -2463,13 +2463,13 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
// Retrieve the bones
Vector<_SelectResult> selection = Vector<_SelectResult>();
_get_bones_at_pos(click, selection);
- if (!selection.empty()) {
+ if (!selection.is_empty()) {
canvas_item = selection[0].item;
} else {
// Retrieve the canvas items
selection = Vector<_SelectResult>();
_get_canvas_items_at_pos(click, selection);
- if (!selection.empty()) {
+ if (!selection.is_empty()) {
canvas_item = selection[0].item;
}
}
@@ -2780,37 +2780,37 @@ void CanvasItemEditor::_update_cursor() {
viewport->set_default_cursor_shape(c);
}
-void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) {
+void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Side p_side) {
Color color = get_theme_color("font_color", "Editor");
color.a = 0.8;
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Size2 text_size = font->get_string_size(p_string, font_size);
switch (p_side) {
- case MARGIN_LEFT:
+ case SIDE_LEFT:
p_position += Vector2(-text_size.x - 5, text_size.y / 2);
break;
- case MARGIN_TOP:
+ case SIDE_TOP:
p_position += Vector2(-text_size.x / 2, -5);
break;
- case MARGIN_RIGHT:
+ case SIDE_RIGHT:
p_position += Vector2(5, text_size.y / 2);
break;
- case MARGIN_BOTTOM:
+ case SIDE_BOTTOM:
p_position += Vector2(-text_size.x / 2, text_size.y + 5);
break;
}
viewport->draw_string(font, p_position, p_string, HALIGN_LEFT, -1, font_size, color);
}
-void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) {
+void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Side p_side) {
String str = TS->format_number(vformat("%d " + TTR("px"), p_value));
if (p_value != 0) {
_draw_text_at_position(p_position, str, p_side);
}
}
-void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) {
+void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Side p_side) {
String str = TS->format_number(vformat("%.1f ", p_value * 100.0)) + TS->percent_sign();
if (p_value != 0) {
_draw_text_at_position(p_position, str, p_side);
@@ -2935,7 +2935,7 @@ void CanvasItemEditor::_draw_rulers() {
// Draw top ruler
viewport->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color);
for (int i = Math::ceil(first.x); i < last.x; i++) {
- Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0));
+ Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).round();
if (i % (major_subdivision * minor_subdivision) == 0) {
viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
@@ -2952,7 +2952,7 @@ void CanvasItemEditor::_draw_rulers() {
// Draw left ruler
viewport->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color);
for (int i = Math::ceil(first.y); i < last.y; i++) {
- Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i));
+ Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).round();
if (i % (major_subdivision * minor_subdivision) == 0) {
viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y;
@@ -3185,10 +3185,10 @@ void CanvasItemEditor::_draw_control_anchors(Control *control) {
if (tool == TOOL_SELECT && !Object::cast_to<Container>(control->get_parent())) {
// Compute the anchors
float anchors_values[4];
- anchors_values[0] = control->get_anchor(MARGIN_LEFT);
- anchors_values[1] = control->get_anchor(MARGIN_TOP);
- anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
- anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
+ anchors_values[0] = control->get_anchor(SIDE_LEFT);
+ anchors_values[1] = control->get_anchor(SIDE_TOP);
+ anchors_values[2] = control->get_anchor(SIDE_RIGHT);
+ anchors_values[3] = control->get_anchor(SIDE_BOTTOM);
Vector2 anchors_pos[4];
for (int i = 0; i < 4; i++) {
@@ -3224,10 +3224,10 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
// Compute the anchors
float anchors_values[4];
- anchors_values[0] = control->get_anchor(MARGIN_LEFT);
- anchors_values[1] = control->get_anchor(MARGIN_TOP);
- anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
- anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
+ anchors_values[0] = control->get_anchor(SIDE_LEFT);
+ anchors_values[1] = control->get_anchor(SIDE_TOP);
+ anchors_values[2] = control->get_anchor(SIDE_RIGHT);
+ anchors_values[3] = control->get_anchor(SIDE_BOTTOM);
Vector2 anchors[4];
Vector2 anchors_pos[4];
@@ -3280,19 +3280,19 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
float percent_val;
percent_val = anchors_values[(dragged_anchor + 2) % 4] - anchors_values[dragged_anchor];
percent_val = (dragged_anchor >= 2) ? -percent_val : percent_val;
- _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 1) % 4]) / 2, (Margin)((dragged_anchor + 1) % 4));
+ _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 1) % 4]) / 2, (Side)((dragged_anchor + 1) % 4));
percent_val = anchors_values[(dragged_anchor + 3) % 4] - anchors_values[(dragged_anchor + 1) % 4];
percent_val = ((dragged_anchor + 1) % 4 >= 2) ? -percent_val : percent_val;
- _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Margin)(dragged_anchor));
+ _draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Side)(dragged_anchor));
percent_val = anchors_values[(dragged_anchor + 1) % 4];
percent_val = ((dragged_anchor + 1) % 4 >= 2) ? ANCHOR_END - percent_val : percent_val;
- _draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Margin)(dragged_anchor));
+ _draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Side)(dragged_anchor));
percent_val = anchors_values[dragged_anchor];
percent_val = (dragged_anchor >= 2) ? ANCHOR_END - percent_val : percent_val;
- _draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Margin)((dragged_anchor + 1) % 4));
+ _draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Side)((dragged_anchor + 1) % 4));
}
// Draw the margin values and the node width/height when dragging control side
@@ -3302,22 +3302,22 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
Rect2 parent_rect = control->get_parent_anchorable_rect();
- node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * parent_rect.size.width + control->get_margin(MARGIN_LEFT) + parent_rect.position.x;
- node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * parent_rect.size.height + control->get_margin(MARGIN_TOP) + parent_rect.position.y;
- node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * parent_rect.size.width + control->get_margin(MARGIN_RIGHT) + parent_rect.position.x;
- node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * parent_rect.size.height + control->get_margin(MARGIN_BOTTOM) + parent_rect.position.y;
+ node_pos_in_parent[0] = control->get_anchor(SIDE_LEFT) * parent_rect.size.width + control->get_offset(SIDE_LEFT) + parent_rect.position.x;
+ node_pos_in_parent[1] = control->get_anchor(SIDE_TOP) * parent_rect.size.height + control->get_offset(SIDE_TOP) + parent_rect.position.y;
+ node_pos_in_parent[2] = control->get_anchor(SIDE_RIGHT) * parent_rect.size.width + control->get_offset(SIDE_RIGHT) + parent_rect.position.x;
+ node_pos_in_parent[3] = control->get_anchor(SIDE_BOTTOM) * parent_rect.size.height + control->get_offset(SIDE_BOTTOM) + parent_rect.position.y;
Point2 start, end;
switch (drag_type) {
case DRAG_LEFT:
case DRAG_TOP_LEFT:
case DRAG_BOTTOM_LEFT:
- _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
+ _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), SIDE_BOTTOM);
[[fallthrough]];
case DRAG_MOVE:
start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio));
- end = start - Vector2(control->get_margin(MARGIN_LEFT), 0);
- _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP);
+ end = start - Vector2(control->get_offset(SIDE_LEFT), 0);
+ _draw_margin_at_position(control->get_offset(SIDE_LEFT), parent_transform.xform((start + end) / 2), SIDE_TOP);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
break;
default:
@@ -3327,12 +3327,12 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
case DRAG_RIGHT:
case DRAG_TOP_RIGHT:
case DRAG_BOTTOM_RIGHT:
- _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
+ _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), SIDE_BOTTOM);
[[fallthrough]];
case DRAG_MOVE:
start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio));
- end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0);
- _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM);
+ end = start - Vector2(control->get_offset(SIDE_RIGHT), 0);
+ _draw_margin_at_position(control->get_offset(SIDE_RIGHT), parent_transform.xform((start + end) / 2), SIDE_BOTTOM);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
break;
default:
@@ -3342,12 +3342,12 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
case DRAG_TOP:
case DRAG_TOP_LEFT:
case DRAG_TOP_RIGHT:
- _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT);
+ _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), SIDE_RIGHT);
[[fallthrough]];
case DRAG_MOVE:
start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]);
- end = start - Vector2(0, control->get_margin(MARGIN_TOP));
- _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT);
+ end = start - Vector2(0, control->get_offset(SIDE_TOP));
+ _draw_margin_at_position(control->get_offset(SIDE_TOP), parent_transform.xform((start + end) / 2), SIDE_LEFT);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
break;
default:
@@ -3357,12 +3357,12 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
case DRAG_BOTTOM:
case DRAG_BOTTOM_LEFT:
case DRAG_BOTTOM_RIGHT:
- _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT);
+ _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), SIDE_RIGHT);
[[fallthrough]];
case DRAG_MOVE:
start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]);
- end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM));
- _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT);
+ end = start - Vector2(0, control->get_offset(SIDE_BOTTOM));
+ _draw_margin_at_position(control->get_offset(SIDE_BOTTOM), parent_transform.xform((start + end) / 2), SIDE_RIGHT);
viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
break;
default:
@@ -3916,7 +3916,7 @@ void CanvasItemEditor::_draw_viewport() {
bool all_locked = true;
bool all_group = true;
List<Node *> selection = editor_selection->get_selected_node_list();
- if (selection.empty()) {
+ if (selection.is_empty()) {
all_locked = false;
all_group = false;
} else {
@@ -3935,13 +3935,13 @@ void CanvasItemEditor::_draw_viewport() {
}
lock_button->set_visible(!all_locked);
- lock_button->set_disabled(selection.empty());
+ lock_button->set_disabled(selection.is_empty());
unlock_button->set_visible(all_locked);
group_button->set_visible(!all_group);
- group_button->set_disabled(selection.empty());
+ group_button->set_disabled(selection.is_empty());
ungroup_button->set_visible(all_group);
- info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
+ info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
_draw_grid();
_draw_ruler_tool();
@@ -3956,11 +3956,11 @@ void CanvasItemEditor::_draw_viewport() {
RenderingServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
- if (!over_plugin_list->empty()) {
+ if (!over_plugin_list->is_empty()) {
over_plugin_list->forward_canvas_draw_over_viewport(viewport);
}
EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over();
- if (!force_over_plugin_list->empty()) {
+ if (!force_over_plugin_list->is_empty()) {
force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport);
}
@@ -4019,17 +4019,17 @@ void CanvasItemEditor::_notification(int p_what) {
Vector2 pivot;
pivot = control->get_pivot_offset();
- anchors[MARGIN_LEFT] = control->get_anchor(MARGIN_LEFT);
- anchors[MARGIN_RIGHT] = control->get_anchor(MARGIN_RIGHT);
- anchors[MARGIN_TOP] = control->get_anchor(MARGIN_TOP);
- anchors[MARGIN_BOTTOM] = control->get_anchor(MARGIN_BOTTOM);
+ anchors[SIDE_LEFT] = control->get_anchor(SIDE_LEFT);
+ anchors[SIDE_RIGHT] = control->get_anchor(SIDE_RIGHT);
+ anchors[SIDE_TOP] = control->get_anchor(SIDE_TOP);
+ anchors[SIDE_BOTTOM] = control->get_anchor(SIDE_BOTTOM);
- if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) {
+ if (pivot != se->prev_pivot || anchors[SIDE_LEFT] != se->prev_anchors[SIDE_LEFT] || anchors[SIDE_RIGHT] != se->prev_anchors[SIDE_RIGHT] || anchors[SIDE_TOP] != se->prev_anchors[SIDE_TOP] || anchors[SIDE_BOTTOM] != se->prev_anchors[SIDE_BOTTOM]) {
se->prev_pivot = pivot;
- se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT];
- se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT];
- se->prev_anchors[MARGIN_TOP] = anchors[MARGIN_TOP];
- se->prev_anchors[MARGIN_BOTTOM] = anchors[MARGIN_BOTTOM];
+ se->prev_anchors[SIDE_LEFT] = anchors[SIDE_LEFT];
+ se->prev_anchors[SIDE_RIGHT] = anchors[SIDE_RIGHT];
+ se->prev_anchors[SIDE_TOP] = anchors[SIDE_TOP];
+ se->prev_anchors[SIDE_BOTTOM] = anchors[SIDE_BOTTOM];
viewport->update();
}
nb_control++;
@@ -4100,8 +4100,8 @@ void CanvasItemEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
select_sb->set_texture(get_theme_icon("EditorRect2D", "EditorIcons"));
for (int i = 0; i < 4; i++) {
- select_sb->set_margin_size(Margin(i), 4);
- select_sb->set_default_margin(Margin(i), 4);
+ select_sb->set_margin_size(Side(i), 4);
+ select_sb->set_default_margin(Side(i), 4);
}
AnimationPlayerEditor::singleton->get_track_editor()->connect("visibility_changed", callable_mp(this, &CanvasItemEditor::_keying_changed));
@@ -4158,26 +4158,26 @@ void CanvasItemEditor::_notification(int p_what) {
PopupMenu *p = presets_menu->get_popup();
p->clear();
- p->add_icon_item(get_theme_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_MARGINS_PRESET_TOP_LEFT);
- p->add_icon_item(get_theme_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT);
- p->add_icon_item(get_theme_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT);
- p->add_icon_item(get_theme_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT);
+ p->add_icon_item(get_theme_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT);
+ p->add_icon_item(get_theme_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT);
+ p->add_icon_item(get_theme_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT);
+ p->add_icon_item(get_theme_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT);
p->add_separator();
- p->add_icon_item(get_theme_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT);
- p->add_icon_item(get_theme_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_MARGINS_PRESET_CENTER_TOP);
- p->add_icon_item(get_theme_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT);
- p->add_icon_item(get_theme_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM);
- p->add_icon_item(get_theme_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_MARGINS_PRESET_CENTER);
+ p->add_icon_item(get_theme_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT);
+ p->add_icon_item(get_theme_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP);
+ p->add_icon_item(get_theme_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT);
+ p->add_icon_item(get_theme_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM);
+ p->add_icon_item(get_theme_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_OFFSETS_PRESET_CENTER);
p->add_separator();
- p->add_icon_item(get_theme_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE);
- p->add_icon_item(get_theme_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_MARGINS_PRESET_TOP_WIDE);
- p->add_icon_item(get_theme_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE);
- p->add_icon_item(get_theme_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE);
- p->add_icon_item(get_theme_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE);
- p->add_icon_item(get_theme_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE);
+ p->add_icon_item(get_theme_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE);
+ p->add_icon_item(get_theme_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE);
+ p->add_icon_item(get_theme_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE);
+ p->add_icon_item(get_theme_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE);
+ p->add_icon_item(get_theme_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE);
+ p->add_icon_item(get_theme_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE);
p->add_separator();
- p->add_icon_item(get_theme_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_MARGINS_PRESET_WIDE);
- p->add_icon_item(get_theme_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO);
+ p->add_icon_item(get_theme_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_OFFSETS_PRESET_WIDE);
+ p->add_icon_item(get_theme_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO);
p->add_separator();
p->add_submenu_item(TTR("Anchors only"), "Anchors");
p->set_item_icon(21, get_theme_icon("Anchor", "EditorIcons"));
@@ -4396,7 +4396,7 @@ void CanvasItemEditor::_popup_warning_depop(Control *p_control) {
timer->queue_delete();
p_control->hide();
popup_temporarily_timers.erase(p_control);
- info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
+ info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
}
void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const float p_duration) {
@@ -4414,7 +4414,7 @@ void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const floa
timer->start(p_duration);
p_control->show();
- info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
+ info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
}
void CanvasItemEditor::_update_scroll(float) {
@@ -4427,10 +4427,10 @@ void CanvasItemEditor::_update_scroll(float) {
viewport->update();
}
-void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) {
+void CanvasItemEditor::_set_anchors_and_offsets_preset(Control::LayoutPreset p_preset) {
List<Node *> selection = editor_selection->get_selected_node_list();
- undo_redo->create_action(TTR("Change Anchors and Margins"));
+ undo_redo->create_action(TTR("Change Anchors and Offsets"));
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Control *control = Object::cast_to<Control>(E->get());
@@ -4446,7 +4446,7 @@ void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_p
case PRESET_CENTER_RIGHT:
case PRESET_CENTER_BOTTOM:
case PRESET_CENTER:
- undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
+ undo_redo->add_do_method(control, "set_offsets_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
break;
case PRESET_LEFT_WIDE:
case PRESET_TOP_WIDE:
@@ -4455,7 +4455,7 @@ void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_p
case PRESET_VCENTER_WIDE:
case PRESET_HCENTER_WIDE:
case PRESET_WIDE:
- undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE);
+ undo_redo->add_do_method(control, "set_offsets_preset", p_preset, Control::PRESET_MODE_MINSIZE);
break;
}
undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
@@ -4468,20 +4468,20 @@ void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_p
anchor_mode_button->set_pressed(anchors_mode);
}
-void CanvasItemEditor::_set_anchors_and_margins_to_keep_ratio() {
+void CanvasItemEditor::_set_anchors_and_offsets_to_keep_ratio() {
List<Node *> selection = editor_selection->get_selected_node_list();
- undo_redo->create_action(TTR("Change Anchors and Margins"));
+ undo_redo->create_action(TTR("Change Anchors and Offsets"));
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Control *control = Object::cast_to<Control>(E->get());
if (control) {
Point2 top_left_anchor = _position_to_anchor(control, Point2());
Point2 bottom_right_anchor = _position_to_anchor(control, control->get_size());
- undo_redo->add_do_method(control, "set_anchor", MARGIN_LEFT, top_left_anchor.x, false, true);
- undo_redo->add_do_method(control, "set_anchor", MARGIN_RIGHT, bottom_right_anchor.x, false, true);
- undo_redo->add_do_method(control, "set_anchor", MARGIN_TOP, top_left_anchor.y, false, true);
- undo_redo->add_do_method(control, "set_anchor", MARGIN_BOTTOM, bottom_right_anchor.y, false, true);
+ undo_redo->add_do_method(control, "set_anchor", SIDE_LEFT, top_left_anchor.x, false, true);
+ undo_redo->add_do_method(control, "set_anchor", SIDE_RIGHT, bottom_right_anchor.x, false, true);
+ undo_redo->add_do_method(control, "set_anchor", SIDE_TOP, top_left_anchor.y, false, true);
+ undo_redo->add_do_method(control, "set_anchor", SIDE_BOTTOM, bottom_right_anchor.y, false, true);
undo_redo->add_do_method(control, "set_meta", "_edit_use_anchors_", true);
bool use_anchors = control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_");
@@ -4934,56 +4934,56 @@ void CanvasItemEditor::_popup_callback(int p_op) {
undo_redo->add_undo_method(viewport, "update", Variant());
undo_redo->commit_action();
} break;
- case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: {
- _set_anchors_and_margins_preset(PRESET_TOP_LEFT);
+ case ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT: {
+ _set_anchors_and_offsets_preset(PRESET_TOP_LEFT);
} break;
- case ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT: {
- _set_anchors_and_margins_preset(PRESET_TOP_RIGHT);
+ case ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT: {
+ _set_anchors_and_offsets_preset(PRESET_TOP_RIGHT);
} break;
- case ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT: {
- _set_anchors_and_margins_preset(PRESET_BOTTOM_LEFT);
+ case ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT: {
+ _set_anchors_and_offsets_preset(PRESET_BOTTOM_LEFT);
} break;
- case ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT: {
- _set_anchors_and_margins_preset(PRESET_BOTTOM_RIGHT);
+ case ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT: {
+ _set_anchors_and_offsets_preset(PRESET_BOTTOM_RIGHT);
} break;
- case ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT: {
- _set_anchors_and_margins_preset(PRESET_CENTER_LEFT);
+ case ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT: {
+ _set_anchors_and_offsets_preset(PRESET_CENTER_LEFT);
} break;
- case ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT: {
- _set_anchors_and_margins_preset(PRESET_CENTER_RIGHT);
+ case ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT: {
+ _set_anchors_and_offsets_preset(PRESET_CENTER_RIGHT);
} break;
- case ANCHORS_AND_MARGINS_PRESET_CENTER_TOP: {
- _set_anchors_and_margins_preset(PRESET_CENTER_TOP);
+ case ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP: {
+ _set_anchors_and_offsets_preset(PRESET_CENTER_TOP);
} break;
- case ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM: {
- _set_anchors_and_margins_preset(PRESET_CENTER_BOTTOM);
+ case ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM: {
+ _set_anchors_and_offsets_preset(PRESET_CENTER_BOTTOM);
} break;
- case ANCHORS_AND_MARGINS_PRESET_CENTER: {
- _set_anchors_and_margins_preset(PRESET_CENTER);
+ case ANCHORS_AND_OFFSETS_PRESET_CENTER: {
+ _set_anchors_and_offsets_preset(PRESET_CENTER);
} break;
- case ANCHORS_AND_MARGINS_PRESET_TOP_WIDE: {
- _set_anchors_and_margins_preset(PRESET_TOP_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE: {
+ _set_anchors_and_offsets_preset(PRESET_TOP_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE: {
- _set_anchors_and_margins_preset(PRESET_LEFT_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE: {
+ _set_anchors_and_offsets_preset(PRESET_LEFT_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE: {
- _set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE: {
+ _set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE: {
- _set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE: {
+ _set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE: {
- _set_anchors_and_margins_preset(PRESET_VCENTER_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE: {
+ _set_anchors_and_offsets_preset(PRESET_VCENTER_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE: {
- _set_anchors_and_margins_preset(PRESET_HCENTER_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE: {
+ _set_anchors_and_offsets_preset(PRESET_HCENTER_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_WIDE: {
- _set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ case ANCHORS_AND_OFFSETS_PRESET_WIDE: {
+ _set_anchors_and_offsets_preset(Control::PRESET_WIDE);
} break;
- case ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO: {
- _set_anchors_and_margins_to_keep_ratio();
+ case ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO: {
+ _set_anchors_and_offsets_to_keep_ratio();
} break;
case ANCHORS_PRESET_TOP_LEFT: {
@@ -5572,12 +5572,12 @@ void CanvasItemEditor::add_control_to_info_overlay(Control *p_control) {
p_control->set_h_size_flags(p_control->get_h_size_flags() & ~Control::SIZE_EXPAND_FILL);
info_overlay->add_child(p_control);
- info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
+ info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
}
void CanvasItemEditor::remove_control_from_info_overlay(Control *p_control) {
info_overlay->remove_child(p_control);
- info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
+ info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
}
void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
@@ -5674,7 +5674,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb = memnew(HBoxContainer);
add_child(hb);
- hb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
bottom_split = memnew(VSplitContainer);
add_child(bottom_split);
@@ -5695,7 +5695,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
SubViewportContainer *scene_tree = memnew(SubViewportContainer);
viewport_scrollable->add_child(scene_tree);
scene_tree->set_stretch(true);
- scene_tree->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ scene_tree->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
scene_tree->add_child(p_editor->get_scene_root());
controls_vb = memnew(VBoxContainer);
@@ -5709,16 +5709,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
viewport = memnew(CanvasItemEditorViewport(p_editor, this));
viewport_scrollable->add_child(viewport);
viewport->set_mouse_filter(MOUSE_FILTER_PASS);
- viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ viewport->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
viewport->set_clip_contents(true);
viewport->set_focus_mode(FOCUS_ALL);
viewport->connect("draw", callable_mp(this, &CanvasItemEditor::_draw_viewport));
viewport->connect("gui_input", callable_mp(this, &CanvasItemEditor::_gui_input_viewport));
info_overlay = memnew(VBoxContainer);
- info_overlay->set_anchors_and_margins_preset(Control::PRESET_BOTTOM_LEFT);
- info_overlay->set_margin(MARGIN_LEFT, 10);
- info_overlay->set_margin(MARGIN_BOTTOM, -15);
+ info_overlay->set_anchors_and_offsets_preset(Control::PRESET_BOTTOM_LEFT);
+ info_overlay->set_offset(SIDE_LEFT, 10);
+ info_overlay->set_offset(SIDE_BOTTOM, -15);
info_overlay->set_v_grow_direction(Control::GROW_DIRECTION_BEGIN);
info_overlay->add_theme_constant_override("separation", 10);
viewport_scrollable->add_child(info_overlay);
@@ -6140,7 +6140,7 @@ CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) {
canvas_item_editor = memnew(CanvasItemEditor(editor));
canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->get_viewport()->add_child(canvas_item_editor);
- canvas_item_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
canvas_item_editor->hide();
}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index c4a1dca593..f5da953810 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -119,23 +119,23 @@ private:
UNLOCK_SELECTED,
GROUP_SELECTED,
UNGROUP_SELECTED,
- ANCHORS_AND_MARGINS_PRESET_TOP_LEFT,
- ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT,
- ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT,
- ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT,
- ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT,
- ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT,
- ANCHORS_AND_MARGINS_PRESET_CENTER_TOP,
- ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM,
- ANCHORS_AND_MARGINS_PRESET_CENTER,
- ANCHORS_AND_MARGINS_PRESET_TOP_WIDE,
- ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE,
- ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE,
- ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE,
- ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE,
- ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE,
- ANCHORS_AND_MARGINS_PRESET_WIDE,
- ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO,
+ ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT,
+ ANCHORS_AND_OFFSETS_PRESET_TOP_RIGHT,
+ ANCHORS_AND_OFFSETS_PRESET_BOTTOM_LEFT,
+ ANCHORS_AND_OFFSETS_PRESET_BOTTOM_RIGHT,
+ ANCHORS_AND_OFFSETS_PRESET_CENTER_LEFT,
+ ANCHORS_AND_OFFSETS_PRESET_CENTER_RIGHT,
+ ANCHORS_AND_OFFSETS_PRESET_CENTER_TOP,
+ ANCHORS_AND_OFFSETS_PRESET_CENTER_BOTTOM,
+ ANCHORS_AND_OFFSETS_PRESET_CENTER,
+ ANCHORS_AND_OFFSETS_PRESET_TOP_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_LEFT_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_RIGHT_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_BOTTOM_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_VCENTER_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_HCENTER_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_WIDE,
+ ANCHORS_AND_OFFSETS_PRESET_KEEP_RATIO,
ANCHORS_PRESET_TOP_LEFT,
ANCHORS_PRESET_TOP_RIGHT,
ANCHORS_PRESET_BOTTOM_LEFT,
@@ -152,22 +152,22 @@ private:
ANCHORS_PRESET_VCENTER_WIDE,
ANCHORS_PRESET_HCENTER_WIDE,
ANCHORS_PRESET_WIDE,
- MARGINS_PRESET_TOP_LEFT,
- MARGINS_PRESET_TOP_RIGHT,
- MARGINS_PRESET_BOTTOM_LEFT,
- MARGINS_PRESET_BOTTOM_RIGHT,
- MARGINS_PRESET_CENTER_LEFT,
- MARGINS_PRESET_CENTER_RIGHT,
- MARGINS_PRESET_CENTER_TOP,
- MARGINS_PRESET_CENTER_BOTTOM,
- MARGINS_PRESET_CENTER,
- MARGINS_PRESET_TOP_WIDE,
- MARGINS_PRESET_LEFT_WIDE,
- MARGINS_PRESET_RIGHT_WIDE,
- MARGINS_PRESET_BOTTOM_WIDE,
- MARGINS_PRESET_VCENTER_WIDE,
- MARGINS_PRESET_HCENTER_WIDE,
- MARGINS_PRESET_WIDE,
+ OFFSETS_PRESET_TOP_LEFT,
+ OFFSETS_PRESET_TOP_RIGHT,
+ OFFSETS_PRESET_BOTTOM_LEFT,
+ OFFSETS_PRESET_BOTTOM_RIGHT,
+ OFFSETS_PRESET_CENTER_LEFT,
+ OFFSETS_PRESET_CENTER_RIGHT,
+ OFFSETS_PRESET_CENTER_TOP,
+ OFFSETS_PRESET_CENTER_BOTTOM,
+ OFFSETS_PRESET_CENTER,
+ OFFSETS_PRESET_TOP_WIDE,
+ OFFSETS_PRESET_LEFT_WIDE,
+ OFFSETS_PRESET_RIGHT_WIDE,
+ OFFSETS_PRESET_BOTTOM_WIDE,
+ OFFSETS_PRESET_VCENTER_WIDE,
+ OFFSETS_PRESET_HCENTER_WIDE,
+ OFFSETS_PRESET_WIDE,
ANIM_INSERT_KEY,
ANIM_INSERT_KEY_EXISTING,
ANIM_INSERT_POS,
@@ -454,9 +454,9 @@ private:
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
- void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side);
- void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side);
- void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side);
+ void _draw_text_at_position(Point2 p_position, String p_string, Side p_side);
+ void _draw_margin_at_position(int p_value, Point2 p_position, Side p_side);
+ void _draw_percentage_at_position(float p_value, Point2 p_position, Side p_side);
void _draw_straight_line(Point2 p_from, Point2 p_to, Color p_color);
void _draw_smart_snapping();
@@ -519,9 +519,9 @@ private:
const Node *p_current);
void _set_anchors_preset(Control::LayoutPreset p_preset);
- void _set_margins_preset(Control::LayoutPreset p_preset);
- void _set_anchors_and_margins_preset(Control::LayoutPreset p_preset);
- void _set_anchors_and_margins_to_keep_ratio();
+ void _set_offsets_preset(Control::LayoutPreset p_preset);
+ void _set_anchors_and_offsets_preset(Control::LayoutPreset p_preset);
+ void _set_anchors_and_offsets_to_keep_ratio();
void _button_toggle_anchor_mode(bool p_status);
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 2fc0e35f82..7c3b393cd5 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -106,7 +106,7 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const RES &p_from, const Siz
}
}
- if (img.is_null() || img->empty()) {
+ if (img.is_null() || img->is_empty()) {
return Ref<Texture2D>();
}
@@ -150,7 +150,7 @@ bool EditorImagePreviewPlugin::handles(const String &p_type) const {
Ref<Texture2D> EditorImagePreviewPlugin::generate(const RES &p_from, const Size2 &p_size) const {
Ref<Image> img = p_from;
- if (img.is_null() || img->empty()) {
+ if (img.is_null() || img->is_empty()) {
return Ref<Image>();
}
diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp
index a82547182c..55419e1042 100644
--- a/editor/plugins/font_editor_plugin.cpp
+++ b/editor/plugins/font_editor_plugin.cpp
@@ -216,7 +216,7 @@ void FontDataEditor::init_script_edit() {
void FontDataEditor::add_lang() {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
- if (fd != nullptr && !le->get_text().empty()) {
+ if (fd != nullptr && !le->get_text().is_empty()) {
fd->set_language_support_override(le->get_text(), chk->is_pressed());
le->set_text("");
chk->set_pressed(false);
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index e49cfd51f7..e45344b427 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -108,7 +108,7 @@ MaterialEditor::MaterialEditor() {
vc = memnew(SubViewportContainer);
vc->set_stretch(true);
add_child(vc);
- vc->set_anchors_and_margins_preset(PRESET_WIDE);
+ vc->set_anchors_and_offsets_preset(PRESET_WIDE);
viewport = memnew(SubViewport);
Ref<World3D> world_3d;
world_3d.instance();
@@ -155,7 +155,7 @@ MaterialEditor::MaterialEditor() {
HBoxContainer *hb = memnew(HBoxContainer);
add_child(hb);
- hb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
+ hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
VBoxContainer *vb_shape = memnew(VBoxContainer);
hb->add_child(vb_shape);
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index 9d396467c3..79dbf7d522 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -137,7 +137,7 @@ MeshEditor::MeshEditor() {
HBoxContainer *hb = memnew(HBoxContainer);
add_child(hb);
- hb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
+ hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
hb->add_spacer();
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 2a08e3a8b5..c8a85267ac 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -63,7 +63,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
List<Node *> selection = editor_selection->get_selected_node_list();
- if (selection.empty()) {
+ if (selection.is_empty()) {
Ref<Shape3D> shape = mesh->create_trimesh_shape();
if (shape.is_null()) {
err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape."));
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index b11a07365c..fb34f4064a 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -298,7 +298,7 @@ MeshLibraryEditorPlugin::MeshLibraryEditorPlugin(EditorNode *p_node) {
mesh_library_editor = memnew(MeshLibraryEditor(p_node));
p_node->get_viewport()->add_child(mesh_library_editor);
- mesh_library_editor->set_anchors_and_margins_preset(Control::PRESET_TOP_WIDE);
+ mesh_library_editor->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE);
mesh_library_editor->set_end(Point2(0, 22));
mesh_library_editor->hide();
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index b8a4f7bc5a..59ab622994 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -337,7 +337,7 @@ MultiMeshEditor::MultiMeshEditor() {
vbc->add_margin_child(TTR("Scale:"), populate_scale);
populate_amount = memnew(SpinBox);
- populate_amount->set_anchor(MARGIN_RIGHT, ANCHOR_END);
+ populate_amount->set_anchor(SIDE_RIGHT, ANCHOR_END);
populate_amount->set_begin(Point2(20, 232));
populate_amount->set_end(Point2(-5, 237));
populate_amount->set_min(1);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index fcbca8ced0..c88c6f488e 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -612,7 +612,7 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_inclu
results.push_back(res);
}
- if (results.empty()) {
+ if (results.is_empty()) {
return;
}
@@ -1045,7 +1045,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
clicked = ObjectID();
}
- } else if (!selection_results.empty()) {
+ } else if (!selection_results.is_empty()) {
NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
@@ -1097,7 +1097,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
{
EditorNode *en = editor;
EditorPluginList *force_input_forwarding_list = en->get_editor_plugins_force_input_forwarding();
- if (!force_input_forwarding_list->empty()) {
+ if (!force_input_forwarding_list->is_empty()) {
bool discard = force_input_forwarding_list->forward_spatial_gui_input(camera, p_event, true);
if (discard) {
return;
@@ -1107,7 +1107,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
{
EditorNode *en = editor;
EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
- if (!over_plugin_list->empty()) {
+ if (!over_plugin_list->is_empty()) {
bool discard = over_plugin_list->forward_spatial_gui_input(camera, p_event, false);
if (discard) {
return;
@@ -2543,12 +2543,12 @@ void Node3DEditorViewport::_notification(int p_what) {
cinema_label->set_visible(show_cinema);
if (show_cinema) {
float cinema_half_width = cinema_label->get_size().width / 2.0f;
- cinema_label->set_anchor_and_margin(MARGIN_LEFT, 0.5f, -cinema_half_width);
+ cinema_label->set_anchor_and_offset(SIDE_LEFT, 0.5f, -cinema_half_width);
}
if (lock_rotation) {
float locked_half_width = locked_label->get_size().width / 2.0f;
- locked_label->set_anchor_and_margin(MARGIN_LEFT, 0.5f, -locked_half_width);
+ locked_label->set_anchor_and_offset(SIDE_LEFT, 0.5f, -locked_half_width);
}
}
@@ -2615,12 +2615,12 @@ static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2
void Node3DEditorViewport::_draw() {
EditorPluginList *over_plugin_list = EditorNode::get_singleton()->get_editor_plugins_over();
- if (!over_plugin_list->empty()) {
+ if (!over_plugin_list->is_empty()) {
over_plugin_list->forward_spatial_draw_over_viewport(surface);
}
EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over();
- if (!force_over_plugin_list->empty()) {
+ if (!force_over_plugin_list->is_empty()) {
force_over_plugin_list->forward_spatial_force_draw_over_viewport(surface);
}
@@ -2674,7 +2674,8 @@ void Node3DEditorViewport::_draw() {
break;
}
handle_color.a = 1.0;
- handle_color *= Color(1.3, 1.3, 1.3, 1.0);
+ const float brightness = 1.3;
+ handle_color *= Color(brightness, brightness, brightness);
RenderingServer::get_singleton()->canvas_item_add_line(
ci,
@@ -3890,7 +3891,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
subviewport_container = c;
c->set_stretch(true);
add_child(c);
- c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ c->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
viewport = memnew(SubViewport);
viewport->set_disable_input(true);
@@ -3898,7 +3899,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
surface = memnew(Control);
surface->set_drag_forwarding(this);
add_child(surface);
- surface->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ surface->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
surface->set_clip_contents(true);
camera = memnew(Camera3D);
camera->set_disable_gizmo(true);
@@ -4033,19 +4034,19 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
preview_node = nullptr;
info_label = memnew(Label);
- info_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE);
- info_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -90 * EDSCALE);
- info_label->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -10 * EDSCALE);
- info_label->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -10 * EDSCALE);
+ info_label->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -90 * EDSCALE);
+ info_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -90 * EDSCALE);
+ info_label->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -10 * EDSCALE);
+ info_label->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -10 * EDSCALE);
info_label->set_h_grow_direction(GROW_DIRECTION_BEGIN);
info_label->set_v_grow_direction(GROW_DIRECTION_BEGIN);
surface->add_child(info_label);
info_label->hide();
fps_label = memnew(Label);
- fps_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE);
- fps_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
- fps_label->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -10 * EDSCALE);
+ fps_label->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -90 * EDSCALE);
+ fps_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
+ fps_label->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -10 * EDSCALE);
fps_label->set_h_grow_direction(GROW_DIRECTION_BEGIN);
fps_label->set_tooltip(TTR("Note: The FPS is estimated on a 60hz refresh rate."));
fps_label->set_mouse_filter(MOUSE_FILTER_PASS); // Otherwise tooltip doesn't show.
@@ -4053,7 +4054,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
fps_label->hide();
cinema_label = memnew(Label);
- cinema_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
+ cinema_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
cinema_label->set_h_grow_direction(GROW_DIRECTION_END);
cinema_label->set_align(Label::ALIGN_CENTER);
surface->add_child(cinema_label);
@@ -4062,8 +4063,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
previewing_cinema = false;
locked_label = memnew(Label);
- locked_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -20 * EDSCALE);
- locked_label->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -10 * EDSCALE);
+ locked_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -20 * EDSCALE);
+ locked_label->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -10 * EDSCALE);
locked_label->set_h_grow_direction(GROW_DIRECTION_END);
locked_label->set_v_grow_direction(GROW_DIRECTION_BEGIN);
locked_label->set_align(Label::ALIGN_CENTER);
@@ -4072,7 +4073,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
locked_label->hide();
top_right_vbox = memnew(VBoxContainer);
- top_right_vbox->set_anchors_and_margins_preset(PRESET_TOP_RIGHT, PRESET_MODE_MINSIZE, 2.0 * EDSCALE);
+ top_right_vbox->set_anchors_and_offsets_preset(PRESET_TOP_RIGHT, PRESET_MODE_MINSIZE, 2.0 * EDSCALE);
top_right_vbox->set_h_grow_direction(GROW_DIRECTION_BEGIN);
rotation_control = memnew(ViewportRotationControl);
@@ -4082,9 +4083,9 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
top_right_vbox->add_child(rotation_control);
fps_label = memnew(Label);
- fps_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE);
- fps_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
- fps_label->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -10 * EDSCALE);
+ fps_label->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -90 * EDSCALE);
+ fps_label->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
+ fps_label->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -10 * EDSCALE);
fps_label->set_h_grow_direction(GROW_DIRECTION_BEGIN);
fps_label->set_tooltip(TTR("Note: The FPS value displayed is the editor's framerate.\nIt cannot be used as a reliable indication of in-game performance."));
fps_label->set_mouse_filter(MOUSE_FILTER_PASS); // Otherwise tooltip doesn't show.
@@ -5252,7 +5253,9 @@ void Node3DEditor::_init_indicators() {
gizmo_color[i] = mat;
Ref<StandardMaterial3D> mat_hl = mat->duplicate();
- mat_hl->set_albedo(Color(col.r * 1.3, col.g * 1.3, col.b * 1.3, 1.0));
+ const float brightness = 1.3;
+ const Color albedo = Color(col.r * brightness, col.g * brightness, col.b * brightness);
+ mat_hl->set_albedo(albedo);
gizmo_color_hl[i] = mat_hl;
Vector3 ivec;
@@ -5347,7 +5350,7 @@ void Node3DEditor::_init_indicators() {
surftool->commit(move_plane_gizmo[i]);
Ref<StandardMaterial3D> plane_mat_hl = plane_mat->duplicate();
- plane_mat_hl->set_albedo(Color(col.r * 1.3, col.g * 1.3, col.b * 1.3, 1.0));
+ plane_mat_hl->set_albedo(albedo);
plane_gizmo_color_hl[i] = plane_mat_hl; // needed, so we can draw planes from both sides
}
@@ -5430,7 +5433,7 @@ void Node3DEditor::_init_indicators() {
rotate_gizmo[i]->surface_set_material(0, rotate_mat);
Ref<ShaderMaterial> rotate_mat_hl = rotate_mat->duplicate();
- rotate_mat_hl->set_shader_param("albedo", Color(col.r * 1.3, col.g * 1.3, col.b * 1.3, 1.0));
+ rotate_mat_hl->set_shader_param("albedo", albedo);
rotate_gizmo_color_hl[i] = rotate_mat_hl;
if (i == 2) { // Rotation white outline
@@ -5557,7 +5560,7 @@ void Node3DEditor::_init_indicators() {
surftool->commit(scale_plane_gizmo[i]);
Ref<StandardMaterial3D> plane_mat_hl = plane_mat->duplicate();
- plane_mat_hl->set_albedo(Color(col.r * 1.3, col.g * 1.3, col.b * 1.3, 1.0));
+ plane_mat_hl->set_albedo(Color(col.r * 1.3, col.g * 1.3, col.b * 1.3));
plane_gizmo_color_hl[i] = plane_mat_hl; // needed, so we can draw planes from both sides
}
}
@@ -5775,7 +5778,7 @@ void Node3DEditor::_refresh_menu_icons() {
List<Node *> &selection = editor_selection->get_selected_node_list();
- if (selection.empty()) {
+ if (selection.is_empty()) {
all_locked = false;
all_grouped = false;
} else {
@@ -5794,11 +5797,11 @@ void Node3DEditor::_refresh_menu_icons() {
}
tool_button[TOOL_LOCK_SELECTED]->set_visible(!all_locked);
- tool_button[TOOL_LOCK_SELECTED]->set_disabled(selection.empty());
+ tool_button[TOOL_LOCK_SELECTED]->set_disabled(selection.is_empty());
tool_button[TOOL_UNLOCK_SELECTED]->set_visible(all_locked);
tool_button[TOOL_GROUP_SELECTED]->set_visible(!all_grouped);
- tool_button[TOOL_GROUP_SELECTED]->set_disabled(selection.empty());
+ tool_button[TOOL_GROUP_SELECTED]->set_disabled(selection.is_empty());
tool_button[TOOL_UNGROUP_SELECTED]->set_visible(all_grouped);
}
@@ -6109,7 +6112,7 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) {
if (!maximized) {
for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) {
if (i == (uint32_t)index) {
- viewports[i]->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ viewports[i]->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
} else {
viewports[i]->hide();
}
diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp
index 608b5c3104..09d2303359 100644
--- a/editor/plugins/packed_scene_translation_parser_plugin.cpp
+++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp
@@ -81,14 +81,14 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path,
Vector<String> str_values = property_value;
for (int k = 0; k < str_values.size(); k++) {
String desc = str_values[k].get_slice(";", 1).strip_edges();
- if (!desc.empty()) {
+ if (!desc.is_empty()) {
parsed_strings.push_back(desc);
}
}
} else if (property_value.get_type() == Variant::STRING) {
String str_value = String(property_value);
// Prevent reading text containing only spaces.
- if (!str_value.strip_edges().empty()) {
+ if (!str_value.strip_edges().is_empty()) {
parsed_strings.push_back(str_value);
}
}
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 0ccca7e06c..0584ee894b 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -86,8 +86,8 @@ void Polygon2DEditor::_notification(int p_what) {
b_snap_enable->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
uv_icon_zoom->set_texture(get_theme_icon("Zoom", "EditorIcons"));
- uv_vscroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
- uv_hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
+ uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
+ uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
@@ -1189,8 +1189,8 @@ void Polygon2DEditor::_uv_draw() {
Size2 vmin = uv_vscroll->get_combined_minimum_size();
// Avoid scrollbar overlapping.
- uv_hscroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0);
- uv_vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0);
+ uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0);
+ uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0);
updating_uv_scroll = false;
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index e0a6fe16f7..10bd7cc952 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -587,7 +587,7 @@ void ScriptEditor::_go_to_tab(int p_idx) {
}
void ScriptEditor::_add_recent_script(String p_path) {
- if (p_path.empty()) {
+ if (p_path.is_empty()) {
return;
}
@@ -702,7 +702,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) {
}
}
if (script.is_valid()) {
- if (!script->get_path().empty()) {
+ if (!script->get_path().is_empty()) {
// Only saved scripts can be restored.
previous_scripts.push_back(script->get_path());
}
@@ -1129,7 +1129,7 @@ void ScriptEditor::_menu_option(int p_option) {
return;
} break;
case FILE_REOPEN_CLOSED: {
- if (previous_scripts.empty()) {
+ if (previous_scripts.is_empty()) {
return;
}
@@ -1381,7 +1381,7 @@ void ScriptEditor::_menu_option(int p_option) {
case SHOW_IN_FILE_SYSTEM: {
const RES script = current->get_edited_resource();
const String path = script->get_path();
- if (!path.empty()) {
+ if (!path.is_empty()) {
FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock();
file_system_dock->navigate_to_path(path);
// Ensure that the FileSystem dock is visible.
@@ -1887,7 +1887,7 @@ void ScriptEditor::_update_script_names() {
if (se) {
Ref<Texture2D> icon = se->get_theme_icon();
String path = se->get_edited_resource()->get_path();
- bool saved = !path.empty();
+ bool saved = !path.is_empty();
if (saved) {
// The script might be deleted, moved, or renamed, so make sure
// to update original path to previously edited resource.
@@ -1934,7 +1934,7 @@ void ScriptEditor::_update_script_names() {
sd.name = name;
} break;
case DISPLAY_DIR_AND_NAME: {
- if (!path.get_base_dir().get_file().empty()) {
+ if (!path.get_base_dir().get_file().is_empty()) {
sd.name = path.get_base_dir().get_file().plus_file(name);
} else {
sd.name = name;
@@ -1954,7 +1954,7 @@ void ScriptEditor::_update_script_names() {
Vector<String> disambiguated_script_names;
Vector<String> full_script_paths;
for (int j = 0; j < sedata.size(); j++) {
- disambiguated_script_names.append(sedata[j].name.replace("(*)", ""));
+ disambiguated_script_names.append(sedata[j].name.replace("(*)", "").get_file());
full_script_paths.append(sedata[j].tooltip);
}
@@ -1988,7 +1988,7 @@ void ScriptEditor::_update_script_names() {
}
}
- if (_sort_list_on_update && !sedata.empty()) {
+ if (_sort_list_on_update && !sedata.is_empty()) {
sedata.sort();
// change actual order of tab_container so that the order can be rearranged by user
@@ -2052,7 +2052,7 @@ void ScriptEditor::_update_script_names() {
_update_help_overview_visibility();
_update_script_colors();
- file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(FILE_REOPEN_CLOSED), previous_scripts.empty());
+ file_menu->get_popup()->set_item_disabled(file_menu->get_popup()->get_item_index(FILE_REOPEN_CLOSED), previous_scripts.is_empty());
}
void ScriptEditor::_update_script_connections() {
@@ -2806,7 +2806,7 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
String path = scripts[i];
Dictionary script_info = scripts[i];
- if (!script_info.empty()) {
+ if (!script_info.is_empty()) {
path = script_info["path"];
}
@@ -2833,7 +2833,7 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
}
}
- if (!script_info.empty()) {
+ if (!script_info.is_empty()) {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(tab_container->get_tab_count() - 1));
if (se) {
se->set_edit_state(script_info["state"]);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index e854ed4fb3..f34224ab95 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -84,10 +84,10 @@ ConnectionInfoDialog::ConnectionInfoDialog() {
set_title(TTR("Connections to method:"));
VBoxContainer *vbc = memnew(VBoxContainer);
- vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -8 * EDSCALE);
- vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE);
add_child(vbc);
method = memnew(Label);
@@ -349,7 +349,7 @@ void ScriptTextEditor::update_settings() {
bool ScriptTextEditor::is_unsaved() {
const bool unsaved =
code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() ||
- script->get_path().empty(); // In memory.
+ script->get_path().is_empty(); // In memory.
return unsaved;
}
@@ -427,7 +427,7 @@ String ScriptTextEditor::get_name() {
if (script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) {
name = script->get_path().get_file();
if (is_unsaved()) {
- if (script->get_path().empty()) {
+ if (script->get_path().is_empty()) {
name = TTR("[unsaved]");
}
name += "(*)";
@@ -551,7 +551,7 @@ void ScriptTextEditor::_validate_script() {
if (safe_lines.has(i + 1)) {
te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
last_is_safe = true;
- } else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().empty())) {
+ } else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().is_empty())) {
te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color);
} else {
te->set_line_gutter_item_color(i, line_number_gutter, default_line_number_color);
@@ -1679,7 +1679,7 @@ void ScriptTextEditor::_enable_code_editor() {
VSplitContainer *editor_box = memnew(VSplitContainer);
add_child(editor_box);
- editor_box->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ editor_box->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
editor_box->set_v_size_flags(SIZE_EXPAND_FILL);
editor_box->add_child(code_editor);
@@ -1809,7 +1809,7 @@ void ScriptTextEditor::_enable_code_editor() {
ScriptTextEditor::ScriptTextEditor() {
code_editor = memnew(CodeTextEditor);
code_editor->add_theme_constant_override("separation", 2);
- code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
code_editor->set_code_complete_func(_code_complete_scripts, this);
code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index d24dcdef83..9bb34f4489 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -558,7 +558,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
shader_editor = memnew(ShaderTextEditor);
shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
shader_editor->add_theme_constant_override("separation", 0);
- shader_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ shader_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders));
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ShaderEditor::_editor_settings_changed));
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index f15a801530..f6ce3f7958 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -59,7 +59,7 @@ void ShaderFileEditor::_version_selected(int p_option) {
ERR_FAIL_COND(bytecode.is_null());
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
- if (bytecode->get_stage_bytecode(RD::ShaderStage(i)).empty() && bytecode->get_stage_compile_error(RD::ShaderStage(i)) == String()) {
+ if (bytecode->get_stage_bytecode(RD::ShaderStage(i)).is_empty() && bytecode->get_stage_compile_error(RD::ShaderStage(i)) == String()) {
stages[i]->set_icon(Ref<Texture2D>());
continue;
}
@@ -182,7 +182,7 @@ void ShaderFileEditor::_update_options() {
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
Vector<uint8_t> bc = bytecode->get_stage_bytecode(RD::ShaderStage(i));
String error = bytecode->get_stage_compile_error(RD::ShaderStage(i));
- bool disable = error == String() && bc.empty();
+ bool disable = error == String() && bc.is_empty();
stages[i]->set_disabled(disable);
if (!disable) {
if (stages[i]->is_pressed()) {
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 22f50c0689..d22157fda7 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -293,7 +293,7 @@ void BoneTransformEditor::_key_button_pressed() {
const BoneId bone_id = property.get_slicec('/', 1).to_int();
const String name = skeleton->get_bone_name(bone_id);
- if (name.empty())
+ if (name.is_empty())
return;
// Need to normalize the basis before you key it
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index 1be6b979b1..0bfd9e0c36 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -340,7 +340,7 @@ void Sprite2DEditor::_convert_to_mesh_2d_node() {
}
void Sprite2DEditor::_convert_to_polygon_2d_node() {
- if (computed_outline_lines.empty()) {
+ if (computed_outline_lines.is_empty()) {
err_dialog->set_text(TTR("Invalid geometry, can't create polygon."));
err_dialog->popup_centered();
return;
@@ -398,7 +398,7 @@ void Sprite2DEditor::_convert_to_polygon_2d_node() {
}
void Sprite2DEditor::_create_collision_polygon_2d_node() {
- if (computed_outline_lines.empty()) {
+ if (computed_outline_lines.is_empty()) {
err_dialog->set_text(TTR("Invalid geometry, can't create collision polygon."));
err_dialog->popup_centered();
return;
@@ -420,7 +420,7 @@ void Sprite2DEditor::_create_collision_polygon_2d_node() {
}
void Sprite2DEditor::_create_light_occluder_2d_node() {
- if (computed_outline_lines.empty()) {
+ if (computed_outline_lines.is_empty()) {
err_dialog->set_text(TTR("Invalid geometry, can't create light occluder."));
err_dialog->popup_centered();
return;
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index b79d829c34..099f2c8a7f 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -318,7 +318,7 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
resources.push_back(resource);
}
- if (resources.empty()) {
+ if (resources.is_empty()) {
return;
}
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 9894d0e1b0..37899293d5 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -119,7 +119,7 @@ String TextEditor::get_name() {
if (text_file->get_path().find("local://") == -1 && text_file->get_path().find("::") == -1) {
name = text_file->get_path().get_file();
if (is_unsaved()) {
- if (text_file->get_path().empty()) {
+ if (text_file->get_path().is_empty()) {
name = TTR("[unsaved]");
}
name += "(*)";
@@ -242,7 +242,7 @@ void TextEditor::apply_code() {
bool TextEditor::is_unsaved() {
const bool unsaved =
code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() ||
- text_file->get_path().empty(); // In memory.
+ text_file->get_path().is_empty(); // In memory.
return unsaved;
}
@@ -548,7 +548,7 @@ TextEditor::TextEditor() {
code_editor->add_theme_constant_override("separation", 0);
code_editor->connect("load_theme_settings", callable_mp(this, &TextEditor::_load_theme_settings));
code_editor->connect("validate_script", callable_mp(this, &TextEditor::_validate_script));
- code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ code_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
code_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
update_settings();
diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp
index 8447a2346f..d13a865534 100644
--- a/editor/plugins/texture_3d_editor_plugin.cpp
+++ b/editor/plugins/texture_3d_editor_plugin.cpp
@@ -160,16 +160,16 @@ Texture3DEditor::Texture3DEditor() {
layer->set_step(1);
layer->set_max(100);
add_child(layer);
- layer->set_anchor(MARGIN_RIGHT, 1);
- layer->set_anchor(MARGIN_LEFT, 1);
+ layer->set_anchor(SIDE_RIGHT, 1);
+ layer->set_anchor(SIDE_LEFT, 1);
layer->set_h_grow_direction(GROW_DIRECTION_BEGIN);
layer->set_modulate(Color(1, 1, 1, 0.8));
info = memnew(Label);
add_child(info);
- info->set_anchor(MARGIN_RIGHT, 1);
- info->set_anchor(MARGIN_LEFT, 1);
- info->set_anchor(MARGIN_BOTTOM, 1);
- info->set_anchor(MARGIN_TOP, 1);
+ info->set_anchor(SIDE_RIGHT, 1);
+ info->set_anchor(SIDE_LEFT, 1);
+ info->set_anchor(SIDE_BOTTOM, 1);
+ info->set_anchor(SIDE_TOP, 1);
info->set_h_grow_direction(GROW_DIRECTION_BEGIN);
info->set_v_grow_direction(GROW_DIRECTION_BEGIN);
info->add_theme_color_override("font_color", Color(1, 1, 1, 1));
diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp
index eafe4d546b..a807e8e99b 100644
--- a/editor/plugins/texture_layered_editor_plugin.cpp
+++ b/editor/plugins/texture_layered_editor_plugin.cpp
@@ -225,16 +225,16 @@ TextureLayeredEditor::TextureLayeredEditor() {
layer->set_step(1);
layer->set_max(100);
add_child(layer);
- layer->set_anchor(MARGIN_RIGHT, 1);
- layer->set_anchor(MARGIN_LEFT, 1);
+ layer->set_anchor(SIDE_RIGHT, 1);
+ layer->set_anchor(SIDE_LEFT, 1);
layer->set_h_grow_direction(GROW_DIRECTION_BEGIN);
layer->set_modulate(Color(1, 1, 1, 0.8));
info = memnew(Label);
add_child(info);
- info->set_anchor(MARGIN_RIGHT, 1);
- info->set_anchor(MARGIN_LEFT, 1);
- info->set_anchor(MARGIN_BOTTOM, 1);
- info->set_anchor(MARGIN_TOP, 1);
+ info->set_anchor(SIDE_RIGHT, 1);
+ info->set_anchor(SIDE_LEFT, 1);
+ info->set_anchor(SIDE_BOTTOM, 1);
+ info->set_anchor(SIDE_TOP, 1);
info->set_h_grow_direction(GROW_DIRECTION_BEGIN);
info->set_v_grow_direction(GROW_DIRECTION_BEGIN);
info->add_theme_color_override("font_color", Color(1, 1, 1, 1));
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index f599b94428..15d5c615bd 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -217,23 +217,23 @@ void TextureRegionEditor::_region_draw() {
Size2 vmin = vscroll->get_combined_minimum_size();
// Avoid scrollbar overlapping.
- hscroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, vscroll->is_visible() ? -vmin.width : 0);
- vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, hscroll->is_visible() ? -hmin.height : 0);
+ hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, vscroll->is_visible() ? -vmin.width : 0);
+ vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, hscroll->is_visible() ? -hmin.height : 0);
updating_scroll = false;
if (node_ninepatch || obj_styleBox.is_valid()) {
float margins[4] = { 0 };
if (node_ninepatch) {
- margins[0] = node_ninepatch->get_patch_margin(MARGIN_TOP);
- margins[1] = node_ninepatch->get_patch_margin(MARGIN_BOTTOM);
- margins[2] = node_ninepatch->get_patch_margin(MARGIN_LEFT);
- margins[3] = node_ninepatch->get_patch_margin(MARGIN_RIGHT);
+ margins[0] = node_ninepatch->get_patch_margin(SIDE_TOP);
+ margins[1] = node_ninepatch->get_patch_margin(SIDE_BOTTOM);
+ margins[2] = node_ninepatch->get_patch_margin(SIDE_LEFT);
+ margins[3] = node_ninepatch->get_patch_margin(SIDE_RIGHT);
} else if (obj_styleBox.is_valid()) {
- margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
- margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
- margins[2] = obj_styleBox->get_margin_size(MARGIN_LEFT);
- margins[3] = obj_styleBox->get_margin_size(MARGIN_RIGHT);
+ margins[0] = obj_styleBox->get_margin_size(SIDE_TOP);
+ margins[1] = obj_styleBox->get_margin_size(SIDE_BOTTOM);
+ margins[2] = obj_styleBox->get_margin_size(SIDE_LEFT);
+ margins[3] = obj_styleBox->get_margin_size(SIDE_RIGHT);
}
Vector2 pos[4] = {
@@ -278,15 +278,15 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
edited_margin = -1;
float margins[4] = { 0 };
if (node_ninepatch) {
- margins[0] = node_ninepatch->get_patch_margin(MARGIN_TOP);
- margins[1] = node_ninepatch->get_patch_margin(MARGIN_BOTTOM);
- margins[2] = node_ninepatch->get_patch_margin(MARGIN_LEFT);
- margins[3] = node_ninepatch->get_patch_margin(MARGIN_RIGHT);
+ margins[0] = node_ninepatch->get_patch_margin(SIDE_TOP);
+ margins[1] = node_ninepatch->get_patch_margin(SIDE_BOTTOM);
+ margins[2] = node_ninepatch->get_patch_margin(SIDE_LEFT);
+ margins[3] = node_ninepatch->get_patch_margin(SIDE_RIGHT);
} else if (obj_styleBox.is_valid()) {
- margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
- margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
- margins[2] = obj_styleBox->get_margin_size(MARGIN_LEFT);
- margins[3] = obj_styleBox->get_margin_size(MARGIN_RIGHT);
+ margins[0] = obj_styleBox->get_margin_size(SIDE_TOP);
+ margins[1] = obj_styleBox->get_margin_size(SIDE_BOTTOM);
+ margins[2] = obj_styleBox->get_margin_size(SIDE_LEFT);
+ margins[3] = obj_styleBox->get_margin_size(SIDE_RIGHT);
}
Vector2 pos[4] = {
@@ -395,13 +395,13 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
} else if (drag) {
if (edited_margin >= 0) {
undo_redo->create_action(TTR("Set Margin"));
- static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
+ static Side side[4] = { SIDE_TOP, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT };
if (node_ninepatch) {
- undo_redo->add_do_method(node_ninepatch, "set_patch_margin", m[edited_margin], node_ninepatch->get_patch_margin(m[edited_margin]));
- undo_redo->add_undo_method(node_ninepatch, "set_patch_margin", m[edited_margin], prev_margin);
+ undo_redo->add_do_method(node_ninepatch, "set_patch_margin", side[edited_margin], node_ninepatch->get_patch_margin(side[edited_margin]));
+ undo_redo->add_undo_method(node_ninepatch, "set_patch_margin", side[edited_margin], prev_margin);
} else if (obj_styleBox.is_valid()) {
- undo_redo->add_do_method(obj_styleBox.ptr(), "set_margin_size", m[edited_margin], obj_styleBox->get_margin_size(m[edited_margin]));
- undo_redo->add_undo_method(obj_styleBox.ptr(), "set_margin_size", m[edited_margin], prev_margin);
+ undo_redo->add_do_method(obj_styleBox.ptr(), "set_margin_size", side[edited_margin], obj_styleBox->get_margin_size(side[edited_margin]));
+ undo_redo->add_undo_method(obj_styleBox.ptr(), "set_margin_size", side[edited_margin], prev_margin);
obj_styleBox->emit_signal(CoreStringNames::get_singleton()->changed);
}
edited_margin = -1;
@@ -438,12 +438,12 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
if (drag) {
drag = false;
if (edited_margin >= 0) {
- static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
+ static Side side[4] = { SIDE_TOP, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT };
if (node_ninepatch) {
- node_ninepatch->set_patch_margin(m[edited_margin], prev_margin);
+ node_ninepatch->set_patch_margin(side[edited_margin], prev_margin);
}
if (obj_styleBox.is_valid()) {
- obj_styleBox->set_margin_size(m[edited_margin], prev_margin);
+ obj_styleBox->set_margin_size(side[edited_margin], prev_margin);
}
edited_margin = -1;
} else {
@@ -486,12 +486,12 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
if (new_margin < 0) {
new_margin = 0;
}
- static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT };
+ static Side side[4] = { SIDE_TOP, SIDE_BOTTOM, SIDE_LEFT, SIDE_RIGHT };
if (node_ninepatch) {
- node_ninepatch->set_patch_margin(m[edited_margin], new_margin);
+ node_ninepatch->set_patch_margin(side[edited_margin], new_margin);
}
if (obj_styleBox.is_valid()) {
- obj_styleBox->set_margin_size(m[edited_margin], new_margin);
+ obj_styleBox->set_margin_size(side[edited_margin], new_margin);
}
} else {
Vector2 new_pos = mtx.affine_inverse().xform(mm->get_position());
@@ -772,8 +772,8 @@ void TextureRegionEditor::_notification(int p_what) {
zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
- vscroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
- hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
+ vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
+ hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
if (snap_mode == SNAP_AUTOSLICE && is_visible() && autoslice_is_dirty) {
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 189e5ec442..860b974632 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -262,7 +262,7 @@ Vector<int> TileMapEditor::get_selected_tiles() const {
}
void TileMapEditor::set_selected_tiles(Vector<int> p_tiles) {
- palette->unselect_all();
+ palette->deselect_all();
for (int i = p_tiles.size() - 1; i >= 0; i--) {
int idx = palette->find_metadata(p_tiles[i]);
@@ -449,7 +449,7 @@ void TileMapEditor::_update_palette() {
List<int> tiles;
tileset->get_tile_list(&tiles);
- if (tiles.empty()) {
+ if (tiles.is_empty()) {
return;
}
@@ -1779,7 +1779,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
return;
}
- if (paint_undo.empty()) {
+ if (paint_undo.is_empty()) {
return;
}
@@ -1810,7 +1810,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
}
}
} else if (tool == TOOL_PASTING) {
- if (copydata.empty()) {
+ if (copydata.is_empty()) {
return;
}
@@ -2085,7 +2085,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
info_message->set_align(Label::ALIGN_CENTER);
info_message->set_autowrap(true);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
palette->add_child(info_message);
// Add autotile override palette.
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 64647b51ba..7747c740df 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -119,19 +119,13 @@ void VersionControlEditorPlugin::_initialize_vcs() {
}
void VersionControlEditorPlugin::_send_commit_msg() {
- String msg = commit_message->get_text();
- if (msg == "") {
- commit_status->set_text(TTR("No commit message was provided"));
- return;
- }
-
if (EditorVCSInterface::get_singleton()) {
if (staged_files_count == 0) {
commit_status->set_text(TTR("No files added to stage"));
return;
}
- EditorVCSInterface::get_singleton()->commit(msg);
+ EditorVCSInterface::get_singleton()->commit(commit_message->get_text());
commit_message->set_text("");
version_control_dock_button->set_pressed(false);
@@ -294,6 +288,10 @@ void VersionControlEditorPlugin::_update_commit_status() {
staged_files_count = 0;
}
+void VersionControlEditorPlugin::_update_commit_button() {
+ commit_button->set_disabled(commit_message->get_text().strip_edges() == "");
+}
+
void VersionControlEditorPlugin::register_editor() {
if (!EditorVCSInterface::get_singleton()) {
EditorNode::get_singleton()->add_control_to_dock(EditorNode::DOCK_SLOT_RIGHT_UL, version_commit_dock);
@@ -463,10 +461,12 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
commit_message->set_v_grow_direction(Control::GrowDirection::GROW_DIRECTION_END);
commit_message->set_custom_minimum_size(Size2(200, 100));
commit_message->set_wrap_enabled(true);
+ commit_message->connect("text_changed", callable_mp(this, &VersionControlEditorPlugin::_update_commit_button));
commit_box_vbc->add_child(commit_message);
commit_button = memnew(Button);
commit_button->set_text(TTR("Commit Changes"));
+ commit_button->set_disabled(true);
commit_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_send_commit_msg));
commit_box_vbc->add_child(commit_button);
diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h
index 34643e85e4..3f107ddffb 100644
--- a/editor/plugins/version_control_editor_plugin.h
+++ b/editor/plugins/version_control_editor_plugin.h
@@ -110,6 +110,7 @@ private:
void _clear_file_diff();
void _update_stage_status();
void _update_commit_status();
+ void _update_commit_button();
friend class EditorVCSInterface;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index da664109dc..ec1de43b6f 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -83,10 +83,10 @@ void VisualShaderNodePlugin::_bind_methods() {
static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
- style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE);
- style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE);
- style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE);
- style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE);
+ style->set_default_margin(SIDE_LEFT, p_margin_left * EDSCALE);
+ style->set_default_margin(SIDE_RIGHT, p_margin_right * EDSCALE);
+ style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * EDSCALE);
+ style->set_default_margin(SIDE_TOP, p_margin_top * EDSCALE);
return style;
}
@@ -283,7 +283,7 @@ VisualShader::Type VisualShaderGraphPlugin::get_shader_type() const {
void VisualShaderGraphPlugin::set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position) {
if (visual_shader->get_shader_type() == p_type && links.has(p_id)) {
- links[p_id].graph_node->set_offset(p_position);
+ links[p_id].graph_node->set_position_offset(p_position);
}
}
@@ -365,7 +365,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expression = expression_node->get_expression();
}
- node->set_offset(visual_shader->get_node_position(p_type, p_id));
+ node->set_position_offset(visual_shader->get_node_position(p_type, p_id));
node->set_title(vsnode->get_caption());
node->set_name(itos(p_id));
@@ -1015,7 +1015,7 @@ void VisualShaderEditor::_update_options_menu() {
TreeItem *root = members->create_item();
String filter = node_filter->get_text().strip_edges();
- bool use_filter = !filter.empty();
+ bool use_filter = !filter.is_empty();
bool is_first_item = true;
@@ -1580,9 +1580,9 @@ void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p
box_size.x = gn->get_size().x;
}
}
- box_size.x -= text_box->get_margin(MARGIN_LEFT);
+ box_size.x -= text_box->get_offset(SIDE_LEFT);
box_size.x -= 28 * EDSCALE;
- box_size.y -= text_box->get_margin(MARGIN_TOP);
+ box_size.y -= text_box->get_offset(SIDE_TOP);
box_size.y -= 28 * EDSCALE;
text_box->set_custom_minimum_size(Size2(box_size.x, box_size.y));
text_box->set_size(Size2(1, 1));
@@ -2108,7 +2108,7 @@ void VisualShaderEditor::_delete_nodes_request() {
}
}
- if (to_erase.empty()) {
+ if (to_erase.is_empty()) {
return;
}
@@ -2145,13 +2145,13 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
}
}
}
- if (to_change.empty() && copy_nodes_buffer.empty()) {
+ if (to_change.is_empty() && copy_nodes_buffer.is_empty()) {
_show_members_dialog(true);
} else {
- popup_menu->set_item_disabled(NodeMenuOptions::COPY, to_change.empty());
- popup_menu->set_item_disabled(NodeMenuOptions::PASTE, copy_nodes_buffer.empty());
- popup_menu->set_item_disabled(NodeMenuOptions::DELETE, to_change.empty());
- popup_menu->set_item_disabled(NodeMenuOptions::DUPLICATE, to_change.empty());
+ popup_menu->set_item_disabled(NodeMenuOptions::COPY, to_change.is_empty());
+ popup_menu->set_item_disabled(NodeMenuOptions::PASTE, copy_nodes_buffer.is_empty());
+ popup_menu->set_item_disabled(NodeMenuOptions::DELETE, to_change.is_empty());
+ popup_menu->set_item_disabled(NodeMenuOptions::DUPLICATE, to_change.is_empty());
menu_point = graph->get_local_mouse_position();
Point2 gpos = Input::get_singleton()->get_mouse_position();
popup_menu->set_position(gpos);
@@ -2445,7 +2445,7 @@ void VisualShaderEditor::_duplicate_nodes() {
_dup_copy_nodes(type, nodes, excluded);
- if (nodes.empty()) {
+ if (nodes.is_empty()) {
return;
}
@@ -2463,7 +2463,7 @@ void VisualShaderEditor::_copy_nodes() {
}
void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2 &p_custom_position) {
- if (copy_nodes_buffer.empty()) {
+ if (copy_nodes_buffer.is_empty()) {
return;
}
@@ -2997,12 +2997,12 @@ VisualShaderEditor::VisualShaderEditor() {
popup_menu = memnew(PopupMenu);
add_child(popup_menu);
- popup_menu->add_item("Add Node", NodeMenuOptions::ADD);
+ popup_menu->add_item(TTR("Add Node"), NodeMenuOptions::ADD);
popup_menu->add_separator();
- popup_menu->add_item("Copy", NodeMenuOptions::COPY);
- popup_menu->add_item("Paste", NodeMenuOptions::PASTE);
- popup_menu->add_item("Delete", NodeMenuOptions::DELETE);
- popup_menu->add_item("Duplicate", NodeMenuOptions::DUPLICATE);
+ popup_menu->add_item(TTR("Copy"), NodeMenuOptions::COPY);
+ popup_menu->add_item(TTR("Paste"), NodeMenuOptions::PASTE);
+ popup_menu->add_item(TTR("Delete"), NodeMenuOptions::DELETE);
+ popup_menu->add_item(TTR("Duplicate"), NodeMenuOptions::DUPLICATE);
popup_menu->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_node_menu_id_pressed));
///////////////////////////////////////
diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp
index 9b3227ad28..789d0e6ba5 100644
--- a/editor/pot_generator.cpp
+++ b/editor/pot_generator.cpp
@@ -135,7 +135,7 @@ void POTGenerator::_write_to_pot(const String &p_file) {
}
// Write context.
- if (!context.empty()) {
+ if (!context.is_empty()) {
file->store_line("msgctxt \"" + context + "\"");
}
@@ -143,7 +143,7 @@ void POTGenerator::_write_to_pot(const String &p_file) {
_write_msgid(file, msgid, false);
// Write msgid_plural
- if (!plural.empty()) {
+ if (!plural.is_empty()) {
_write_msgid(file, plural, true);
file->store_line("msgstr[0] \"\"");
file->store_line("msgstr[1] \"\"\n");
@@ -185,7 +185,7 @@ void POTGenerator::_add_new_msgid(const String &p_msgid, const String &p_context
Vector<MsgidData> &v_mdata = all_translation_strings[p_msgid];
for (int i = 0; i < v_mdata.size(); i++) {
if (v_mdata[i].ctx == p_context) {
- if (!v_mdata[i].plural.empty() && !p_plural.empty() && v_mdata[i].plural != p_plural) {
+ if (!v_mdata[i].plural.is_empty() && !p_plural.is_empty() && v_mdata[i].plural != p_plural) {
WARN_PRINT("Redefinition of plural message (msgid_plural), under the same message (msgid) and context (msgctxt)");
}
v_mdata.write[i].locations.insert(p_location);
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index 46a656e0af..d6d8e5789e 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -50,7 +50,7 @@ void BackgroundProgress::_add_task(const String &p_task, const String &p_label,
Control *ec = memnew(Control);
ec->set_h_size_flags(SIZE_EXPAND_FILL);
ec->set_v_size_flags(SIZE_EXPAND_FILL);
- t.progress->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ t.progress->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
ec->add_child(t.progress);
ec->set_custom_minimum_size(Size2(80, 5) * EDSCALE);
t.hb->add_child(ec);
@@ -111,7 +111,7 @@ void BackgroundProgress::task_step(const String &p_task, int p_step) {
bool no_updates = true;
{
_THREAD_SAFE_METHOD_
- no_updates = updates.empty();
+ no_updates = updates.is_empty();
}
if (no_updates) {
@@ -141,10 +141,10 @@ void ProgressDialog::_popup() {
Ref<StyleBox> style = main->get_theme_stylebox("panel", "PopupMenu");
ms += style->get_minimum_size();
- main->set_margin(MARGIN_LEFT, style->get_margin(MARGIN_LEFT));
- main->set_margin(MARGIN_RIGHT, -style->get_margin(MARGIN_RIGHT));
- main->set_margin(MARGIN_TOP, style->get_margin(MARGIN_TOP));
- main->set_margin(MARGIN_BOTTOM, -style->get_margin(MARGIN_BOTTOM));
+ main->set_offset(SIDE_LEFT, style->get_margin(SIDE_LEFT));
+ main->set_offset(SIDE_RIGHT, -style->get_margin(SIDE_RIGHT));
+ main->set_offset(SIDE_TOP, style->get_margin(SIDE_TOP));
+ main->set_offset(SIDE_BOTTOM, -style->get_margin(SIDE_BOTTOM));
//raise();
popup_centered(ms);
@@ -218,7 +218,7 @@ void ProgressDialog::end_task(const String &p_task) {
memdelete(t.vb);
tasks.erase(p_task);
- if (tasks.empty()) {
+ if (tasks.is_empty()) {
hide();
} else {
_popup();
@@ -235,7 +235,7 @@ void ProgressDialog::_bind_methods() {
ProgressDialog::ProgressDialog() {
main = memnew(VBoxContainer);
add_child(main);
- main->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ main->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
set_exclusive(true);
last_progress_tick = 0;
singleton = this;
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 68710920a5..c0f2f25465 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -196,7 +196,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
export_path->hide();
runnable->set_disabled(true);
parameters->edit(nullptr);
- presets->unselect_all();
+ presets->deselect_all();
duplicate_preset->set_disabled(true);
delete_preset->set_disabled(true);
sections->hide();
@@ -516,7 +516,7 @@ void ProjectExportDialog::_script_encryption_key_changed(const String &p_key) {
bool ProjectExportDialog::_validate_script_encryption_key(const String &p_key) {
bool is_valid = false;
- if (!p_key.empty() && p_key.is_valid_hex_number(false) && p_key.length() == 64) {
+ if (!p_key.is_empty() && p_key.is_valid_hex_number(false) && p_key.length() == 64) {
is_valid = true;
}
return is_valid;
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index ad0c9532d8..6e32445124 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1545,7 +1545,7 @@ bool ProjectList::is_any_project_missing() const {
}
void ProjectList::erase_missing_projects() {
- if (_projects.empty()) {
+ if (_projects.is_empty()) {
return;
}
@@ -1824,7 +1824,7 @@ void ProjectManager::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
- settings_hb->set_anchors_and_margins_preset(Control::PRESET_TOP_RIGHT);
+ settings_hb->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT);
update();
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -1875,7 +1875,7 @@ void ProjectManager::_dim_window() {
void ProjectManager::_update_project_buttons() {
Vector<ProjectList::Item> selected_projects = _project_list->get_selected_projects();
- bool empty_selection = selected_projects.empty();
+ bool empty_selection = selected_projects.is_empty();
bool is_missing_project_selected = false;
for (int i = 0; i < selected_projects.size(); ++i) {
@@ -2440,19 +2440,19 @@ ProjectManager::ProjectManager() {
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
- set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ set_anchors_and_offsets_preset(Control::PRESET_WIDE);
set_theme(create_custom_theme());
- set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ set_anchors_and_offsets_preset(Control::PRESET_WIDE);
Panel *panel = memnew(Panel);
add_child(panel);
- panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ panel->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
panel->add_theme_style_override("panel", get_theme_stylebox("Background", "EditorStyles"));
VBoxContainer *vb = memnew(VBoxContainer);
panel->add_child(vb);
- vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE);
+ vb->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8 * EDSCALE);
Control *center_box = memnew(Control);
center_box->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -2460,7 +2460,7 @@ ProjectManager::ProjectManager() {
tabs = memnew(TabContainer);
center_box->add_child(tabs);
- tabs->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ tabs->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
tabs->set_tab_align(TabContainer::ALIGN_LEFT);
HBoxContainer *projects_hb = memnew(HBoxContainer);
@@ -2571,7 +2571,7 @@ ProjectManager::ProjectManager() {
settings_hb = memnew(HBoxContainer);
settings_hb->set_alignment(BoxContainer::ALIGN_END);
settings_hb->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN);
- settings_hb->set_anchors_and_margins_preset(Control::PRESET_TOP_RIGHT);
+ settings_hb->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT);
Label *version_label = memnew(Label);
String hash = String(VERSION_HASH);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 9995c6ad65..a294a64dbe 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -156,7 +156,7 @@ void ProjectSettingsEditor::_update_advanced_bar() {
bool disable_add = true;
bool disable_del = true;
- if (!property_box->get_text().empty()) {
+ if (!property_box->get_text().is_empty()) {
const String setting = _get_setting_name();
bool setting_exists = ps->has_setting(setting);
if (setting_exists) {
@@ -197,7 +197,7 @@ void ProjectSettingsEditor::_update_advanced_bar() {
String ProjectSettingsEditor::_get_setting_name() const {
const String cat = category_box->get_text();
- const String name = (cat.empty() ? "global" : cat.strip_edges()).plus_file(property_box->get_text().strip_edges());
+ const String name = (cat.is_empty() ? "global" : cat.strip_edges()).plus_file(property_box->get_text().strip_edges());
const String feature = feature_override->get_item_text(feature_override->get_selected());
return (feature == "") ? name : (name + "." + feature);
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 847af0f2c2..9a58a23cb0 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -251,7 +251,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
emit_signal("variant_changed");
break;
}
- ERR_FAIL_COND(inheritors_array.empty());
+ ERR_FAIL_COND(inheritors_array.is_empty());
String intype = inheritors_array[p_which - TYPE_BASE_ID];
@@ -367,18 +367,18 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
int c = hint_text.get_slice_count(",");
float min = 0, max = 100, step = type == Variant::FLOAT ? .01 : 1;
if (c >= 1) {
- if (!hint_text.get_slice(",", 0).empty()) {
+ if (!hint_text.get_slice(",", 0).is_empty()) {
min = hint_text.get_slice(",", 0).to_float();
}
}
if (c >= 2) {
- if (!hint_text.get_slice(",", 1).empty()) {
+ if (!hint_text.get_slice(",", 1).is_empty()) {
max = hint_text.get_slice(",", 1).to_float();
}
}
if (c >= 3) {
- if (!hint_text.get_slice(",", 2).empty()) {
+ if (!hint_text.get_slice(",", 2).is_empty()) {
step = hint_text.get_slice(",", 2).to_float();
}
}
@@ -456,14 +456,14 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
set_size(Vector2(4, 4) * EDSCALE + checks20gc->get_position() + checks20gc->get_size());
} else if (hint == PROPERTY_HINT_EXP_EASING) {
- easing_draw->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5 * EDSCALE);
- easing_draw->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5 * EDSCALE);
- easing_draw->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 5 * EDSCALE);
- easing_draw->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -30 * EDSCALE);
- type_button->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 3 * EDSCALE);
- type_button->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -3 * EDSCALE);
- type_button->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_END, -25 * EDSCALE);
- type_button->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -7 * EDSCALE);
+ easing_draw->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 5 * EDSCALE);
+ easing_draw->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -5 * EDSCALE);
+ easing_draw->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_BEGIN, 5 * EDSCALE);
+ easing_draw->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -30 * EDSCALE);
+ type_button->set_anchor_and_offset(SIDE_LEFT, Control::ANCHOR_BEGIN, 3 * EDSCALE);
+ type_button->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -3 * EDSCALE);
+ type_button->set_anchor_and_offset(SIDE_TOP, Control::ANCHOR_END, -25 * EDSCALE);
+ type_button->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_END, -7 * EDSCALE);
type_button->set_text(TTR("Preset..."));
type_button->get_popup()->clear();
type_button->get_popup()->add_item(TTR("Linear"), EASING_LINEAR);
@@ -536,10 +536,10 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
int button_margin = text_edit->get_theme_constant("button_margin", "Dialogs");
int margin = text_edit->get_theme_constant("margin", "Dialogs");
- action_buttons[0]->set_anchor(MARGIN_LEFT, Control::ANCHOR_END);
- action_buttons[0]->set_anchor(MARGIN_TOP, Control::ANCHOR_END);
- action_buttons[0]->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
- action_buttons[0]->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END);
+ action_buttons[0]->set_anchor(SIDE_LEFT, Control::ANCHOR_END);
+ action_buttons[0]->set_anchor(SIDE_TOP, Control::ANCHOR_END);
+ action_buttons[0]->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
+ action_buttons[0]->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
action_buttons[0]->set_begin(Point2(-70 * EDSCALE, -button_margin + 5 * EDSCALE));
action_buttons[0]->set_end(Point2(-margin, -margin));
action_buttons[0]->set_text(TTR("Close"));
@@ -882,7 +882,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
bool is_custom_resource = false;
Ref<Texture2D> icon;
- if (!custom_resources.empty()) {
+ if (!custom_resources.is_empty()) {
for (int k = 0; k < custom_resources.size(); k++) {
if (custom_resources[k].name == t) {
is_custom_resource = true;
@@ -1246,7 +1246,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
} break;
case Variant::OBJECT: {
if (p_which == 0) {
- ERR_FAIL_COND(inheritors_array.empty());
+ ERR_FAIL_COND(inheritors_array.is_empty());
String intype = inheritors_array[0];
@@ -1661,10 +1661,10 @@ void CustomPropertyEditor::_focus_exit() {
void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox("panel");
- int margin_top = sb->get_margin(MARGIN_TOP);
- int margin_left = sb->get_margin(MARGIN_LEFT);
- int margin_bottom = sb->get_margin(MARGIN_BOTTOM);
- int margin_right = sb->get_margin(MARGIN_RIGHT);
+ int margin_top = sb->get_margin(SIDE_TOP);
+ int margin_left = sb->get_margin(SIDE_LEFT);
+ int margin_bottom = sb->get_margin(SIDE_BOTTOM);
+ int margin_right = sb->get_margin(SIDE_RIGHT);
int max_width = 0;
int height = 0;
@@ -1794,8 +1794,8 @@ CustomPropertyEditor::CustomPropertyEditor() {
text_edit = memnew(TextEdit);
add_child(text_edit);
- text_edit->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
- text_edit->set_margin(MARGIN_BOTTOM, -30);
+ text_edit->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
+ text_edit->set_offset(SIDE_BOTTOM, -30);
text_edit->hide();
text_edit->connect("text_changed", callable_mp(this, &CustomPropertyEditor::_text_edit_changed));
@@ -1853,12 +1853,12 @@ CustomPropertyEditor::CustomPropertyEditor() {
spinbox = memnew(SpinBox);
add_child(spinbox);
- spinbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
+ spinbox->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
spinbox->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified));
slider = memnew(HSlider);
add_child(slider);
- slider->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
+ slider->set_anchors_and_offsets_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
slider->connect("value_changed", callable_mp(this, &CustomPropertyEditor::_range_modified));
create_dialog = nullptr;
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index a60937a86b..379faf2131 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -572,7 +572,7 @@ void RenameDialog::rename() {
// Forward recursive as opposed to the actual renaming.
_iterate_scene(root_node, selected_node_list, &global_count);
- if (undo_redo && !to_rename.empty()) {
+ if (undo_redo && !to_rename.is_empty()) {
undo_redo->create_action(TTR("Batch Rename"));
// Make sure to iterate reversed so that child nodes will find parents.
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 72703623ab..89750f6043 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -361,7 +361,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (current_edited_scene_root) {
String root_class = current_edited_scene_root->get_class_name();
static Vector<String> preferred_types;
- if (preferred_types.empty()) {
+ if (preferred_types.is_empty()) {
preferred_types.push_back("Control");
preferred_types.push_back("Node2D");
preferred_types.push_back("Node3D");
@@ -416,7 +416,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
Node *selected = scene_tree->get_selected();
- if (!selected && !editor_selection->get_selected_node_list().empty()) {
+ if (!selected && !editor_selection->get_selected_node_list().is_empty()) {
selected = editor_selection->get_selected_node_list().front()->get();
}
@@ -438,7 +438,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Array selection = editor_selection->get_selected_nodes();
- if (selection.empty()) {
+ if (selection.is_empty()) {
return;
}
@@ -737,7 +737,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
List<Node *> remove_list = editor_selection->get_selected_node_list();
- if (remove_list.empty()) {
+ if (remove_list.is_empty()) {
return;
}
@@ -1015,7 +1015,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
break;
case TOOL_CREATE_USER_INTERFACE: {
Control *node = memnew(Control);
- node->set_anchors_and_margins_preset(PRESET_WIDE); //more useful for resizable UIs.
+ node->set_anchors_and_offsets_preset(PRESET_WIDE); //more useful for resizable UIs.
new_node = node;
} break;
@@ -1107,7 +1107,7 @@ void SceneTreeDock::_notification(int p_what) {
node_shortcuts_toggle->set_toggle_mode(true);
node_shortcuts_toggle->set_tooltip(TTR("Switch to Favorite Nodes"));
node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection"));
- node_shortcuts_toggle->set_anchors_and_margins_preset(Control::PRESET_CENTER_RIGHT);
+ node_shortcuts_toggle->set_anchors_and_offsets_preset(Control::PRESET_CENTER_RIGHT);
node_shortcuts_toggle->connect("pressed", callable_mp(this, &SceneTreeDock::_update_create_root_dialog));
top_row->add_child(node_shortcuts_toggle);
@@ -1529,7 +1529,7 @@ void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
List<Node *> selection = editor_selection->get_selected_node_list();
- if (selection.empty()) {
+ if (selection.is_empty()) {
return; // Nothing to reparent.
}
@@ -1703,7 +1703,7 @@ bool SceneTreeDock::_is_collapsed_recursive(TreeItem *p_item) const {
List<TreeItem *> needs_check;
needs_check.push_back(p_item);
- while (!needs_check.empty()) {
+ while (!needs_check.is_empty()) {
TreeItem *item = needs_check.back()->get();
needs_check.pop_back();
@@ -1725,7 +1725,7 @@ void SceneTreeDock::_set_collapsed_recursive(TreeItem *p_item, bool p_collapsed)
List<TreeItem *> to_collapse;
to_collapse.push_back(p_item);
- while (!to_collapse.empty()) {
+ while (!to_collapse.is_empty()) {
TreeItem *item = to_collapse.back()->get();
to_collapse.pop_back();
@@ -1742,7 +1742,7 @@ void SceneTreeDock::_set_collapsed_recursive(TreeItem *p_item, bool p_collapsed)
void SceneTreeDock::_script_created(Ref<Script> p_script) {
List<Node *> selected = editor_selection->get_selected_node_list();
- if (selected.empty()) {
+ if (selected.is_empty()) {
return;
}
@@ -1811,7 +1811,7 @@ void SceneTreeDock::_toggle_editable_children(Node *p_node) {
void SceneTreeDock::_delete_confirm() {
List<Node *> remove_list = editor_selection->get_selected_node_list();
- if (remove_list.empty()) {
+ if (remove_list.is_empty()) {
return;
}
@@ -2349,7 +2349,7 @@ void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) {
List<Node *> selection = editor_selection->get_selected_node_list();
- if (selection.empty()) {
+ if (selection.is_empty()) {
return; //nothing to reparent
}
@@ -2601,7 +2601,7 @@ void SceneTreeDock::attach_script_to_selected(bool p_extend) {
}
List<Node *> selection = editor_selection->get_selected_node_list();
- if (selection.empty()) {
+ if (selection.is_empty()) {
return;
}
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 685833da55..f30ad02f5e 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -251,7 +251,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
if (can_rename) { //should be can edit..
String warning = p_node->get_configuration_warning();
- if (!warning.empty()) {
+ if (!warning.is_empty()) {
item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + p_node->get_configuration_warning());
}
@@ -754,7 +754,7 @@ void SceneTreeEditor::_renamed() {
ERR_FAIL_COND(!n);
// Empty node names are not allowed, so resets it to previous text and show warning
- if (which->get_text(0).strip_edges().empty()) {
+ if (which->get_text(0).strip_edges().is_empty()) {
which->set_text(0, n->get_name());
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
return;
@@ -765,7 +765,7 @@ void SceneTreeEditor::_renamed() {
error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + Node::invalid_character);
error->popup_centered();
- if (new_name.empty()) {
+ if (new_name.is_empty()) {
which->set_text(0, n->get_name());
return;
}
@@ -931,7 +931,7 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from
next = tree->get_next_selected(next);
}
- if (selected.empty()) {
+ if (selected.is_empty()) {
return Variant();
}
@@ -1150,8 +1150,8 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
}
tree = memnew(Tree);
- tree->set_anchor(MARGIN_RIGHT, ANCHOR_END);
- tree->set_anchor(MARGIN_BOTTOM, ANCHOR_END);
+ tree->set_anchor(SIDE_RIGHT, ANCHOR_END);
+ tree->set_anchor(SIDE_BOTTOM, ANCHOR_END);
tree->set_begin(Point2(0, p_label ? 18 : 0));
tree->set_end(Point2(0, 0));
tree->add_theme_constant_override("button_margin", 0);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 9c3e381dc8..7fd2613c1e 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -50,7 +50,7 @@ void ScriptCreateDialog::_theme_changed() {
}
String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", "");
- if (!last_lang.empty()) {
+ if (!last_lang.is_empty()) {
for (int i = 0; i < language_menu->get_item_count(); i++) {
if (language_menu->get_item_text(i) == last_lang) {
language_menu->select(i);
@@ -568,6 +568,8 @@ void ScriptCreateDialog::_create() {
void ScriptCreateDialog::_browse_class_in_tree() {
select_class->set_base_type(base_type);
select_class->popup_create(true);
+ select_class->set_title(vformat(TTR("Inherit %s"), base_type));
+ select_class->get_ok_button()->set_text(TTR("Inherit"));
}
void ScriptCreateDialog::_path_changed(const String &p_path) {
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index a29b6aded7..c152c2625f 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -471,10 +471,10 @@ EditorSettingsDialog::EditorSettingsDialog() {
Label *l = memnew(Label);
l->set_text(TTR("Press a Key..."));
- l->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ l->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
l->set_align(Label::ALIGN_CENTER);
- l->set_margin(MARGIN_TOP, 20);
- l->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_BEGIN, 30);
+ l->set_offset(SIDE_TOP, 20);
+ l->set_anchor_and_offset(SIDE_BOTTOM, Control::ANCHOR_BEGIN, 30);
press_a_key_label = l;
press_a_key->add_child(l);
press_a_key->connect("window_input", callable_mp(this, &EditorSettingsDialog::_wait_for_key));