diff options
-rw-r--r-- | core/debugger/local_debugger.cpp | 7 | ||||
-rw-r--r-- | editor/editor_help.cpp | 80 | ||||
-rw-r--r-- | editor/editor_help.h | 2 | ||||
-rw-r--r-- | editor/editor_node.cpp | 12 | ||||
-rw-r--r-- | editor/plugins/asset_library_editor_plugin.cpp | 11 | ||||
-rw-r--r-- | editor/plugins/asset_library_editor_plugin.h | 2 | ||||
-rw-r--r-- | editor/plugins/texture_editor_plugin.cpp | 52 | ||||
-rw-r--r-- | editor/project_manager.cpp | 6 | ||||
-rw-r--r-- | main/main.cpp | 7 | ||||
-rw-r--r-- | scene/2d/navigation_agent_2d.cpp | 9 | ||||
-rw-r--r-- | scene/3d/navigation_agent_3d.cpp | 11 | ||||
-rw-r--r-- | servers/movie_writer/movie_writer.cpp | 137 | ||||
-rw-r--r-- | servers/movie_writer/movie_writer.h | 37 | ||||
-rw-r--r-- | servers/movie_writer/movie_writer_mjpeg.h | 2 | ||||
-rw-r--r-- | servers/movie_writer/movie_writer_pngwav.cpp | 168 | ||||
-rw-r--r-- | servers/movie_writer/movie_writer_pngwav.h | 71 | ||||
-rw-r--r-- | servers/register_server_types.cpp | 1 |
17 files changed, 388 insertions, 227 deletions
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 06e08081e9..58d239ccb9 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -31,7 +31,7 @@ #include "local_debugger.h" #include "core/debugger/script_debugger.h" -#include "scene/main/scene_tree.h" +#include "core/os/os.h" struct LocalDebugger::ScriptsProfiler { struct ProfileInfoSort { @@ -273,7 +273,10 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { script_debugger->set_depth(-1); script_debugger->set_lines_left(-1); - SceneTree::get_singleton()->quit(); + MainLoop *main_loop = OS::get_singleton()->get_main_loop(); + if (main_loop->get_class() == "SceneTree") { + main_loop->call("quit"); + } break; } else if (line.begins_with("delete")) { if (line.get_slice_count(" ") <= 1) { diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index b4325f09c5..36360954d9 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -63,6 +63,8 @@ void EditorHelp::_update_theme() { doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); doc_title_font = get_theme_font(SNAME("doc_title"), SNAME("EditorFonts")); doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); + + doc_title_font_size = get_theme_font_size(SNAME("doc_title_size"), SNAME("EditorFonts")); } void EditorHelp::_search(bool p_search_previous) { @@ -362,8 +364,9 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) { void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods, bool &r_method_descrpitons) { Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // title font size + class_desc->pop(); // title font + class_desc->pop(); // title color class_desc->add_newline(); class_desc->push_font(doc_code_font); @@ -431,8 +434,9 @@ void EditorHelp::_update_method_descriptions(const DocData::ClassDoc p_classdoc, Ref<Font> doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); String link_color_text = title_color.to_html(false); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // title font size + class_desc->pop(); // title font + class_desc->pop(); // title color class_desc->add_newline(); class_desc->add_newline(); @@ -535,15 +539,17 @@ void EditorHelp::_update_doc() { // Class name section_line.push_back(Pair<String, int>(TTR("Top"), 0)); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->push_color(title_color); class_desc->add_text(TTR("Class:") + " "); class_desc->add_image(icon, icon->get_width(), icon->get_height()); class_desc->add_text(" "); class_desc->push_color(headline_color); _add_text(edited_class); - class_desc->pop(); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // color + class_desc->pop(); // color + class_desc->pop(); // font size + class_desc->pop(); // font class_desc->add_newline(); // Inheritance tree @@ -624,9 +630,11 @@ void EditorHelp::_update_doc() { description_line = class_desc->get_paragraph_count() - 2; class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Description")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->add_newline(); class_desc->add_newline(); @@ -646,9 +654,11 @@ void EditorHelp::_update_doc() { if (cd.tutorials.size()) { class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Online Tutorials")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->push_indent(1); class_desc->push_font(doc_code_font); @@ -694,9 +704,11 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Properties"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Properties")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->add_newline(); class_desc->push_font(doc_code_font); @@ -858,6 +870,7 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Constructors"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Constructors")); _update_method_list(cd.constructors, constructor_descriptions); } @@ -869,6 +882,7 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Methods"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Methods")); _update_method_list(methods, method_descriptions); } @@ -881,6 +895,7 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Operators"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Operators")); _update_method_list(cd.operators, operator_descriptions); } @@ -890,9 +905,11 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Theme Properties"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Theme Properties")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->add_newline(); class_desc->add_newline(); @@ -916,13 +933,15 @@ void EditorHelp::_update_doc() { class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); if (data_type_names.has(theme_data_type)) { class_desc->add_text(data_type_names[theme_data_type]); } else { class_desc->add_text(""); } - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->add_newline(); class_desc->add_newline(); @@ -984,9 +1003,11 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Signals"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Signals")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->add_newline(); class_desc->add_newline(); @@ -1070,9 +1091,11 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Enumerations"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Enumerations")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->push_indent(1); class_desc->add_newline(); @@ -1174,9 +1197,11 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Constants"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Constants")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->push_indent(1); class_desc->add_newline(); @@ -1235,9 +1260,11 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Property Descriptions"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Property Descriptions")); - class_desc->pop(); - class_desc->pop(); + class_desc->pop(); // font size + class_desc->pop(); // font + class_desc->pop(); // color class_desc->add_newline(); class_desc->add_newline(); @@ -1401,6 +1428,7 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Constructor Descriptions"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Constructor Descriptions")); _update_method_descriptions(cd, cd.constructors, "constructor"); } @@ -1410,6 +1438,7 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Method Descriptions"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Method Descriptions")); _update_method_descriptions(cd, methods, "method"); } @@ -1419,6 +1448,7 @@ void EditorHelp::_update_doc() { section_line.push_back(Pair<String, int>(TTR("Operator Descriptions"), class_desc->get_paragraph_count() - 2)); class_desc->push_color(title_color); class_desc->push_font(doc_title_font); + class_desc->push_font_size(doc_title_font_size); class_desc->add_text(TTR("Operator Descriptions")); _update_method_descriptions(cd, cd.operators, "operator"); } diff --git a/editor/editor_help.h b/editor/editor_help.h index 766a09f485..7f91a8102d 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -140,6 +140,8 @@ class EditorHelp : public VBoxContainer { Ref<Font> doc_title_font; Ref<Font> doc_code_font; + int doc_title_font_size; + int scroll_to = -1; void _update_theme(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b196cadcb1..e3caaf93c6 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -460,7 +460,7 @@ void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) { _editor_select(EDITOR_SCRIPT); } else if (ED_IS_SHORTCUT("editor/editor_help", p_event)) { emit_signal(SNAME("request_help_search"), ""); - } else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && StreamPeerSSL::is_available()) { + } else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && AssetLibraryEditorPlugin::is_available()) { _editor_select(EDITOR_ASSETLIB); } else if (ED_IS_SHORTCUT("editor/editor_next", p_event)) { _editor_select_next(); @@ -5752,12 +5752,12 @@ void EditorNode::_feature_profile_changed() { main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)); main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT)); - if (StreamPeerSSL::is_available()) { + if (AssetLibraryEditorPlugin::is_available()) { main_editor_buttons[EDITOR_ASSETLIB]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB)); } if ((profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D) && singleton->main_editor_buttons[EDITOR_3D]->is_pressed()) || (profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT) && singleton->main_editor_buttons[EDITOR_SCRIPT]->is_pressed()) || - (StreamPeerSSL::is_available() && profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) && singleton->main_editor_buttons[EDITOR_ASSETLIB]->is_pressed())) { + (AssetLibraryEditorPlugin::is_available() && profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) && singleton->main_editor_buttons[EDITOR_ASSETLIB]->is_pressed())) { _editor_select(EDITOR_2D); } } else { @@ -5769,7 +5769,7 @@ void EditorNode::_feature_profile_changed() { FileSystemDock::get_singleton()->set_visible(true); main_editor_buttons[EDITOR_3D]->set_visible(true); main_editor_buttons[EDITOR_SCRIPT]->set_visible(true); - if (StreamPeerSSL::is_available()) { + if (AssetLibraryEditorPlugin::is_available()) { main_editor_buttons[EDITOR_ASSETLIB]->set_visible(true); } } @@ -7073,13 +7073,11 @@ EditorNode::EditorNode() { // Asset Library can't work on Web editor for now as most assets are sourced // directly from GitHub which does not set CORS. -#ifndef JAVASCRIPT_ENABLED - if (StreamPeerSSL::is_available()) { + if (AssetLibraryEditorPlugin::is_available()) { add_editor_plugin(memnew(AssetLibraryEditorPlugin)); } else { WARN_PRINT("Asset Library not available, as it requires SSL to work."); } -#endif // Add interface before adding plugins. diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 249b3a6d6a..e9435faae1 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "core/input/input.h" #include "core/io/json.h" +#include "core/io/stream_peer_ssl.h" #include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_file_dialog.h" @@ -1588,6 +1589,16 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { /////// +bool AssetLibraryEditorPlugin::is_available() { +#ifdef JAVASCRIPT_ENABLED + // Asset Library can't work on Web editor for now as most assets are sourced + // directly from GitHub which does not set CORS. + return false; +#else + return StreamPeerSSL::is_available(); +#endif +} + void AssetLibraryEditorPlugin::make_visible(bool p_visible) { if (p_visible) { addon_library->show(); diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index e09700b646..2b43719cdd 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -322,6 +322,8 @@ class AssetLibraryEditorPlugin : public EditorPlugin { EditorAssetLibrary *addon_library = nullptr; public: + static bool is_available(); + virtual String get_name() const override { return "AssetLib"; } bool has_main_screen() const override { return true; } virtual void edit(Object *p_object) override {} diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index 15f03fd46d..98e80c5513 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -59,7 +59,7 @@ void TexturePreview::_notification(int p_what) { } void TexturePreview::_update_metadata_label_text() { - Ref<Texture2D> texture = texture_display->get_texture(); + const Ref<Texture2D> texture = texture_display->get_texture(); String format; if (Object::cast_to<ImageTexture>(*texture)) { @@ -70,7 +70,49 @@ void TexturePreview::_update_metadata_label_text() { format = texture->get_class(); } - metadata_label->set_text(vformat(String::utf8("%s×%s %s"), itos(texture->get_width()), itos(texture->get_height()), format)); + const Ref<Image> image = texture->get_image(); + if (image.is_valid()) { + const int mipmaps = image->get_mipmap_count(); + // Avoid signed integer overflow that could occur with huge texture sizes by casting everything to uint64_t. + uint64_t memory = uint64_t(image->get_width()) * uint64_t(image->get_height()) * uint64_t(Image::get_format_pixel_size(image->get_format())); + // Handle VRAM-compressed formats that are stored with 4 bpp. + memory >>= Image::get_format_pixel_rshift(image->get_format()); + + float mipmaps_multiplier = 1.0; + float mipmap_increase = 0.25; + for (int i = 0; i < mipmaps; i++) { + // Each mip adds 25% memory usage of the previous one. + // With a complete mipmap chain, memory usage increases by ~33%. + mipmaps_multiplier += mipmap_increase; + mipmap_increase *= 0.25; + } + memory *= mipmaps_multiplier; + + if (mipmaps >= 1) { + metadata_label->set_text( + vformat(String::utf8("%d×%d %s\n") + TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"), + texture->get_width(), + texture->get_height(), + format, + mipmaps, + String::humanize_size(memory))); + } else { + // "No Mipmaps" is easier to distinguish than "0 Mipmaps", + // especially since 0, 6, and 8 look quite close with the default code font. + metadata_label->set_text( + vformat(String::utf8("%d×%d %s\n") + TTR("No Mipmaps") + "\n" + TTR("Memory: %s"), + texture->get_width(), + texture->get_height(), + format, + String::humanize_size(memory))); + } + } else { + metadata_label->set_text( + vformat(String::utf8("%d×%d %s"), + texture->get_width(), + texture->get_height(), + format)); + } } TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) { @@ -97,11 +139,9 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) { metadata_label->add_theme_color_override("font_color", Color::named("white")); metadata_label->add_theme_color_override("font_color_shadow", Color::named("black")); - metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE); + metadata_label->add_theme_font_size_override("font_size", 14 * EDSCALE); metadata_label->add_theme_color_override("font_outline_color", Color::named("black")); - metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE); - - metadata_label->add_theme_constant_override("shadow_outline_size", 1); + metadata_label->add_theme_constant_override("outline_size", 8 * EDSCALE); metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END); metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 2e7b6f7476..ef91128146 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2792,10 +2792,7 @@ ProjectManager::ProjectManager() { center_box->add_child(settings_hb); } - // Asset Library can't work on Web editor for now as most assets are sourced - // directly from GitHub which does not set CORS. -#ifndef JAVASCRIPT_ENABLED - if (StreamPeerSSL::is_available()) { + if (AssetLibraryEditorPlugin::is_available()) { asset_library = memnew(EditorAssetLibrary(true)); asset_library->set_name(TTR("Asset Library Projects")); tabs->add_child(asset_library); @@ -2803,7 +2800,6 @@ ProjectManager::ProjectManager() { } else { WARN_PRINT("Asset Library not available, as it requires SSL to work."); } -#endif { // Dialogs diff --git a/main/main.cpp b/main/main.cpp index f3c56c7205..00b7483406 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -673,6 +673,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph packed_data->add_pack_source(zip_packed_data); #endif + // Default exit code, can be modified for certain errors. + Error exit_code = ERR_INVALID_PARAMETER; + I = args.front(); while (I) { #ifdef OSX_ENABLED @@ -688,10 +691,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help show_help = true; + exit_code = OK; goto error; } else if (I->get() == "--version") { print_line(get_full_version_string()); + exit_code = OK; goto error; } else if (I->get() == "-v" || I->get() == "--verbose") { // verbose output @@ -1636,7 +1641,7 @@ error: OS::get_singleton()->finalize_core(); locale = String(); - return ERR_INVALID_PARAMETER; + return exit_code; } Error Main::setup2(Thread::ID p_main_tid_override) { diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 5a451a6dab..a5f7faffef 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -87,16 +87,19 @@ void NavigationAgent2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent2D::_avoidance_done); + ADD_GROUP("Pathfinding", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:px"), "set_path_desired_distance", "get_path_desired_distance"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); + + ADD_GROUP("Avoidance", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,suffix:px"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px"), "set_neighbor_dist", "get_neighbor_dist"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_SIGNAL(MethodInfo("path_changed")); ADD_SIGNAL(MethodInfo("target_reached")); diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index e5ec444335..3752713d6a 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -91,18 +91,21 @@ void NavigationAgent3D::_bind_methods() { ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent3D::_avoidance_done); + ADD_GROUP("Pathfinding", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_path_desired_distance", "get_path_desired_distance"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_target_desired_distance", "get_target_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); + + ADD_GROUP("Avoidance", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_dist", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m"), "set_neighbor_dist", "get_neighbor_dist"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_SIGNAL(MethodInfo("path_changed")); ADD_SIGNAL(MethodInfo("target_reached")); diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp index 8560d92aa2..9f96b8cfda 100644 --- a/servers/movie_writer/movie_writer.cpp +++ b/servers/movie_writer/movie_writer.cpp @@ -30,7 +30,6 @@ #include "movie_writer.h" #include "core/config/project_settings.h" -#include "core/io/dir_access.h" MovieWriter *MovieWriter::writers[MovieWriter::MAX_WRITERS]; uint32_t MovieWriter::writer_count = 0; @@ -170,139 +169,3 @@ void MovieWriter::add_frame(const Ref<Image> &p_image) { void MovieWriter::end() { write_end(); } -///////////////////////////////////////// - -uint32_t MovieWriterPNGWAV::get_audio_mix_rate() const { - return mix_rate; -} -AudioServer::SpeakerMode MovieWriterPNGWAV::get_audio_speaker_mode() const { - return speaker_mode; -} - -void MovieWriterPNGWAV::get_supported_extensions(List<String> *r_extensions) const { - r_extensions->push_back("png"); -} - -bool MovieWriterPNGWAV::handles_file(const String &p_path) const { - return p_path.get_extension().to_lower() == "png"; -} - -String MovieWriterPNGWAV::zeros_str(uint32_t p_index) { - char zeros[MAX_TRAILING_ZEROS + 1]; - for (uint32_t i = 0; i < MAX_TRAILING_ZEROS; i++) { - uint32_t idx = MAX_TRAILING_ZEROS - i - 1; - uint32_t digit = (p_index / uint32_t(Math::pow(double(10), double(idx)))) % 10; - zeros[i] = '0' + digit; - } - zeros[MAX_TRAILING_ZEROS] = 0; - return zeros; -} - -Error MovieWriterPNGWAV::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) { - // Quick & Dirty PNGWAV Code based on - https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference - - base_path = p_base_path.get_basename(); - if (base_path.is_relative_path()) { - base_path = "res://" + base_path; - } - - { - //Remove existing files before writing anew - uint32_t idx = 0; - Ref<DirAccess> d = DirAccess::open(base_path.get_base_dir()); - String file = base_path.get_file(); - while (true) { - String path = file + zeros_str(idx) + ".png"; - if (d->remove(path) != OK) { - break; - } - } - } - - f_wav = FileAccess::open(base_path + ".wav", FileAccess::WRITE_READ); - ERR_FAIL_COND_V(f_wav.is_null(), ERR_CANT_OPEN); - - fps = p_fps; - - f_wav->store_buffer((const uint8_t *)"RIFF", 4); - int total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */; - f_wav->store_32(total_size); //will store final later - f_wav->store_buffer((const uint8_t *)"WAVE", 4); - - /* FORMAT CHUNK */ - - f_wav->store_buffer((const uint8_t *)"fmt ", 4); - - uint32_t channels = 2; - switch (speaker_mode) { - case AudioServer::SPEAKER_MODE_STEREO: - channels = 2; - break; - case AudioServer::SPEAKER_SURROUND_31: - channels = 4; - break; - case AudioServer::SPEAKER_SURROUND_51: - channels = 6; - break; - case AudioServer::SPEAKER_SURROUND_71: - channels = 8; - break; - } - - f_wav->store_32(16); //standard format, no extra fields - f_wav->store_16(1); // compression code, standard PCM - f_wav->store_16(channels); //CHANNELS: 2 - - f_wav->store_32(mix_rate); - - /* useless stuff the format asks for */ - - int bits_per_sample = 32; - int blockalign = bits_per_sample / 8 * channels; - int bytes_per_sec = mix_rate * blockalign; - - audio_block_size = (mix_rate / fps) * blockalign; - - f_wav->store_32(bytes_per_sec); - f_wav->store_16(blockalign); // block align (unused) - f_wav->store_16(bits_per_sample); - - /* DATA CHUNK */ - - f_wav->store_buffer((const uint8_t *)"data", 4); - - f_wav->store_32(0); //data size... wooh - wav_data_size_pos = f_wav->get_position(); - - return OK; -} - -Error MovieWriterPNGWAV::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) { - ERR_FAIL_COND_V(!f_wav.is_valid(), ERR_UNCONFIGURED); - - Vector<uint8_t> png_buffer = p_image->save_png_to_buffer(); - - Ref<FileAccess> fi = FileAccess::open(base_path + zeros_str(frame_count) + ".png", FileAccess::WRITE); - fi->store_buffer(png_buffer.ptr(), png_buffer.size()); - f_wav->store_buffer((const uint8_t *)p_audio_data, audio_block_size); - - frame_count++; - - return OK; -} - -void MovieWriterPNGWAV::write_end() { - if (f_wav.is_valid()) { - uint32_t total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */; - uint32_t datasize = f_wav->get_position() - wav_data_size_pos; - f_wav->seek(4); - f_wav->store_32(total_size + datasize); - f_wav->seek(0x28); - f_wav->store_32(datasize); - } -} - -MovieWriterPNGWAV::MovieWriterPNGWAV() { - mix_rate = GLOBAL_GET("editor/movie_writer/mix_rate"); - speaker_mode = AudioServer::SpeakerMode(int(GLOBAL_GET("editor/movie_writer/speaker_mode"))); -} diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h index 11e739df39..1ec6e93052 100644 --- a/servers/movie_writer/movie_writer.h +++ b/servers/movie_writer/movie_writer.h @@ -85,39 +85,4 @@ public: void end(); }; -class MovieWriterPNGWAV : public MovieWriter { - GDCLASS(MovieWriterPNGWAV, MovieWriter) - - enum { - MAX_TRAILING_ZEROS = 8 // more than 10 days at 60fps, no hard drive can put up with this anyway :) - }; - - uint32_t mix_rate = 48000; - AudioServer::SpeakerMode speaker_mode = AudioServer::SPEAKER_MODE_STEREO; - String base_path; - uint32_t frame_count = 0; - uint32_t fps = 0; - - uint32_t audio_block_size = 0; - - Ref<FileAccess> f_wav; - uint32_t wav_data_size_pos = 0; - - String zeros_str(uint32_t p_index); - -protected: - virtual uint32_t get_audio_mix_rate() const override; - virtual AudioServer::SpeakerMode get_audio_speaker_mode() const override; - virtual void get_supported_extensions(List<String> *r_extensions) const override; - - virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) override; - virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) override; - virtual void write_end() override; - - virtual bool handles_file(const String &p_path) const override; - -public: - MovieWriterPNGWAV(); -}; - -#endif // VIDEO_WRITER_H +#endif // MOVIE_WRITER_H diff --git a/servers/movie_writer/movie_writer_mjpeg.h b/servers/movie_writer/movie_writer_mjpeg.h index 822bedfedf..233267df30 100644 --- a/servers/movie_writer/movie_writer_mjpeg.h +++ b/servers/movie_writer/movie_writer_mjpeg.h @@ -70,4 +70,4 @@ public: MovieWriterMJPEG(); }; -#endif // MOVIE_WRITER_AVIJPEG_H +#endif // MOVIE_WRITER_MJPEG_H diff --git a/servers/movie_writer/movie_writer_pngwav.cpp b/servers/movie_writer/movie_writer_pngwav.cpp new file mode 100644 index 0000000000..bd79b0bd98 --- /dev/null +++ b/servers/movie_writer/movie_writer_pngwav.cpp @@ -0,0 +1,168 @@ +/*************************************************************************/ +/* movie_writer_pngwav.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 "movie_writer_pngwav.h" +#include "core/config/project_settings.h" +#include "core/io/dir_access.h" + +uint32_t MovieWriterPNGWAV::get_audio_mix_rate() const { + return mix_rate; +} +AudioServer::SpeakerMode MovieWriterPNGWAV::get_audio_speaker_mode() const { + return speaker_mode; +} + +void MovieWriterPNGWAV::get_supported_extensions(List<String> *r_extensions) const { + r_extensions->push_back("png"); +} + +bool MovieWriterPNGWAV::handles_file(const String &p_path) const { + return p_path.get_extension().to_lower() == "png"; +} + +String MovieWriterPNGWAV::zeros_str(uint32_t p_index) { + char zeros[MAX_TRAILING_ZEROS + 1]; + for (uint32_t i = 0; i < MAX_TRAILING_ZEROS; i++) { + uint32_t idx = MAX_TRAILING_ZEROS - i - 1; + uint32_t digit = (p_index / uint32_t(Math::pow(double(10), double(idx)))) % 10; + zeros[i] = '0' + digit; + } + zeros[MAX_TRAILING_ZEROS] = 0; + return zeros; +} + +Error MovieWriterPNGWAV::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) { + // Quick & Dirty PNGWAV Code based on - https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference + + base_path = p_base_path.get_basename(); + if (base_path.is_relative_path()) { + base_path = "res://" + base_path; + } + + { + //Remove existing files before writing anew + uint32_t idx = 0; + Ref<DirAccess> d = DirAccess::open(base_path.get_base_dir()); + String file = base_path.get_file(); + while (true) { + String path = file + zeros_str(idx) + ".png"; + if (d->remove(path) != OK) { + break; + } + } + } + + f_wav = FileAccess::open(base_path + ".wav", FileAccess::WRITE_READ); + ERR_FAIL_COND_V(f_wav.is_null(), ERR_CANT_OPEN); + + fps = p_fps; + + f_wav->store_buffer((const uint8_t *)"RIFF", 4); + int total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */; + f_wav->store_32(total_size); //will store final later + f_wav->store_buffer((const uint8_t *)"WAVE", 4); + + /* FORMAT CHUNK */ + + f_wav->store_buffer((const uint8_t *)"fmt ", 4); + + uint32_t channels = 2; + switch (speaker_mode) { + case AudioServer::SPEAKER_MODE_STEREO: + channels = 2; + break; + case AudioServer::SPEAKER_SURROUND_31: + channels = 4; + break; + case AudioServer::SPEAKER_SURROUND_51: + channels = 6; + break; + case AudioServer::SPEAKER_SURROUND_71: + channels = 8; + break; + } + + f_wav->store_32(16); //standard format, no extra fields + f_wav->store_16(1); // compression code, standard PCM + f_wav->store_16(channels); //CHANNELS: 2 + + f_wav->store_32(mix_rate); + + /* useless stuff the format asks for */ + + int bits_per_sample = 32; + int blockalign = bits_per_sample / 8 * channels; + int bytes_per_sec = mix_rate * blockalign; + + audio_block_size = (mix_rate / fps) * blockalign; + + f_wav->store_32(bytes_per_sec); + f_wav->store_16(blockalign); // block align (unused) + f_wav->store_16(bits_per_sample); + + /* DATA CHUNK */ + + f_wav->store_buffer((const uint8_t *)"data", 4); + + f_wav->store_32(0); //data size... wooh + wav_data_size_pos = f_wav->get_position(); + + return OK; +} + +Error MovieWriterPNGWAV::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) { + ERR_FAIL_COND_V(!f_wav.is_valid(), ERR_UNCONFIGURED); + + Vector<uint8_t> png_buffer = p_image->save_png_to_buffer(); + + Ref<FileAccess> fi = FileAccess::open(base_path + zeros_str(frame_count) + ".png", FileAccess::WRITE); + fi->store_buffer(png_buffer.ptr(), png_buffer.size()); + f_wav->store_buffer((const uint8_t *)p_audio_data, audio_block_size); + + frame_count++; + + return OK; +} + +void MovieWriterPNGWAV::write_end() { + if (f_wav.is_valid()) { + uint32_t total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */; + uint32_t datasize = f_wav->get_position() - wav_data_size_pos; + f_wav->seek(4); + f_wav->store_32(total_size + datasize); + f_wav->seek(0x28); + f_wav->store_32(datasize); + } +} + +MovieWriterPNGWAV::MovieWriterPNGWAV() { + mix_rate = GLOBAL_GET("editor/movie_writer/mix_rate"); + speaker_mode = AudioServer::SpeakerMode(int(GLOBAL_GET("editor/movie_writer/speaker_mode"))); +} diff --git a/servers/movie_writer/movie_writer_pngwav.h b/servers/movie_writer/movie_writer_pngwav.h new file mode 100644 index 0000000000..64608ce387 --- /dev/null +++ b/servers/movie_writer/movie_writer_pngwav.h @@ -0,0 +1,71 @@ +/*************************************************************************/ +/* movie_writer_pngwav.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 MOVIE_WRITER_PNGWAV_H +#define MOVIE_WRITER_PNGWAV_H + +#include "servers/movie_writer/movie_writer.h" + +class MovieWriterPNGWAV : public MovieWriter { + GDCLASS(MovieWriterPNGWAV, MovieWriter) + + enum { + MAX_TRAILING_ZEROS = 8 // more than 10 days at 60fps, no hard drive can put up with this anyway :) + }; + + uint32_t mix_rate = 48000; + AudioServer::SpeakerMode speaker_mode = AudioServer::SPEAKER_MODE_STEREO; + String base_path; + uint32_t frame_count = 0; + uint32_t fps = 0; + + uint32_t audio_block_size = 0; + + Ref<FileAccess> f_wav; + uint32_t wav_data_size_pos = 0; + + String zeros_str(uint32_t p_index); + +protected: + virtual uint32_t get_audio_mix_rate() const override; + virtual AudioServer::SpeakerMode get_audio_speaker_mode() const override; + virtual void get_supported_extensions(List<String> *r_extensions) const override; + + virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) override; + virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) override; + virtual void write_end() override; + + virtual bool handles_file(const String &p_path) const override; + +public: + MovieWriterPNGWAV(); +}; + +#endif // MOVIE_WRITER_PNGWAV_H diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index d7d2340119..db473f6296 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -59,6 +59,7 @@ #include "display_server.h" #include "movie_writer/movie_writer.h" #include "movie_writer/movie_writer_mjpeg.h" +#include "movie_writer/movie_writer_pngwav.h" #include "navigation_server_2d.h" #include "navigation_server_3d.h" #include "physics_2d/godot_physics_server_2d.h" |