diff options
Diffstat (limited to 'editor')
32 files changed, 791 insertions, 154 deletions
diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp index 81d5309712..06d7d5fdc8 100644 --- a/editor/array_property_edit.cpp +++ b/editor/array_property_edit.cpp @@ -251,7 +251,7 @@ void ArrayPropertyEdit::edit(Object *p_obj, const StringName &p_prop, const Stri page = 0; property = p_prop; - obj = p_obj->get_instance_ID(); + obj = p_obj->get_instance_id(); default_type = p_deftype; if (!p_hint_string.empty()) { diff --git a/editor/asset_library_editor_plugin.cpp b/editor/asset_library_editor_plugin.cpp index f92b70d0c0..2a22cde2fb 100644 --- a/editor/asset_library_editor_plugin.cpp +++ b/editor/asset_library_editor_plugin.cpp @@ -1136,7 +1136,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const item->connect("category_selected", this, "_select_category"); if (r.has("icon_url") && r["icon_url"] != "") { - _request_image(item->get_instance_ID(), r["icon_url"], IMAGE_QUEUE_ICON, 0); + _request_image(item->get_instance_id(), r["icon_url"], IMAGE_QUEUE_ICON, 0); } } } break; @@ -1173,7 +1173,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const item->connect("category_selected",this,"_category_selected");*/ if (r.has("icon_url") && r["icon_url"] != "") { - _request_image(description->get_instance_ID(), r["icon_url"], IMAGE_QUEUE_ICON, 0); + _request_image(description->get_instance_id(), r["icon_url"], IMAGE_QUEUE_ICON, 0); } if (d.has("previews")) { @@ -1195,12 +1195,12 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const description->add_preview(i, is_video, video_url); if (p.has("thumbnail")) { - _request_image(description->get_instance_ID(), p["thumbnail"], IMAGE_QUEUE_THUMBNAIL, i); + _request_image(description->get_instance_id(), p["thumbnail"], IMAGE_QUEUE_THUMBNAIL, i); } if (is_video) { - //_request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i); + //_request_image(description->get_instance_id(),p["link"],IMAGE_QUEUE_SCREENSHOT,i); } else { - _request_image(description->get_instance_ID(), p["link"], IMAGE_QUEUE_SCREENSHOT, i); + _request_image(description->get_instance_id(), p["link"], IMAGE_QUEUE_SCREENSHOT, i); } } } diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 9762bd2000..47c2cb5536 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -220,7 +220,7 @@ void ConnectDialog::_add_bind() { if (cdbinds->params.size() >= VARIANT_ARG_MAX) return; - Variant::Type vt = (Variant::Type)type_list->get_item_ID(type_list->get_selected()); + Variant::Type vt = (Variant::Type)type_list->get_item_id(type_list->get_selected()); Variant value; diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index c82e8f1226..c3c3f0d3ca 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -183,7 +183,7 @@ ObjectID EditorHistory::get_current() { if (!obj) return 0; - return obj->get_instance_ID(); + return obj->get_instance_id(); } int EditorHistory::get_path_size() const { @@ -208,7 +208,7 @@ ObjectID EditorHistory::get_path_object(int p_index) const { if (!obj) return 0; - return obj->get_instance_ID(); + return obj->get_instance_id(); } String EditorHistory::get_path_property(int p_index) const { diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index ed58116304..0fd643d031 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -512,6 +512,8 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) // skip if another project inside this continue; + if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) // skip if another project inside this + continue; dirs.push_back(f); @@ -691,6 +693,8 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) // skip if another project inside this continue; + if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) // skip if another project inside this + continue; EditorFileSystemDirectory *efd = memnew(EditorFileSystemDirectory); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index e890082ee1..f80c4ee0e2 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1621,12 +1621,18 @@ void EditorHelp::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - //forward->set_icon(get_icon("Forward","EditorIcons")); //back->set_icon(get_icon("Back","EditorIcons")); _update_doc(); + } break; + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); + style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color")); + background_panel->add_style_override("panel", style); } break; + + default: break; } } @@ -1695,14 +1701,14 @@ EditorHelp::EditorHelp() { //class_list->set_selection_enabled(true); { - Panel *pc = memnew(Panel); + background_panel = memnew(Panel); Ref<StyleBoxFlat> style(memnew(StyleBoxFlat)); style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color")); - pc->set_v_size_flags(SIZE_EXPAND_FILL); - pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit")); - vbc->add_child(pc); + background_panel->set_v_size_flags(SIZE_EXPAND_FILL); + background_panel->add_style_override("panel", style); //get_stylebox("normal","TextEdit")); + vbc->add_child(background_panel); class_desc = memnew(RichTextLabel); - pc->add_child(class_desc); + background_panel->add_child(class_desc); class_desc->set_area_as_parent_rect(8); class_desc->connect("meta_clicked", this, "_class_desc_select"); class_desc->connect("gui_input", this, "_class_desc_input"); diff --git a/editor/editor_help.h b/editor/editor_help.h index 46d83490f4..de30b543fc 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -129,6 +129,7 @@ class EditorHelp : public VBoxContainer { HSplitContainer *h_split; static DocData *doc; + Panel *background_panel; ConfirmationDialog *search_dialog; LineEdit *search; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 5d13c7c254..addffd6ea3 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -36,7 +36,7 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type) { EditorLog *self = (EditorLog *)p_self; - if (self->current != Thread::get_caller_ID()) + if (self->current != Thread::get_caller_id()) return; String err_str; @@ -204,7 +204,7 @@ EditorLog::EditorLog() { eh.userdata = this; add_error_handler(&eh); - current = Thread::get_caller_ID(); + current = Thread::get_caller_id(); EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk, this); } diff --git a/editor/editor_name_dialog.cpp b/editor/editor_name_dialog.cpp index 7435e9a9f7..6ebfcbf313 100644 --- a/editor/editor_name_dialog.cpp +++ b/editor/editor_name_dialog.cpp @@ -42,8 +42,8 @@ void EditorNameDialog::_line_gui_input(const Ref<InputEvent> &p_event) { return; switch (k->get_scancode()) { - case KEY_ENTER: - case KEY_RETURN: { + case KEY_KP_ENTER: + case KEY_ENTER: { if (get_hide_on_ok()) hide(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4d5dd14172..730ba3cacc 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1358,7 +1358,7 @@ void EditorNode::push_item(Object *p_object, const String &p_property) { return; } - uint32_t id = p_object->get_instance_ID(); + uint32_t id = p_object->get_instance_id(); if (id != editor_history.get_current()) { if (p_property == "") diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 8ce4f88590..fdac68ea1f 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -63,7 +63,7 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) { int index = popup->get_item_count(); popup->add_icon_item(icon, E->get().name.capitalize(), objects.size()); popup->set_item_h_offset(index, p_depth * 10 * EDSCALE); - objects.push_back(obj->get_instance_ID()); + objects.push_back(obj->get_instance_id()); _add_children_to_popup(obj, p_depth + 1); } diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 89fa004eb1..3d761d7289 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -295,7 +295,7 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p preview_mutex->lock(); - String path_id = "ID:" + itos(p_res->get_instance_ID()); + String path_id = "ID:" + itos(p_res->get_instance_id()); if (cache.has(path_id) && cache[path_id].last_hash == p_res->hash_edited_version()) { @@ -310,7 +310,7 @@ void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p //print_line("send to thread "+p_path); QueueItem item; item.function = p_receiver_func; - item.id = p_receiver->get_instance_ID(); + item.id = p_receiver->get_instance_id(); item.resource = p_res; item.path = path_id; item.userdata = p_userdata; @@ -334,7 +334,7 @@ void EditorResourcePreview::queue_resource_preview(const String &p_path, Object //print_line("send to thread "+p_path); QueueItem item; item.function = p_receiver_func; - item.id = p_receiver->get_instance_ID(); + item.id = p_receiver->get_instance_id(); item.path = p_path; item.userdata = p_userdata; diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index aa97dd237b..4954b1f741 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -55,7 +55,7 @@ Error EditorRun::run(const String &p_scene, const String p_custom_args, const Li } args.push_back("-epid"); - args.push_back(String::num(OS::get_singleton()->get_process_ID())); + args.push_back(String::num(OS::get_singleton()->get_process_id())); if (debug_collisions) { args.push_back("-debugcol"); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 755ac75180..07af60d634 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -216,17 +216,43 @@ Variant _EDITOR_DEF(const String &p_var, const Variant &p_default) { return p_default; } +static Dictionary _get_builtin_script_templates() { + Dictionary templates; + + //No Comments + templates["no_comments.gd"] = + "extends %BASE%\n" + "\n" + "func _ready():\n" + "%TS%pass\n"; + + //Empty + templates["empty.gd"] = + "extends %BASE%" + "\n" + "\n"; + + return templates; +} + static void _create_script_templates(const String &p_path) { - FileAccess *file = FileAccess::open(p_path.plus_file("no_comments.gd"), FileAccess::WRITE); - ERR_FAIL_COND(!file); - String script = String("extends %BASE%\n\nfunc _ready():\n%TS%pass\n"); - file->store_string(script); - file->close(); - file->reopen(p_path.plus_file("empty.gd"), FileAccess::WRITE); - script = "extends %BASE%\n\n"; - file->store_string(script); - file->close(); + Dictionary templates = _get_builtin_script_templates(); + List<Variant> keys; + templates.get_key_list(&keys); + FileAccess *file = FileAccess::create(FileAccess::ACCESS_FILESYSTEM); + + DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + dir->change_dir(p_path); + for (int i = 0; i < keys.size(); i++) { + if (!dir->file_exists(keys[i])) { + file->reopen(p_path.plus_file((String)keys[i]), FileAccess::WRITE); + ERR_FAIL_COND(!file); + file->store_string(templates[keys[i]]); + file->close(); + } + } + memdelete(file); } @@ -308,10 +334,10 @@ void EditorSettings::create() { if (dir->change_dir("script_templates") != OK) { dir->make_dir("script_templates"); - _create_script_templates(dir->get_current_dir() + "/script_templates"); } else { dir->change_dir(".."); } + _create_script_templates(dir->get_current_dir() + "/script_templates"); if (dir->change_dir("tmp") != OK) { dir->make_dir("tmp"); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index df16de947e..807aed4267 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -143,7 +143,7 @@ Ref<Theme> create_editor_theme() { Color light_color_1 = base_color.linear_interpolate(Color(1, 1, 1, 1), contrast); Color light_color_2 = base_color.linear_interpolate(Color(1, 1, 1, 1), contrast * 1.5); - const int border_width = (border_size % 3) * EDSCALE; + const int border_width = CLAMP(border_size, 0, 3) * EDSCALE; Color title_color_hl = base_color; if (highlight_tabs) @@ -238,7 +238,7 @@ Ref<Theme> create_editor_theme() { theme->set_stylebox("panel", "TabContainer", style_content_panel); theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp); - Ref<StyleBoxFlat> style_button_type = make_flat_stylebox(dark_color_1, 4, 4, 6, 4); + Ref<StyleBoxFlat> style_button_type = make_flat_stylebox(dark_color_1, 6, 4, 6, 4); style_button_type->set_draw_center(true); style_button_type->set_border_size(border_width); style_button_type->set_light_color(light_color_1); @@ -287,12 +287,12 @@ Ref<Theme> create_editor_theme() { // PopupMenu Ref<StyleBoxFlat> style_popup_menu = make_flat_stylebox(dark_color_1, 8, 8, 8, 8); - style_popup_menu->set_border_size(border_width); + style_popup_menu->set_border_size(MAX(EDSCALE, border_width)); style_popup_menu->set_light_color(light_color_1); style_popup_menu->set_dark_color(light_color_1); style_popup_menu->set_border_blend(false); theme->set_stylebox("panel", "PopupMenu", style_popup_menu); - theme->set_stylebox("separator", "PopupMenu", make_line_stylebox(separator_color, border_width, 8 - border_width)); + theme->set_stylebox("separator", "PopupMenu", make_line_stylebox(separator_color, MAX(EDSCALE, border_width), 8 - MAX(EDSCALE, border_width))); // Tree & ItemList background Ref<StyleBoxFlat> style_tree_bg = make_flat_stylebox(dark_color_1, 2, 4, 2, 4); @@ -431,7 +431,7 @@ Ref<Theme> create_editor_theme() { // WindowDialog Ref<StyleBoxFlat> style_window = make_flat_stylebox(dark_color_2, 4, 4, 4, 4); - style_window->set_border_size(border_width); + style_window->set_border_size(MAX(EDSCALE, border_width)); style_window->set_border_blend(false); style_window->set_light_color(title_color_hl); style_window->set_dark_color(title_color_hl); @@ -478,6 +478,9 @@ Ref<Theme> create_editor_theme() { theme->set_icon("grabber", "VSlider", theme->get_icon("GuiSliderGrabber", "EditorIcons")); theme->set_icon("grabber_highlight", "VSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons")); + //RichTextLabel + theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); + // Panel theme->set_stylebox("panel", "Panel", style_panel); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 77ca1a5145..7c5cd48605 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -102,7 +102,7 @@ void FileSystemDock::_notification(int p_what) { case NOTIFICATION_RESIZED: { - bool new_mode = get_size().height < get_viewport_rect().size.height * 3 / 4; + bool new_mode = get_size().height < get_viewport_rect().size.height / 2; if (new_mode != split_mode) { @@ -589,7 +589,7 @@ void FileSystemDock::_go_to_dir(const String &p_dir) { void FileSystemDock::_preview_invalidated(const String &p_path) { - if (p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { + if (display_mode == DISPLAY_THUMBNAILS && p_path.get_base_dir() == path && search_box->get_text() == String() && file_list_vb->is_visible_in_tree()) { for (int i = 0; i < files->get_item_count(); i++) { diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 35b31b56b4..1c42bcef8a 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -4,6 +4,7 @@ #include "os/os.h" #include "scene/3d/camera.h" #include "scene/3d/mesh_instance.h" +#include "scene/animation/animation_player.h" #include "scene/resources/surface_tool.h" #include "thirdparty/misc/base64.h" @@ -14,7 +15,7 @@ uint32_t EditorSceneImporterGLTF::get_import_flags() const { void EditorSceneImporterGLTF::get_extensions(List<String> *r_extensions) const { r_extensions->push_back("gltf"); - r_extensions->push_back("gfb"); + r_extensions->push_back("glb"); } Error EditorSceneImporterGLTF::_parse_json(const String &p_path, GLTFState &state) { @@ -44,6 +45,60 @@ Error EditorSceneImporterGLTF::_parse_json(const String &p_path, GLTFState &stat 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 + uint32_t version = f->get_32(); + uint32_t length = f->get_32(); + + 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.ptr(), 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.ptr(), 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]); @@ -208,8 +263,8 @@ Error EditorSceneImporterGLTF::_parse_buffers(GLTFState &state, const String &p_ Array buffers = state.json["buffers"]; for (int i = 0; i < buffers.size(); i++) { - if (i == 0 && state.gfb_data.size()) { - state.buffers.push_back(state.gfb_data); + if (i == 0 && state.glb_data.size()) { + state.buffers.push_back(state.glb_data); } else { Dictionary buffer = buffers[i]; @@ -685,6 +740,23 @@ PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState & } return ret; } +Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state, int p_accessor, bool p_for_vertex) { + + 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(); + int ret_size = attribs.size() / 4; + ret.resize(ret_size); + { + for (int i = 0; i < ret_size; i++) { + ret[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]); + } + } + return ret; +} Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFState &state, int p_accessor, bool p_for_vertex) { Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); @@ -1359,6 +1431,136 @@ Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) { state.cameras.push_back(camera); } + + print_line("total cameras: " + itos(state.cameras.size())); +} + +Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) { + + if (!state.json.has("animations")) + return OK; + + Array animations = state.json["animations"]; + + for (int i = 0; i < animations.size(); i++) { + + 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")) { + animation.name = d["name"]; + } + + for (int j = 0; j < channels.size(); j++) { + + Dictionary c = channels[j]; + if (!c.has("target")) + continue; + + Dictionary t = c["target"]; + if (!t.has("node") || !t.has("path")) { + continue; + } + + ERR_FAIL_COND_V(!c.has("sampler"), ERR_PARSE_ERROR); + int sampler = c["sampler"]; + ERR_FAIL_INDEX_V(sampler, samplers.size(), ERR_PARSE_ERROR); + + int node = t["node"]; + String path = t["path"]; + + ERR_FAIL_INDEX_V(node, state.nodes.size(), ERR_PARSE_ERROR); + + GLTFAnimation::Track *track = NULL; + + if (!animation.tracks.has(node)) { + animation.tracks[node] = GLTFAnimation::Track(); + } + + track = &animation.tracks[node]; + + Dictionary s = samplers[sampler]; + + ERR_FAIL_COND_V(!s.has("input"), ERR_PARSE_ERROR); + ERR_FAIL_COND_V(!s.has("output"), ERR_PARSE_ERROR); + + int input = s["input"]; + int output = s["output"]; + + GLTFAnimation::Interpolation interp = GLTFAnimation::INTERP_LINEAR; + if (s.has("interpolation")) { + 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; + } else if (in == "CUBICSPLINE") { + interp = GLTFAnimation::INTERP_CUBIC_SPLINE; + } + } + + print_line("path: " + path); + PoolVector<float> times = _decode_accessor_as_floats(state, input, false); + if (path == "translation") { + PoolVector<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") { + 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") { + PoolVector<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") { + PoolVector<float> weights = _decode_accessor_as_floats(state, output, false); + + ERR_FAIL_INDEX_V(state.nodes[node]->mesh, state.meshes.size(), ERR_PARSE_ERROR); + GLTFMesh *mesh = &state.meshes[state.nodes[node]->mesh]; + ERR_FAIL_COND_V(mesh->blend_weights.size() == 0, ERR_PARSE_ERROR); + int wc = mesh->blend_weights.size(); + + track->weight_tracks.resize(wc); + + int wlen = weights.size() / wc; + PoolVector<float>::Read r = weights.read(); + 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[l] = r[l * wc + k]; + } + + cf.values = wdata; + track->weight_tracks[k] = cf; + } + } else { + WARN_PRINTS("Invalid path: " + path); + } + } + + state.animations.push_back(animation); + } + + print_line("total animations: " + itos(state.animations.size())); + + return OK; } void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) { @@ -1423,6 +1625,8 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node node->set_owner(p_owner); node->set_transform(n->xform); + n->godot_node = node; + for (int i = 0; i < n->skeleton_children.size(); i++) { Skeleton *s = skeletons[n->skeleton_children[i]]; @@ -1454,13 +1658,308 @@ void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vecto } skeletons[n->joint_skin]->set_bone_rest(bone_index, state.skins[n->joint_skin].bones[n->joint_bone].inverse_bind.affine_inverse()); + n->godot_node = skeletons[n->joint_skin]; + n->godot_bone_index = bone_index; + for (int i = 0; i < n->children.size(); i++) { ERR_CONTINUE(state.nodes[n->children[i]]->joint_skin < 0); _generate_bone(state, n->children[i], skeletons, bone_index); } } -Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state) { +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) { + + float t2 = t * t; + float t3 = t2 * t; + + return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * 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. */ + real_t omt = (1.0 - t); + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + 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, float c) const { + + return a.slerp(b, c); + } + + Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) { + + return p1.slerp(p2, c); + } + + Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) { + return start.slerp(end, t); + } +}; + +template <class T> +T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, 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]; + } + + 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]; + } + + 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]; + } + + float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]); + + T from = p_values[idx * 3 + 1]; + T c1 = from + p_values[idx * 3 + 0]; + T to = p_values[idx * 3 + 3]; + T c2 = to + p_values[idx * 3 + 2]; + + return interp.bezier(from, c1, c2, to, c); + + } break; + } + + ERR_FAIL_V(p_values[0]); +} + +void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons) { + + const GLTFAnimation &anim = state.animations[index]; + + String name = anim.name; + if (name == "") { + name = _gen_unique_name(state, "Animation"); + } + + Ref<Animation> animation; + animation.instance(); + animation->set_name(name); + + 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; + + GLTFNode *node = state.nodes[E->key()]; + ERR_CONTINUE(!node->godot_node); + + if (node->godot_bone_index >= 0) { + Skeleton *sk = (Skeleton *)node->godot_node; + String path = ap->get_parent()->get_path_to(sk); + String bone = sk->get_bone_name(node->godot_bone_index); + node_path = path + ":" + bone; + } else { + node_path = ap->get_parent()->get_path_to(node->godot_node); + } + + float length = 0; + + 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]); + } + } + + animation->set_length(length); + + 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); + //first determine animation length + + 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; + } + + 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->godot_bone_index >= 0) { + + Transform xform; + xform.basis = Basis(rot); + xform.basis.scale(scale); + xform.origin = pos; + + Skeleton *skeleton = skeletons[node->joint_skin]; + int bone = node->godot_bone_index; + xform = skeleton->get_bone_rest(bone).affine_inverse() * xform; + + rot = xform.basis; + 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]; + String prop = "blend_shapes/" + mesh.mesh->get_blend_shape_name(i); + node_path = String(node_path) + ":" + prop; + + int track_idx = animation->get_track_count(); + animation->add_track(Animation::TYPE_VALUE); + animation->track_set_path(track_idx, node_path); + + if (track.weight_tracks[i].interpolation <= GLTFAnimation::INTERP_STEP) { + animation->track_set_interpolation_type(track_idx, track.weight_tracks[i].interpolation == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_NEAREST); + for (int j = 0; j < track.weight_tracks[i].times.size(); j++) { + float t = track.weight_tracks[i].times[j]; + float w = track.weight_tracks[i].values[j]; + animation->track_insert_key(track_idx, t, w); + } + } else { + //must bake, apologies. + float increment = 1.0 / float(bake_fps); + float time = 0.0; + + bool last = false; + while (true) { + + float value = _interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, track.weight_tracks[i].interpolation); + if (last) { + break; + } + time += increment; + if (time >= length) { + last = true; + time = length; + } + } + } + } + } + + ap->add_animation(name, animation); +} + +Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_fps) { Spatial *root = memnew(Spatial); root->set_name(state.scene_name); @@ -1489,15 +1988,36 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state) { skeletons[i]->localize_rests(); } + 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, skeletons); + } + } + 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) { GLTFState state; - Error err = _parse_json(p_path, state); - if (err) - return NULL; + + if (p_path.to_lower().ends_with("glb")) { + //binary file + //text file + Error err = _parse_glb(p_path, state); + if (err) + return NULL; + } else { + //text file + Error err = _parse_json(p_path, state); + if (err) + return NULL; + } ERR_FAIL_COND_V(!state.json.has("asset"), NULL); @@ -1511,7 +2031,7 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla state.minor_version = version.get_slice(".", 1).to_int(); /* STEP 0 PARSE SCENE */ - err = _parse_scenes(state); + Error err = _parse_scenes(state); if (err != OK) return NULL; @@ -1565,9 +2085,16 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla if (err != OK) return NULL; + /* STEP 11 PARSE ANIMATIONS */ + err = _parse_animations(state); + if (err != OK) + return NULL; + + /* STEP 12 ASSIGN SCENE NAMES */ _assign_scene_names(state); - Spatial *scene = _generate_scene(state); + /* STEP 13 MAKE SCENE! */ + Spatial *scene = _generate_scene(state, p_bake_fps); return scene; } diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h index ab6dc6939a..d9479fae6f 100644 --- a/editor/import/editor_scene_importer_gltf.h +++ b/editor/import/editor_scene_importer_gltf.h @@ -5,6 +5,8 @@ #include "scene/3d/skeleton.h" #include "scene/3d/spatial.h" +class AnimationPlayer; + class EditorSceneImporterGLTF : public EditorSceneImporter { GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter); @@ -50,6 +52,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Transform xform; String name; + Node *godot_node; + int godot_bone_index; int mesh; int camera; @@ -69,6 +73,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Vector<int> children; GLTFNode() { + godot_node = NULL; + godot_bone_index = -1; joint_skin = -1; joint_bone = -1; child_of_skeleton = -1; @@ -172,12 +178,41 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { } }; + struct GLTFAnimation { + + 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; int minor_version; - Vector<uint8_t> gfb_data; + Vector<uint8_t> glb_data; Vector<GLTFNode *> nodes; Vector<Vector<uint8_t> > buffers; @@ -198,6 +233,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Set<String> unique_names; + Vector<GLTFAnimation> animations; + Map<int, Vector<int> > skin_users; //cache skin users ~GLTFState() { @@ -212,6 +249,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Ref<Texture> _get_texture(GLTFState &state, int 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); @@ -226,13 +264,16 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { PoolVector<Vector2> _decode_accessor_as_vec2(GLTFState &state, int p_accessor, bool p_for_vertex); PoolVector<Vector3> _decode_accessor_as_vec3(GLTFState &state, int p_accessor, bool p_for_vertex); PoolVector<Color> _decode_accessor_as_color(GLTFState &state, int p_accessor, bool p_for_vertex); + Vector<Quat> _decode_accessor_as_quat(GLTFState &state, int p_accessor, bool p_for_vertex); Vector<Transform2D> _decode_accessor_as_xform2d(GLTFState &state, int p_accessor, bool p_for_vertex); Vector<Basis> _decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex); Vector<Transform> _decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex); void _generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, int p_parent_bone); void _generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector<Skeleton *> &skeletons); - Spatial *_generate_scene(GLTFState &state); + void _import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons); + + Spatial *_generate_scene(GLTFState &state, int p_bake_fps); Error _parse_meshes(GLTFState &state); Error _parse_images(GLTFState &state, const String &p_base_path); @@ -244,8 +285,13 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Error _parse_cameras(GLTFState &state); + Error _parse_animations(GLTFState &state); + void _assign_scene_names(GLTFState &state); + template <class T> + T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, GLTFAnimation::Interpolation p_interp); + public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a809a68c23..f5d9da195a 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -385,7 +385,7 @@ void CanvasItemEditor::_add_canvas_item(CanvasItem *p_canvas_item) { return; canvas_items.insert(p_canvas_item,p_info); - p_canvas_item->connect("hide",this,"_visibility_changed",varray(p_canvas_item->get_instance_ID()),CONNECT_ONESHOT); + p_canvas_item->connect("hide",this,"_visibility_changed",varray(p_canvas_item->get_instance_id()),CONNECT_ONESHOT); #endif } @@ -2204,7 +2204,7 @@ void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2 &r_rect, cons if (c->has_meta("_edit_bone_")) { - ObjectID id = c->get_instance_ID(); + ObjectID id = c->get_instance_id(); if (!bone_list.has(id)) { BoneList bone; bone.bone = id; @@ -2769,7 +2769,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { pc.pos = n2d->get_position(); pc.rot = n2d->get_rotation(); pc.scale = n2d->get_scale(); - pc.id = n2d->get_instance_ID(); + pc.id = n2d->get_instance_id(); pose_clipboard.push_back(pc); } } diff --git a/editor/plugins/item_list_editor_plugin.h b/editor/plugins/item_list_editor_plugin.h index 4fed8e49f5..bc009b3d7a 100644 --- a/editor/plugins/item_list_editor_plugin.h +++ b/editor/plugins/item_list_editor_plugin.h @@ -116,8 +116,8 @@ public: virtual void set_item_enabled(int p_idx, int p_enabled) { ob->set_item_disabled(p_idx, !p_enabled); } virtual bool is_item_enabled(int p_idx) const { return !ob->is_item_disabled(p_idx); } - virtual void set_item_id(int p_idx, int p_id) { ob->set_item_ID(p_idx, p_id); } - virtual int get_item_id(int p_idx) const { return ob->get_item_ID(p_idx); } + virtual void set_item_id(int p_idx, int p_id) { ob->set_item_id(p_idx, p_id); } + virtual int get_item_id(int p_idx) const { return ob->get_item_id(p_idx); } virtual void add_item(); virtual int get_item_count() const; @@ -152,8 +152,8 @@ public: virtual void set_item_enabled(int p_idx, int p_enabled) { pp->set_item_disabled(p_idx, !p_enabled); } virtual bool is_item_enabled(int p_idx) const { return !pp->is_item_disabled(p_idx); } - virtual void set_item_id(int p_idx, int p_id) { pp->set_item_ID(p_idx, p_idx); } - virtual int get_item_id(int p_idx) const { return pp->get_item_ID(p_idx); } + virtual void set_item_id(int p_idx, int p_id) { pp->set_item_id(p_idx, p_idx); } + virtual int get_item_id(int p_idx) const { return pp->get_item_id(p_idx); } virtual void set_item_separator(int p_idx, bool p_separator) { pp->set_item_as_separator(p_idx, p_separator); } virtual bool is_item_separator(int p_idx) const { return pp->is_item_separator(p_idx); } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 77c540b746..1873a3f58b 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -211,9 +211,11 @@ void ScriptEditorQuickOpen::_confirmed() { void ScriptEditorQuickOpen::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { - connect("confirmed", this, "_confirmed"); + connect("confirmed", this, "_confirmed"); + } break; } } @@ -1064,58 +1066,73 @@ void ScriptEditor::_tab_changed(int p_which) { void ScriptEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - - editor->connect("play_pressed", this, "_editor_play"); - editor->connect("pause_pressed", this, "_editor_pause"); - editor->connect("stop_pressed", this, "_editor_stop"); - editor->connect("script_add_function_request", this, "_add_callback"); - editor->connect("resource_saved", this, "_res_saved_callback"); - script_list->connect("item_selected", this, "_script_selected"); - members_overview->connect("item_selected", this, "_members_overview_selected"); - script_split->connect("dragged", this, "_script_split_dragged"); - autosave_timer->connect("timeout", this, "_autosave_scripts"); - { - float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs"); - if (autosave_time > 0) { - autosave_timer->set_wait_time(autosave_time); - autosave_timer->start(); - } else { - autosave_timer->stop(); + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + + editor->connect("play_pressed", this, "_editor_play"); + editor->connect("pause_pressed", this, "_editor_pause"); + editor->connect("stop_pressed", this, "_editor_stop"); + editor->connect("script_add_function_request", this, "_add_callback"); + editor->connect("resource_saved", this, "_res_saved_callback"); + script_list->connect("item_selected", this, "_script_selected"); + members_overview->connect("item_selected", this, "_members_overview_selected"); + script_split->connect("dragged", this, "_script_split_dragged"); + autosave_timer->connect("timeout", this, "_autosave_scripts"); + { + float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs"); + if (autosave_time > 0) { + autosave_timer->set_wait_time(autosave_time); + autosave_timer->start(); + } else { + autosave_timer->stop(); + } } - } - EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed"); - help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); - site_search->set_icon(get_icon("Instance", "EditorIcons")); - class_search->set_icon(get_icon("ClassList", "EditorIcons")); + EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed"); + help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); + site_search->set_icon(get_icon("Instance", "EditorIcons")); + class_search->set_icon(get_icon("ClassList", "EditorIcons")); - script_forward->set_icon(get_icon("Forward", "EditorIcons")); - script_back->set_icon(get_icon("Back", "EditorIcons")); - } + script_forward->set_icon(get_icon("Forward", "EditorIcons")); + script_back->set_icon(get_icon("Back", "EditorIcons")); + } break; - if (p_what == NOTIFICATION_READY) { + case NOTIFICATION_READY: { - get_tree()->connect("tree_changed", this, "_tree_changed"); - editor->connect("request_help", this, "_request_help"); - editor->connect("request_help_search", this, "_help_search"); - editor->connect("request_help_index", this, "_help_index"); - } + get_tree()->connect("tree_changed", this, "_tree_changed"); + editor->connect("request_help", this, "_request_help"); + editor->connect("request_help_search", this, "_help_search"); + editor->connect("request_help_index", this, "_help_index"); + } break; - if (p_what == NOTIFICATION_EXIT_TREE) { + case NOTIFICATION_EXIT_TREE: { - editor->disconnect("play_pressed", this, "_editor_play"); - editor->disconnect("pause_pressed", this, "_editor_pause"); - editor->disconnect("stop_pressed", this, "_editor_stop"); - } + editor->disconnect("play_pressed", this, "_editor_play"); + editor->disconnect("pause_pressed", this, "_editor_pause"); + editor->disconnect("stop_pressed", this, "_editor_stop"); + } break; - if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { + case MainLoop::NOTIFICATION_WM_FOCUS_IN: { - _test_script_times_on_disk(); - _update_modified_scripts_for_external_editor(); - } + _test_script_times_on_disk(); + _update_modified_scripts_for_external_editor(); + } break; + + case NOTIFICATION_PROCESS: { + } break; - if (p_what == NOTIFICATION_PROCESS) { + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + + tab_container->add_style_override("panel", editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles")); + + Ref<StyleBox> sb = editor->get_gui_base()->get_stylebox("panel", "TabContainer")->duplicate(); + sb->set_default_margin(MARGIN_TOP, 0); + add_style_override("panel", sb); + } break; + + default: + break; } } diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index e260b1ea22..62fcc4b489 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -456,7 +456,7 @@ String ScriptTextEditor::get_name() { } else if (script->get_name() != "") name = script->get_name(); else - name = script->get_class() + "(" + itos(script->get_instance_ID()) + ")"; + name = script->get_class() + "(" + itos(script->get_instance_id()) + ")"; return name; } @@ -634,7 +634,17 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c } ScriptLanguage::LookupResult result; - if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path().get_base_dir(), base, result) == OK) { + if (p_symbol.is_resource_file()) { + List<String> scene_extensions; + ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); + + if (scene_extensions.find(p_symbol.get_extension())) { + EditorNode::get_singleton()->load_scene(p_symbol); + } else { + EditorNode::get_singleton()->load_resource(p_symbol); + } + + } else if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path().get_base_dir(), base, result) == OK) { _goto_line(p_row); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 2d77bfb2c1..50d2f193ed 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -57,6 +57,12 @@ #define FREELOOK_MIN_SPEED 0.1 +#define MIN_Z 0.01 +#define MAX_Z 10000 + +#define MIN_FOV 0.01 +#define MAX_FOV 179 + void SpatialEditorViewport::_update_camera() { if (orthogonal) { //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar()); @@ -153,26 +159,15 @@ int SpatialEditorViewport::get_selected_count() const { float SpatialEditorViewport::get_znear() const { - float val = spatial_editor->get_znear(); - if (val < 0.001) - val = 0.001; - return val; + return CLAMP(spatial_editor->get_znear(), MIN_Z, MAX_Z); } float SpatialEditorViewport::get_zfar() const { - float val = spatial_editor->get_zfar(); - if (val < 0.001) - val = 0.001; - return val; + return CLAMP(spatial_editor->get_zfar(), MIN_Z, MAX_Z); } float SpatialEditorViewport::get_fov() const { - float val = spatial_editor->get_fov(); - if (val < 0.001) - val = 0.001; - if (val > 89) - val = 89; - return val; + return CLAMP(spatial_editor->get_fov(), MIN_FOV, MAX_FOV); } Transform SpatialEditorViewport::_get_camera_transform() const { @@ -665,7 +660,7 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) { if (selection_results.size() == 1) { - clicked = selection_results[0].item->get_instance_ID(); + clicked = selection_results[0].item->get_instance_id(); selection_results.clear(); if (clicked) { @@ -2166,7 +2161,7 @@ void SpatialEditorViewport::_selection_result_pressed(int p_result) { if (selection_results.size() <= p_result) return; - clicked = selection_results[p_result].item->get_instance_ID(); + clicked = selection_results[p_result].item->get_instance_id(); if (clicked) { _select_clicked(clicked_wants_append, true); @@ -2390,7 +2385,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu = memnew(MenuButton); surface->add_child(view_menu); - view_menu->set_position(Point2(4, 4)); + view_menu->set_position(Point2(4, 4) * EDSCALE); view_menu->set_self_modulate(Color(1, 1, 1, 0.5)); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP); view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM); @@ -2434,8 +2429,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed preview_camera = memnew(Button); preview_camera->set_toggle_mode(true); - preview_camera->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, 90); - preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10); + preview_camera->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, 90 * EDSCALE); + preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE); preview_camera->set_text("preview"); surface->add_child(preview_camera); preview_camera->hide(); @@ -2455,7 +2450,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed selection_menu = memnew(PopupMenu); add_child(selection_menu); - selection_menu->set_custom_minimum_size(Vector2(100, 0)); + selection_menu->set_custom_minimum_size(Size2(100, 0) * EDSCALE); selection_menu->connect("id_pressed", this, "_selection_result_pressed"); selection_menu->connect("popup_hide", this, "_selection_menu_hide"); @@ -2464,7 +2459,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed viewport->set_as_audio_listener(true); } - name = TTR("Top"); + name = ""; _update_name(); EditorSettings::get_singleton()->connect("settings_changed", this, "update_transform_gizmo_view"); @@ -3039,9 +3034,9 @@ void SpatialEditor::edit(Spatial *p_spatial) { /* if (p_spatial) { _validate_selection(); - if (selected.has(p_spatial->get_instance_ID()) && selected.size()==1) + if (selected.has(p_spatial->get_instance_id()) && selected.size()==1) return; - _select(p_spatial->get_instance_ID(),false,true); + _select(p_spatial->get_instance_id(),false,true); // should become the selection } @@ -3933,27 +3928,27 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { settings_dialog->set_title(TTR("Viewport Settings")); add_child(settings_dialog); settings_vbc = memnew(VBoxContainer); - settings_vbc->set_custom_minimum_size(Size2(200, 0)); + settings_vbc->set_custom_minimum_size(Size2(200, 0) * EDSCALE); settings_dialog->add_child(settings_vbc); //settings_dialog->set_child_rect(settings_vbc); settings_fov = memnew(SpinBox); - settings_fov->set_max(179); - settings_fov->set_min(1); + settings_fov->set_max(MAX_FOV); + settings_fov->set_min(MIN_FOV); settings_fov->set_step(0.01); settings_fov->set_value(EDITOR_DEF("editors/3d/default_fov", 55.0)); settings_vbc->add_margin_child(TTR("Perspective FOV (deg.):"), settings_fov); settings_znear = memnew(SpinBox); - settings_znear->set_max(10000); - settings_znear->set_min(0.1); + settings_znear->set_max(MAX_Z); + settings_znear->set_min(MIN_Z); settings_znear->set_step(0.01); settings_znear->set_value(EDITOR_DEF("editors/3d/default_z_near", 0.1)); settings_vbc->add_margin_child(TTR("View Z-Near:"), settings_znear); settings_zfar = memnew(SpinBox); - settings_zfar->set_max(10000); - settings_zfar->set_min(0.1); + settings_zfar->set_max(MAX_Z); + settings_zfar->set_min(MIN_Z); settings_zfar->set_step(0.01); settings_zfar->set_value(EDITOR_DEF("editors/3d/default_z_far", 1500)); settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index f5bb9d4a35..d45a3b1312 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -104,7 +104,7 @@ struct _TECategory { Ref<T> item; StringName name; - bool operator<(const RefItem<T> &p) const { return item->get_instance_ID() < p.item->get_instance_ID(); } + bool operator<(const RefItem<T> &p) const { return item->get_instance_id() < p.item->get_instance_id(); } }; template <class T> diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index d12b979121..e7bc8a4dab 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -330,6 +330,8 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era if (id == TileMap::INVALID_CELL) return PoolVector<Vector2>(); + } else if (prev_id == TileMap::INVALID_CELL) { + return PoolVector<Vector2>(); } Rect2i r = node->get_item_rect(); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 82f17b80d5..d5a56f644f 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -573,7 +573,7 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) { switch (k->get_scancode()) { - case KEY_RETURN: { + case KEY_ENTER: { _open_project(); } break; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 42485317c1..a3a10c6c5a 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -2370,7 +2370,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String &p p_item->set_text(1, res->get_path().get_file()); } else if (!res->is_class("Texture")) { //texture already previews via itself - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview_done", p_item->get_instance_ID()); + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview_done", p_item->get_instance_id()); } } @@ -3630,7 +3630,7 @@ void PropertyEditor::update_tree() { item->set_text(1, res->get_path().get_file()); } else if (!res->is_class("Texture")) { //texture already previews via itself - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview_done", item->get_instance_ID()); + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_resource_preview_done", item->get_instance_id()); } } @@ -3858,7 +3858,7 @@ void PropertyEditor::_item_edited() { break; if (type == Variant::INT) - _edit_set(name, round(item->get_range(1)), refresh_all); + _edit_set(name, int64_t(round(item->get_range(1))), refresh_all); else _edit_set(name, item->get_range(1), refresh_all); } break; @@ -4586,7 +4586,7 @@ void SectionedPropertyEditor::edit(Object *p_object) { return; } - ObjectID id = p_object->get_instance_ID(); + ObjectID id = p_object->get_instance_id(); if (obj != id) { diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index c6af993676..bd68eac9f2 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -418,7 +418,7 @@ void PropertySelector::select_method_from_script(const Ref<Script> &p_script, co base_type = p_script->get_instance_base_type(); selected = p_current; type = Variant::NIL; - script = p_script->get_instance_ID(); + script = p_script->get_instance_id(); properties = false; instance = NULL; @@ -452,7 +452,7 @@ void PropertySelector::select_method_from_instance(Object *p_instance, const Str { Ref<Script> scr = p_instance->get_script(); if (scr.is_valid()) - script = scr->get_instance_ID(); + script = scr->get_instance_id(); } properties = false; instance = NULL; @@ -485,7 +485,7 @@ void PropertySelector::select_property_from_script(const Ref<Script> &p_script, base_type = p_script->get_instance_base_type(); selected = p_current; type = Variant::NIL; - script = p_script->get_instance_ID(); + script = p_script->get_instance_id(); properties = true; instance = NULL; diff --git a/editor/resources_dock.cpp b/editor/resources_dock.cpp index d3b68d92e4..db3bf6a352 100644 --- a/editor/resources_dock.cpp +++ b/editor/resources_dock.cpp @@ -204,7 +204,7 @@ void ResourcesDock::_update_name(TreeItem *item) { else if (res->get_path() != "" && res->get_path().find("::") == -1) item->set_text(0, res->get_path().get_file()); else - item->set_text(0, res->get_class() + " (" + itos(res->get_instance_ID()) + ")"); + item->set_text(0, res->get_class() + " (" + itos(res->get_instance_id()) + ")"); } void ResourcesDock::remove_resource(const Ref<Resource> &p_resource) { diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 47a9185389..ce3b85332f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1369,8 +1369,8 @@ void SceneTreeDock::_delete_confirm() { editor_data->get_undo_redo().add_undo_reference(n); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); - editor_data->get_undo_redo().add_do_method(sed, "live_debug_remove_and_keep_node", edited_scene->get_path_to(n), n->get_instance_ID()); - editor_data->get_undo_redo().add_undo_method(sed, "live_debug_restore_node", n->get_instance_ID(), edited_scene->get_path_to(n->get_parent()), n->get_index()); + editor_data->get_undo_redo().add_do_method(sed, "live_debug_remove_and_keep_node", edited_scene->get_path_to(n), n->get_instance_id()); + editor_data->get_undo_redo().add_undo_method(sed, "live_debug_restore_node", n->get_instance_id(), edited_scene->get_path_to(n->get_parent()), n->get_index()); } } editor_data->get_undo_redo().commit_action(); @@ -1824,7 +1824,7 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) { int index = menu->get_item_count(); menu->add_icon_item(icon, E->get().name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size()); menu->set_item_h_offset(index, p_depth * 10 * EDSCALE); - subresources.push_back(obj->get_instance_ID()); + subresources.push_back(obj->get_instance_id()); _add_children_to_popup(obj, p_depth + 1); } diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index f35e098065..390d13e64e 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -411,9 +411,9 @@ void SceneTreeEditor::_update_tree() { void SceneTreeEditor::_compute_hash(Node *p_node, uint64_t &hash) { - hash = hash_djb2_one_64(p_node->get_instance_ID(), hash); + hash = hash_djb2_one_64(p_node->get_instance_id(), hash); if (p_node->get_parent()) - hash = hash_djb2_one_64(p_node->get_parent()->get_instance_ID(), hash); //so a reparent still produces a different hash + hash = hash_djb2_one_64(p_node->get_parent()->get_instance_id(), hash); //so a reparent still produces a different hash for (int i = 0; i < p_node->get_child_count(); i++) { @@ -625,8 +625,8 @@ void SceneTreeEditor::_renamed() { } else { undo_redo->create_action(TTR("Rename Node")); emit_signal("node_prerename", n, new_name); - undo_redo->add_do_method(this, "_rename_node", n->get_instance_ID(), new_name); - undo_redo->add_undo_method(this, "_rename_node", n->get_instance_ID(), n->get_name()); + undo_redo->add_do_method(this, "_rename_node", n->get_instance_id(), new_name); + undo_redo->add_undo_method(this, "_rename_node", n->get_instance_id(), n->get_name()); undo_redo->commit_action(); } } diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index faf9dee5d0..659a3cf0d2 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -70,7 +70,7 @@ void EditorSpatialGizmo::redraw() { void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) { instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); - VS::get_singleton()->instance_attach_object_instance_ID(instance, p_base->get_instance_ID()); + VS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id()); if (skeleton.is_valid()) VS::get_singleton()->instance_attach_skeleton(instance, skeleton); if (extra_margin) |