Merge pull request #52841 from akien-mga/3.x-cherrypicks
This commit is contained in:
commit
da8cd3d7a7
32 changed files with 146 additions and 75 deletions
|
@ -768,7 +768,7 @@ Basis::operator String() const {
|
|||
|
||||
Quat Basis::get_quat() const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_rotation(), Quat(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() instead.");
|
||||
ERR_FAIL_COND_V_MSG(!is_rotation(), Quat(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() if the Basis contains linearly independent vectors.");
|
||||
#endif
|
||||
/* Allow getting a quaternion from an unnormalized transform */
|
||||
Basis m = *this;
|
||||
|
|
|
@ -54,11 +54,7 @@ String ProjectSettings::get_resource_path() const {
|
|||
};
|
||||
|
||||
String ProjectSettings::localize_path(const String &p_path) const {
|
||||
if (resource_path == "") {
|
||||
return p_path; //not initialized yet
|
||||
}
|
||||
|
||||
if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
|
||||
if (resource_path.empty() || p_path.begins_with("res://") || p_path.begins_with("user://") ||
|
||||
(p_path.is_abs_path() && !p_path.begins_with(resource_path))) {
|
||||
return p_path.simplify_path();
|
||||
}
|
||||
|
|
|
@ -1394,13 +1394,13 @@ String String::num_scientific(double p_num) {
|
|||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
|
||||
#if (defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
|
||||
// MinGW and old MSC require _set_output_format() to conform to C99 output for printf
|
||||
#if defined(__MINGW32__) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
|
||||
// MinGW requires _set_output_format() to conform to C99 output for printf
|
||||
unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
|
||||
#endif
|
||||
snprintf(buf, 256, "%lg", p_num);
|
||||
|
||||
#if (defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
|
||||
#if defined(__MINGW32__) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT)
|
||||
_set_output_format(old_exponent_format);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
<description>
|
||||
Creates request on the underlying [HTTPClient]. If there is no configuration errors, it tries to connect using [method HTTPClient.connect_to_host] and passes parameters onto [method HTTPClient.request].
|
||||
Returns [constant OK] if request is successfully created. (Does not imply that the server has responded), [constant ERR_UNCONFIGURED] if not in the tree, [constant ERR_BUSY] if still processing previous request, [constant ERR_INVALID_PARAMETER] if given string is not a valid URL format, or [constant ERR_CANT_CONNECT] if not using thread and the [HTTPClient] cannot connect to host.
|
||||
[b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example.
|
||||
[b]Note:[/b] When [code]method[/code] is [constant HTTPClient.METHOD_GET], the payload sent via [code]request_data[/code] might be ignored by the server or even cause the server to reject the request (check [url=https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.1]RFC 7231 section 4.3.1[/url] for more details). As a workaround, you can send data as a query string in the URL. See [method String.http_escape] for an example.
|
||||
</description>
|
||||
</method>
|
||||
<method name="request_raw">
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="JNISingleton" inherits="Object" version="3.4">
|
||||
<brief_description>
|
||||
Singleton that connects the engine with Android plugins to interface with native Android code.
|
||||
</brief_description>
|
||||
<description>
|
||||
The JNISingleton is implemented only in the Android export. It's used to call methods and connect signals from an Android plugin written in Java or Kotlin. Methods and signals can be called and connected to the JNISingleton as if it is a Node. See [url=https://en.wikipedia.org/wiki/Java_Native_Interface]Java Native Interface - Wikipedia[/url] for more information.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Creating Android plugins">https://docs.godotengine.org/en/3.4/tutorials/plugins/android/android_plugin.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
|
|
|
@ -138,6 +138,7 @@
|
|||
<description>
|
||||
Adds the node to a group. Groups are helpers to name and organize a subset of nodes, for example "enemies" or "collectables". A node can be in any number of groups. Nodes can be assigned a group at any time, but will not be added until they are inside the scene tree (see [method is_inside_tree]). See notes in the description, and the group methods in [SceneTree].
|
||||
The [code]persistent[/code] option is used when packing node to [PackedScene] and saving to file. Non-persistent groups aren't stored.
|
||||
[b]Note:[/b] For performance reasons, the order of node groups is [i]not[/i] guaranteed. The order of node groups should not be relied upon as it can vary across project runs.
|
||||
</description>
|
||||
</method>
|
||||
<method name="can_process" qualifiers="const">
|
||||
|
@ -200,6 +201,7 @@
|
|||
<return type="Array" />
|
||||
<description>
|
||||
Returns an array listing the groups that the node is a member of.
|
||||
[b]Note:[/b] For performance reasons, the order of node groups is [i]not[/i] guaranteed. The order of node groups should not be relied upon as it can vary across project runs.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_index" qualifiers="const">
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
Provides direct access to a physics body in the [Physics2DServer], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid/character bodies, and is intended for changing the direct state of that body. See [method RigidBody2D._integrate_forces].
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
<link title="Physics introduction">https://docs.godotengine.org/en/3.4/tutorials/physics/physics_introduction.html</link>
|
||||
<link title="Ray-casting">https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_central_force">
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
Direct access object to a space in the [Physics2DServer]. It's used mainly to do queries against objects and areas residing in a given space.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
<link title="Physics introduction">https://docs.godotengine.org/en/3.4/tutorials/physics/physics_introduction.html</link>
|
||||
<link title="Ray-casting">https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="cast_motion">
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
Provides direct access to a physics body in the [PhysicsServer], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid/character bodies, and is intended for changing the direct state of that body. See [method RigidBody._integrate_forces].
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Physics introduction">https://docs.godotengine.org/en/3.4/tutorials/physics/physics_introduction.html</link>
|
||||
<link title="Ray-casting">https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_central_force">
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
Direct access object to a space in the [PhysicsServer]. It's used mainly to do queries against objects and areas residing in a given space.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
<link title="Physics introduction">https://docs.godotengine.org/en/3.4/tutorials/physics/physics_introduction.html</link>
|
||||
<link title="Ray-casting">https://docs.godotengine.org/en/3.4/tutorials/physics/ray-casting.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="cast_motion">
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
<return type="Variant" />
|
||||
<description>
|
||||
Joins the [Thread] and waits for it to finish. Returns what the method called returned.
|
||||
Should either be used when you want to retrieve the value returned from the method called by the [Thread] or before freeing the instance that contains the [Thread].
|
||||
[b]Note:[/b] After the [Thread] finishes joining it will be disposed. If you want to use it again you will have to create a new instance of it.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
|
|
@ -543,6 +543,10 @@ void EditorData::remove_scene(int p_idx) {
|
|||
current_edited_scene--;
|
||||
}
|
||||
|
||||
if (edited_scene[p_idx].path != String()) {
|
||||
ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(edited_scene[p_idx].path);
|
||||
}
|
||||
|
||||
edited_scene.remove(p_idx);
|
||||
}
|
||||
|
||||
|
|
|
@ -1985,7 +1985,6 @@ void EditorNode::_edit_current() {
|
|||
|
||||
Object *prev_inspected_object = get_inspector()->get_edited_object();
|
||||
|
||||
bool capitalize = bool(EDITOR_GET("interface/inspector/capitalize_properties"));
|
||||
bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
|
||||
bool is_resource = current_obj->is_class("Resource");
|
||||
bool is_node = current_obj->is_class("Node");
|
||||
|
@ -2043,7 +2042,6 @@ void EditorNode::_edit_current() {
|
|||
|
||||
if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) {
|
||||
editable_warning = TTR("This is a remote object, so changes to it won't be kept.\nPlease read the documentation relevant to debugging to better understand this workflow.");
|
||||
capitalize = false;
|
||||
disable_folding = true;
|
||||
} else if (current_obj->is_class("MultiNodeEdit")) {
|
||||
Node *scene = get_edited_scene();
|
||||
|
@ -2080,10 +2078,6 @@ void EditorNode::_edit_current() {
|
|||
|
||||
inspector_dock->set_warning(editable_warning);
|
||||
|
||||
if (get_inspector()->is_capitalize_paths_enabled() != capitalize) {
|
||||
get_inspector()->set_enable_capitalize_paths(capitalize);
|
||||
}
|
||||
|
||||
if (get_inspector()->is_using_folding() == disable_folding) {
|
||||
get_inspector()->set_use_folding(!disable_folding);
|
||||
}
|
||||
|
@ -3281,10 +3275,6 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) {
|
|||
new_index = 1;
|
||||
}
|
||||
|
||||
if (editor_data.get_scene_path(old_index) != String()) {
|
||||
ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index));
|
||||
}
|
||||
|
||||
if (p_change_tab) {
|
||||
_scene_tab_changed(new_index);
|
||||
}
|
||||
|
|
|
@ -2127,6 +2127,14 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
|
|||
return true;
|
||||
}
|
||||
|
||||
if (drag_data.has("type") && String(drag_data["type"]) == "nodes") {
|
||||
// Save branch as scene.
|
||||
String to_dir;
|
||||
bool favorite;
|
||||
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
|
||||
return !favorite && Array(drag_data["nodes"]).size() == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2265,6 +2273,13 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
|
|||
_update_tree(_compute_uncollapsed_paths());
|
||||
}
|
||||
}
|
||||
|
||||
if (drag_data.has("type") && String(drag_data["type"]) == "nodes") {
|
||||
String to_dir;
|
||||
bool favorite;
|
||||
_get_drag_target_folder(to_dir, favorite, p_point, p_from);
|
||||
EditorNode::get_singleton()->get_scene_tree_dock()->save_branch_to_file(to_dir);
|
||||
}
|
||||
}
|
||||
|
||||
void FileSystemDock::_get_drag_target_folder(String &target, bool &target_favorites, const Point2 &p_point, Control *p_from) const {
|
||||
|
|
|
@ -99,9 +99,10 @@ Skeleton2DEditor::Skeleton2DEditor() {
|
|||
options->set_text(TTR("Skeleton2D"));
|
||||
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Skeleton2D", "EditorIcons"));
|
||||
|
||||
options->get_popup()->add_item(TTR("Make Rest Pose (From Bones)"), MENU_OPTION_MAKE_REST);
|
||||
options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_MAKE_REST);
|
||||
options->get_popup()->add_separator();
|
||||
options->get_popup()->add_item(TTR("Set Bones to Rest Pose"), MENU_OPTION_SET_REST);
|
||||
// Use the "Overwrite" word to highlight that this is a destructive operation.
|
||||
options->get_popup()->add_item(TTR("Overwrite Rest Pose"), MENU_OPTION_SET_REST);
|
||||
options->set_switch_on_hover(true);
|
||||
|
||||
options->get_popup()->connect("id_pressed", this, "_menu_option");
|
||||
|
|
|
@ -2841,6 +2841,11 @@ void SceneTreeDock::set_filter(const String &p_filter) {
|
|||
scene_tree->set_filter(p_filter);
|
||||
}
|
||||
|
||||
void SceneTreeDock::save_branch_to_file(String p_directory) {
|
||||
new_scene_from_dialog->set_current_dir(p_directory);
|
||||
_tool_selected(TOOL_NEW_SCENE_FROM);
|
||||
}
|
||||
|
||||
void SceneTreeDock::_focus_node() {
|
||||
Node *node = scene_tree->get_selected();
|
||||
ERR_FAIL_COND(!node);
|
||||
|
|
|
@ -265,6 +265,7 @@ protected:
|
|||
public:
|
||||
String get_filter();
|
||||
void set_filter(const String &p_filter);
|
||||
void save_branch_to_file(String p_directory);
|
||||
|
||||
void _focus_node();
|
||||
|
||||
|
|
|
@ -290,10 +290,12 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
|
|||
}
|
||||
}
|
||||
|
||||
// Display the node name in all tooltips so that long node names can be previewed
|
||||
// without having to rename them.
|
||||
if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) {
|
||||
item->add_button(0, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
|
||||
|
||||
String tooltip = TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path() + "\n" + TTR("Type:") + " " + p_node->get_class();
|
||||
String tooltip = String(p_node->get_name()) + "\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path() + "\n" + TTR("Type:") + " " + p_node->get_class();
|
||||
if (p_node->get_editor_description() != String()) {
|
||||
tooltip += "\n\n" + p_node->get_editor_description();
|
||||
}
|
||||
|
@ -302,7 +304,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
|
|||
} else if (p_node != get_scene_node() && p_node->get_filename() != "" && can_open_instance) {
|
||||
item->add_button(0, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
|
||||
|
||||
String tooltip = TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class();
|
||||
String tooltip = String(p_node->get_name()) + "\n" + TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class();
|
||||
if (p_node->get_editor_description() != String()) {
|
||||
tooltip += "\n\n" + p_node->get_editor_description();
|
||||
}
|
||||
|
@ -314,7 +316,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
|
|||
type = p_node->get_class();
|
||||
}
|
||||
|
||||
String tooltip = TTR("Type:") + " " + type;
|
||||
String tooltip = String(p_node->get_name()) + "\n" + TTR("Type:") + " " + type;
|
||||
if (p_node->get_editor_description() != String()) {
|
||||
tooltip += "\n\n" + p_node->get_editor_description();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "camera_osx.h"
|
||||
#include "servers/camera/camera_feed.h"
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -253,10 +254,25 @@ CameraFeedOSX::~CameraFeedOSX() {
|
|||
|
||||
bool CameraFeedOSX::activate_feed() {
|
||||
if (capture_session) {
|
||||
// already recording!
|
||||
// Already recording!
|
||||
} else {
|
||||
// start camera capture
|
||||
capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device];
|
||||
// Start camera capture, check permission.
|
||||
if (@available(macOS 10.14, *)) {
|
||||
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
if (status == AVAuthorizationStatusAuthorized) {
|
||||
capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device];
|
||||
} else if (status == AVAuthorizationStatusNotDetermined) {
|
||||
// Request permission.
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
|
||||
completionHandler:^(BOOL granted) {
|
||||
if (granted) {
|
||||
capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device];
|
||||
}
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device];
|
||||
}
|
||||
};
|
||||
|
||||
return true;
|
||||
|
|
|
@ -38,9 +38,11 @@
|
|||
GDScriptLanguageServer::GDScriptLanguageServer() {
|
||||
thread_running = false;
|
||||
started = false;
|
||||
|
||||
use_thread = false;
|
||||
host = "127.0.0.1";
|
||||
port = 6008;
|
||||
|
||||
_EDITOR_DEF("network/language_server/remote_host", host);
|
||||
_EDITOR_DEF("network/language_server/remote_port", port);
|
||||
_EDITOR_DEF("network/language_server/enable_smart_resolve", true);
|
||||
_EDITOR_DEF("network/language_server/show_native_symbols_in_editor", false);
|
||||
|
@ -61,9 +63,10 @@ void GDScriptLanguageServer::_notification(int p_what) {
|
|||
}
|
||||
} break;
|
||||
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
|
||||
String host = String(_EDITOR_GET("network/language_server/remote_host"));
|
||||
int port = (int)_EDITOR_GET("network/language_server/remote_port");
|
||||
bool use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
|
||||
if (port != this->port || use_thread != this->use_thread) {
|
||||
if (host != this->host || port != this->port || use_thread != this->use_thread) {
|
||||
this->stop();
|
||||
this->start();
|
||||
}
|
||||
|
@ -81,9 +84,10 @@ void GDScriptLanguageServer::thread_main(void *p_userdata) {
|
|||
}
|
||||
|
||||
void GDScriptLanguageServer::start() {
|
||||
host = String(_EDITOR_GET("network/language_server/remote_host"));
|
||||
port = (int)_EDITOR_GET("network/language_server/remote_port");
|
||||
use_thread = (bool)_EDITOR_GET("network/language_server/use_thread");
|
||||
if (protocol.start(port, IP_Address("127.0.0.1")) == OK) {
|
||||
if (protocol.start(port, IP_Address(host)) == OK) {
|
||||
EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR);
|
||||
if (use_thread) {
|
||||
thread_running = true;
|
||||
|
|
|
@ -44,6 +44,7 @@ class GDScriptLanguageServer : public EditorPlugin {
|
|||
bool thread_running;
|
||||
bool started;
|
||||
bool use_thread;
|
||||
String host;
|
||||
int port;
|
||||
static void thread_main(void *p_userdata);
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ String str_format(const char *p_format, ...) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MINGW_ENABLED) || defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#if defined(MINGW_ENABLED)
|
||||
#define gd_vsnprintf(m_buffer, m_count, m_format, m_args_copy) vsnprintf_s(m_buffer, m_count, _TRUNCATE, m_format, m_args_copy)
|
||||
#define gd_vscprintf(m_format, m_args_copy) _vscprintf(m_format, m_args_copy)
|
||||
#else
|
||||
|
|
|
@ -43,9 +43,8 @@ allprojects {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation libraries.supportCoreUtils
|
||||
implementation libraries.kotlinStdLib
|
||||
implementation libraries.v4Support
|
||||
implementation libraries.androidxFragment
|
||||
|
||||
if (rootProject.findProject(":lib")) {
|
||||
implementation project(":lib")
|
||||
|
|
|
@ -4,9 +4,8 @@ ext.versions = [
|
|||
minSdk : 19,
|
||||
targetSdk : 30,
|
||||
buildTools : '30.0.3',
|
||||
supportCoreUtils : '1.0.0',
|
||||
kotlinVersion : '1.5.10',
|
||||
v4Support : '1.0.0',
|
||||
fragmentVersion : '1.3.6',
|
||||
javaVersion : 1.8,
|
||||
ndkVersion : '21.4.7075529' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated.
|
||||
|
||||
|
@ -14,10 +13,9 @@ ext.versions = [
|
|||
|
||||
ext.libraries = [
|
||||
androidGradlePlugin: "com.android.tools.build:gradle:$versions.androidGradlePlugin",
|
||||
supportCoreUtils : "androidx.legacy:legacy-support-core-utils:$versions.supportCoreUtils",
|
||||
kotlinGradlePlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion",
|
||||
kotlinStdLib : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$versions.kotlinVersion",
|
||||
v4Support : "androidx.legacy:legacy-support-v4:$versions.v4Support"
|
||||
androidxFragment : "androidx.fragment:fragment:$versions.fragmentVersion",
|
||||
]
|
||||
|
||||
ext.getExportPackageName = { ->
|
||||
|
|
|
@ -2,9 +2,8 @@ apply plugin: 'com.android.library'
|
|||
apply plugin: 'kotlin-android'
|
||||
|
||||
dependencies {
|
||||
implementation libraries.supportCoreUtils
|
||||
implementation libraries.kotlinStdLib
|
||||
implementation libraries.v4Support
|
||||
implementation libraries.androidxFragment
|
||||
}
|
||||
|
||||
def pathToRootDir = "../../../../"
|
||||
|
|
|
@ -398,7 +398,11 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||
View pluginView = plugin.onMainCreate(activity);
|
||||
if (pluginView != null) {
|
||||
containerLayout.addView(pluginView);
|
||||
if (plugin.shouldBeOnTop()) {
|
||||
containerLayout.addView(pluginView);
|
||||
} else {
|
||||
containerLayout.addView(pluginView, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,6 +190,9 @@ public abstract class GodotPlugin {
|
|||
* The plugin can return a non-null {@link View} layout in order to add it to the Godot view
|
||||
* hierarchy.
|
||||
*
|
||||
* Use shouldBeOnTop() to set whether the plugin's {@link View} should be added on top or behind
|
||||
* the main Godot view.
|
||||
*
|
||||
* @see Activity#onCreate(Bundle)
|
||||
* @return the plugin's view to be included; null if no views should be included.
|
||||
*/
|
||||
|
@ -293,6 +296,17 @@ public abstract class GodotPlugin {
|
|||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the plugin's {@link View} returned in onMainCreate() should be placed on
|
||||
* top of the main Godot view.
|
||||
*
|
||||
* Returning false causes the plugin's {@link View} to be placed behind, which can be useful
|
||||
* when used with transparency in order to let the Godot view handle inputs.
|
||||
*/
|
||||
public boolean shouldBeOnTop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the specified action on the UI thread. If the current thread is the UI
|
||||
* thread, then the action is executed immediately. If the current thread is
|
||||
|
|
|
@ -66,17 +66,17 @@ class RingBuffer {
|
|||
const mw = this.buffer.length - this.wpos;
|
||||
if (mw >= to_write) {
|
||||
this.buffer.set(p_buffer, this.wpos);
|
||||
this.wpos += to_write;
|
||||
if (mw === to_write) {
|
||||
this.wpos = 0;
|
||||
}
|
||||
} else {
|
||||
const high = p_buffer.subarray(0, to_write - mw);
|
||||
const low = p_buffer.subarray(to_write - mw);
|
||||
const high = p_buffer.subarray(0, mw);
|
||||
const low = p_buffer.subarray(mw);
|
||||
this.buffer.set(high, this.wpos);
|
||||
this.buffer.set(low);
|
||||
this.wpos = low.length;
|
||||
}
|
||||
let diff = to_write;
|
||||
if (this.wpos + diff >= this.buffer.length) {
|
||||
diff -= this.buffer.length;
|
||||
}
|
||||
this.wpos += diff;
|
||||
Atomics.add(this.avail, 0, to_write);
|
||||
Atomics.notify(this.avail, 0);
|
||||
}
|
||||
|
|
|
@ -306,6 +306,8 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
|
|||
|
||||
[OS_OSX::singleton->window_object setContentMinSize:NSMakeSize(0, 0)];
|
||||
[OS_OSX::singleton->window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
|
||||
// Force window resize event.
|
||||
[self windowDidResize:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidExitFullScreen:(NSNotification *)notification {
|
||||
|
@ -325,6 +327,9 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
|
|||
|
||||
if (OS_OSX::singleton->on_top)
|
||||
[OS_OSX::singleton->window_object setLevel:NSFloatingWindowLevel];
|
||||
|
||||
// Force window resize event.
|
||||
[self windowDidResize:notification];
|
||||
}
|
||||
|
||||
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
|
||||
|
|
|
@ -19,40 +19,42 @@ def can_build():
|
|||
# Check the minimal dependencies
|
||||
x11_error = os.system("pkg-config --version > /dev/null")
|
||||
if x11_error:
|
||||
print("Error: pkg-config not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config x11 --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config x11 --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("Error: X11 libraries not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xcursor --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config xcursor --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("xcursor not found.. x11 disabled.")
|
||||
print("Error: Xcursor library not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xinerama --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config xinerama --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("xinerama not found.. x11 disabled.")
|
||||
print("Error: Xinerama library not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xext --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config xext --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("xext not found.. x11 disabled.")
|
||||
print("Error: Xext library not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xrandr --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config xrandr --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("xrandr not found.. x11 disabled.")
|
||||
print("Error: XrandR library not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xrender --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config xrender --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("xrender not found.. x11 disabled.")
|
||||
print("Error: XRender library not found. Aborting.")
|
||||
return False
|
||||
|
||||
x11_error = os.system("pkg-config xi --modversion > /dev/null ")
|
||||
x11_error = os.system("pkg-config xi --modversion > /dev/null")
|
||||
if x11_error:
|
||||
print("xi not found.. Aborting.")
|
||||
print("Error: Xi library not found. Aborting.")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -138,7 +140,7 @@ def configure(env):
|
|||
# A convenience so you don't need to write use_lto too when using SCons
|
||||
env["use_lto"] = True
|
||||
else:
|
||||
print("Using LLD with GCC is not supported yet, try compiling with 'use_llvm=yes'.")
|
||||
print("Using LLD with GCC is not supported yet. Try compiling with 'use_llvm=yes'.")
|
||||
sys.exit(255)
|
||||
|
||||
if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]:
|
||||
|
@ -318,28 +320,25 @@ def configure(env):
|
|||
## Flags
|
||||
|
||||
if os.system("pkg-config --exists alsa") == 0: # 0 means found
|
||||
print("Enabling ALSA")
|
||||
env["alsa"] = True
|
||||
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
|
||||
else:
|
||||
print("ALSA libraries not found, disabling driver")
|
||||
print("Warning: ALSA libraries not found. Disabling the ALSA audio driver.")
|
||||
|
||||
if env["pulseaudio"]:
|
||||
if os.system("pkg-config --exists libpulse") == 0: # 0 means found
|
||||
print("Enabling PulseAudio")
|
||||
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
|
||||
env.ParseConfig("pkg-config --cflags libpulse")
|
||||
else:
|
||||
print("PulseAudio development libraries not found, disabling driver")
|
||||
print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
|
||||
|
||||
if platform.system() == "Linux":
|
||||
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
|
||||
if env["udev"]:
|
||||
if os.system("pkg-config --exists libudev") == 0: # 0 means found
|
||||
print("Enabling udev support")
|
||||
env.Append(CPPDEFINES=["UDEV_ENABLED"])
|
||||
else:
|
||||
print("libudev development libraries not found, disabling udev support")
|
||||
print("Warning: libudev development libraries not found. Disabling controller hotplugging support.")
|
||||
else:
|
||||
env["udev"] = False # Linux specific
|
||||
|
||||
|
@ -368,7 +367,7 @@ def configure(env):
|
|||
gnu_ld_version = re.search("^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE)
|
||||
if not gnu_ld_version:
|
||||
print(
|
||||
"Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld"
|
||||
"Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld, not gold or LLD."
|
||||
)
|
||||
else:
|
||||
if float(gnu_ld_version.group(1)) >= 2.30:
|
||||
|
|
|
@ -724,7 +724,7 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) {
|
|||
|
||||
} else { // cross-fading from prev to current
|
||||
|
||||
float blend = xfade ? (prev_xfading / xfade) : 1;
|
||||
float blend = xfade == 0 ? 0 : (prev_xfading / xfade);
|
||||
|
||||
if (!p_seek && switched) { //just switched, seek to start of current
|
||||
|
||||
|
|
|
@ -1635,10 +1635,16 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
|
|||
}
|
||||
|
||||
if (groups.size()) {
|
||||
// Write all groups on the same line as they're part of a section header.
|
||||
// This improves readability while not impacting VCS friendliness too much,
|
||||
// since it's rare to have more than 5 groups assigned to a single node.
|
||||
groups.sort_custom<StringName::AlphCompare>();
|
||||
String sgroups = " groups=[\n";
|
||||
String sgroups = " groups=[";
|
||||
for (int j = 0; j < groups.size(); j++) {
|
||||
sgroups += "\"" + String(groups[j]).c_escape() + "\",\n";
|
||||
sgroups += "\"" + String(groups[j]).c_escape() + "\"";
|
||||
if (j < groups.size() - 1) {
|
||||
sgroups += ", ";
|
||||
}
|
||||
}
|
||||
sgroups += "]";
|
||||
header += sgroups;
|
||||
|
|
Loading…
Reference in a new issue