diff options
Diffstat (limited to 'modules')
23 files changed, 911 insertions, 105 deletions
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index cbf30c8a2e..37e45cfff8 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -142,6 +142,9 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) { + if (m_count >= m_resultMax) + return cp.getDistance(); + if (cp.getDistance() <= 0) { PhysicsDirectSpaceState::ShapeResult &result = m_results[m_count]; @@ -165,7 +168,7 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con ++m_count; } - return m_count < m_resultMax; + return cp.getDistance(); } bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 669b2c3f0c..5e736c1856 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -264,6 +264,7 @@ RigidBodyBullet::RigidBodyBullet() : can_sleep(true), force_integration_callback(NULL), isTransformChanged(false), + previousActiveState(true), maxCollisionsDetection(0), collisionsCount(0), maxAreasWhereIam(10), @@ -287,6 +288,7 @@ RigidBodyBullet::RigidBodyBullet() : for (int i = areasWhereIam.size() - 1; 0 <= i; --i) { areasWhereIam[i] = NULL; } + btBody->setSleepingThresholds(0.2, 0.2); } RigidBodyBullet::~RigidBodyBullet() { @@ -337,7 +339,7 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) { void RigidBodyBullet::dispatch_callbacks() { /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent - if (btBody->isActive() && force_integration_callback && isTransformChanged) { + if ((btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { BulletPhysicsDirectBodyState *bodyDirect = BulletPhysicsDirectBodyState::get_singleton(this); @@ -364,6 +366,8 @@ void RigidBodyBullet::dispatch_callbacks() { /// Lock axis btBody->setLinearVelocity(btBody->getLinearVelocity() * btBody->getLinearFactor()); btBody->setAngularVelocity(btBody->getAngularVelocity() * btBody->getAngularFactor()); + + previousActiveState = btBody->isActive(); } void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { @@ -580,7 +584,8 @@ Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const { void RigidBodyBullet::apply_central_impulse(const Vector3 &p_impulse) { btVector3 btImpu; G_TO_B(p_impulse, btImpu); - btBody->activate(); + if (Vector3() != p_impulse) + btBody->activate(); btBody->applyCentralImpulse(btImpu); } @@ -589,14 +594,16 @@ void RigidBodyBullet::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impul btVector3 btPos; G_TO_B(p_impulse, btImpu); G_TO_B(p_pos, btPos); - btBody->activate(); + if (Vector3() != p_impulse) + btBody->activate(); btBody->applyImpulse(btImpu, btPos); } void RigidBodyBullet::apply_torque_impulse(const Vector3 &p_impulse) { btVector3 btImp; G_TO_B(p_impulse, btImp); - btBody->activate(); + if (Vector3() != p_impulse) + btBody->activate(); btBody->applyTorqueImpulse(btImp); } @@ -605,28 +612,32 @@ void RigidBodyBullet::apply_force(const Vector3 &p_force, const Vector3 &p_pos) btVector3 btPos; G_TO_B(p_force, btForce); G_TO_B(p_pos, btPos); - btBody->activate(); + if (Vector3() != p_force) + btBody->activate(); btBody->applyForce(btForce, btPos); } void RigidBodyBullet::apply_central_force(const Vector3 &p_force) { btVector3 btForce; G_TO_B(p_force, btForce); - btBody->activate(); + if (Vector3() != p_force) + btBody->activate(); btBody->applyCentralForce(btForce); } void RigidBodyBullet::apply_torque(const Vector3 &p_torque) { btVector3 btTorq; G_TO_B(p_torque, btTorq); - btBody->activate(); + if (Vector3() != p_torque) + btBody->activate(); btBody->applyTorque(btTorq); } void RigidBodyBullet::set_applied_force(const Vector3 &p_force) { btVector3 btVec = btBody->getTotalTorque(); - btBody->activate(); + if (Vector3() != p_force) + btBody->activate(); btBody->clearForces(); btBody->applyTorque(btVec); @@ -644,7 +655,8 @@ Vector3 RigidBodyBullet::get_applied_force() const { void RigidBodyBullet::set_applied_torque(const Vector3 &p_torque) { btVector3 btVec = btBody->getTotalForce(); - btBody->activate(); + if (Vector3() != p_torque) + btBody->activate(); btBody->clearForces(); btBody->applyCentralForce(btVec); @@ -711,7 +723,8 @@ bool RigidBodyBullet::is_continuous_collision_detection_enabled() const { void RigidBodyBullet::set_linear_velocity(const Vector3 &p_velocity) { btVector3 btVec; G_TO_B(p_velocity, btVec); - btBody->activate(); + if (Vector3() != p_velocity) + btBody->activate(); btBody->setLinearVelocity(btVec); } @@ -724,7 +737,8 @@ Vector3 RigidBodyBullet::get_linear_velocity() const { void RigidBodyBullet::set_angular_velocity(const Vector3 &p_velocity) { btVector3 btVec; G_TO_B(p_velocity, btVec); - btBody->activate(); + if (Vector3() != p_velocity) + btBody->activate(); btBody->setAngularVelocity(btVec); } @@ -833,6 +847,9 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { void RigidBodyBullet::reload_space_override_modificator() { + if (!is_active()) + return; + Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude()); real_t newLinearDamp(linearDamp); real_t newAngularDamp(angularDamp); diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index c0eb148e24..c3b72172d9 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -207,6 +207,7 @@ private: bool isScratchedSpaceOverrideModificator; bool isTransformChanged; + bool previousActiveState; // Last check state ForceIntegrationCallback *force_integration_callback; diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index fd11c8d094..4e73ebfb9d 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -3,12 +3,12 @@ Import('env') gdn_env = env.Clone() - -gdn_env.add_source_files(env.modules_sources, "gd_native_library_editor.cpp") gdn_env.add_source_files(env.modules_sources, "gdnative.cpp") gdn_env.add_source_files(env.modules_sources, "register_types.cpp") gdn_env.add_source_files(env.modules_sources, "gdnative/*.cpp") gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp") +gdn_env.add_source_files(env.modules_sources, "gdnative_library_singleton_editor.cpp") +gdn_env.add_source_files(env.modules_sources, "gdnative_library_editor_plugin.cpp") gdn_env.Append(CPPPATH=['#modules/gdnative/include/']) diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp new file mode 100644 index 0000000000..1e638ab702 --- /dev/null +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -0,0 +1,423 @@ +/*************************************************************************/ +/* gdnative_library_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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. */ +/*************************************************************************/ + +#ifdef TOOLS_ENABLED +#include "gdnative_library_editor_plugin.h" +#include "gdnative.h" + +void GDNativeLibraryEditor::edit(Ref<GDNativeLibrary> p_library) { + library = p_library; + Ref<ConfigFile> config = p_library->get_config_file(); + + for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) { + for (List<String>::Element *it = E->value().entries.front(); it; it = it->next()) { + + String target = E->key() + "." + it->get(); + TargetConfig ecfg; + ecfg.library = config->get_value("entry", target, ""); + ecfg.dependencies = config->get_value("dependencies", target, Array()); + entry_configs[target] = ecfg; + } + } + + _update_tree(); +} + +void GDNativeLibraryEditor::_bind_methods() { + + ClassDB::bind_method("_on_item_button", &GDNativeLibraryEditor::_on_item_button); + ClassDB::bind_method("_on_library_selected", &GDNativeLibraryEditor::_on_library_selected); + ClassDB::bind_method("_on_dependencies_selected", &GDNativeLibraryEditor::_on_dependencies_selected); + ClassDB::bind_method("_on_filter_selected", &GDNativeLibraryEditor::_on_filter_selected); + ClassDB::bind_method("_on_item_collapsed", &GDNativeLibraryEditor::_on_item_collapsed); + ClassDB::bind_method("_on_item_activated", &GDNativeLibraryEditor::_on_item_activated); + ClassDB::bind_method("_on_create_new_entry", &GDNativeLibraryEditor::_on_create_new_entry); +} + +void GDNativeLibraryEditor::_update_tree() { + + tree->clear(); + TreeItem *root = tree->create_item(); + + for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) { + + if (showing_platform != E->key() && showing_platform != "All") + continue; + + TreeItem *platform = tree->create_item(root); + platform->set_text(0, E->get().name); + platform->set_metadata(0, E->get().library_extension); + + platform->set_custom_bg_color(0, get_color("prop_category", "Editor")); + platform->set_custom_bg_color(1, get_color("prop_category", "Editor")); + platform->set_custom_bg_color(2, get_color("prop_category", "Editor")); + platform->set_selectable(0, false); + platform->set_expand_right(0, true); + + for (List<String>::Element *it = E->value().entries.front(); it; it = it->next()) { + + String target = E->key() + "." + it->get(); + TreeItem *bit = tree->create_item(platform); + + bit->set_text(0, it->get()); + bit->set_metadata(0, target); + bit->set_selectable(0, false); + bit->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + + bit->add_button(1, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry")); + String file = entry_configs[target].library; + if (!file.empty()) { + bit->add_button(1, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear")); + } + bit->set_text(1, file); + + bit->add_button(2, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry")); + Array files = entry_configs[target].dependencies; + if (files.size()) { + bit->add_button(2, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear")); + } + bit->set_text(2, Variant(files)); + + bit->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up")); + bit->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down")); + bit->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry")); + } + + TreeItem *new_arch = tree->create_item(platform); + new_arch->set_text(0, TTR("Double click to create a new entry")); + new_arch->set_text_align(0, TreeItem::ALIGN_CENTER); + new_arch->set_custom_color(0, get_color("accent_color", "Editor")); + new_arch->set_expand_right(0, true); + new_arch->set_metadata(1, E->key()); + + platform->set_collapsed(collapsed_items.find(E->get().name) != NULL); + } +} + +void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { + + String target = Object::cast_to<TreeItem>(item)->get_metadata(0); + String platform = target.substr(0, target.find(".")); + String entry = target.substr(platform.length() + 1, target.length()); + String section = (id == BUTTON_SELECT_DEPENDENCES || id == BUTTON_CLEAR_DEPENDENCES) ? "dependencies" : "entry"; + + if (id == BUTTON_SELECT_LIBRARY || id == BUTTON_SELECT_DEPENDENCES) { + + EditorFileDialog::Mode mode = EditorFileDialog::MODE_OPEN_FILE; + if (id == BUTTON_SELECT_DEPENDENCES) + mode = EditorFileDialog::MODE_OPEN_FILES; + + file_dialog->set_meta("target", target); + file_dialog->set_meta("section", section); + file_dialog->clear_filters(); + file_dialog->add_filter(Object::cast_to<TreeItem>(item)->get_parent()->get_metadata(0)); + file_dialog->set_mode(mode); + file_dialog->popup_centered_ratio(); + + } else if (id == BUTTON_CLEAR_LIBRARY) { + _set_target_value(section, target, ""); + } else if (id == BUTTON_CLEAR_DEPENDENCES) { + _set_target_value(section, target, Array()); + } else if (id == BUTTON_ERASE_ENTRY) { + _erase_entry(platform, entry); + } else if (id == BUTTON_MOVE_UP || id == BUTTON_MOVE_DOWN) { + _move_entry(platform, entry, id); + } +} + +void GDNativeLibraryEditor::_on_library_selected(const String &file) { + + _set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), file); +} + +void GDNativeLibraryEditor::_on_dependencies_selected(const PoolStringArray &files) { + + _set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), files); +} + +void GDNativeLibraryEditor::_on_filter_selected(int id) { + + showing_platform = filter->get_item_metadata(id); + _update_tree(); +} + +void GDNativeLibraryEditor::_on_item_collapsed(Object *p_item) { + + TreeItem *item = Object::cast_to<TreeItem>(p_item); + String name = item->get_text(0); + + if (item->is_collapsed()) { + collapsed_items.insert(name); + } else if (Set<String>::Element *e = collapsed_items.find(name)) { + collapsed_items.erase(e); + } +} + +void GDNativeLibraryEditor::_on_item_activated() { + + TreeItem *item = tree->get_selected(); + if (item && tree->get_selected_column() == 0 && item->get_metadata(0).get_type() == Variant::NIL) { + new_architecture_dialog->set_meta("platform", item->get_metadata(1)); + new_architecture_dialog->popup_centered(); + } +} + +void GDNativeLibraryEditor::_on_create_new_entry() { + + String platform = new_architecture_dialog->get_meta("platform"); + String entry = new_architecture_input->get_text().strip_edges(); + if (!entry.empty()) { + platforms[platform].entries.push_back(entry); + _update_tree(); + } +} + +void GDNativeLibraryEditor::_set_target_value(const String §ion, const String &target, Variant file) { + if (section == "entry") + entry_configs[target].library = file; + else if (section == "dependencies") + entry_configs[target].dependencies = file; + _translate_to_config_file(); + _update_tree(); +} + +void GDNativeLibraryEditor::_erase_entry(const String &platform, const String &entry) { + + if (platforms.has(platform)) { + if (List<String>::Element *E = platforms[platform].entries.find(entry)) { + + String target = platform + "." + entry; + Ref<ConfigFile> config = library->get_config_file(); + + platforms[platform].entries.erase(E); + _set_target_value("entry", target, ""); + _set_target_value("dependencies", target, Array()); + _translate_to_config_file(); + _update_tree(); + } + } +} + +void GDNativeLibraryEditor::_move_entry(const String &platform, const String &entry, int dir) { + if (List<String>::Element *E = platforms[platform].entries.find(entry)) { + if (E->prev() && dir == BUTTON_MOVE_UP) { + platforms[platform].entries.insert_before(E->prev(), E->get()); + platforms[platform].entries.erase(E); + } else if (E->next() && dir == BUTTON_MOVE_DOWN) { + platforms[platform].entries.insert_after(E->next(), E->get()); + platforms[platform].entries.erase(E); + } + _translate_to_config_file(); + _update_tree(); + } +} + +void GDNativeLibraryEditor::_translate_to_config_file() { + + if (!library.is_null()) { + + Ref<ConfigFile> config = library->get_config_file(); + config->erase_section("entry"); + config->erase_section("dependencies"); + + for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) { + for (List<String>::Element *it = E->value().entries.front(); it; it = it->next()) { + + String target = E->key() + "." + it->get(); + if (entry_configs[target].library.empty() && entry_configs[target].dependencies.empty()) + continue; + + config->set_value("entry", target, entry_configs[target].library); + config->set_value("dependencies", target, entry_configs[target].dependencies); + } + } + + library->_change_notify(); + } +} + +GDNativeLibraryEditor::GDNativeLibraryEditor() { + + showing_platform = "All"; + + { // Define platforms + NativePlatformConfig platform_windows; + platform_windows.name = "Windows"; + platform_windows.entries.push_back("64"); + platform_windows.entries.push_back("32"); + platform_windows.library_extension = "*.dll"; + platforms["Windows"] = platform_windows; + + NativePlatformConfig platform_linux; + platform_linux.name = "Linux/X11"; + platform_linux.entries.push_back("64"); + platform_linux.entries.push_back("32"); + platform_linux.library_extension = "*.so"; + platforms["X11"] = platform_linux; + + NativePlatformConfig platform_osx; + platform_osx.name = "Mac OSX"; + platform_osx.entries.push_back("64"); + platform_osx.entries.push_back("32"); + platform_osx.library_extension = "*.dylib"; + platforms["OSX"] = platform_osx; + + NativePlatformConfig platform_haiku; + platform_haiku.name = "Haiku"; + platform_haiku.entries.push_back("64"); + platform_haiku.entries.push_back("32"); + platform_haiku.library_extension = "*.so"; + platforms["Haiku"] = platform_haiku; + + NativePlatformConfig platform_uwp; + platform_uwp.name = "Windows Universal"; + platform_uwp.entries.push_back("arm"); + platform_uwp.entries.push_back("x86"); + platform_uwp.entries.push_back("x64"); + platform_uwp.library_extension = "*.dll"; + platforms["UWP"] = platform_uwp; + + NativePlatformConfig platform_android; + platform_android.name = "Android"; + platform_android.entries.push_back("armeabi-v7a"); + platform_android.entries.push_back("arm64-v8a"); + platform_android.entries.push_back("x86"); + platform_android.entries.push_back("x86_64"); + platform_android.library_extension = "*.so"; + platforms["Android"] = platform_android; + + // TODO: Javascript platform is not supported yet + // NativePlatformConfig platform_html5; + // platform_html5.name = "HTML5"; + // platform_html5.library_extension = "*.wasm"; + // platforms["Javascript"] = platform_html5; + + NativePlatformConfig platform_ios; + platform_ios.name = "iOS"; + platform_ios.entries.push_back("armv7"); + platform_ios.entries.push_back("arm64"); + platform_ios.library_extension = "*.dylib"; + platforms["iOS"] = platform_ios; + } + + VBoxContainer *container = memnew(VBoxContainer); + add_child(container); + container->set_anchors_and_margins_preset(PRESET_WIDE); + + HBoxContainer *hbox = memnew(HBoxContainer); + container->add_child(hbox); + Label *label = memnew(Label); + label->set_text(TTR("Platform:")); + hbox->add_child(label); + filter = memnew(OptionButton); + hbox->add_child(filter); + filter->set_h_size_flags(SIZE_EXPAND_FILL); + + int idx = 0; + filter->add_item(TTR("All"), idx); + filter->set_item_metadata(idx, "All"); + idx += 1; + for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) { + filter->add_item(E->get().name, idx); + filter->set_item_metadata(idx, E->key()); + idx += 1; + } + filter->connect("item_selected", this, "_on_filter_selected"); + + tree = memnew(Tree); + container->add_child(tree); + tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_hide_root(true); + tree->set_column_titles_visible(true); + tree->set_columns(4); + tree->set_column_expand(0, false); + tree->set_column_min_width(0, int(200 * EDSCALE)); + tree->set_column_title(0, TTR("Platform")); + tree->set_column_title(1, TTR("Dynamic Library")); + tree->set_column_title(2, TTR("Dependencies")); + tree->set_column_expand(3, false); + tree->set_column_min_width(3, int(110 * EDSCALE)); + tree->connect("button_pressed", this, "_on_item_button"); + tree->connect("item_collapsed", this, "_on_item_collapsed"); + tree->connect("item_activated", this, "_on_item_activated"); + + file_dialog = memnew(EditorFileDialog); + file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); + file_dialog->set_resizable(true); + add_child(file_dialog); + file_dialog->connect("file_selected", this, "_on_library_selected"); + file_dialog->connect("files_selected", this, "_on_dependencies_selected"); + + new_architecture_dialog = memnew(ConfirmationDialog); + add_child(new_architecture_dialog); + new_architecture_dialog->set_title(TTR("Add an architecture entry")); + new_architecture_input = memnew(LineEdit); + new_architecture_dialog->add_child(new_architecture_input); + new_architecture_dialog->set_custom_minimum_size(Vector2(300, 80) * EDSCALE); + new_architecture_input->set_anchors_and_margins_preset(PRESET_HCENTER_WIDE, PRESET_MODE_MINSIZE, 5 * EDSCALE); + new_architecture_dialog->get_ok()->connect("pressed", this, "_on_create_new_entry"); +} + +void GDNativeLibraryEditorPlugin::edit(Object *p_node) { + + if (Object::cast_to<GDNativeLibrary>(p_node)) { + library_editor->edit(Object::cast_to<GDNativeLibrary>(p_node)); + library_editor->show(); + } else + library_editor->hide(); +} + +bool GDNativeLibraryEditorPlugin::handles(Object *p_node) const { + + return p_node->is_class("GDNativeLibrary"); +} + +void GDNativeLibraryEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + button->show(); + EditorNode::get_singleton()->make_bottom_panel_item_visible(library_editor); + + } else { + if (library_editor->is_visible_in_tree()) + EditorNode::get_singleton()->hide_bottom_panel(); + button->hide(); + } +} + +GDNativeLibraryEditorPlugin::GDNativeLibraryEditorPlugin(EditorNode *p_node) { + + library_editor = memnew(GDNativeLibraryEditor); + library_editor->set_custom_minimum_size(Size2(0, 250 * EDSCALE)); + button = p_node->add_bottom_panel_item(TTR("GDNativeLibrary"), library_editor); + button->hide(); +} + +#endif diff --git a/modules/gdnative/gdnative_library_editor_plugin.h b/modules/gdnative/gdnative_library_editor_plugin.h new file mode 100644 index 0000000000..1fa6a0c945 --- /dev/null +++ b/modules/gdnative/gdnative_library_editor_plugin.h @@ -0,0 +1,113 @@ +/*************************************************************************/ +/* gdnative_library_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 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 GDNATIVE_LIBRARY_EDITOR_PLUGIN_H +#define GDNATIVE_LIBRARY_EDITOR_PLUGIN_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_node.h" +#include "gdnative.h" + +class GDNativeLibraryEditor : public Control { + + GDCLASS(GDNativeLibraryEditor, Control); + + struct NativePlatformConfig { + String name; + String library_extension; + List<String> entries; + }; + + struct TargetConfig { + String library; + Array dependencies; + }; + + enum ItemButton { + BUTTON_SELECT_LIBRARY, + BUTTON_CLEAR_LIBRARY, + BUTTON_SELECT_DEPENDENCES, + BUTTON_CLEAR_DEPENDENCES, + BUTTON_ERASE_ENTRY, + BUTTON_MOVE_UP, + BUTTON_MOVE_DOWN, + }; + + Tree *tree; + OptionButton *filter; + EditorFileDialog *file_dialog; + ConfirmationDialog *new_architecture_dialog; + LineEdit *new_architecture_input; + Set<String> collapsed_items; + + String showing_platform; + Ref<GDNativeLibrary> library; + Map<String, NativePlatformConfig> platforms; + Map<String, TargetConfig> entry_configs; + +protected: + static void _bind_methods(); + void _update_tree(); + void _on_item_button(Object *item, int column, int id); + void _on_library_selected(const String &file); + void _on_dependencies_selected(const PoolStringArray &files); + void _on_filter_selected(int id); + void _on_item_collapsed(Object *item); + void _on_item_activated(); + void _on_create_new_entry(); + void _set_target_value(const String §ion, const String &target, Variant file); + void _erase_entry(const String &platform, const String &entry); + void _move_entry(const String &platform, const String &entry, int dir); + void _translate_to_config_file(); + +public: + void edit(Ref<GDNativeLibrary> p_library); + + GDNativeLibraryEditor(); +}; + +class GDNativeLibraryEditorPlugin : public EditorPlugin { + + GDCLASS(GDNativeLibraryEditorPlugin, EditorPlugin); + + GDNativeLibraryEditor *library_editor; + EditorNode *editor; + Button *button; + +public: + virtual String get_name() const { return "GDNativeLibrary"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + GDNativeLibraryEditorPlugin(EditorNode *p_node); +}; +#endif +#endif // GDNATIVE_LIBRARY_EDITOR_PLUGIN_H diff --git a/modules/gdnative/gd_native_library_editor.cpp b/modules/gdnative/gdnative_library_singleton_editor.cpp index fda5dcdcad..2ad497fcad 100644 --- a/modules/gdnative/gd_native_library_editor.cpp +++ b/modules/gdnative/gdnative_library_singleton_editor.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gd_native_library_editor.cpp */ +/* gdnative_library_singleton_editor.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #ifdef TOOLS_ENABLED -#include "gd_native_library_editor.h" - +#include "gdnative_library_singleton_editor.h" #include "gdnative.h" -void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list) { +void GDNativeLibrarySingletonEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list) { // check children @@ -65,7 +64,7 @@ void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory } } -void GDNativeLibraryEditor::_update_libraries() { +void GDNativeLibrarySingletonEditor::_update_libraries() { updating = true; libraries->clear(); @@ -88,7 +87,7 @@ void GDNativeLibraryEditor::_update_libraries() { updating = false; } -void GDNativeLibraryEditor::_item_edited() { +void GDNativeLibrarySingletonEditor::_item_edited() { if (updating) return; @@ -119,7 +118,7 @@ void GDNativeLibraryEditor::_item_edited() { } } -void GDNativeLibraryEditor::_notification(int p_what) { +void GDNativeLibrarySingletonEditor::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { if (is_visible_in_tree()) { @@ -128,12 +127,12 @@ void GDNativeLibraryEditor::_notification(int p_what) { } } -void GDNativeLibraryEditor::_bind_methods() { +void GDNativeLibrarySingletonEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibraryEditor::_item_edited); + ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibrarySingletonEditor::_item_edited); } -GDNativeLibraryEditor::GDNativeLibraryEditor() { +GDNativeLibrarySingletonEditor::GDNativeLibrarySingletonEditor() { libraries = memnew(Tree); libraries->set_columns(2); libraries->set_column_titles_visible(true); diff --git a/modules/gdnative/gd_native_library_editor.h b/modules/gdnative/gdnative_library_singleton_editor.h index a11c4620dd..ee1a32c5a5 100644 --- a/modules/gdnative/gd_native_library_editor.h +++ b/modules/gdnative/gdnative_library_singleton_editor.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* gd_native_library_editor.h */ +/* gdnative_library_singleton_editor.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -34,7 +34,7 @@ #include "editor/editor_file_system.h" #include "editor/project_settings_editor.h" -class GDNativeLibraryEditor : public VBoxContainer { +class GDNativeLibrarySingletonEditor : public VBoxContainer { Tree *libraries; bool updating; @@ -48,7 +48,7 @@ protected: static void _bind_methods(); public: - GDNativeLibraryEditor(); + GDNativeLibrarySingletonEditor(); }; #endif diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 1cb35ec006..bd9bae5294 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -45,7 +45,8 @@ #ifdef TOOLS_ENABLED #include "editor/editor_node.h" -#include "gd_native_library_editor.h" +#include "gdnative_library_editor_plugin.h" +#include "gdnative_library_singleton_editor.h" // Class used to discover singleton gdnative files static void actual_discoverer_handler(); @@ -267,7 +268,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty static void editor_init_callback() { - GDNativeLibraryEditor *library_editor = memnew(GDNativeLibraryEditor); + GDNativeLibrarySingletonEditor *library_editor = memnew(GDNativeLibrarySingletonEditor); library_editor->set_name(TTR("GDNative")); ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor); @@ -278,6 +279,8 @@ static void editor_init_callback() { export_plugin.instance(); EditorExport::get_singleton()->add_export_plugin(export_plugin); + + EditorNode::get_singleton()->add_editor_plugin(memnew(GDNativeLibraryEditorPlugin(EditorNode::get_singleton()))); } #endif diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 8c862b52e8..e9bb90631d 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -21,6 +21,26 @@ Clear all cells. </description> </method> + <method name="clear_baked_meshes"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="get_bake_mesh_instance"> + <return type="RID"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_bake_meshes"> + <return type="Array"> + </return> + <description> + </description> + </method> <method name="get_cell_item" qualifiers="const"> <return type="int"> </return> @@ -103,6 +123,16 @@ Array of [Vector3] with the non empty cell coordinates in the grid map. </description> </method> + <method name="make_baked_meshes"> + <return type="void"> + </return> + <argument index="0" name="gen_lightmap_uv" type="bool" default="false"> + </argument> + <argument index="1" name="lightmap_uv_texel_size" type="float" default="0.1"> + </argument> + <description> + </description> + </method> <method name="map_to_world" qualifiers="const"> <return type="Vector3"> </return> diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index bebf8bcf8f..0b73cbfc6d 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -101,6 +101,27 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) { } } _recreate_octant_data(); + } else if (name == "baked_meshes") { + + clear_baked_meshes(); + + Array meshes = p_value; + + for (int i = 0; i < meshes.size(); i++) { + BakedMesh bm; + bm.mesh = meshes[i]; + ERR_CONTINUE(!bm.mesh.is_valid()); + bm.instance = VS::get_singleton()->instance_create(); + VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); + VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); + if (is_inside_tree()) { + VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); + VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); + } + baked_meshes.push_back(bm); + } + + _recreate_octant_data(); } else return false; @@ -145,6 +166,15 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const { d["cells"] = cells; r_ret = d; + } else if (name == "baked_meshes") { + + Array ret; + ret.resize(baked_meshes.size()); + for (int i = 0; i < baked_meshes.size(); i++) { + ret.push_back(baked_meshes[i].mesh); + } + r_ret = ret; + } else return false; @@ -161,6 +191,9 @@ void GridMap::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_y")); p_list->push_back(PropertyInfo(Variant::BOOL, "cell_center_z")); p_list->push_back(PropertyInfo(Variant::REAL, "cell_scale")); + if (baked_meshes.size()) { + p_list->push_back(PropertyInfo(Variant::ARRAY, "baked_meshes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + } p_list->push_back(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); } @@ -235,6 +268,12 @@ bool GridMap::get_center_z() const { void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { + if (baked_meshes.size() && !recreating_octants) { + //if you set a cell item, baked meshes go good bye + clear_baked_meshes(); + _recreate_octant_data(); + } + ERR_FAIL_INDEX(ABS(p_x), 1 << 20); ERR_FAIL_INDEX(ABS(p_y), 1 << 20); ERR_FAIL_INDEX(ABS(p_z), 1 << 20); @@ -436,16 +475,17 @@ bool GridMap::_octant_update(const OctantKey &p_key) { xform.basis.set_orthogonal_index(c.rot); xform.set_origin(cellpos * cell_size + ofs); xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale)); + if (baked_meshes.size() == 0) { + if (theme->get_item_mesh(c.item).is_valid()) { + if (!multimesh_items.has(c.item)) { + multimesh_items[c.item] = List<Pair<Transform, IndexKey> >(); + } - if (theme->get_item_mesh(c.item).is_valid()) { - if (!multimesh_items.has(c.item)) { - multimesh_items[c.item] = List<Pair<Transform, IndexKey> >(); + Pair<Transform, IndexKey> p; + p.first = xform; + p.second = E->get(); + multimesh_items[c.item].push_back(p); } - - Pair<Transform, IndexKey> p; - p.first = xform; - p.second = E->get(); - multimesh_items[c.item].push_back(p); } Vector<MeshLibrary::ShapeData> shapes = theme->get_item_shapes(c.item); @@ -477,41 +517,44 @@ bool GridMap::_octant_update(const OctantKey &p_key) { } } - //update multimeshes - for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) { - Octant::MultimeshInstance mmi; + //update multimeshes, only if not baked + if (baked_meshes.size() == 0) { + + for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) { + Octant::MultimeshInstance mmi; - RID mm = VS::get_singleton()->multimesh_create(); - VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE); - VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid()); + RID mm = VS::get_singleton()->multimesh_create(); + VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE); + VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid()); - int idx = 0; - for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) { - VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first); + int idx = 0; + for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) { + VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first); #ifdef TOOLS_ENABLED - Octant::MultimeshInstance::Item it; - it.index = idx; - it.transform = F->get().first; - it.key = F->get().second; - mmi.items.push_back(it); + Octant::MultimeshInstance::Item it; + it.index = idx; + it.transform = F->get().first; + it.key = F->get().second; + mmi.items.push_back(it); #endif - idx++; - } + idx++; + } - RID instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(instance, mm); + RID instance = VS::get_singleton()->instance_create(); + VS::get_singleton()->instance_set_base(instance, mm); - if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(instance, get_global_transform()); - } + if (is_inside_tree()) { + VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); + VS::get_singleton()->instance_set_transform(instance, get_global_transform()); + } - mmi.multimesh = mm; - mmi.instance = instance; + mmi.multimesh = mm; + mmi.instance = instance; - g.multimesh_instances.push_back(mmi); + g.multimesh_instances.push_back(mmi); + } } if (col_debug.size()) { @@ -642,6 +685,11 @@ void GridMap::_notification(int p_what) { _octant_enter_world(E->key()); } + for (int i = 0; i < baked_meshes.size(); i++) { + VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world()->get_scenario()); + VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); + } + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -655,6 +703,10 @@ void GridMap::_notification(int p_what) { last_transform = new_xform; + for (int i = 0; i < baked_meshes.size(); i++) { + VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); + } + } break; case NOTIFICATION_EXIT_WORLD: { @@ -667,6 +719,9 @@ void GridMap::_notification(int p_what) { //_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS); //_update_octants_callback(); //_update_area_instances(); + for (int i = 0; i < baked_meshes.size(); i++) { + VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID()); + } } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -701,12 +756,14 @@ void GridMap::_queue_octants_dirty() { void GridMap::_recreate_octant_data() { + recreating_octants = true; Map<IndexKey, Cell> cell_copy = cell_map; _clear_internal(); for (Map<IndexKey, Cell>::Element *E = cell_copy.front(); E; E = E->next()) { set_cell_item(E->key().x, E->key().y, E->key().z, E->get().item, E->get().rot); } + recreating_octants = false; } void GridMap::_clear_internal() { @@ -726,6 +783,7 @@ void GridMap::_clear_internal() { void GridMap::clear() { _clear_internal(); + clear_baked_meshes(); } void GridMap::resource_changed(const RES &p_res) { @@ -791,6 +849,11 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_used_cells"), &GridMap::get_used_cells); ClassDB::bind_method(D_METHOD("get_meshes"), &GridMap::get_meshes); + ClassDB::bind_method(D_METHOD("get_bake_meshes"), &GridMap::get_bake_meshes); + ClassDB::bind_method(D_METHOD("get_bake_mesh_instance", "idx"), &GridMap::get_bake_mesh_instance); + + ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes); + ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1)); BIND_CONSTANT(INVALID_CELL_ITEM); } @@ -883,10 +946,129 @@ Vector3 GridMap::_get_offset() const { cell_size.z * 0.5 * int(center_z)); } +void GridMap::clear_baked_meshes() { + + for (int i = 0; i < baked_meshes.size(); i++) { + VS::get_singleton()->free(baked_meshes[i].instance); + } + baked_meshes.clear(); + + _recreate_octant_data(); +} + +void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texel_size) { + + if (!theme.is_valid()) + return; + + //generate + Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool> > > surface_map; + + for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next()) { + + IndexKey key = E->key(); + + int item = E->get().item; + if (!theme->has_item(item)) + continue; + + Ref<Mesh> mesh = theme->get_item_mesh(item); + if (!mesh.is_valid()) + continue; + + Vector3 cellpos = Vector3(key.x, key.y, key.z); + Vector3 ofs = _get_offset(); + + Transform xform; + + xform.basis.set_orthogonal_index(E->get().rot); + xform.set_origin(cellpos * cell_size + ofs); + xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale)); + + OctantKey ok; + ok.x = key.x / octant_size; + ok.y = key.y / octant_size; + ok.z = key.z / octant_size; + + if (!surface_map.has(ok)) { + surface_map[ok] = Map<Ref<Material>, Ref<SurfaceTool> >(); + } + + Map<Ref<Material>, Ref<SurfaceTool> > &mat_map = surface_map[ok]; + + for (int i = 0; i < mesh->get_surface_count(); i++) { + + if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) + continue; + + Ref<Material> surf_mat = mesh->surface_get_material(i); + if (!mat_map.has(surf_mat)) { + Ref<SurfaceTool> st; + st.instance(); + st->begin(Mesh::PRIMITIVE_TRIANGLES); + st->set_material(surf_mat); + mat_map[surf_mat] = st; + } + + mat_map[surf_mat]->append_from(mesh, i, xform); + } + } + + int ofs = 0; + + for (Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool> > >::Element *E = surface_map.front(); E; E = E->next()) { + + print_line("generating mesh " + itos(ofs++) + "/" + itos(surface_map.size())); + Ref<ArrayMesh> mesh; + mesh.instance(); + for (Map<Ref<Material>, Ref<SurfaceTool> >::Element *F = E->get().front(); F; F = F->next()) { + F->get()->commit(mesh); + } + + BakedMesh bm; + bm.mesh = mesh; + bm.instance = VS::get_singleton()->instance_create(); + VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); + VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); + if (is_inside_tree()) { + VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); + VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); + } + + if (p_gen_lightmap_uv) { + mesh->lightmap_unwrap(get_global_transform(), p_lightmap_uv_texel_size); + } + baked_meshes.push_back(bm); + } + + _recreate_octant_data(); +} + +Array GridMap::get_bake_meshes() { + + if (!baked_meshes.size()) { + make_baked_meshes(true); + } + + Array arr; + for (int i = 0; i < baked_meshes.size(); i++) { + arr.push_back(baked_meshes[i].mesh); + arr.push_back(Transform()); + } + + return arr; +} + +RID GridMap::get_bake_mesh_instance(int p_idx) { + + ERR_FAIL_INDEX_V(p_idx, baked_meshes.size(), RID()); + return baked_meshes[p_idx].instance; +} + GridMap::GridMap() { cell_size = Vector3(2, 2, 2); - octant_size = 4; + octant_size = 8; awaiting_update = false; _in_tree = false; center_x = true; @@ -901,6 +1083,7 @@ GridMap::GridMap() { navigation = NULL; set_notify_transform(true); + recreating_octants = false; } GridMap::~GridMap() { diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index ab66bf123e..241ac7a434 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -148,6 +148,9 @@ class GridMap : public Spatial { bool clip; bool clip_above; int clip_floor; + + bool recreating_octants; + Vector3::Axis clip_axis; Ref<MeshLibrary> theme; @@ -188,9 +191,11 @@ class GridMap : public Spatial { struct BakedMesh { Ref<Mesh> mesh; - Transform transform; + RID instance; }; + Vector<BakedMesh> baked_meshes; + protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -237,8 +242,14 @@ public: Array get_meshes(); + void clear_baked_meshes(); + void make_baked_meshes(bool p_gen_lightmap_uv = false, float p_lightmap_uv_texel_size = 0.1); + void clear(); + Array get_bake_meshes(); + RID get_bake_mesh_instance(int p_idx); + GridMap(); ~GridMap(); }; diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp index 9a1efb4423..d5819a4ca3 100644 --- a/modules/mono/editor/csharp_project.cpp +++ b/modules/mono/editor/csharp_project.cpp @@ -54,7 +54,7 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi ERR_FAIL_V(String()); } - return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : ""; + return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String(); } String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files) { @@ -75,7 +75,7 @@ String generate_editor_api_project(const String &p_dir, const String &p_core_dll ERR_FAIL_V(String()); } - return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : ""; + return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String(); } String generate_game_project(const String &p_dir, const String &p_name, const Vector<String> &p_files) { @@ -96,7 +96,7 @@ String generate_game_project(const String &p_dir, const String &p_name, const Ve ERR_FAIL_V(String()); } - return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : ""; + return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String(); } void add_item(const String &p_project_path, const String &p_item_type, const String &p_include) { diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index 1bc1e8a515..1e61646769 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -50,9 +50,9 @@ GodotSharpEditor *GodotSharpEditor::singleton = NULL; bool GodotSharpEditor::_create_project_solution() { - EditorProgress pr("create_csharp_solution", "Generating solution...", 2); + EditorProgress pr("create_csharp_solution", TTR("Generating solution..."), 2); - pr.step("Generating C# project..."); + pr.step(TTR("Generating C# project...")); String path = OS::get_singleton()->get_resource_dir(); String name = ProjectSettings::get_singleton()->get("application/config/name"); @@ -67,7 +67,7 @@ bool GodotSharpEditor::_create_project_solution() { NETSolution solution(name); if (!solution.set_path(path)) { - show_error_dialog("Failed to create solution."); + show_error_dialog(TTR("Failed to create solution.")); return false; } @@ -79,7 +79,7 @@ bool GodotSharpEditor::_create_project_solution() { Error sln_error = solution.save(); if (sln_error != OK) { - show_error_dialog("Failed to save solution."); + show_error_dialog(TTR("Failed to save solution.")); return false; } @@ -89,13 +89,13 @@ bool GodotSharpEditor::_create_project_solution() { if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR)) return false; - pr.step("Done"); + pr.step(TTR("Done")); // Here, after all calls to progress_task_step call_deferred("_remove_create_sln_menu_option"); } else { - show_error_dialog("Failed to create C# project."); + show_error_dialog(TTR("Failed to create C# project.")); } return true; @@ -194,14 +194,14 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { error_dialog = memnew(AcceptDialog); editor->get_gui_base()->add_child(error_dialog); - bottom_panel_btn = editor->add_bottom_panel_item("Mono", memnew(MonoBottomPanel(editor))); + bottom_panel_btn = editor->add_bottom_panel_item(TTR("Mono"), memnew(MonoBottomPanel(editor))); godotsharp_builds = memnew(GodotSharpBuilds); editor->add_child(memnew(MonoReloadNode)); menu_button = memnew(MenuButton); - menu_button->set_text("Mono"); + menu_button->set_text(TTR("Mono")); menu_popup = menu_button->get_popup(); String sln_path = GodotSharpDirs::get_project_sln_path(); @@ -209,7 +209,7 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) { bottom_panel_btn->hide(); - menu_popup->add_item("Create C# solution", MENU_CREATE_SLN); + menu_popup->add_item(TTR("Create C# solution"), MENU_CREATE_SLN); } menu_popup->connect("id_pressed", this, "_menu_option_pressed"); diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 31dc09856a..be714026ad 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -197,7 +197,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { panel_builds_tab->add_child(toolbar_hbc); ToolButton *build_project_btn = memnew(ToolButton); - build_project_btn->set_text("Build Project"); + build_project_btn->set_text(TTR("Build Project")); build_project_btn->set_focus_mode(FOCUS_NONE); build_project_btn->connect("pressed", this, "_build_project_pressed"); toolbar_hbc->add_child(build_project_btn); @@ -205,7 +205,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { toolbar_hbc->add_spacer(); warnings_btn = memnew(ToolButton); - warnings_btn->set_text("Warnings"); + warnings_btn->set_text(TTR("Warnings")); warnings_btn->set_toggle_mode(true); warnings_btn->set_pressed(true); warnings_btn->set_visible(false); @@ -214,7 +214,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) { toolbar_hbc->add_child(warnings_btn); errors_btn = memnew(ToolButton); - errors_btn->set_text("Errors"); + errors_btn->set_text(TTR("Errors")); errors_btn->set_toggle_mode(true); errors_btn->set_pressed(true); errors_btn->set_visible(false); diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index eb34f9dd3f..63b24f3ee6 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -290,7 +290,7 @@ int GDMonoField::get_int_value(MonoObject *p_object) { String GDMonoField::get_string_value(MonoObject *p_object) { MonoObject *val = get_value(p_object); - return val ? GDMonoMarshal::mono_string_to_godot((MonoString *)val) : String(); + return GDMonoMarshal::mono_string_to_godot((MonoString *)val); } bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) { diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index e473348897..e8aea8624d 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -70,7 +70,9 @@ void gdmono_MonoLogCallback(const char *log_domain, const char *log_level, const } if (fatal) { - ERR_PRINTS("Mono: FALTAL ERROR, ABORTING! Logfile: " + GDMonoLog::get_singleton()->get_log_file_path() + "\n"); + ERR_PRINTS("Mono: FATAL ERROR, ABORTING! Logfile: " + GDMonoLog::get_singleton()->get_log_file_path() + "\n"); + // If we were to abort without flushing, the log wouldn't get written. + f->flush(); abort(); } } diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 8bc2bb5096..d744d24f24 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -490,8 +490,9 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) { return unbox<double>(p_obj); case MONO_TYPE_STRING: { - String str = mono_string_to_godot((MonoString *)p_obj); - return str; + if (p_obj == NULL) + return Variant(); // NIL + return mono_string_to_godot_not_null((MonoString *)p_obj); } break; case MONO_TYPE_VALUETYPE: { diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 443e947fb5..1be4be1a1c 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -62,13 +62,20 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type); String mono_to_utf8_string(MonoString *p_mono_string); String mono_to_utf16_string(MonoString *p_mono_string); -_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { +_FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) { if (sizeof(CharType) == 2) return mono_to_utf16_string(p_mono_string); return mono_to_utf8_string(p_mono_string); } +_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { + if (p_mono_string == NULL) + return String(); + + return mono_string_to_godot_not_null(p_mono_string); +} + _FORCE_INLINE_ MonoString *mono_from_utf8_string(const String &p_string) { return mono_string_new(mono_domain_get(), p_string.utf8().get_data()); } diff --git a/modules/opus/register_types.cpp b/modules/opus/register_types.cpp index a69c8bf9f3..6d7a3575ed 100644 --- a/modules/opus/register_types.cpp +++ b/modules/opus/register_types.cpp @@ -34,13 +34,18 @@ static ResourceFormatLoaderAudioStreamOpus *opus_stream_loader = NULL; void register_opus_types() { - - opus_stream_loader = memnew(ResourceFormatLoaderAudioStreamOpus); - ResourceLoader::add_resource_format_loader(opus_stream_loader); - ClassDB::register_class<AudioStreamOpus>(); + // Sorry guys, do not enable this unless you can figure out a way + // to get Opus to not do any memory allocation or system calls + // in the audio thread. + // Currently the implementation even reads files from the audio thread, + // and this is not how audio programming works. + + //opus_stream_loader = memnew(ResourceFormatLoaderAudioStreamOpus); + //ResourceLoader::add_resource_format_loader(opus_stream_loader); + //ClassDB::register_class<AudioStreamOpus>(); } void unregister_opus_types() { - memdelete(opus_stream_loader); + //memdelete(opus_stream_loader); } diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 5c252bda86..6f5bbba8d1 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -42,12 +42,17 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra int todo = p_frames; - while (todo && active) { + int start_buffer = 0; - int mixed = stb_vorbis_get_samples_float_interleaved(ogg_stream, 2, (float *)p_buffer, todo * 2); + while (todo && active) { + float *buffer = (float *)p_buffer; + if (start_buffer > 0) { + buffer = (buffer + start_buffer * 2); + } + int mixed = stb_vorbis_get_samples_float_interleaved(ogg_stream, 2, buffer, todo * 2); if (vorbis_stream->channels == 1 && mixed > 0) { //mix mono to stereo - for (int i = 0; i < mixed; i++) { + for (int i = start_buffer; i < mixed; i++) { p_buffer[i].r = p_buffer[i].l; } } @@ -60,11 +65,14 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra //loop seek(vorbis_stream->loop_offset); loops++; + // we still have buffer to fill, start from this element in the next iteration. + start_buffer = p_frames - todo; } else { - for (int i = mixed; i < p_frames; i++) { + for (int i = p_frames - todo; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); } active = false; + todo = 0; } } } diff --git a/modules/thekla_unwrap/register_types.cpp b/modules/thekla_unwrap/register_types.cpp index ab3203068f..da6c1bab2a 100644 --- a/modules/thekla_unwrap/register_types.cpp +++ b/modules/thekla_unwrap/register_types.cpp @@ -65,7 +65,7 @@ bool thekla_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver Thekla::atlas_set_default_options(&options); options.packer_options.witness.packing_quality = 1; options.packer_options.witness.texel_area = 1.0 / p_texel_size; - options.packer_options.witness.conservative = true; + options.packer_options.witness.conservative = false; //generate Thekla::Atlas_Error err; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 0bb235436e..faf3aecbd4 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -228,7 +228,7 @@ protected: if (String(p_name) == "type") { - Dictionary dc = d.copy(); + Dictionary dc = d.duplicate(); dc["type"] = p_value; undo_redo->create_action(TTR("Set Variable Type")); undo_redo->add_do_method(script.ptr(), "set_variable_info", var, dc); @@ -241,7 +241,7 @@ protected: if (String(p_name) == "hint") { - Dictionary dc = d.copy(); + Dictionary dc = d.duplicate(); dc["hint"] = p_value; undo_redo->create_action(TTR("Set Variable Type")); undo_redo->add_do_method(script.ptr(), "set_variable_info", var, dc); @@ -254,7 +254,7 @@ protected: if (String(p_name) == "hint_string") { - Dictionary dc = d.copy(); + Dictionary dc = d.duplicate(); dc["hint_string"] = p_value; undo_redo->create_action(TTR("Set Variable Type")); undo_redo->add_do_method(script.ptr(), "set_variable_info", var, dc); @@ -481,9 +481,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Ref<Texture> type_icons[Variant::VARIANT_MAX] = { Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("Bool", "EditorIcons"), - Control::get_icon("Int", "EditorIcons"), - Control::get_icon("Float", "EditorIcons"), + Control::get_icon("bool", "EditorIcons"), + Control::get_icon("int", "EditorIcons"), + Control::get_icon("float", "EditorIcons"), Control::get_icon("String", "EditorIcons"), Control::get_icon("Vector2", "EditorIcons"), Control::get_icon("Rect2", "EditorIcons"), @@ -491,7 +491,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Control::get_icon("Transform2D", "EditorIcons"), Control::get_icon("Plane", "EditorIcons"), Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("Aabb", "EditorIcons"), + Control::get_icon("AABB", "EditorIcons"), Control::get_icon("Basis", "EditorIcons"), Control::get_icon("Transform", "EditorIcons"), Control::get_icon("Color", "EditorIcons"), @@ -775,9 +775,9 @@ void VisualScriptEditor::_update_members() { Ref<Texture> type_icons[Variant::VARIANT_MAX] = { Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("Bool", "EditorIcons"), - Control::get_icon("Int", "EditorIcons"), - Control::get_icon("Float", "EditorIcons"), + Control::get_icon("bool", "EditorIcons"), + Control::get_icon("int", "EditorIcons"), + Control::get_icon("float", "EditorIcons"), Control::get_icon("String", "EditorIcons"), Control::get_icon("Vector2", "EditorIcons"), Control::get_icon("Rect2", "EditorIcons"), @@ -785,7 +785,7 @@ void VisualScriptEditor::_update_members() { Control::get_icon("Transform2D", "EditorIcons"), Control::get_icon("Plane", "EditorIcons"), Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("Aabb", "EditorIcons"), + Control::get_icon("AABB", "EditorIcons"), Control::get_icon("Basis", "EditorIcons"), Control::get_icon("Transform", "EditorIcons"), Control::get_icon("Color", "EditorIcons"), |